977.有序数组的平方
因为是递增且有负数的数组,那么他们的平方如果还是按照原来的顺序排列的话,是两边的值会相对大,所以用两个指针分别从左右两侧寻找新数组里面的元素
我的错误代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int size = nums.size();
vector<int> result;
int newIndex = size - 1;
int left = 0;
int right = size - 1;
while(left < right){
if(nums[left]*nums[left] > nums[right]*nums[right]){
result[newIndex] = nums[left]*nums[left];
left++;
}else{
result[newIndex] = nums[right]*nums[right];
right--;
}
newIndex--;
}
return result;
}
};
代码出现的问题:
1.runtime error: applying non-zero offset 16 to null pointer (stl_vector.h)
一开始定义vector有问题: vector <int> result(nums.size(),0); 括号里面先是大小,然后是数组的数值
2.while(left < right){ 如果没有相等,那就少了left=right指向同一个数组元素的情况了
正确代码如下:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int size = nums.size();
vector<int> result(size,0);
int newIndex = size - 1;
int left = 0;
int right = size - 1;
//如果没有相等,那就少了left=right指向同一个数组元素的情况了
while(left <= right){
if(nums[left]*nums[left] > nums[right]*nums[right]){
result[newIndex] = nums[left]*nums[left];
left++;
}else{
result[newIndex] = nums[right]*nums[right];
right--;
}
newIndex--;
}
return result;
}
};
209.长度最小的子数组
1.暴力输出法
用两个for循环输出所有的子集,当找到第一个sum>=target的时候就马上停止,然后需要创建一个sum还有一个子集的长度大小,这样每一个不一样的起始位置之间都可以进行对比,留下来长度最小的那个
接下来又是我的错误代码展示:(好像就没写对过sad)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int length = 0;
int sum = 0;
int size = nums.size();
for(int i = 0; i < size; i++){
for(int j = i; j < size; j++){
sum += nums[j];
if(sum >= target){
length = j - i + 1;
result = result < length ? result : length; //把result的初始值设成一个相对较大的数,这样第一次赋值一定是length
break;
}
}
}
return result == INT_MAX ? 0 : result;
}
};
错误分析:没有在每一次更换新的起始位置的时候把sum的值重新赋为0,这样的话即使开始新的起始位置,留存的子集还是上一个起始位置时得到的结果,没有办法做到更新
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int length = 0;
int sum = 0;
int size = nums.size();
for(int i = 0; i < size; i++){
sum = 0;
for(int j = i; j < size; j++){
sum += nums[j];
if(sum >= target){
length = j - i + 1;
result = result < length ? result : length; //把result的初始值设成一个相对较大的数,这样第一次赋值一定是length
break;
}
}
}
return result == INT_MAX ? 0 : result;
}
};
2.滑动窗口法
for循环里面的j表达的是终止位置,起始位置默认从0开始,当终止位置一位一位向前移的时候,直到他们的和 > target,起始默认位置就加1,这样就比暴力解法省去了一个一个代入算的繁琐过程
我的代码终于写对了:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int size = nums.size();
int result = INT_MAX;
int length = 0;
int sum = 0;
int leftIndex = 0;
for(int i = 0; i < size; i++){
sum += nums[i];
while(sum >= target){
length = i - leftIndex + 1;
sum -= nums[leftIndex++];
result = result < length ? result : length;
}
}
return result == INT_MAX ? 0 : result;
}
};
我觉得这个和暴力解法是有相似处,代码逻辑搞明白之后基本上能立马写出来,就是少了一个for循环的概念
59.螺旋矩阵II
1.需要把1到n平方按照顺时针的方式排列组合,也就是排列成矩阵(二维数组)的模式,经过推演,发现当n为偶数的时候,一共需要转n/2圈,但是当n为奇数的时候( n%2 = 1),还是需要n/2圈(结果为int这个数据类型,会保留整数部分),但是需要把最后一个值放到中间
---->创建二维数组:vector<<int>vector> matrix = (n, vector<int>(n,0))
2.每一行的赋值都要有同一性,在这里我们左闭右开(参考二分法用到的概念),所以平常我们想要取到整行的元素的话,应该是从0开始,i<nums.size(),这样可以取到所有的元素,从0到size-1,但是这一次是左闭右开,也就是右边少取一个,是 i<size-1,要转第二圈的话就是i< size-2。所以这里还要再引入一个offset的概念,每转完一圈,这个offset++
3.需要写四个for循环,左到右,上到下,右到左,下到上
我的错误代码和debug记录:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//创建一个二维数组
vector<vector<int>> matrix = vector(n, vector<int>(n,0));
//创建每一次赋给数组元素的值
int val = 1;
//数组的行列起始index
int startI = 0;
int startJ = 0;
//根据不同的圈,需要减去的会变化的值
int offset = 1;
int loop = n/2;
while(loop != 0){
//赋值给第0行的每一列,所以for循环里面是j
for(int j = startJ; j < n - offset; j++ ){
int[i][j] = val++;
}
//赋值给第j列的每一行,所以for循环里面是i
for(int i = startI; i < n - offset; i++ ){
int[i][j] = val++;
}
//赋值给第i行的每一列,所以for循环里面是j,这回往回走,要变成减法了
for( j = j; j > startJ; j-- ){
int[i][j] = val++;
}
//赋值给第j列的每一行,所以for循环里面是i
for(i = i; i > startI; i-- ){
int[i][j] = val++;
}
startI++;
startJ++;
offset++;
loop--;
}
if(n%2 == 1){
int[n/2][n/2] = n*n;
}
return matrix;
}
};
- 1.error: decomposition declaration cannot be declared with type 'int'; declared type must be 'auto' or reference to 'auto' int[i][j] = val++; -> 再定义完二维数组之后,应该直接用matrix[i][j],不知道我怎么用了int?
- use of undeclared identifier 'i' matrix[i][j] = val++; -> 第一个for循环里面用的是没有定义的i,可以用startI,反正都是对的
- error: use of undeclared identifier 'j' matrix[i][j] = val++; -> 同样的错误,如果再用上一把的极值也就是n-offset实在是太麻烦了,所以可以在一开始的时候直接定义好int i,j,这样就可以直接使用了
- runtime error: addition of unsigned offset to 0x607000000020 overflowed to 0x606b9b8170b8 (stl_vector.h) -> 出现这个问题说明在给二维数组赋值时的index是有问题的,所以在纸上过了一遍赋值的过程,在最后i和j都会变成0,所以可以是i++,j++,或者 i = startI 和 j =startJ,然后两个start++
在纸上推导的过程:
debug之后的代码:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//创建一个二维数组
vector<vector<int>> matrix = vector(n, vector<int>(n,0));
//创建每一次赋给数组元素的值
int val = 1;
//数组的行列起始index
int startI = 0;
int startJ = 0;
//根据不同的圈,需要减去的会变化的值
int offset = 1;
int loop = n/2;
int i,j;
while(loop != 0){
i = startI;
j = startJ;
//赋值给第0行的每一列,所以for循环里面是j
for(j = startJ; j < n - offset; j++ ){
matrix[i][j] = val++;
}
//赋值给第j列的每一行,所以for循环里面是i
for(i = startI; i < n - offset; i++ ){
matrix[i][j] = val++;
}
//赋值给第i行的每一列,所以for循环里面是j,这回往回走,要变成减法了
for( j = j; j > startJ; j-- ){
matrix[i][j] = val++;
}
//赋值给第j列的每一行,所以for循环里面是i
for(i = i; i > startI; i-- ){
matrix[i][j] = val++;
}
startI++;
startJ++;
offset++;
loop--;
}
if(n%2 == 1){
matrix[n/2][n/2] = n*n;
}
return matrix;
}
};
可以精进的地方:
1.while后面的括号里面如果只放一个变量,那么就是这个变量为真的时候可以运行,也就是 loop != 0,所以可以直接换成loop
2.while大括号里面的最后需要 loop--,可以直接把这个放在while判断语句的括号里面
3.for循环里面,如果第一个语句不需要给变量赋值,比如在第三四个for循环里面都是 j = j,那么直接不用写这句话也是可以的
最后精进的版本:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//创建一个二维数组
vector<vector<int>> matrix = vector(n, vector<int>(n,0));
//创建每一次赋给数组元素的值
int val = 1;
//数组的行列起始index
int startI = 0;
int startJ = 0;
//根据不同的圈,需要减去的会变化的值
int offset = 1;
int loop = n/2;
int i,j;
while(loop--){
i = startI;
j = startJ;
//赋值给第0行的每一列,所以for循环里面是j
for(j = startJ; j < n - offset; j++ ){
matrix[i][j] = val++;
}
//赋值给第j列的每一行,所以for循环里面是i
for(i = startI; i < n - offset; i++ ){
matrix[i][j] = val++;
}
//赋值给第i行的每一列,所以for循环里面是j,这回往回走,要变成减法了
for( ; j > startJ; j-- ){
matrix[i][j] = val++;
}
//赋值给第j列的每一行,所以for循环里面是i
for(; i > startI; i-- ){
matrix[i][j] = val++;
}
startI++;
startJ++;
offset++;
}
if(n%2 == 1){
matrix[n/2][n/2] = n*n;
}
return matrix;
}
};
总结:
今日收获:
开始感到学习知识的快乐了,睡觉之前也想要再打开电脑看看,当然学习时间还是挺长的,可能还是6h左右,但是学到了很多东西就不亏,而且这次已经可以在看完carl的视频之后自行写代码了,并且自己debug