c++中的数组
一般使用vector或者array来表示数组。vector其实是容器。
有序数组的平方
题目链接:Leetcode977
双指针解法
vector<int> sortedSquares(vector<int>& nums) {
int left=0, right =nums.size()-1;
vector<int> res;
res.resize(nums.size());
int index = right;
while(left<=right){
if(nums[right]*nums[right] < nums[left]*nums[left]){
res[index--] = nums[left]*nums[left];
left++;
}
else{
res[index--] = nums[right]*nums[right];
right--;
}
}
return res;
}
思路
- 使用暴力解法:先对所有元素求平方和,然后排序。时间复杂度O(n +logn)
- 双指针,构建一个新的同样大小的数组,左右指针进行对比,哪个大,哪个放到最后。时间复杂度O(n)
长度最小的子数组
题目链接:leetcode209
int minSubArrayLen(int target, vector<int>& nums) {
int left =0, sum=nums[left], length = nums.size()+1;
if(sum>target) return 1;
for(int right=1; right<nums.size(); right++){
sum += nums[right];
while(sum >= target){
length = right-left+1 < length ? right-left+1: length;
sum -= nums[left++];
}
}
return length > nums.size() ? 0:length;
}
思路
- 一开始上来理解错了题意,当作了要完全等于target的情况。想到双指针的时候,是以左右指针的形式。
- 问题:左右指针的使用基本应用于有排序的数组。在无排序的情况下,考虑滑动窗口法。
- 滑动窗口需要明确的点是:窗口的起点和终点怎么开始,终点怎么移动,起点怎么移动。
- 在该问题中求解最小子数组长度,肯定会存在满足该条件下的多个子数组,寻找的是最小的长度,涉及到了长度的对比,需要记录遍历过的满足该子数组的最小长度。
- 窗口记录的是什么?满足该条件的子数组。窗口的右移是一层for循环的向右遍历。窗口左移的标准是,当该窗口满足条件后,继续左移,直到不满足为止。
- 时间复杂度:O(n)。最差应该是2n。
螺旋矩阵
题目链接:leetcode59
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0));
int i=0, j=0;
int num = 1;
int leftstart = 0;
int rightstart = 0;
int rightbound = n-1;
int leftbound = n-1;
while(num <= n*n){
for(int i=leftstart, j=rightstart; j<=rightbound && num <= n*n; j++){
res[i][j] = num++;
}
leftstart++;
for(int i=leftstart, j=rightbound; i<=leftbound && num <= n*n; i++){
res[i][j] = num++;
}
rightbound--;
for(int i=leftbound, j=rightbound; j>=rightstart && num <= n*n; j--){
res[i][j] = num++;
}
leftbound--;
for(int i=leftbound, j=rightstart; i>=leftstart&& num <= n*n; i--){
res[i][j] = num++;
}
rightstart++;
}
return res;
}
思路
关键点:
- 确定好区间,每一次包含到什么位置,个人习惯闭区间,比较好减。
- 确定好每一次的边界条件,虽然有了while判断,但是是所有的while中包含的语句都走完了之后,才会去判断是否满足下一次的循环。所以需要在for循环语句中,也去添加判断条件。
- 代码要细心,rightstart++写成了,rightbound++,找这个bug太心累了。