文章目录
Day 1 习题
二分法
昨天对二分法新增的理解包括:左开右闭区间的思路、操作下标的思路。
35. 搜索插入位置
本题较704多了一个插入位置的返回。使用左闭右开的写法,函数返回left或right都可以,因为跳出循环的时候left=right。
另外一种写法是只分为大于和不大于两类,最终都通过区间收窄至1个元素时返回其下标。
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while (left < right)
{
int middle = left + ((right - left) >> 1);
if (target < nums[middle])
left = middle + 1;
else
right = middle;
}
return left;
}
双指针
目前见到的双指针类型有快慢指针和头尾指针。
26. 删除排序数组中的重复项
因为题目要求删除后的数组是有序的,初步考虑头尾指针难以实现。考虑快慢指针的方法,思路和标准题27相同。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slow = 1;
int len = nums.size();
for (int fast = 1; fast < len; fast++)
{
if (nums[fast - 1] != nums[fast])
{
nums[slow++] = nums[fast];
}
}
return slow;
}
};
977. 有序数组的平方(双指针)
思路:双指针,申请一个新的数组,左右两指针比较大小后从后向前输入新数组。
209. 长度最小的子数组(滑动窗口)
用单个循环来实现的思路:每一步要么右端点扩展一个元素,要么左端点缩进一个元素。这样写会出现的一个问题是当右指针走到尾部时,如果当前窗口总和仍达不到目标值,则会进入下一次循环,进而造成索引溢出。因此需要额外加上一个判断。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0;
int right = 1;
int minLength = INT32_MAX;
if (nums.size() == 0)
return 0;
int sum = nums[0];
while (right <= nums.size()){
if (sum < target){
if (right == nums.size()) //如果不加这个判断,则会导致索引溢出
break;
sum += nums[right];
right++;
}
else{
if (minLength > right - left)
minLength = right - left; //这里可以直接用min(minLength, right-left)
sum -= nums[left];
left++;
}
}
return minLength == INT32_MAX ? 0 : minLength;
}
};
标准答案中使用双循环,从代码实现结果上来看省去了单循环中繁琐的判断过程。思路是用大循环将右端点视为一个锚点,并在每一步中用小循环将左端点收至最窄,之后再接入下一个右端点。
59. 螺旋矩阵II、 54. 螺旋矩阵
考察对下标的控制。力扣上的方法同网站里给的方法有所不同。
C++语法及特性
- 乘方没有运算符,使用pow(x,n);
- 初始化一个向量:
vector<int> a(len, init_value);
初始化一个二维矩阵:vector<vector<int>> res(n, vector<int>(n, 0));
- 当需要赋一个极大值给某变量时使用 INT32_MAX;
总结
- 使用左闭右开的逻辑去判断边界情况,较以往思路更清晰,但仍不熟练,需后续多加练习。
- 总感觉还没开窍,可能需要再积累积累做题经验。