【Day1】代码随想录二刷Chapter1——数组

本文介绍了数组理论中的关键概念,如二分查找的边界处理、移除元素的双指针方法,以及排序算法(如快速排序、平方数组、长度最小子数组和螺旋矩阵),强调了算法分析和实践技巧。
摘要由CSDN通过智能技术生成

因为时间进度的安排,我想去的公司的实习的招聘开始时间还不是太紧,因此还是从代码随想录二刷开始,重点要做到以下方面:

1、每一章的套路总结,以及常遇到的问题(以思维导图的方式记录下来),如果有模板把模板记住;
2、分析代码的时间复杂度和空间复杂度(不要写完了就写完了,这个是在一刷中没有注意的);
3、C++在刷算法题中的常见语法(简单的排序等、迭代器这种的);
4、熟悉刷题中ACM模式(后面机试和笔试都是相关的);
5、排序的十种算法(冒泡、插入排序、归并排序、快排等)

今日任务:

  • 数组理论基础
  • 二分查找
  • 移除元素
  • 长度最小的子数组
  • 螺旋矩阵(再联系)

一、数组的理论基础

1、数组的特点:

  • 数组下标都是从0开始的;
  • 数组在内存空间的地址是连续的;
  • 数组只能被覆盖并不可以被删除。

题目一:704.二分查找(重点在边界处理)

Leetcode题目:【704.二分查找】

在这里插入图片描述

1.1 暴力解法:

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

时间复杂度:o(n);
空间复杂度:o(1);

1.2 二分查找法:

二分查找可以降低时间复杂度,变为logn;
采用二分查找法,其实就是左边区间不变量的问题,是左闭右闭还是左闭右开;
这个我选择左闭右闭,注意这里的终止条件是采用while的,这个就跟暴力的方法有区别

注意:因为我这里采用的是左闭右闭,所以left <= right是有意义的。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size()-1;
        while(left<=right){
            int mid = (left + right)/2;
            if(nums[mid] > target){
                right = mid - 1;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else {
                return mid;
            }
        }
        return -1;
    }
};

时间复杂度:o(logn);
空间复杂度:o(1)

题目二:27.移除元素

Leetcode题目:【27.移除元素】

在这里插入图片描述
直接用双指针的方法还是比较简单的,只不过需要注意下,最后的nums[slowindex++] = nums[fastindex],因为数组要改变,后面相当于做一个截断。

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowindex = 0, fastindex = 0;
        for(int fastindex = 0; fastindex<nums.size(); fastindex++){
            if(nums[fastindex] != val){
                nums[slowindex++] = nums[fastindex];
            }
        }
        return slowindex;
    }
};

时间复杂度o(n);
空间复杂度o(1);

题目三:有序数组的平方

Leetcode题目:【977.有序数组的平方】

在这里插入图片描述

3.1 sort函数

这个很直接的思路就是利用一个sort函数,进行快排就好了;

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());
        return nums;
    }

};

时间复杂度:o(n) + o(logn);
空间复杂度:o(1)

3.2 双指针(以空间换取时间)

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
       // 非常新的思路,双指针,重开一个数组,倒着放
       vector<int> result(nums.size());
       int i, j, k = nums.size() - 1;
       for(int i = 0, j = nums.size()-1; i<=j; ){
           if(nums[i] * nums[i] < nums[j] * nums[j]){
               result[k--] = nums[j] * nums[j];
               j--;
           }
           else{
               result[k--] = nums[i] * nums[i];
               i++;
           }
       }
       return result;
    }

};

时间复杂度:o(n);
空间复杂度:o(n)。

注意此处代码的双指针不要想着直接在原数组上进行修改,可以重新开一个数组,只放大的元素即可。

题目四:209.长度最小的子数组

Leetcode题目:【209.长度最小的子数组】

在这里插入图片描述

4.1 暴力解法

暴力解法的思路也很简单,直接两层for循环判断,但是时间会超时。
时间复杂度为:o(n^2);
空间复杂度为:o(1);

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT_MAX;
        for(int i = 0; i<nums.size(); i++){
            int sum = 0;
            for(int j = i; j<nums.size(); j++){
                sum += nums[j];
                if(sum >= target){
                    int len = j - i + 1;
                    result = result > len? len : result; 
                }
            }
        }
        return result == INT_MAX ? 0 : result;
    }
};

4.2 滑动窗口

此题也可以采用滑动窗口的方法,不断判断串口内的数据是否满足情况,满足情况,那前面的初始窗口指针就要后移。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT_MAX, i = 0, sum = 0, sublength = 0;
        for(int j = 0; j<nums.size(); j++){
            sum += nums[j];
            while( sum >= target){
                sublength = j - i + 1;
                result = result > sublength? sublength:result;
                sum -= nums[i++];  // 这里体现了滑动窗口的精髓,不断变更i
            }
        }
        return result == INT_MAX ? 0 : result;
    }
};

时间复杂度:o(n);
空间复杂度:o(1);

题目五:螺旋矩阵II(纯模拟题目)

Leetcode题目:【59.螺旋矩阵】

在这里插入图片描述
这个题非常麻烦,基本只需要放一圈就可以实现,然后直接用循环就可以实现。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 循环不变量,按照左闭右开来
        vector<vector<int>> num_matrix(n, vector<int>(n));
        int i = 0, j = 0, stay_x = 0, stay_y = 0, offset = 1;
        int cycle = n/2;  // 不管n是奇数还是偶数
        int count = 1;
        while(cycle--){
            for(j = stay_y; j<n-offset; j++){
                num_matrix[stay_x][j] = count++;
            }
            for(i = stay_x; i<n-offset; i++){
                num_matrix[i][j] = count++;
            }
            for(;j>stay_y; j--){
                num_matrix[i][j] = count++;
            }
            for(;i>stay_x; i--){
                num_matrix[i][j] = count++;
            }
            stay_x++;
            stay_y++;
            offset++;
        }
        if(n%2 == 1) num_matrix[n/2][n/2] = n*n;
        return num_matrix;
    }
};

有下面几个注意点:
(1)需要另外定义三个变量,stay_x,stay_y,offset,同时也需要把i,j定义为全局的,这样后面会很省事;
(2)围圈的时候的下半部分的终止条件为j > stay_y;

数组部分总结:

在这里插入图片描述

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值