题目一:977. 有序数组的平方
初见:用了冒泡先归整齐再一次计算,第一次到几百ms的,时间复杂度太大了
思路:
1. 解法:双指针
2.两个指针分别指向数组的最左边和最右边,因为为非递减数组,所以当负数时最左最大,正数最右最大
3. 比较两个指针对应的平方,创建一个新数组,将较大指针的数放入新数组,同时较大的指针移动
直到最后一个数据录入数组.
代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size();
//设置一个新数组存放平方后的数据
vector<int> result(k);
int i = 0;
int j = k - 1;
//注意“=” 防止最后一个元素没有存放
while(i <= j)
{
//因为两边的数都是最大值,根据最大值和最大值比,得到更大的放入新数组
if((nums[i] * nums[i]) > (nums[j] * nums[j]))
{
result[--k] = (nums[i] * nums[i]);
i++;
}
else
{
result[--k] = nums[j] * nums[j];
j--;
}
}
return result;
}
};
题目二:209. 长度最小的子数组
初见:第一次只想到两层for循环的暴力解法,完全没有窗口移动这个概念
思路:
1. 解法:窗口移动
2. 先用for循环,寻找一个区间能使总和值sum 大于等于 target,此时的位置为终止位置
3.同时初始位置开始向后移动,直到sum 小于 target
4. 终止位置向后移动,重复234,得出一个最小区间的result返回
代码:
感觉难点在于有没有窗口移动这个概念。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i = 0; //起始位置
int sum = 0; //记录总和
int subL = 0; //窗口大小
int result = INT32_MAX; //表示整数的最大值,记录长度最小的子数组
for(int j = 0; j < nums.size(); j++)
{
sum += nums[j];
while(sum >= target)
{
subL = (j - i + 1);
//比较长度
if(subL < result) result = subL;
sum -= nums[i++];
}
}
if(result == INT32_MAX) return 0; //长度不变表示不存在符合条件的子数组
return result;
}
};
题目三:
初见:将每种情况分开计算,但题解竟然也是这样的,开心
思路:
1. 建议画图理解
2. 从上左到上右,右上到右下等四种情况的边界变化想清楚就可以了
代码:
难点在于记录每一次循环的边界的变化
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0)); //定义二维数组
int l1 = 0,l2 = 0, w1 = 0, w2 = 0; //记录长宽的边界
int num = 0;
int max= n*n;
while(num <= max)
{
//左到右
for(int i = w1; i < n - w2; i++)
{
res[l1][i] = ++num;
if(num >= max) return res;
}
l1++;
//右上到右下
for(int i = l1; i < n -l2; i++)
{
res[i][n- w2 -1] = ++num;
if(num >= max) return res;
}
w2++;
//下右到下左
for(int i = n - w2 -1; i >= w1; i--)
{
res[n-l2-1][i] = ++num;
if(num >= max) return res;
}
l2++;
//左下到左上
for(int i = n - l2 -1; i >= l1; i--)
{
res[i][w1] = ++num;
if(num >= max) return res;
}
w1++;
}
return res;
}
};