代码随想录算法训练营Day02

Day02 数组

一、力扣相关例题

977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 :
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

这道题的关键在于:
①理解快速排序sort内层机制,快速排序时间复杂度O(nlogn)
②如何实现O(n)时间复杂度的算法,如何巧妙运用双指针实现O(n)的解法
③对于新手来说,掌握动态创建数组
④冒泡排序O(n^2),时间超时

//调用函数sort,快速排序,时间复杂度O(nlogn)
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
       for (int i = 0; i < nums.size(); i++) {  //每个数平方
           nums[i] = nums[i] * nums[i];
       }
       sort(nums.begin(), nums.end());  //sort排序
       return nums;
    }
};
//双指针
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result(nums.size(), 0);   //创建数组的方式,需掌握!
        int k = nums.size()-1;
        int left, right;   //一个左指针,一个右指针,分别指向数组的左右两侧,因为平方的较大值往往出现在两侧之一(数组是递增)
        for (left=0, right=nums.size()-1; left<=right;) {   //这里的left--、right--不在for内写,是因为加减是有条件的,所以放在后续If条件内
            if(nums[left]*nums[left] > nums[right]*nums[right]) {   //左侧平方较大,则将平方后的值填入result数组中
                result[k] = nums[left]*nums[left];
                k--;  //因返回递增数组,所以填入从下标大→小
                left++;
            } else {     //右侧平方较大或者左右相等,则将平方后的值填入result数组中
                result[k] = nums[right]*nums[right];
                k--;
                right--;
            }
        }
        return result;
    }
};

209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 :
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

这道题的关键在于:
①大于target的数组长度怎么变换更新
②滑动窗口到底是什么?(滑动窗口是不断的调节子序列的起始位置和终止位置,得出想要的结果序列)
③滑动窗口内的双指针怎么规定呢?怎么表示起始位置和结束位置呢?

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //因为int占4字节32位,根据二进制编码的规则,INT_MAX = 2^31-1,INT_MIN= -2^31
        int sum = 0;
        int first = 0;
        int len = 0;
        int result = INT32_MAX;
        for (int last = 0; last < nums.size(); last++) {  //这里的循环变量需特别注意,是滑动窗口的关键,循环变量的结束位置
            sum += nums[last];
            while (sum >= target) {
                len = last - first + 1;
                result = min(result, len);
                sum = sum - nums[first];
                first++;
            }
        }
        return result == INT32_MAX ? 0 : result;   //若resul在while内有另新赋值,则返回result;否则返回0
    }
};

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 :
在这里插入图片描述
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

这道题的关键在于:
①循环几次
②联想二分法(左开右闭进行遍历)
③每个边界的点怎么处理
④n偶数or奇数的遍历的不同点(奇数n最中间的数需额外填写,偶数n通过遍历即可完成)

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> nums(n, vector<int>(n, 0)); //使用vector定义二维数组(掌握!)
        int startx = 0, starty = 0;  //定义x,y起始位置
        int offset = 1, count = 1;  //offset是控制左闭右开的右开部分,count是需要填写入二维数组的元素
        int loop = n / 2;   //循环次数,奇数循环一次,偶数循环两次
        int i, j;
        while (loop--) {
            //遍历上下左右特须注意左闭右开,以及边界的考虑
            //遍历上行
            for (j = starty; j < n - offset ; j++) {
                nums[startx][j] = count;
                count++;
            }
            //遍历右行
            for (i = startx; i < n - offset; i++) {
                nums[i][j] = count;
                count++;
            }
            //遍历下行
            for (; j > starty; j--) {
                nums[i][j] = count;
                count++;
            }
            //遍历左行
            for (; i > startx; i--) {
                nums[i][j] = count;
                count++;
            }
            startx++;
            starty++;
            offset += 1;
        }
        if (n % 2 == 1) {    //如果n为奇数的话,则剩余最中间的点未填写
            nums[n/2][n/2] = count;
        }
        return nums;
    }
};

二、数组总结

数组的解题思路

二分法

二分法关注点:
①循环不变量原则,只有在循环中坚持对区间的定义,才能清楚的把握循环中的各种细节。
②循环不变量:在循环过程中保持不变的性质。
③区间选定:左闭右闭、左闭右开、左开右闭、左开右开(掌握前两个即可),选定完区间,循环条件就要多加注意
时间复杂度O(logn)

双指针法

双指针法(快慢指针法):通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
时间复杂度O(n)

滑动窗口

理解滑动窗口
①如何移动窗口起始位置,达到更新符合题目要求的子序列窗口大小,从而得出长度最小的符合条件的长度。
②精妙之处:根据当前子序列和大小的情况,不断调节子序列的起始位置
时间复杂度O(n)

循环模拟

循环不变量原则
区间选择
边界处理

录友总结:

在这里插入图片描述

每日一更实属不容易,加油!
欢迎大家指正!感谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值