代码随想录-数组

理论基础

什么是数组?

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

二分查找

在这里插入图片描述

有两种解法:左闭右闭、左闭右开

左闭右闭

即 [ left , right ]

class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
		int left = 0;
        int right = nums.size() - 1; //定义为左闭右闭
        while (left <= right) {
    
     //见注1
            //这一步等同于(left + right) / 2,如下处理为了防止内存溢出
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
    
     //说明target在左区间
                right = middle - 1;
            }else if (nums[middle] < target) {
    
    
                left = middle + 1;
            }else {
    
    
                return middle;
            }
        }
        return -1;
    }
};

  1. 因为定义了左闭右闭,所以 left 可以取到 right ,用<=

左闭右开

即 [ left , right )

class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
		int left = 0;
        int right = nums.size(); //定义为左闭右开
        while (left < right) {
    
     //left取不到right
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
    
    
                right = middle; //左区间是[left,middle)
            }else if (nums[middle] < target) {
    
    
                left = middle + 1;
            }else {
    
    
                return middle;
            }
        }
        return -1;
    }
};

移除元素

在这里插入图片描述

两种解法:暴力法、双指针法

暴力法

用两层for循环向前覆盖元素

扫描二维码关注公众号,回复: 15383900 查看本文章
class Solution {
    
    
public:
    int removeElement(vector<int>& nums, int val) {
    
    
		int size = nums.size();
        for (int i = 0; i < size; i++)  {
    
     //第一个for循环遍历数组元素
            if (nums[i] == val) {
    
    
                for (int j = i + 1; j < size; j++) {
    
     //第二个for循环更新数组
                    nums[j - 1] = nums[j];
                }
                i--; //i后的元素都向前移了一位,所以i--
                size--;
            }
        }
        return size;
    }
};

时间复杂度:O(n^2)

空间复杂度:O(1)

双指针法

用两个指针(快指针和慢指针)在一层for循环实现两层for循环的工作

class Solution {
    
    
public:
    int removeElement(vector<int>& nums, int val) {
    
    
		int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
    
    
            //若找到该元素,fastIndex++,slowIndex不动
            if (nums[fastIndex] != val) {
    
    
			//在下一次循环,用fastIndex指向的元素覆盖slowIndex的
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
};

时间复杂度:O(n)

空间复杂度:O(1)

长度最小的子数组

在这里插入图片描述

两种解法:暴力法、滑动窗口

暴力法

第一个for循环遍历所有元素,第二个for循环查找从该元素到数组末尾

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;
            for (int j = i; j < nums.size(); j++) {
    
    
                sum += nums[j];
                if (sum >= target) {
    
     //一旦和大于target,记录最小长度
                    subLength = j - i + 1;
                    result = result < subLength ? result : subLength;
                    break;
                }
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

时间复杂度:O(n^2)

空间复杂度:O(1)

滑动窗口

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 = result > subLength ? subLength : result;
                //滑动窗口的精髓,i一直在变
                sum -= nums[i++];
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

时间复杂度:O(n)

空间复杂度:O(1)

螺旋矩阵

在这里插入图片描述

坚持循环不变量:左闭右开

class Solution {
    
    
public:
    vector<vector<int>> generateMatrix(int n) {
    
    
		vector<vector<int>> res(n, vector<int>(n, 0));
        int startx = 0, starty = 0;
        int loop = n / 2; //圈数,n=3时就一圈
        int mid = n / 2; //如果n为奇数,最后要给中间位置赋值
        int count = 1; //记录赋的值
        int offset = 1; //控制每圈的长度,但不是长度
        int i, j;
        while (loop--) {
    
    
            i = startx;
            j = starty;
            //四次循环就是一圈
            for (j = starty; j < starty + n - offset; j++) {
    
    
                res[startx][j] = count++;
            }
            for (i = startx; i < startx + n - offset; i++) {
    
    
                res[i][j] = count++;
            }
            for (; j > starty; j--) {
    
    
                res[i][j] = count++;
            }
            for (; i > startx; i--) {
    
    
                res[i][j] = count++;
            }
            
            //每次循环后的处理
            startx++;
            starty++;
            offset += 2;
        }
        //如果是奇数
        if (n % 2) {
    
    
            res[mid][mid] = count;
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_50209297/article/details/130635160