算法专题:前缀和

参考练习习题总集

文章目录

  • 53. 最大子数组和(LCR 161 连续天数的最高销售额)
  • 85. 最大矩形
  • 187. 重复的DNA序列
  • 209. 长度最小的子数组
  • 238. 除自身以外数组的乘积
  • 363. 矩形区域不超过 K 的最大数值和
  • 396. 旋转函数

53. 最大子数组和(LCR 161 连续天数的最高销售额)

线性DP

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        for (int i=1;i<nums.size();i++)
            if (nums[i-1]>0)
                nums[i]+=nums[i-1];
        int result=INT_MIN;
        for (int i=0;i<nums.size();i++)
            if (nums[i]>result)
                result=nums[i];
        return result;
    }
};

前缀和

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int * lb=new int [nums.size()+1];lb[0]=0;
        for (int i=1;i<nums.size()+1;i++)
            lb[i]=lb[i-1]+nums[i-1];
        int min_value=0,result=INT_MIN;
        for (int i=1;i<nums.size()+1;i++)
        {
            int result_temp=lb[i]-min_value;
            if (result_temp>result) result=result_temp;
            if (lb[i]<min_value) min_value=lb[i];
        }
        delete [] lb;
        return result;
    }
};

85. 最大矩形

单调栈那里已经做过了。

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        vector<vector<int>> my_matrix(matrix.size(),vector<int> (matrix[0].size()));
        for (int i=0;i<matrix[0].size();i++)
            my_matrix[0][i]=(matrix[0][i]-'0');
        for (int i=1;i<matrix.size();i++)
            for (int j=0;j<matrix[0].size();j++)
                my_matrix[i][j]=matrix[i][j]=='0'?0:my_matrix[i-1][j]+(matrix[i][j]-'0');
        int result=0;
        for (int i=0;i<my_matrix.size();i++)
        {
            int result_temp=fc(my_matrix[i]);
            if (result_temp>result) result=result_temp;
        }
        return result;
    }
    int fc(const vector<int> & heights)
    {
        vector<int> my_vector1(heights.size(),-1);
        stack<int> my_stack1;
        for (int i=0;i<heights.size();i++)
        {
            while (!my_stack1.empty() and heights[i]<heights[my_stack1.top()])
            {
                my_vector1[my_stack1.top()]=i;my_stack1.pop();
            }
            my_stack1.push(i);
        }
        vector<int> my_vector2(heights.size(),-1);
        stack<int> my_stack2;
        for (int i=heights.size()-1;i>=0;i--)
        {
            while (!my_stack2.empty() and heights[i]<heights[my_stack2.top()])
            {
                my_vector2[my_stack2.top()]=i;my_stack2.pop();
            }
            my_stack2.push(i);
        }
        int result=0;
        for (int i=0;i<heights.size();i++)
        {
            int r,l;
            if (my_vector1[i]==-1) r=heights.size()-1-i;
            else r=my_vector1[i]-1-i;
            if (my_vector2[i]==-1) l=i;
            else l=i-1-my_vector2[i];
            int result_temp=heights[i]*(r+l+1);
            if (result_temp>result) result=result_temp;
        }
        return result;
    }
};

187. 重复的DNA序列

滑动窗口那里已经做过了。
不知道这道题跟前缀和有啥关系。

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        vector<string> lb;
        if (s.size()<=10) return lb;
        unordered_map<string,int> zd;
        string s_new=s.substr(0,10);
        zd[s_new]=1;
        for (int i=10;i<s.size();i++)
        {
            s_new.erase(0,1);s_new+=s[i];
            if (zd.find(s_new)==zd.end()) zd[s_new]=1;
            else
            {
                if (zd[s_new]==1) lb.push_back(s_new);
                zd[s_new]+=1;
            }
        }
        return lb;
    }
};

209. 长度最小的子数组

滑动窗口

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        if (nums[0]>=target) return 1;
        int begin=0,length=1,value=nums[0],result=INT_MAX;
        while (begin-1+length<nums.size())
            if (value<target)
            {
                if (begin+length==nums.size()) break;  
                length+=1;value+=nums[begin+length-1];
            }
            else
            {
                if (length<result) result=length;
                value-=nums[begin];begin+=1;length-=1;
            }
        return result==INT_MAX?0:result;
    }
};

前缀和

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int * lb=new int [nums.size()+1];lb[0]=0;
        for (int i=0;i<nums.size();i++)
            lb[i+1]=lb[i]+nums[i];
        int result=INT_MAX;
        for (int i=0;i<nums.size()+1;i++)
        {
            int l=i,r=nums.size(),value=lb[i]+target;
            if (value>lb[nums.size()]) break;
            while (l<=r)
            {
                int m=l+(r-l)/2;
                if (lb[m]<value) l=m+1;
                else if (m==i or lb[m-1]<value)
                {
                    if (m-i+1<result) result=m-i+1;
                    break;
                }
                else r=m-1; 
            }
        }
        return result==INT_MAX?0:result-1;
    }
};

238. 除自身以外数组的乘积

前缀积、后缀积

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> lb1(nums.size());lb1[0]=nums[0];
        for (int i=1;i<nums.size();i++)
            lb1[i]=lb1[i-1]*nums[i];
        vector<int> lb2(nums.size());lb2[nums.size()-1]=nums[nums.size()-1];
        for (int i=nums.size()-2;i>=0;i--)
            lb2[i]=lb2[i+1]*nums[i];
        vector<int> lb3(nums.size());
        for (int i=0;i<nums.size();i++)
        {
            int l=i==0?1:lb1[i-1];
            int r=i==nums.size()-1?1:lb2[i+1];
            lb3[i]=l*r;
        }
        return lb3;
    }
};

她的有些题涉及到了其他我没有学的知识。这些题暂时不做吧,等我学完了再在对应部分补充。主要是我真心不会,已经开摆了。

363. 矩形区域不超过 K 的最大数值和

下面代码的时间复杂度为 O ( m 2 n 2 ) O(m^2n^2) O(m2n2)。不想优化了,反正能过而且n最大也就100,开摆开摆。官方题解代码的时间复杂度为 O ( m 2 n l o g 2 n ) O(m^2 nlog_2^n) O(m2nlog2n),应该是哪里用了一下二分查找。唉,不想去想了,大脑已经动不了了。

class Solution {
public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        int m=matrix.size()+1,n=matrix[0].size()+1;
        int * * lb=new int * [m];
        for (int i=0;i<m;i++)
        {
            lb[i]=new int [n];
            for (int j=0;j<n;j++)
                lb[i][j]=0;
        }
        for (int i=1;i<m;i++)
            for (int j=1;j<n;j++)
            {
                lb[i][j]=lb[i][j-1]+matrix[i-1][j-1];
            }
        for (int j=1;j<n;j++)
            for (int i=1;i<m;i++)
            {
                lb[i][j]=lb[i-1][j]+lb[i][j];
            }
        int result=INT_MIN;
        for (int i=1;i<m;i++)
            for (int j=1;j<n;j++)
                for (int length=1;length<m-i+1;length++)
                    for (int width=1;width<n-j+1;width++)
                    {
                        int result_temp=lb[i+length-1][j+width-1]+lb[i-1][j-1]-
                            lb[i+length-1][j-1]-lb[i-1][j+width-1];
                        if (result_temp==k) return k;
                        if (result_temp<k and result_temp>result)
                            result=result_temp;
                    }
        for (int i=0;i<m;i++)
            delete [] lb[i];
        return result;
    }
};

396. 旋转函数

滑动窗口那里已经做过了。
前缀积、后缀积

class Solution {
public:
    int maxRotateFunction(vector<int>& nums) {
        int count=0;
        for (int x:nums) count+=x;
        int f0=0;
        for (int i=0;i<nums.size();i++)
            f0+=i*nums[i];
        int result=f0;
        for (int i=1;i<nums.size();i++)
        {
            f0=f0+count-nums[nums.size()-i]*nums.size();
            if (f0>result) result=f0;
        }
        return result;
    }
};

唉,那就这样吧,不做了。

你可能感兴趣的:(算法导论,算法,leetcode,前缀和)