今天早晨复习了一下昨天的题,做的速度提高了,但是写完又报错,还找不出来为什么。感觉这样浪费时间比较多,打算调整下思路:
先直接全敲一遍,第二天复习的时候自己做,不熟练的、做错的,隔一段时间会回头重做。
例 1
题号:448, 难度:简单
题目描述:
解题思路:
数组两用,数组里存值,(下标+1)记录是否存在该数。
具体代码:
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int>ans;
int n = nums.size();
for(int i = 0; i < n; i++)
{
//以值+1为索引,整个数组的索引代表数字是否存在,存在的为负数,不存在的是正数
//特别要注意:nums[i]这个值有可能是负数,得取绝对值
int index = abs(nums[i]) - 1;
if(nums[index] > 0)
{
nums[index] = -nums[index] ;
}
}
for(int i = 0; i < n; i++)
{
//找到所有为正数的索引
if(nums[i] > 0)
{
ans.push_back(i + 1);
}
}
return ans;
}
};
运行结果:
总结:
要注意两点:
- 遍历到后面有重复数的时候,读出来的值可能是负数,如果直接拿去当下标会出现问题,要取绝对值
- nums[index]改成nums[ abs(nums[i]) - ]的话,运行时间会增加好多。第一遍写完代码后,可以提炼一下,看看有哪些重复的地方,可以新定义一个变量然后赋值。用变量表示的话就调用函数快一些。也可能是测试的输入不同的缘故,反正代码看起来更清楚了。
例 2
题号:48, 难度:中等
题目描述:
解题思路:
先按照左上到右下对角线交换一遍,再逆置每一个数组。
具体代码:
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
//沿左上右下对角线交换数字
for(int i = 0; i < n ; i++)
for(int j = i; j < n ; j++)
{
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
//每行数字反转
for(auto &nums: matrix)
{
int tail = n -1;
for(int i = 0; i < tail; i++, tail--)
{
int temp = nums[i];
nums[i] = nums[tail];
nums[tail] = temp;
}
}
}
};
总结
1.处理技巧,剩下就是for循环的基础应用,如何把想要交换的数字交换。我这块不太熟,好好研究了一下。
假设n = 3;
最重要的点,从始至终要记牢:两重for循环过程:一行完了,下一行。
遍历范围是三角形的重点:行里元素个数不能大于列数。
for循环 第一重 可以从上到下 i = 0; i < n; i++; [0,n)
也可以从下到上 i = n - 1; i >= 0; i--; (n,0]
第二重 要打印三角形,限制条件一定是i,一行分成两段,[0,i) 和 [i,n)
可以从头到尾 j = 0; j < i; j++; 正着的三角形 [0,i)
也可以从尾到头 j = n - 1; j >= i; j--; 倒着的三角形 (n,i]
for循环一定要明确每重循环的功能,分开来看。一起看很容易混了。
练习1: 以下都用dev c++验证过输出的值是否正确
i,j: [0,0],[ ],[ ],
[0,1],[1,1],[ ],
[0,2],[1,2],[2,2],
法1:上到下,头到尾[0,i)
for(int i = 0; i < n; i++)
for(int j = 0; j <= i; j++)
法2:上到下,尾到头[i,n)
for(int i = 0; i < n; i++)
for(int j = n - 1; j >= i; j--)
从下往上会有一些要注意的地方。
法3: 下到上,头到尾[0,i) 特别注意:因为i的初始值是n - 1, 第二重循环实际上范围是[0,i],包含i
for(int i = n - 1; i >= 0; i--)
for(int j = 0; j <= i; j++ )
法4: 下到上,尾到头(i,n] 特别注意:因为i的初始值是n - 1, 第二重循环实际上范围是[i,0],包含i
for(int i = n -1; i >= 0; i--)
for(int j = n - 1; j >= 0; j--)
思考:如果用--i的话,i初始值是否可以赋值为n
又发现一个知识点,for循环里不管是--i还是i--,循环体里的i得值不变。
但是while的话就会变。
练习2: (在旋转数组这道题中,不管的得到的是上面部分或者下面部分都可以执行交换操作)
i,j: [0,0],[1,0],[2,0],
[ ],[1,1],[2,1],
[ ],[ ],[2,2],
法1: 上到下,头到尾[0,i)
for(int i = 0; i < n; i++)
for(int j = i; j < n; j++)
法2: 上到下,尾到头[i,n)
for(int i = 0; i < n; i++)
for(int j = n - 1; j >= i; j--)
法3: 下到上,头到尾[0,i)
for(int i = n - 1; i >= 0; i--)
for(int j = 0; j <= i; j++)
法4: 下到上, 尾到头[i,n)
for(int i = n - 1; i >= 0; i--)
for(int j = n - 1; i >= i; j--)
可以发现公式都是一样的,第一重循环i管列,第二重循环j管行里咋写。区间就是[0------i-------n)。
特殊:如果是从下到上的话,i初始值是n-1,头到尾的区间要包含i,[0-------i],[i-------n],i用了两次,i就是对角线,不管算上面的部分还是算下面的部分,斜边上的点都用到了。
例
题号:, 难度: