1.1 暴力解法
class Solution {
public:
vector sortedSquares(vector& nums) {
int size = nums.size();
for (int i = 0; i < size; i++) {
nums[i] = nums[i] * nums[i];
}
sort(nums.begin(),nums.end());
return nums;
}
};
1.2重点
思考:怎么变成时间复杂度为O(n)?
2.1双指针解法
代码随想录官方题解
||因为该题目是有序数组,所以最大值一定再两边,不可能在中间 ,可以用双指针 来比较两边再存入一个数组中。把两个for循环压缩成一个for循环
class Solution {
public:
vector sortedSquares(vector& nums) {
int k = nums.size() - 1;
vectorresult(nums.size(), 0);
for (int i=0, j=nums.size()-1; i <= j; ) {
if (nums[j] * nums[j] >= nums[i] * nums[i]) {
result[k--] = nums[j] * nums[j];
j--;
} else {
result[k--] = nums[i] * nums[i];
i++;
}
}
return result;
}
};
2.2理解:比较两边数组找出局部最大值,并存入新数组中,直到旧数组中的元素全部遍历完为止。
2.3重点: vector
快慢指针(这里快慢指针是左右边都行)
快指针:右边(假设),找最大值赋给新数组,没找到下边不变
1.1暴力解法
class Solution {
public:
int minSubArrayLen(int target, vector& nums) {
int size = nums.size();
int cnt = 0;
for (int i = 0; i < size; i++) {
int res = 0;
for (int j = i ;j < size; j++) {
res += nums[j];
if (res >= target) {
if (cnt == 0 || cnt > j - i + 1) cnt = j-i+1;
break;
}
}
}
return cnt;
}
};
1.2结果:超时了,时间复杂度为O(n*n)
2.1滑动窗口(特殊双指针)解法
链接:官方题解
class Solution {
public:
int minSubArrayLen(int target, vector& nums) {
int size = nums.size();
int result = INT32_MAX;
int res = 0;
for (int i = 0, j = 0; j < size; j++) {
res += nums[j];
while (res >= target) {
int sublength = j - i + 1;
result = result < sublength ? result : sublength;
res -= nums[i++];
}
}
return result == INT32_MAX ? 0 : result;
}
};
用一个for循环来做2个for循环所做的事情。----->其实双指针都是这样
2.2思考:这个索引下标
j
表示的究竟是滑动窗口里面的终止位置还是起始位置?
可以先假设 j
表示的是起始位置,
若 j
表示的是起始位置,这个for循环一次一次把索引下标向后移动,这个终止位置要把后面所有的元素遍历一遍,才能返回所有以这个起始 i
为起始位置的集合,然后我们再去判断这个集合里面的所有元素:
如果 >= target
,去搜集所有 >= target
这些集合里面的所有的长度,再取一个最小的。 如果终止位置是一个一个向后移动的话,那么和这个暴力的解法又存在什么区别呢?
此时你会发现:如果这一个for循环里面的这个j表示的是起始位置的话,那终止位置依然要把所有位置都遍历一遍,那么它的思路就和暴力是一样的。
因此这一个for循环里面的j一定指向的是终止位置,而起始位置需要我们用动态移动的策略来移动起始位置,这样才能用一个for循环的思路来解决这道题。
总结:如果是起始位置就相当于暴力
起始位置和结束位置
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。直到移动到小于目标值结束位置再开始移动寻找新的集合(移动窗口)
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。当集合内和小于目标值时开始移动
总结:寻找窗口+缩小窗口+移动窗口
为什么时间复杂度是O(n)。
不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)
金牌讲解:讲解1 讲解2
class Solution {
public:
vector> generateMatrix(int n) {
vector>result(n, vector(n, 0)); //结果
int loop = n/2; //可以转几圈
int startx = 0;
int starty = 0; //起始坐标
int offset = 1; //可以控制结束位置
int count = 1; //数组中的具体值
while (loop--) {
int i = startx;
int j = starty;
//分别遍历四边并赋初值
for (j = starty; j < n - offset; j++) { //设置为左闭右开可以一劳永逸,每边都可以这样写
result[i][j] = count++;
}
for (i = startx; i < n - offset; i++) {
result[i][j] = count++;
}
for (; j > starty; j--) {
result[i][j] = count++;
}
for (; i > startx; i--) {
result[i][j] = count++;
}
startx++;
starty++;
offset++;
}
//如果n是奇数就留下了中间的值没有赋值
if (n % 2 == 1) {
result[n/2][n/2] = count;
}
return result;
}
};
理解:
1.我们可以看出只要一圈一圈的赋值就能赋值成功,所以要用到四个for循环
2.当我们遍历一圈时,有很多的边界问题让我们十分烦,必须按照规则来
这里的边界规则为 左闭右开(最后一个不赋值,留给下一个for循环)
3.奇数和偶数圈不一样,如果是奇数的话,中间元素还是没有赋值,所以要特判
//如果n是奇数就留下了中间的值没有赋值
if (n % 2 == 1) {
result[n/2][n/2] = count;
}
return result;
4. 二维容器赋值方式
vector>result(n, vector(n, 0)); //结果
第一个参数为个数,第二个为值是什么。
需要什么变量再去定义什么变量