977.有序数组的平方 ,
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路:
非递减-->递增
方法一:双指针
每个元素平方后,因为是升序数组,所以从两端比较新数组元素的大值。依次放入新数组内。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
//方法一
int k = nums.size() - 1;
vector<int> news(nums.size(), 0); //定义新数组result
//因为是顺序数组,所以从数组比较两端元素来确定最大的新元素
for (int i = 0, j = nums.size() - 1; i <= j;){
if (pow(nums[i], 2) < pow(nums[j], 2)){
news[k--] = pow(nums[j], 2);
j--;
}
else{
news[k--] = pow(nums[i], 2);
i++;
}
}
return news;
}
};
方法二:暴力排序
先对数组内的元素进行平方运算,后进行升序排序,关于sort()方法的详解参照如下链接:sort()方法
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i = 0; i < nums.size(); i++){ //先求出平方后的数组
nums[i] = pow(nums[i], 2);
}
//对数组进行快速排序,默认升序
sort(nums.begin(), nums.end());
return nums;
}
};
209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
错误思路:(忽略连续子数组)
步骤1:进行倒序排序,
步骤2:在循环中,查找是否有大于等于target的单个元素
有,则输出“1“;无,则进行下一步骤
步骤3:固定第一个元素,逐步与下一个元素相加,直到>=target
//错误解法(忽略连续子数组)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i=0,flag=0,sum=0;
struct
{
bool operator()(int a, int b) const { return a > b; }
}descMax;
sort(nums.begin(),nums.end(),descMax);
int k=nums.size();
if(nums[i]>=target){
flag=1;
}else{
sum=nums[i];
for(i=1;i<k;i++){
sum+=nums[i];
if(sum>=target){
flag= 2;
break;
}
}
}
return flag >0 ? i+1 : 0;
}
};
正确解法:
连续的最小长度的元素之和大于target
方法一:暴力解法
一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
//方法一:暴力法
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int size= nums.size();
if (size == 0) { //不存在符合条件的子数组,返回 0
return 0;
}
int result= INT_MAX; //最终结果
for (int i = 0; i < size; i++) {
int sum = 0; //每次求和前,清零
for (int j = i; j < size; j++) {
sum += nums[j];
if (sum >= target) {
// result = min(result, j - i + 1);
//判断每次当子数组之和大于target后的长度偏小的子数组的长度
result=result<j-i+1?result:j-i+1;
break;
//因为要求长度最小,且在循环求和中,子数组长度地递增,
//所以每次符合条件“子数组之和大于target “,即可结束当前子循环
}
}
}
//验证result有无被赋值,有则返回result值,无则返回0,
return result == INT_MAX ? 0 : result;
}
};
备注:暴力解法超时
方法二:滑动窗口
不断的调节子序列的起始位置和终止位置
关键代码块:
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
while (sum >= s) { // 每次更新 i(起始位置),并不断比较子序列是否符合条件
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 不断变更i(子序列的起始位置)
}
}
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0; // 滑动窗口数值之和
int i = 0; // 滑动窗口起始位置
int subLength = 0; // 滑动窗口的长度
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 不断变更i(子序列的起始位置)
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
59.螺旋矩阵
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
思路:
01 02
04 03
01 02 03
08 09 04
07 06 05
01 02 03 04
12 13 14 05
11 16 15 06
10 09 08 07
01 02 03 04 05
16 17 18 19 06
15 24 25 20 07
14 23 22 21 08
13 12 11 10 09
坚持不变量原则:
模拟顺时针绘制矩阵,有四种路线:
从左到右,从上到下,从右到左,从下到上,由外及内。
随想录中提到的左闭右开,左开右闭,主要针对的是,在不同路线的拐弯处,所统一采取的原则,如图
依据代码随想录的思路:
首先判断矩阵可以绕几圈:n/2
n%2>0:n为奇数,最后剩的一个数在中间;
下列代码采取左闭右开的原则。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//定义二维数组
vector<vector<int>> res(n, vector<int>(n, 0));
int loop=0;//标记循环的次数
int count=1;//显示的数值
// int starx=0,stary=n-1;//循环的初始状态(0,n-1);
int start=0;
int mid=n/2;
int i,j;
while(loop++<=mid){
//从左右
for(j=start;j<n-loop;j++){
res[start][j]=count++;
}
//从上下
for(i=start;i<n-loop;i++){
res[i][j]=count++;
}
//从右左
for(;j>=loop;j--){
res[i][j]=count++;
}
//从下上
for(;i>=loop;i--){
res[i][j]=count++;
}
start++;
}
if(n%2){
res[mid][mid]=count;
}
return res;
}
};
疑难:
起初,我以为每个数的起点是(0,n-1),可是编译后的结果很让我疑惑,至今我也不明白为什么从左到右的路径的代码会是:
for(j=start;j<n-loop;j++){
res[start][j]=count++;
}
我总会写成这样:
for(i=start;i<n-loop;i++){
res[i][star]=count++;
}
在此过程中我遇到了这样一个报错,
使用了AddressSanitizer检查是否存在内存非法访问,该问题检查内存非法访问问题。查阅过资料,有的博客是这么解决的:点击
而我的问题则是因为代码逻辑问题,导致矩阵某些位置的值重叠了。通常是位于for循环语句的条件判断是否要加等号。