思路:序列为非递减(递增)序列,按平方值递增排序,数组两头一定是最大和第二大的。
法一(暴力解):对数组遍历平方,再进行递增排序。时间复杂度最坏O()
法二:可以利用双指针法,数组特性最大第二大分别在数组两头,head指数组头,tail指数组尾,两两分别比较,大的值进行平方放尾部,小的放回头部,tail指针逐步往前遍历。该法更类似于交换排序,时间复杂度O(n),空间复杂度(1)
vector sortedSquares(vector& nums) {
int head = 0;
int tail = nums.size()-1;
for(int i = 0;i < nums.size();i++){
if(nums[head] < 0 || nums[tail] < 0){//两者都取绝对值再比较
nums[head] = abs(nums[head]);
nums[tail] = abs(nums[tail]);
}
if(nums[tail] >= nums[head]){//更大的值放尾部再平方
nums[tail--] *= nums[tail];
}
else{
int h = nums[tail];//若前者更大,把后者放前面,前面的值平方放尾部
nums[tail--] = nums[head]*nums[head];
nums[head] = h;
}
}
return nums;
}
法一(暴力解):外层for循环控制头指针,内层for循环控制尾指针,每次外层循环一次,内层尾指针循环至尾部.枚举出所有结果,记录最小数组长度.时间复杂度O().
法二:双指针法(形象理解为滑动窗口),窗口内的元素和必须满足目标值,这是一个重要条件,然后根据窗口内的值进行窗口缩放。
思路:设置头尾指针为0,第一步,尾指针控制后窗口往后移动直至找到第一个符合条件的子集合,第二步,先记录窗口长度,然后尝试缩小前窗口(前指针),若窗口内的和符合条件则继续循环执行第二步,直到不符合条件值,则执行第一步,直到数组尾部。
时间复杂度O(n)
int minSubArrayLen(int target, vector& nums) {
int result = INT32_MAX;//设置一个最大值,result记录最小窗口长度
int sum = 0;//记录窗口内的所有元素的和
int targetLength = 0;//记录当前窗口长度
int head = 0;
for(int tail = 0;tail < nums.size(); tail++){
sum += nums[tail];
while(target <= sum){//注1
targetLength = (tail - head + 1);//记录目前满足条件子集合的长度
if(targetLength < result){
result = targetLength;
}
sum -= nums[head++];//缩小窗口还需要把前一个元素减去再缩小
}
}
return result == INT32_MAX ? 0:result;//注2
}
本题还需要注意两个细节,注1能否把target <= sum改成target 重点是要遵循循环不变量原则,即每次处理的边的规则都需相同,下面代码遵循左闭右开原则. 1,2,3,4分别表示每条边的处理顺序和处理的格数 如上图每次处理包含头节点但不包含尾节点,并且如果循环圈数只有一圈,则中间元素需要单独处理 空间复杂度为O(1),因为返回数组是题目给定的,没有所用的额外空间59.螺旋矩阵||
1
1
2
4
5
2
4
3
3
1
1
1
2
4
5
6
2
4
8
7
2
4
3
3
3
vector