1.有序数组的平方
双指针法:
代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
// 非递减数组平方后,较大的值都分布在两端,可以利用这个特性从两边入手取值
// 双指针
int count = nums.size() - 1; // 新数组的下标,因为是非递增,所以从大到小遍历
vector<int> result (count + 1);
int left = 0;
int right = nums.size() - 1;
while(left <= right){
if(nums[left]*nums[left] >= nums[right]*nums[right] ){
result[count--] = nums[left]*nums[left];
left++;
}else{
result[count--] = nums[right]*nums[right];
right--;
}
}
return result;
}
};
思路:
这道题我终于自己做出来了!撒花!我没有按照卡哥用for循环(其实都一样),想到了昨天的二分法边界条件是通过思考两个指针最后把搜索范围缩到多小就算遍历完了。这次我想到两个指针都是从两边向中间走,两个相遇就算结束了。(能不能取等就直接思考相等会怎样,最后剩下那个元素我们也要平方放到我们新数组里的,所以要取。)
暴力法:
代码:
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;
}
};
思路:
很直接的想法,平方完直接再排序。
关于sort()快排这里有一些我做的笔记:
2.长度最小的子数组
滑动窗口:
代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
// 先从左往右依次求和,看看什么时候比target大,然后再试着剔除最左边的元素,看看还满不满足条件
int sum = 0;
int result = INT32_MAX;
int i = 0;
int sublenth = 0;
for(int j =0;j < nums.size();j++){
sum += nums[j];
while(sum >= target){
sublenth =( j - i + 1);
result = sublenth < result ? sublenth : result ;
sum -= nums[i];
i++;
}
}
return result == INT32_MAX? 0 :result ;
}
};
思路:
模糊记得一点思路。是先满足总和大于要求,再在此基础上去减少元素,不断更新我们的最短长度。写的过程很艰难,首先确定了我要用到的变量sum,sublenth,还有我肯定要遍历一遍数组。一段时间后,我才想到:上帝,滑动窗口没有左右边界我怎么确定窗口大小!所以就明确了分工,我的窗口右边界j用来遍历数组,不断添加新的元素到sum里;我的窗口左边界i用来把元素剔除出去,追求长度最短。(而我之所以可以这样做,是因为题目让求的是相邻的满足条件的元素)
写的时候,出现了很多bug:最后返回结果时,我没有考虑如果result没有被更新过,我应该返回0,而不是最大值!以及,我在while循环的条件又写错了,这是因为我纯粹就没有能不能取等于这个意识。
暴力法:
代码:(这个会超时)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum =0;
int result = INT32_MAX;
int sublenth = 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){
sublenth = j - i + 1;
result = sublenth < result ? sublenth : result;
break;
}
}
}
return result == INT32_MAX ? 0 : result;
}
};
思路:
感觉暴力法是固定左端,移动右端;双指针法是固定右端,移动左端。暴力法我犯了一个低级错误,找最短的长度,我应该初始化为最大值,我脑抽写成了最小值。
3.螺旋矩阵
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res (n, vector(n,0));
int loop = n/2;
int mid = n/2;
int startx = 0;
int starty = 0;
int offset = 1;
int count = 1;
int x,y;
while(loop--){
x = startx;
y = starty;
for( ;y < n - offset ; y++){
res[x][y] = count++;
}
for( ;x < n - offset ; x++){
res[x][y] = count++;
}
for( ;y > starty; y--){
res[x][y] = count++;
}
for( ;x > startx; x--){
res[x][y] = count++;
}
startx++;
starty++;
offset++;
}
if(n % 2){
res[mid][mid] = count;
}
return res;
}
};
思路:
这次写的很通,但是我又犯了错误,我把里面的for循环都写成了if语句(我也不懂我怎么想的,可能是因为写的时候没怎么动脑子吧)
这一次,我终于把offset和startx/starty区分开了。我以前一直以为,它们两个相等。其实这个举个例子就想明白了。循环第一圈的时候,开始位置是(0,0),offet=1。不过它们的大小确实有关系,startx比offset小1。感觉,填这个数字,每一次的for语句就是拿一块长条拼起来。就像我下图画的。