算法基础2:数组,双指针,滑动窗口法

c++中的数组

一般使用vector或者array来表示数组。vector其实是容器。

有序数组的平方

题目链接:Leetcode977

双指针解法

 vector<int> sortedSquares(vector<int>& nums) {
   int left=0, right =nums.size()-1;
   vector<int> res;
   res.resize(nums.size());
   int index = right;

   while(left<=right){
       if(nums[right]*nums[right] < nums[left]*nums[left]){
           res[index--] = nums[left]*nums[left];
           left++;
       }
       else{
           res[index--] = nums[right]*nums[right];
           right--;
       }
   }
   return res;
}

思路

  1. 使用暴力解法:先对所有元素求平方和,然后排序。时间复杂度O(n +logn)
  2. 双指针,构建一个新的同样大小的数组,左右指针进行对比,哪个大,哪个放到最后。时间复杂度O(n)

长度最小的子数组

题目链接:leetcode209

int minSubArrayLen(int target, vector<int>& nums) {

    int left =0, sum=nums[left], length = nums.size()+1;
    if(sum>target) return 1;
    for(int right=1; right<nums.size(); right++){
        sum += nums[right];
        while(sum >= target){
            length = right-left+1 < length ? right-left+1: length;
            sum -= nums[left++];
        }
    }
    return length > nums.size() ? 0:length;
}

思路

  1. 一开始上来理解错了题意,当作了要完全等于target的情况。想到双指针的时候,是以左右指针的形式。
  2. 问题:左右指针的使用基本应用于有排序的数组。在无排序的情况下,考虑滑动窗口法。
  3. 滑动窗口需要明确的点是:窗口的起点和终点怎么开始,终点怎么移动,起点怎么移动。
  4. 在该问题中求解最小子数组长度,肯定会存在满足该条件下的多个子数组,寻找的是最小的长度,涉及到了长度的对比,需要记录遍历过的满足该子数组的最小长度。
  5. 窗口记录的是什么?满足该条件的子数组。窗口的右移是一层for循环的向右遍历。窗口左移的标准是,当该窗口满足条件后,继续左移,直到不满足为止。
  6. 时间复杂度:O(n)。最差应该是2n。

螺旋矩阵

题目链接:leetcode59

vector<vector<int>> generateMatrix(int n) {
    vector<vector<int>> res(n,vector<int>(n,0));
    int i=0, j=0;
    int num = 1;
    int leftstart = 0;
    int rightstart = 0;
    int rightbound = n-1;
    int leftbound = n-1;
    while(num <= n*n){
        for(int i=leftstart, j=rightstart; j<=rightbound && num <= n*n; j++){
            res[i][j] = num++;
        }
        leftstart++;
        for(int i=leftstart, j=rightbound; i<=leftbound && num <= n*n; i++){
            res[i][j] = num++;
        }
        rightbound--;
        for(int i=leftbound, j=rightbound; j>=rightstart && num <= n*n; j--){
            res[i][j] = num++;
        }
        leftbound--;
        for(int i=leftbound, j=rightstart; i>=leftstart&& num <= n*n; i--){
            res[i][j] = num++;
        }
        rightstart++;
    }
    return res;
    
}

思路

关键点:

  1. 确定好区间,每一次包含到什么位置,个人习惯闭区间,比较好减。
  2. 确定好每一次的边界条件,虽然有了while判断,但是是所有的while中包含的语句都走完了之后,才会去判断是否满足下一次的循环。所以需要在for循环语句中,也去添加判断条件。
  3. 代码要细心,rightstart++写成了,rightbound++,找这个bug太心累了。
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值