《代码随想录》——数组部分
二分查找
左闭右闭
左闭右开
移除元素
暴力法
没什么可说的,这样时间复杂度就变成了n平方了
双指针(前后指针)(数组变短的操作,可以扩展数组变成的操作,是从后往前遍历)
其实就是两句规则
- 遇到相同的元素,快的走,慢的不走
- 遇到不同的元素,快的把指向的值赋值给慢的,快的慢的都走
则可直接写出以下代码
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int fast = 0;
int slow = 0;
while (fast < nums.size()) {
if (nums[fast] == val) {//遇到相同的元素,快的走,慢的不走
fast++;
} else {//遇到不同的元素,快的把指向的值赋值给慢的,快的慢的都走
nums[slow] = nums[fast];
slow++;
fast++;
}
}
return slow;
}
};
然后if else
中其实都有fast++
,提到外面,就变成了下面的代码,或者再把slow++
,放进括号中,变成了nums[slow++]
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int fast = 0;
int slow = 0;
while (fast < nums.size()) {
if (nums[fast] == val) {
} else {
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
};
但这时候发现if中没有东西了,于是发现其实只需要写 不等于 的情况就可以,再次修改
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int fast = 0;
int slow = 0;
while (fast < nums.size()) {
if (nums[fast] != val) {//遇到不同的元素,快的把指向的值赋值给慢的,快的慢的都走
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
};
会发现代码越来越简洁,但是思想是不变的
有序数组的平方
暴力法
他说什么就是什么,先乘,然后直接调用sort,一步到位,但是这样复杂度高,是快速排序的复杂度,nlogn
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++) {
(*it) = (*it) * (*it);
}
sort(nums.begin(), nums.end());
return nums;
}
};
双指针(左右指针)
考虑双指针的原因是因为他们本身是有序的,但是如果平方以后就变成了这组数是两端大中间小的了,因此我们两端各自定义一个指针,比出来大的就放到新数组的最后一个
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++) {
(*it) = (*it) * (*it);
}
int left = 0;
int right = nums.size() - 1;
vector<int> result(nums.size());
int index = result.size() - 1;
while (left <= right) {
if (nums[left] < nums[right]) {
result[index--] = nums[right--];
} else {
result[index--] = nums[left++];
}
}
return result;
}
};
长度最小的子数组
暴力法
没啥可说的,而且似乎有个很长的用例用carl的源代码也过不去,先知道思想吧
滑动窗口(前后指针)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0;
int subArrayLen = 0;
int slow = 0;
int result = INT_MAX;
for (int fast = 0; fast < nums.size(); fast++) {
sum = sum + nums[fast];
while (sum >= target) {
subArrayLen = fast - slow + 1;
if (result > subArrayLen) {
result = subArrayLen;
}
sum = sum - nums[slow++];
}
}
if (result == INT_MAX) {
return 0;
} else {
return result;
}
}
};
螺旋数组II
与二分查找的共同点:考察代码掌控能力
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n, vector<int>(n, 0));//定义一个vector,作为我们返回的结果
int count = 1;//定义一个我们要填的数字
int startx = 0;//我们写的开始的位置
int starty = 0;//我们写的结束的位置,startx,starty才是我们每圈循环的回来的终点,也就是1号位置
int loop = n / 2;//我们转几圈,3的话其实就是转一圈,4的话就要转两圈了
int offset = 1;//每一条边遍历的长度
for (int i = startx, j = starty; loop > 0; loop--, startx++, starty++, offset += 2) {
//从左往右
for (j = starty; j < starty + n - offset; j++) {
result[startx][j] = count++;
}
//从上往下
for (i = startx; i < startx + n - offset; i++) {
result[i][j] = count++;
}
//从右往左
for (; j > starty; j--) {
result[i][j] = count++;
}
//从下往上
for (; i > startx; i--) {
result[i][j] = count++;
}
}
if (n % 2) {//n是奇数的时候存在说我只需要填充这么一下的场景
result[startx][starty] = count;
}
return result;
}
};