数组
二分法
快慢指针(移除元素)
双指针(有序数组的平方)
滑动窗口( 长度最小的子数组)
区间和
螺旋矩阵II (边界问题)
二分法
思想 : 不断把区间二分为一,逼进目标值
使用前提 :有序数组
关于二分mid溢出:
- mid={l+r)/2时 如果l+r大于INT_MAX (int整型的上限)会溢出
- 所以写成mid=l+(r-l)/2 / mid=l+(r-l)>>1
注意区间:
左闭右闭区间 [left, right]
左闭右开区间 [left, right)
704. 二分查找 - 力扣(LeetCode)
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while (left < right) {
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle;
} else if (nums[middle] < target) {
left = middle + 1;
} else {
return middle;
}
}
return -1;
}
快慢指针
快指针在旧数组中找非目标值,然后赋值给慢指针指向的新数组
27. 移除元素 - 力扣(LeetCode)
vector.size()空数组返回0,再减去一会溢出,变成一个很大的负数
int removeElement(vector<int>& nums, int val) {
int j=0;
for(int i=0;i<nums.size();i++){
if(nums[i]!=val){
nums[ j++]= nums[i];
}
}
return j;
}
双指针
使用前提 :有序数组
977. 有序数组的平方 - 力扣(LeetCode)
vector<int> sortedSquares(vector<int>& A) {
int k = A.size() - 1;
vector<int> result(A.size(), 0);
for (int i = 0, j = A.size() - 1; i <= j;) {
// 注意这里要i <= j,因为最后要处理两个元素
if (A[i] * A[i] < A[j] * A[j]) {
result[k--] = A[j] * A[j];
j--;
}
else {
result[k--] = A[i] * A[i];
i++;
}
}
return result;
}
区间和(前缀和)
预先计算并存储数组前i个元素的和
[___这样在查询区间和的时候只需要做一次减法操作,时间复杂度可以降到O(1) _ ]
原数组 → [1, 3, 2, 5]
前缀和 → [0, 1, 4, 6, 11]
##
问:求[1,3]号元素和( 3+2+5 )?
答:prefix[4] - prefix[1] = 11 - 1 = 10 ✔
int main()
{
int n, a, b;
cin >> n;
vector<int>nums(n, 0);
vector<int>sum_nums(n, 0);
for (int i = 0; i < n; i++)
{
cin >> nums[i];
if (i > 0)
sum_nums[i] = nums[i] + sum_nums[i - 1];
else if (i == 0) sum_nums[i] = nums[i];
}
while (cin >> a >> b) {
int sum;
if (a == 0) sum = sum_nums[b];
else sum = sum_nums[b] - sum_nums[a - 1];
cout << sum << endl;
}
}
滑动窗口
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引
209. 长度最小的子数组 - 力扣(LeetCode)
int minSubArrayLen(int target, vector<int>& nums) {
int i=0;
int sum=0;
int length=0;
int result=INT32_MAX;
for(int j=0;j<nums.size();j++)
{
sum+=nums[j];
while(sum>=target){
length=(j-i+1);
result=length<result?length:result;
sum-=nums[i++];
}
}
return result==INT32_MAX?0:result;
}
螺旋矩阵II
阴间细节
左闭右开原则
每次拐角,即每个for循环不处理最后一个元素,避免重复填充
奇数的特殊关怀
当n为奇数时,最后会剩下一个中心点
偏移
每完成一层,offset++
使得下一层的遍历范围减少:
59. 螺旋矩阵 II - 力扣(LeetCode)