当前位置 博文首页 > MARSHCW的博客:c++算法模板

    MARSHCW的博客:c++算法模板

    作者:[db:作者] 时间:2021-09-04 15:32

    ? 一、数组

    1184. 公交站间的距离

    难度:简单

    环形公交路线上有 n 个站,按次序从 0n - 1 进行编号。我们已知每一对相邻公交站之间的距离,distance[i] 表示编号为 i 的车站和编号为 (i + 1) % n 的车站之间的距离。

    环线上的公交车都可以按顺时针和逆时针的方向行驶。

    返回乘客从出发点 start 到目的地 destination 之间的最短距离。

    示例 1:

    img

    输入:distance = [1,2,3,4], start = 0, destination = 1
    输出:1
    解释:公交站 0 和 1 之间的距离是 1 或 9,最小值是 1。
    

    示例 2:

    img

    输入:distance = [1,2,3,4], start = 0, destination = 2
    输出:3
    解释:公交站 0 和 2 之间的距离是 3 或 7,最小值是 3。
    

    示例 3:

    img

    输入:distance = [1,2,3,4], start = 0, destination = 3
    输出:4
    解释:公交站 0 和 3 之间的距离是 6 或 4,最小值是 4。
    

    提示:

    • 1 <= n <= 10^4
    • distance.length == n
    • 0 <= start, destination < n
    • 0 <= distance[i] <= 10^4

    题解

    计算start-end的加和,计算这个范围外的加和,输出较小者。

    class Solution {
    public:
        int distanceBetweenBusStops(vector<int>& nums, int start, int end) {
            int d1 = 0, d2 = 0;
            int l = min(start,end);
            int r = max(start,end);
            for(int i=0;i<nums.size();i++){
                if(i>=l && i<r){d1 += nums[i];}
                else{d2 += nums[i];}
            }
            return d1<d2?d1:d2;
        }
    };
    

    1539. 第 k 个缺失的正整数

    难度:简单

    给你一个 严格升序排列正整数数组 arr 和一个整数 k

    请你找到这个数组里第 k 个缺失的正整数。

    示例 1:

    输入:arr = [2,3,4,7,11], k = 5
    输出:9
    解释:缺失的正整数包括 [1,5,6,8,9,10,12,13,...] 。第 5 个缺失的正整数为 9 。
    

    示例 2:

    输入:arr = [1,2,3,4], k = 2
    输出:6
    解释:缺失的正整数包括 [5,6,7,...] 。第 2 个缺失的正整数为 6 。
    

    提示:

    • 1 <= arr.length <= 1000
    • 1 <= arr[i] <= 1000
    • 1 <= k <= 1000
    • 对于所有 1 <= i < j <= arr.lengthij 满足 arr[i] < arr[j]

    题解

    方法一:

    相当于找空座位

    1. 正常排列时,缺失的正整数一定 >= k
    2. 数组中每出现一个 <= k 的数字, 意味着少了一个缺失的数字, 此时k+1,向后挪一个位置
     int findKthPositive(vector<int>& a, int k) {
         for(int i=0;i<a.size();++i){
                 if(a[i]<=k)++k;
         }
         return k;
        }
    

    方法二:二分法(需要找到各个元素与缺失元素个数的关系)

     int findKthPositive(vector<int>& arr, int k) {
            if (arr[0] > k) {
                return k;
            }
    
            int l = 0, r = arr.size();
            while (l < r) {
                int mid = l+((r-l) >> 1);
                int x = mid < arr.size() ? arr[mid] : INT_MAX;
                if (x - mid - 1 >= k) {
                    r = mid;
                } else {
                    l = mid + 1;
                }
            }
    
            return k - (arr[l - 1] - (l - 1) - 1) + arr[l - 1];
        }
    
    

    41. 缺失的第一个正数

    难度: 困难

    给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

    请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

    示例 1:

    输入:nums = [1,2,0]
    输出:3
    

    示例 2:

    输入:nums = [3,4,-1,1]
    输出:2
    

    示例 3:

    输入:nums = [7,8,9,11,12]
    输出:1
    

    提示:

    • 1 <= nums.length <= 5 * 105
    • -231 <= nums[i] <= 231 - 1

    题解

    class Solution {
    public:
        int firstMissingPositive(vector<int>& nums) {
          int n=nums.size();
          for(int i=0;i<n;++i){
              while(nums[i]>0&&nums[i]<n && nums[nums[i]-1]!=nums[i]){//将(0,n)的元素就位
                 swap(nums[i],nums[nums[i]-1]);
            }
         }
         for(int i=0;i<n;++i){
           if(nums[i]!=i+1)return i+1;
         }
         return n+1;
        }
    };
    

    剑指 Offer 03. 数组中重复的数字

    难度: 简单

    找出数组中重复的数字。

    在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

    示例 1:

    输入:
    [2, 3, 1, 0, 2, 5, 3]
    输出:2 或 3 
    

    限制:

    2 <= n <= 100000
    

    题解

      int findRepeatNumber(vector<int>& a) {
                if(a.size()<2)return -1;
                for(int i=0;i<a.size();i++){
                       if(a[i]!=i){//如果不相等
                            if(a[i]==a[a[i]]){ //如果相等,说明重复
                                    return a[i];
                             }
                             swap(a[i],a[a[i]]);
                        }
                }
                return -1;
        }
    

    136. 只出现一次的数字

    难度: 简单

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

    说明:

    你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

    示例 1:

    输入: [2,2,1]
    输出: 1
    

    示例 2:

    输入: [4,1,2,1,2]
    输出: 4
    

    题解

    class Solution {
    public:
        int singleNumber(vector<int>& nums) {
            int ans=0;
            for(const int&e:nums)ans ^=e;
            return ans ;
        }
    };
    

    283. 移动零

    难度: 简单

    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

    示例:

    输入: [0,1,0,3,12]
    输出: [1,3,12,0,0]
    

    说明:

    1. 必须在原数组上操作,不能拷贝额外的数组。
    2. 尽量减少操作次数。

    题解

    一次切分

    class Solution {
    public:
        void moveZeroes(vector<int>& nums) {
          if(nums.size()<2)return;
          int i=-1;      
          for(int j=0;j<nums.size();++j){
              if(nums[j]!=0) {//0在右边
                i++;
                swap(nums[i],nums[j]);  
              }  
          }
          return;
        }
    };
    
    //对比快排一次切分
    int partition(vector<int>& nums,int start,int end){
        int x=nums[end];
        int i=start-1;
        for(int j=start;j<end;++j){
            if(nums[j]<= x){
                ++i;
                swap(nums[i],nums[j]);
            }
        }
        swap(nums[i+1],nums[end]);
        return i+1;
    }
    
    
    

    88. 合并两个有序数组

    难度: 简单

    给你两个有序整数数组 nums1nums2,请你将 nums2 合并到 nums1 中*,*使 nums1 成为一个有序数组。

    初始化 nums1nums2 的元素数量分别为 mn 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

    示例 1:

    输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
    输出:[1,2,2,3,5,6]
    

    示例 2:

    输入:nums1 = [1], m = 1, nums2 = [], n = 0
    输出:[1]
    

    提示:

    • nums1.length == m + n
    • nums2.length == n
    • 0 <= m, n <= 200
    • 1 <= m + n <= 200
    • -109 <= nums1[i], nums2[i] <= 109

    题解

    逆向遍历,如果前一个数组为空,则直接放第二个数组的元素。

    特殊示例:

    (1)
    [0,0,0]  [1,2,3]  //m:0  n:3
    
    (2)
    [1,2,3,0] [1] //m:4 n:1
    
    class Solution {
    public:
        void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         int last = m+n-1;    //合并后元素的个数
         while(n){     //注意n
            if(m==0||nums1[m-1]<=nums2[n-1]){  //注意nums2
                nums1[last--] = nums2[--n];    
            }
            else{
                nums1[last--] = nums1[--m];    
            }     
         }  
        }
    };
    

    54. 螺旋矩阵

    难度:中等

    给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

    示例 1:

    img

    输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
    输出:[1,2,3,6,9,8,7,4,5]
    

    示例 2:

    img

    输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
    输出:[1,2,3,4,8,12,11,10,9,5,6,7]
    

    提示:

    • m == matrix.length
    • n == matrix[i].length
    • 1 <= m, n <= 10
    • -100 <= matrix[i][j] <= 100

    题解

     vector<int> spiralOrder(vector<vector<int>>& matrix) {
              if(matrix.empty())return {};
              vector<int>ans;
              int n=matrix[0].size();
              int m=matrix.size();
              int z=0,y=n-1,s=0,x=m-1; //左右上下
              int i=0;
              while(1){
                      //①从左到右
                      for(i=z;i<=y ;++i)ans.emplace_back(matrix[s][i]);
                      
                      //②从上到下
                       if(++s>x)break;           //判断是否越界
                      for(i=s; i<=x;++i)ans.emplace_back(matrix[i][y]);
                     
                      //③从右到左
                        if(--y<z)break;         //Judging whether it is out of bounds
                        for(i=y;i>=z;--i) ans.emplace_back(matrix[x][i]);
                      
                     //④从下往上
                       if(--x<s)       break; //judging whether it is out of bounds      
                       for(i=x;i>=s;--i)ans.emplace_back(matrix[i][z]);
                       
                       if(++z>y)break;  /*!!!*/
              }
              return ans;
        }
    

    48. 旋转图像

    难度:中等

    给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

    你必须在** 原地** 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

    示例 1:

    img

    输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
    输出:[[7,4,1],[8,5,2],[9,6,3]]
    

    示例 2:

    img

    输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
    输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
    

    示例 3:

    输入:matrix = [[1]]
    输出:[[1]]
    

    示例 4:

    输入:matrix = [[1,2],[3,4]]
    输出:[[3,1],[4,2]]
    

    提示:

    • matrix.length == n
    • matrix[i].length == n
    • 1 <= n <= 20
    • -1000 <= matrix[i][j] <= 1000

    题解

    class Solution {
    public:
        void rotate(vector<vector<int>>& matrix) {
          int n=matrix.size();
          for(int i=0;i<(n/2);++i)matrix[i].swap(matrix[n-i-1]) ;//先上下反转
          for(int i=0;i<n;++i){      //再转置
              for(int j=i;j<n;++j)
              swap(matrix[i][j],matrix[j][i]);    
          }
          return ;
        }
    };
    
    //旋转模拟
    class Solution {
    public:
        void rotate(vector<vector<int>>& matrix) {
            int n = matrix.size();
            for (int i = 0; i < n / 2; ++i) {
                for (int j = 0; j < (n + 1) / 2; ++j) {
                    int temp = matrix[i][j];
                    matrix[i][j] = matrix[n - j - 1][i];
                    matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
                    matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                    matrix[j][n - i - 1] = temp;
                }
            }
        }
    };
    

    349. 两个数组的交集

    难度:简单

    给定两个数组,编写一个函数来计算它们的交集。

    示例 1:

    输入:nums1 = [1,2,2,1], nums2 = [2,2]
    输出:[2]
    

    示例 2:

    输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    输出:[9,4]
    

    说明:

    • 输出结果中的每个元素一定是唯一的。
    • 我们可以不考虑输出结果的顺序。

    题解

    //调库函数:time: O(mlogm+nlogn)  space: O(logm+logn)
    #define all(x) begin(x), end(x)  //!!!
    class Solution {
    public:
        vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
            vector<int> ret;
            sort(all(nums1));
            sort(all(nums2));
            set_intersection(all(nums1), all(nums2), back_inserter(ret));
            ret.erase(unique(all(ret)), end(ret)); 
            return ret;
        }
    };
    
    //hash表法:time: O(n) space: O(n)
    class Solution {
    public:
            std::unordered_map<int,int> map;
            vector<int> ans;
        vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
            
            for(int i = 0;i<nums1.size();i++){
                map[nums1[i]] = 1;
            }
    
            for(int i = 0;i<nums2.size();i++){
                if(map[nums2[i]] == 1){
                    map[nums2[i]] = 0;
                    ans.emplace_back(nums2[i]);
                }
            }
            return ans;
        }
    };
    

    189. 旋转数组

    难度中等1002

    给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

    进阶:

    • 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
    • 你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

    示例 1:

    输入: nums = [1,2,3,4,5,6,7], k = 3
    输出: [5,6,7,1,2,3,4]
    解释:
    向右旋转 1 步: [7,1,2,3,4,5,6]
    向右旋转 2 步: [6,7,1,2,3,4,5]
    向右旋转 3 步: [5,6,7,1,2,3,4]
    

    示例 2:

    输入:nums = [-1,-100,3,99], k = 2
    输出:[3,99,-1,-100]
    解释: 
    向右旋转 1 步: [99,-1,-100,3]
    向右旋转 2 步: [3,99,-1,-100]
    

    提示:

    • 1 <= nums.length <= 2 * 104
    • -231 <= nums[i] <= 231 - 1
    • 0 <= k <= 105

    题解

    class Solution {
    public:
        void rotate(vector<int>& a,  int k) {
            int n=a.size();
            k%=n;
            if (n<2||k==0)return;
            reverse(a.begin(),a.end());
            reverse(a.begin(),a.begin()+k);
            reverse(a.begin()+k,a.end());   
        } 
    };
    

    525. 连续数组

    难度中等432

    给定一个二进制数组 nums , 找到含有相同数量的 01 的最长连续子数组,并返回该子数组的长度。

    示例 1:

    输入: nums = [0,1]
    输出: 2
    说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
    

    示例 2:

    输入: nums = [0,1,0]
    输出: 2
    说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
    

    提示:

    • 1 <= nums.length <= 105
    • nums[i] 不是 0 就是 1

    题解

    //前缀和问题,基础解法
    class Solution {
    public:
        int findMaxLength(vector<int>& nums) {
         int res=0,sum=0;
        
         unordered_map<int,int>umap; //key: prefix sum, v: index
         umap[0]=-1;
         for(int i=0;i<nums.size();++i){
          sum+=  (nums[i]==0?-1:1);
       
          if(umap.count(sum)){  //sum-0
                  res=max(res,i-umap[sum]);
          }
          else{
                  umap[sum]=i;
          }
         }
         return res;
        }
    };
    
    //优化hash表
    class Solution {
    public:
        int findMaxLength(vector<int>& nums) {
         int res=0,sum=0;
        const  int n=nums.size();
        vector<int>hash(2*n+1,-2);//存放下标,初始化为全-2
         hash[n]=-1;
         for(int i=0;i<n;++i){
          sum+=  (nums[i]==0?-1:1);
       
          if(hash[sum+n]!=-2){
                  res=max(res,i-hash[n+sum]);
          }
          else{
                  hash[n+sum]=i;
          }
         }
         return res;
        }
    };
    

    14. 最长公共前缀

    难度简单1684收藏分享切换为英文接收动态反馈

    编写一个函数来查找字符串数组中的最长公共前缀。

    如果不存在公共前缀,返回空字符串 ""

    示例 1:

    输入:strs = ["flower","flow","flight"]
    输出:"fl"
    

    示例 2:

    输入:strs = ["dog","racecar","car"]
    输出:""
    解释:输入不存在公共前缀。
    

    提示:

    • 0 <= strs.length <= 200
    • 0 <= strs[i].length <= 200
    • strs[i] 仅由小写英文字母组成

    题解

    class Solution {
    public:
        string longestCommonPrefix(vector<string>& strs) {
            if(strs.empty()) return string();
            sort(strs.begin(), strs.end());
            
            string start = strs.front(), end = strs.back();
            int i, num = min(start.size(), end.size());
            for(i = 0; i < num && start[i] == end[i]; i++);
            return start.substr(0,i);
        }
    };
    

    657. 机器人能否返回原点

    难度简单204

    在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束

    移动顺序由字符串表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R(右),L(左),U(上)和 D(下)。如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。

    **注意:**机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L” 将始终向左移动等。此外,假设每次移动机器人的移动幅度相同。

    示例 1:

    输入: "UD"
    输出: true
    解释:机器人向上移动一次,然后向下移动一次。所有动作都具有相同的幅度,因此它最终回到它开始的原点。因此,我们返回 true。
    

    示例 2:

    输入: "LL"
    输出: false
    解释:机器人向左移动两次。它最终位于原点的左侧,距原点有两次 “移动” 的距离。我们返回 false,因为它在移动结束时没有返回原点。
    

    题解

    class Solution {
    public:
        bool judgeCircle(string moves) {
            int x = 0, y = 0;
            for (int i = 0; i < moves.size(); i++) {
                if (moves[i] == 'U') y++;
                if (moves[i] == 'D') y--;
                if (moves[i] == 'L') x--;
                if (moves[i] == 'R') x++;
            }
            if (x == 0 && y == 0) return true;
            return false;
        }
    };
    

    15. 三数之和

    难度中等3487

    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 *a,b,c ,*使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

    **注意:**答案中不可以包含重复的三元组。

    示例 1:

    输入:nums = [-1,0,1,2,-1,-4]
    输出:[[-1,-1,2],[-1,0,1]]
    

    示例 2:

    输入:nums = []
    输出:[]
    

    示例 3:

    输入:nums = [0]
    输出:[]
    

    提示:

    • 0 <= nums.length <= 3000
    • -105 <= nums[i] <= 105

    题解

    class Solution {
    public:
        vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;//首先创建一个存放一个符合题意的一个三数组
        
        int n=nums.size();      
        if(n<3){            //如果这个数组小于3三个元素 不可能满足
            return {};
        }
        sort(nums.begin(),nums.end());//对这个数组进行排序
        for(int i=0;i<n;i++){               //进入循环 开始 把i当作第一个数  
            if(nums[i]>0){return ans;}      //这是排序过的 如果第一个数大于0 那么后面的数没有负的 就不可能三个数相加等于0;
            if(i>0&&nums[i]==nums[i-1]){continue;}//如果这个数前面用过了 就跳过
    
            int l=i+1;//左指针
            int r=n-1;//右指针
            // 进入双指针法找到 i后面  两个数之和=-i的;
            while(l<r){
                //如果两数之和大 就要减小 右指针向左收缩
                if(nums[l]+nums[r]>-nums[i]){
                    r--;
                    
                }
                     //如果两数之和小 就要增加 左指针向右收缩
                    else if(nums[l]+nums[r]<-nums[i]){
                    l++;
                   
                }
                    //如果相等     
                    else{
                    ans.push_back(vector<int>{nums[i],nums[l],nums[r]});//将符合的 三个坐标插入 我们的答案二维数组
                    //然后收缩指针 看看 之间还有没有 符合的
                    l++;
                    r--;
                        
                    //在找到相等的情况下,有数字重复就跳过
                    while(l<r&&nums[r]==nums[r+1]){ r--; }
                    while(l<r&&nums[l]==nums[l-1]){ l++; }
                }
            }
        }
        return ans;
        }
    };
    
    

    16. 最接近的三数之和

    难度中等820

    给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

    示例:

    输入:nums = [-1,2,1,-4], target = 1
    输出:2
    解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
    

    提示:

    • 3 <= nums.length <= 10^3
    • -10^3 <= nums[i] <= 10^3
    • -10^4 <= target <= 10^4

    题解

    class Solution {
    public:
        int threeSumClosest(vector<int>& nums, int target) {
         int n=nums.size();
         sort(nums.begin(),nums.end());
         int l,r,sum,ans=nums[0]+nums[1]+nums[2];
         for(int i=0;i<nums.size()-2;++i){   
            if(i>0 &&nums[i-1] == nums[i]) continue;
            l = i+1; 
            r = n-1;
            while(l<r){
               sum=nums[i]+nums[l]+nums[r] ;   
               if(sum == target) return target;
               if(abs(sum-target)<abs(ans-target)) ans=sum;  
               if(sum>target)r--;
               else l++;
            }  
         }
         return ans;
        }
    };
    

    304. 二维区域和检索 - 矩阵不可变

    难度中等

    给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)

    Range Sum Query 2D
    上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = **(4, 3),**该子矩形内元素的总和为 8。

    示例:

    给定 matrix = [
      [3, 0, 1, 4, 2],
      [5, 6, 3, 2, 1],
      [1, 2, 0, 1, 5],
      [4, 1, 0, 1, 7],
      [1, 0, 3, 0, 5]
    ]
    
    sumRegion(2, 1, 4, 3) -> 8
    sumRegion(1, 1, 2, 2) -> 11
    sumRegion(1, 2, 2, 4) -> 12
    

    提示:

    • 你可以假设矩阵不可变。
    • 会多次调用 sumRegion 方法*。*
    • 你可以假设 row1 ≤ row2col1 ≤ col2

    题解

    using namespace std;
    #include <vector>
    
    class NumMatrix {
    private:
        vector<vector<int> > sums;
    public:
        NumMatrix(vector<vector<int> >& matrix) {
            int n = matrix.size();
            int m = matrix[0].size();
            if (n == 0 || m == 0) {
                return;
            }
    
            sums.resize(n + 1, vector<int>(m + 1, 0));
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    sums[i][j] = matrix[i - 1][j- 1] + sums[i - 1][j] + sums[i][j - 1] - sums[i - 1][j - 1];
                }
            }
    
            return;
        }
        
        int sumRegion(int row1, int col1, int row2, int col2) {
            return sums[row2 + 1][col2 + 1] - sums[row2 + 1][col1] - sums[row1][col2 + 1] + sums[row1][col1];
        }
    };
    
    /**
     * Your NumMatrix object will be instantiated and called as such:
     * NumMatrix* obj = new NumMatrix(matrix);
     * int param_1 = obj->sumRegion(row1,col1,row2,col2);
     */
    

    413. 等差数列划分

    难度中等250

    如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。

    例如,以下数列为等差数列:

    1, 3, 5, 7, 9
    7, 7, 7, 7
    3, -1, -5, -9
    

    以下数列不是等差数列。

    1, 1, 2, 5, 7
    

    数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。

    如果满足以下条件,则称子数组(P, Q)为等差数组:

    元素 A[P], A[p + 1], …, A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。

    函数要返回数组 A 中所有为等差数组的子数组个数。

    示例:

    A = [1, 2, 3, 4]
    
    返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。
    

    题解

    //dp
    class Solution {
    public:
        int numberOfArithmeticSlices(vector<int>& nums) {
           int n=nums.size();
           if(n<3) return 0; 
           int sum=0;
           vector<int> dp(n,0);  
           for(int i=2;i<n;++i){
             if(nums[i]-nums[i-1]==nums[i-1]-nums[i-2]) {
               dp[i]=dp[i-1]+1;
               sum+=dp[i];  //前缀和  
             }  
           }
           return sum;
        }
    };
    
    //优化dp
    class Solution {
    public:
        int numberOfArithmeticSlices(vector<int>& nums) {
           int n=nums.size();
           if(n<3) return 0; 
           int sum=0;
           int pre=0; 
           for(int i=2;i<n;++i){
             if(nums[i]-nums[i-1]==nums[i-1]-nums[i-2]) {
               pre=pre+1;
               sum+=pre;    
             }
             else pre=0;  
           }
           return sum;
        }
    };
    
    
    下一篇:没有了