代码随想录刷题DAY2|双指针977、209(附代码)

Leetcode: 977有序数组的平方

基本思路

结合昨天学习到的双指针的思想。首先审题的过程中,发现数据存在负数,因此就存在负数的平方可能更大的情况,因此产生了数组排序的问题。但是整体数组的平方规律为先降低,然后在上升。因此最大数肯定存在两端。从而产生双指针从数组两端开始向中间搜索的策略。

时间复杂度O(n)

代码

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;
        int k = right;//编程技巧:从数组的最后开始赋值,这样不用产生调换顺序的操作
        vector<int> result(nums.size(),0);//对新的数组的定义,用空间换时间
        while(left <= right){
            if(nums[left] * nums[left] > nums[right] * nums[right]){
                result[k] = nums[left] * nums[left];
                left++;
                k--;
            }
            else{//因为left=right的情况下,随便哪一个都行,因此不用单独分支
                result[k] = nums[right] * nums[right];//注意最后输出的是平放,不要忘记乘了
                right--;
                k--;
            }
        }
        return result;
    }
};

Leetcode: 209最小长度的子数组

基本思路

这题的双指针起点从同侧开始,右指针移动快,左指针移动慢。当没有达到目标值的时候,移动右指针,当目标值达到的时候移动左指针。当左指针移动后就需要判断当前的长度是不是最小的,从而更新最小长度。最后输出结果。(也叫滑动窗)

代码

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left = 0, right = 0, sum = 0;
        int count = INT32_MAX;//用于判断count是否赋值,没有赋值就输出0
        while(right < nums.size()){
            sum = sum + nums[right];//右指针向右移动
            while(sum >= target){//当和大于目标值的时候,左指针向右移动
                sum = sum - nums[left];
                if((right - left + 1) < count){//判断是否需要更新最小长度
                    count = right - left + 1;
                }
                left++;
            }
            right++;
        }
        return count == INT32_MAX ? 0 : count;//判断输出
    }
};

附加题: 26 删除有序数组中的重复元素

本题主要考察双指针的应用,本身题目很简单,但是容易犯错,对一些等号和判断条件把握不准确。

如果 nums[fast]≠nums[fast−1],说明 nums[fast]和之前的元素都不同,因此可以更新慢指针。

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int fast = 1, slow = 1;//因为涉及到fast-1,如果初始化为0的话,会导致越界
        if(nums.size() == 0) return 0;//特殊条件判断
        for( ; fast <= nums.size() - 1; fast++){//第一层循环
            if(nums[fast] != nums[fast - 1]){//当此条件的时候,一定是不重复的元素
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }
};

Leetcode: 59 螺旋矩阵

一道基本的模拟题,整体思路不难,就是写不出来。。。(bushi)

主要错误点

  • 参数太多了,没有规划容易搞混,或者定义少了,因此在开始之前需要预先思考需要多少个参数
  • 不知道循环n/2圈
  • 最后奇数的中间和偶数中间不一样,还有一个数字
  • 没有定义好规则,需要秉承着左闭右开或者其他规则,防止重复统计位置,或者少了位置,或者条件判断失误,出现细小的问题
  • 最好配合着画图,如果数字关系把握不准确,可以用笔算算
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {//二次矩阵的定义方式
        int starti = 0, startj = 0, i = 0, j = 0; 
        int count = n / 2;//圈数定义
        int number = 1;
        int flag = 1;//循环边界条件定义
        vector<vector<int>> res(n, vector<int>(n, 0));
        while(count--){
            i = starti;//起始位置更新
            j = startj;
            for( ; j < n - flag; j++){
                res[i][j] = number;
                number++;
            }
            for( ; i < n - flag ;i++){
                res[i][j] = number;
                number++;
            }
            for(;j > startj ;j--){
                res[i][j] = number;
                number++;
            }
            for(; i > starti; i--){
                res[i][j] = number;
                number++;
            }
            flag++;
            starti++;
            startj++;
        }
        if(n % 2){//如果是奇数,中间的数字
            res[n/2][n/2] = n*n;
        }
        return res;
    }
};

小结

今天主要联系了双指针的题目,在审题过程中需要思考

  • 指针开始的方式和移动方向
  • 快慢指针的更新规则,以及条件判断
  • 小心数量关系的错误,导致边界条件不清晰
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值