Leetcode 977. 有序数组的平方
初见想法:因为数组存在负数,所以想设置左右两个指针,不断比较平方,直到左指针>0。或者直接先平方,然后直接sort ??
直接平方,然后用自带函数排序,时间复杂度为O(nlogn):
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
// int left = 0, right = nums.size()-1;
int sz = nums.size();
for (int i = 0; i < sz; i++)
nums[i] = nums[i] * nums[i];
sort(nums.begin(), nums.end());
return nums;
}
};
最简单的方法,不是很好看
双指针法,重点是找到负数与非负数的分界线,然后就和归并排序的思想差不多。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int size = nums.size();
int negative = -1;
// 这里的前提是数组是非递减顺序
for (int i = 0; i < size; i++)
{
if (nums[i] < 0) negative = i;
else break;
}
vector<int> ans;
int i = negative, j = negative+1;
while (i >= 0 || j < size)
{
// 先判断i和j,防止越界
if (i < 0)
{
ans.push_back(nums[j]*nums[j]);
j++;
}
else if (j == size)
{
ans.push_back(nums[i]*nums[i]);
i--;
}
else if (-nums[i] < nums[j])
{
ans.push_back(nums[i]*nums[i]);
i--;
}
else
{
ans.push_back(nums[j]*nums[j]);
j++;
}
}
return ans;
}
};
时间复杂度为O(n), 需要辅助数组,与归并排序类似。
最后一种双指针法,倒排,需要确定新数组的长度。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int m = nums.size();
vector<int> ans(m);
for (int i = 0, j = m-1, pos = m-1; i <= j; pos--)
{
if (nums[i]*nums[i] > nums[j]*nums[j])
{
ans[pos] = nums[i]*nums[i];
i++;
}
else
{
ans[pos] = nums[j]*nums[j];
j--;
}
}
return ans;
}
};
双指针法,最巧妙的办法,左右两个指针,左指针往右,右指针往左,当两个指针相遇时即遍历完整个数组。新数组从后往前排。时间复杂度为o(n),空间复杂度为o(n)
总结:两个指针快速遍历数组,排序不仅可以正着排,也可以倒着排。
Leetcode 209. 长度最小的子数组
初见想法:想到了滑动窗口的方法,但是怎么表示滑动窗口呢,用两个指针吗?
要思考如何移动窗口的初始位置和终止位置。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;
int i = 0;
int sum = 0;
int size = nums.size();
for (int j = 0; j < size; j++)
{
sum += nums[j];
while (sum >= target)
{
int sublength = j - i + 1;
result = sublength < result ? sublength:result;
sum -= nums[i++];
}
}
return result == INT32_MAX ? 0:result;
}
};
使用两个指针表示滑动窗口
for循环表示滑动窗口的终止条件
最大值可以用INT32_MAX表示
Leetcode 59.螺旋矩阵II
初见想法:循环不断的填入数据
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int left = 0, right = n-1, top = 0, bottom = n-1;
int count = 1, target = n*n;
vector<vector<int>> ans(n, vector<int>(n));
while (count <= target)
{
for (int i = left; i <= right; i++) ans[top][i] = count++;
top++;
for (int i = top; i <= bottom; i++) ans[i][right] = count++;
right--;
for (int i = right; i >= left; i--) ans[bottom][i] = count++;
bottom--;
for(int i = bottom; i >= top; i--) ans[i][left] = count++;
left++;
}
return ans;
}
};
总结:模拟法,不考察算法,考察边界处理。