数组的题目不算是难题,锻炼的是代码的操控能力。
- 主要运用的方法:
暴力解法就是for循环的嵌套使用
双指针法
滑动窗口 - 考察的题目:
二分法排序、元素查找与删除、寻找最小子数组、螺旋矩阵等
下文以题目分类来解释 - 二分法排序:
注意:记住循环不变量原则:每一次边界的处理都要根据区间的定义来确定。
例如:
左闭右开区间时,即初始化时定义left=0,right=nums.size(), while(left<right), middle = left+(right-left)/2;
left = middle +1; right = middle;
代码如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size();
int mid = 0;
while(left<right){
mid = left+((right-left)/2);
if(nums[mid]>target){
right = mid;
}
else if(nums[mid]<target){
left = mid + 1;
}
else if(nums[mid]==target){
return mid;
}
}
return -1;
}
};
左闭右闭时,即初始化时定义left =0; right = nums.size()-1;
while(left<=right), middle = left+(right-left)/2;
left = middle +1; right = middle-1; 相关更改根据上述代码可完成。
- 移除元素
(1)leetcode 题目地址:
https://leetcode-cn.com/problems/remove-element/
快慢指针解法:
(知道是使用快慢指针解决原地更改数组元素,但是具体细节也有技巧):后一元素覆盖前一元素,判断快指针元素不等于目标值时,快指针+1,慢指针不动,快指针跳过相等值时,快指针元素赋值给慢指针元素。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowindex = 0, fastindex = 0;
int i = nums.size();
for(fastindex = 0 ; fastindex < i ; fastindex++){
if(nums[fastindex] != val){
nums[slowindex++]=nums[fastindex];
}
}
return slowindex;
}
};
(2)leetcode 题目地址:
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
快慢指针解法:
两个判断:当快慢指针元素相等时,快指针+1;直至不等,慢指针+1,再将快指针元素赋值给慢指针元素。要注意的是,容易忽略输入是一个空数组的情况,加一个判断。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slowindex = 0, fastindex = 0;
if(nums.size() == 0){
return 0;
}
while(fastindex < nums.size()){
if(nums[slowindex] == nums[fastindex]){
fastindex++;
}
else if(nums[slowindex] != nums[fastindex]){
slowindex++;
nums[slowindex] = nums[fastindex];
}
}
return slowindex+1;
}
};
- 有序数组的平方,输出仍然有序
leetcode 题目地址:
https://leetcode-cn.com/problems/squares-of-a-sorted-array/
正常思路就是先平方后排序,前文使用的二分法并不适合,因为可能在平方之后有重复元素的出现。
这里依然可以使用双指针解法,快指针指向末尾,慢指针指向第一个元素,对比大小,大的从后往前赋值给容器,因为平方后,大数是在数组的头部或者尾部
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int len = nums.size();
vector<int> result(len, 0); //定义一个容器,因为数组的初始化不允许有变量,不可以用数组去接排序后的结果
int fastindex = len-1, slowindex = 0, a = len-1;
while(slowindex <= fastindex){ //这里要有等号
if(nums[fastindex]*nums[fastindex] >= nums[slowindex]*nums[slowindex]){
result[a] = nums[fastindex]*nums[fastindex];
fastindex--;
a--;
}
else{
result[a] = nums[slowindex]*nums[slowindex];
slowindex++;
a--;
}
}
return result;
}
};
- 滑动窗口寻找最小子数组
leetcode 题目地址:
https://leetcode-cn.com/problems/minimum-size-subarray-sum/
快慢指针解法:
慢指针为0,遍历快指针,找中间元素记录最小长度值
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int slowindex = 0, fastindex = 0, sum = 0, a = nums.size()+1 ;
int len = 0;
for(fastindex = 0; fastindex < nums.size(); fastindex++){
sum += nums[fastindex];
while(sum>=target){
len = fastindex-slowindex+1;
sum -= nums[slowindex];
slowindex++;
if(len < a){ //记录最小长度
a = len;
}
}
}
return a == nums.size()+1? 0 : a; //判断没有改变长度时,没有最小子数组,输出0 用“==”
}
};
- 生成顺时针螺旋排序数组
leetcode 题目地址:
https://leetcode-cn.com/problems/spiral-matrix-ii/
这题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。
像二分法一样,始终注意循环不变量原则,即始终左闭右闭,或者左闭右开
下图是左闭右开,循环
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n, vector<int>(n,0)); //输出n*n的正方形矩阵
int startx = 0, starty = 0; //横纵起始元素
int loop = n/2, mid = n/2; //循环次数、中间点坐标
int offset = 1; //控制一行输出个数
int count = 1; //赋值
while(loop--){
int i = startx;
int j = starty;
for(j; j < n + starty -offset; j++){ //左闭右开,如果n=3,则赋值result[0][0]\result[0][1]
result[i][j]=count++;
}
for(i; i <n + startx - offset; i++){
result[i][j] = count++;
}
for( ; j > startx; j-- ){
result[i][j] = count++;
}
for( ; i > starty; i--){
result[i][j] = count++;
}
offset += 2; //每进行一圈循环,可赋值的位置-2
startx++; //每进行一圈循环,起始位置+1
starty++;
}
if(n%2 != 0){ //当n为奇数,中间位置单独赋值
result[mid][mid] = count;
}
return result;
}
};