【LeetCode】2.数组系列

总目录:

LeetCode系列导航目录

 

0.理论基础

0.1.要点

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

数组可以方便的通过下标索引的方式获取到下标下对应的数据。

在删除或者增添元素的时候,就难免要移动其他元素的地址,只能覆盖而不能删除。

多维数组的地址也是连续的。

 

1.二分查找

1.1.问题描述

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
链接:https://leetcode.cn/problems/binary-search

1.2.要点

二分查找就是二分查找范围,注意边界的索引处理

在计算中值索引时注意防止溢出,固定套路为mid=left+(right-left)/2;

1.3.代码实例

 1 class Solution {
 2 public:
 3     int search(vector<int>& nums, int target) {
 4         int start=0,end=nums.size()-1;
 5         int mid=0;
 6         while(start<=end){
 7             mid=start+((end-start)>>1);//防止溢出
 8             if(nums[mid]==target){
 9                 return mid;
10             }
11             if(nums[mid]>target){
12                 end=mid-1;
13             }
14             if(nums[mid]<target){
15                 start=mid+1;
16             }
17         }
18 
19         return -1;
20     }
21 };
View Code

 

2.移除指定元素

2.1.问题描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
链接:https://leetcode.cn/problems/remove-element

2.2.要点

不要开辟额外空间,绝对是使用双指针。有快慢指针和对撞指针2种解法。

快慢指针,可以保证有效数据的顺序不变,但存在较多的内存copy。

对撞指针,有效数据的顺序将发生改变,但只存在尽量少的内存copy。

2.3.代码实例

快慢指针

 1 class Solution {
 2     public int removeElement(int[] nums, int val) {
 3         int curIndex = 0;
 4         int len = nums.length;
 5         for (int i = 0; i < len; i++) {
 6             // 如果等于就被删除, 后面的向前合并
 7             if(nums[i] != val){
 8                 nums[curIndex++] = nums[i];
 9             }
10         }
11         return curIndex;
12     }
13 }
View Code

对撞指针

 1 class Solution {
 2 public:
 3     int removeElement(vector<int>& nums, int val) {
 4         int left=0,right=nums.size()-1;
 5         if(right<0){
 6             return 0;
 7         }
 8 
 9         //对撞之后不再迭代
10         while(left<=right){
11             //先找到最后一个非目标数的值
12             if(nums[right]==val){
13                 right--;
14                 continue;
15             }
16 
17             //如果在前面遇到目标值,则将其交换到后面
18             if(nums[left]==val){
19                 swap(nums[left],nums[right]);
20                 right--;
21             }
22 
23             left++;
24         }
25 
26         //right值既为最后一个不为val的索引
27         return right+1;
28     }
29 };
View Code

 

3.有序数组的平方

3.1.问题描述

非递减顺序:相邻元素不是相等就是递增。

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

链接:https://leetcode.cn/problems/squares-of-a-sorted-array/

3.2.要点

这是合并两个有序集合的变种

双指针,分别比较两个集合的顶部元素,放入新的集合中,是一种归并排序算法

3.3.代码实例

归并排序

 1 class Solution {
 2 public:
 3     vector<int> sortedSquares(vector<int>& nums) {
 4         int n = nums.size();
 5         int negative = -1;
 6         for (int i = 0; i < n; ++i) {
 7             if (nums[i] < 0) {
 8                 negative = i;
 9             } else {
10                 break;
11             }
12         }
13 
14         vector<int> ans;
15         int i = negative, j = negative + 1;
16         while (i >= 0 || j < n) {
17             if (i < 0) {
18                 ans.push_back(nums[j] * nums[j]);
19                 ++j;
20             }
21             else if (j == n) {
22                 ans.push_back(nums[i] * nums[i]);
23                 --i;
24             }
25             else if (nums[i] * nums[i] < nums[j] * nums[j]) {
26                 ans.push_back(nums[i] * nums[i]);
27                 --i;
28             }
29             else {
30                 ans.push_back(nums[j] * nums[j]);
31                 ++j;
32             }
33         }
34 
35         return ans;
36     }
37 };
View Code

 

4.长度最小的子数组

4.1.问题描述

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
链接:https://leetcode.cn/problems/minimum-size-subarray-sum

4.2.要点

都是正整数,要连续的最短,只需要返回长度

1.滑动窗口法,左缩右伸

4.3.代码实例

1.滑动窗口法

 1 class Solution {
 2 public:
 3     int minSubArrayLen(int target, vector<int>& nums) {
 4         int minLen=INT_MAX;
 5         if(nums.size()<1){
 6             return 0;
 7         }
 8 
 9         queue<int> sumQ;
10         int curLen=0;
11         int curSum=0;
12         int curId=0;
13 
14         while(curId<nums.size()){
15             //加上当前到达的值
16             sumQ.push(nums[curId]);
17             curSum+=nums[curId];
18 
19             //满足条件时持续左缩寻找最短长度
20             while(curSum>=target){
21                 curLen=sumQ.size();
22                 curSum-=sumQ.front();
23                 sumQ.pop();
24 
25                 minLen=min(minLen,curLen);
26             }    
27 
28             //不够时向右延伸1步
29             curId++;
30         }
31 
32         return minLen==INT_MAX?0:minLen;
33     }
34 };
View Code

 

5.螺旋矩阵2

5.1.问题描述

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

链接:https://leetcode.cn/problems/spiral-matrix-ii/

5.2.要点

顺时针

1.模拟,边界收缩

5.3.代码实例

边界收缩法

 1 class Solution {
 2 public:
 3     vector<vector<int>> generateMatrix(int n) {        
 4         vector<vector<int>> ret(n,vector<int>(n,0));
 5 
 6         int i=0;
 7         int curVal=1;        
 8         int up=0,down=n-1,left=0,right=n-1;
 9         while(up<=down&&left<=right){
10             for(i=left;i<=right;i++){
11                 ret[up][i]=curVal;
12                 curVal++;
13             }
14             up++;
15 
16             for(i=up;i<=down;i++){
17                 ret[i][right]=curVal;
18                 curVal++;
19             }
20             right--;
21 
22             for(i=right;i>=left;i--){
23                 ret[down][i]=curVal;
24                 curVal++;
25             }
26             down--;
27 
28             for(i=down;i>=up;i--){
29                 ret[i][left]=curVal;
30                 curVal++;
31             }
32             left++;
33         }
34 
35         return ret;
36     }
37 };
View Code

 

6.总结

6.1.经典套路

二分法

双指针

滑动窗口,精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。

模拟行为,核心是模拟行为+控制边界。

6.2.Fabulaous Mind

 

 


 

 

 

 

 

 

xxx.问题

xxx.1.问题描述

111

xxx.2.要点

222

xxx.3.代码实例

333

 

posted @ 2022-12-12 17:47  啊原来是这样呀  阅读(38)  评论(0)    收藏  举报