代码随想录-数组

数组是存放在连续内存空间上的相同类型数据的集合。

3.1.1移除元素-暴力解法

双层 for 循环,内层for循环遍历外层for循环剩余未遍历数组元素。

// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
                for (int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j];
                }
                i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
                size--; // 此时数组的大小-1
            }
        }
        return size;

    }
};
3.1.2移除元素-快慢指针法:

快指针for循环遍历数组。对于非目标值,快指针将该元素赋值于慢指针数组位置处,然后慢指针自加1;
如果快指针指向元素是目标值,快指针自加,慢指针不动。最后返回慢指针。

// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};
3.1.3移除元素-双向指针

左侧负责寻找val位置,右侧负责寻找不为val的位置,找到后将右侧的值覆盖到左侧。
循环中需要写成 left <= right,当left-right区间内没有val时,left需要自增到right位置

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int leftindex = 0;
        int rightindex = nums.size()-1;
        while(leftindex <= rightindex){
            //左侧寻找val
            while(leftindex <= rightindex && nums[leftindex] != val){
                leftindex++;
            }
            //右侧寻找不为val
            while(leftindex <= rightindex && nums[rightindex] == val){
                rightindex--;
            }
            if(leftindex<rightindex){
                nums[leftindex++] = nums[rightindex--];
            }
        }
        return leftindex;

    }
};
3.2.1有序数组的平方-暴力解法

先遍历,计算平方,然后排序

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for(int i = 0;i<nums.size();i++){
            nums[i] *= nums[i];
        }
        sort(nums.begin(),nums.end());//这里直接调用了排序算法
        return nums;
    }
};
3.2.2有序数组的平方-双指针法

两两比较,最后会剩下两个元素,这两个元素都需要加到新数组中,所以需要添加等号。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& A) {
        int k = A.size()-1;
        vector<int> result(A.size(),0);
        int j = A.size()-1;
        for(int i = 0;i<=j;){
            if(A[i]*A[i]<A[j]*A[j]){
                result[k--] = A[j]*A[j];
                j--;
            }
            else{
                result[k--] = A[i]*A[i];
                i++;
            }
        }
        return result;
    }
};
3.3.1长度最小的子数组-暴力解法

两个循环遍历数组,外层循环 i 从0到nums.size,内层循环由 i 到nums.size()

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT32_MAX;
        int sum = 0;
        int sublength = 0;
        for(int i=0;i<nums.size();i++){
            sum = 0;//每次计算时需要将sum清零
            for(int j=i;j<nums.size();j++){//计算i及后面元素和
                sum+=nums[j];
                if(sum >= target){
                    sublength = j - i + 1;//计算数组元素连续长度
                    result = result < sublength ? result : sublength;//判断是否需要更新
                    break; //找到符合要求的就不需要往下找了
                }
            }
        }
        return result == INT32_MAX? 0:result;
    }
};
3.3.2长度最小的子数组-滑动窗口法

类似于双指针,右侧指针用于遍历,将新遍历得到的数组元素放进sum中,左侧指针根据条件选择性右移。
while循环不断判断两个指针间的元素和是否大于等于target,若超出需要将左指针往右移,并且将sum更新。
while中加入等于判断是因为题目中要求找 >= target 的子数组。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT32_MAX;
        int sum = 0;
        int sublength = 0;
        int i = 0;
        for(int j=0;j<nums.size();j++){
            sum += nums[j];
            while(sum>=target){
                sublength = j-i+1;
                result = sublength<result ? sublength:result;
                sum -=nums[i++];
            }
        }
        return result == INT32_MAX? 0:result;
    }
};
3.4螺旋矩阵

首先遵循顺时针从左到右,从上到下的顺序,一圈一圈更新矩阵数据。
更新过程中遵循左闭右开,即对于拐角处数据,每次处理左侧,右侧留给下一组。
在这里插入图片描述
循环写入后,还需要判断一下n是否为奇数,如果是奇数,需要单独填充最中间的值。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n,vector<int>(n,0));
        int middle = n/2;
        int offset = 1;//统一按照左闭右开的方式逐圈更新
        int startx = 0,starty = 0;
        int loop = n/2;
        int count = 1;
        while(loop--){
            int i = startx;
            int j = starty;
            for(j = starty;j < n-offset;j++){//上行从左到右,左闭右开
                res[startx][j] = count;
                count++;
            }
            for(i = startx;i < n-offset;i++){//右列从上到下,左闭右开
                res[i][j] = count;
                count++;
            }
            for(;j>starty;j--){//下行从右到左,左闭右开
                res[i][j] = count;
                count++;
            }
            for(;i>startx;i--){//左列从下到上,左闭右开
                res[i][starty] = count;
                count++;
            }
            startx++;//写完一圈更新初始值
            starty++;
            offset++;//左闭右开偏移值也需要更新
        }
        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、付费专栏及课程。

余额充值