一、704. 二分查找
// 左闭右开
public int search(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n;
while(left < right) {
int mid = left + ((right-left)>>>1);
if(nums[mid] > target) {
right = mid;
} else if(nums[mid] < target) {
left = mid+1;
} else {
return mid;
}
}
return -1;
}
// 左闭右闭
public int search1(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n-1;
while(left <= right) {
int mid = left + ((right-left)>>>1);
if(nums[mid] > target) {
right = mid-1;
} else if(nums[mid] < target) {
left = mid+1;
} else {
return mid;
}
}
return -1;
}
常见问题:
1.奇怪的左右边界问题,到底是左闭右开还是左闭右闭区间
2.循环判断是小于还是小于等于
3.更新左右下标是加1减1还是不做操作
一切根据定义的数组下标实现后续操作!!!
左闭右开还是左闭右闭区间,其实都能选,这里是不唯一的
左闭右开
- 问题:首先,左闭右开说明右边边界是无效的,它不被包含在求值本身中;
- 循环判断:那么循环判断根据区间有效性,不能出现相等,因为如果左右相等了,数组的条件又是不相等,那不就是矛盾的地方吗,因此我们不选择在循环中出现等于的符号;
- 下标加1减1:在更新左右下标中,更新左边,mid已经判断不是所求的值,左边又是闭区间,我们需要刨除掉,因此需要对左边进行=mid+1,更新右边,mid不是所求,但是右区间也是不被算进去的,那么我们只要更新到mid即可
左闭右闭
- 左右边界问题:首先,左闭右闭说明右边边界是有效的,它包含在求值本身中;
- 循环判断:那么循环判断根据区间有效性,一定要能出现相等,因为如果左右相等了,数组的条件也是相等,那么我们其实还要对该值进行判断,因为其在数组中有效
- 下标加1减1:在更新左右下标中,更新左边,mid已经判断不是所求的值,左边又是闭区间,我们需要刨除掉,因此需要对左边进行=mid+1,更新右边,mid是所求,右区间也是被算进去的,mid我们已经求过了不在范围内,那么我们要更新到mid-1
推荐题目
二、27. 移除元素
思路
双指针法:快指针用来判断元素是否需要留下来,慢指针表示有效元素
public int removeElement(int[] nums, int val) {
int slow = 0, fast = 0;
while (fast < nums.length) {
if(val == nums[fast]) {
fast++;
} else {
nums[slow++] = nums[fast++];
}
}
return slow;
}
三、209. 长度最小的子数组
思路
- 暴力:双层for循环
- 滑动窗口:拥有两个指针slow,fast(fast一直往前走,知道区间和 > target,这时就轮到slow走了,逐渐逼近 target,把满足条件的数组的长度记录下来,每次满足条件都进行一下判断,最终返回最小的)
public int minSubArrayLen(int target, int[] nums) {
int sum = 0;
int ret = nums.length + 1;
int slow = 0;
for (int fast = 0; fast < nums.length; fast++) {
sum += nums[fast];
while (sum >= target) {
if(sum >= target) {
ret = Math.min(fast - slow + 1,ret);
}
sum -= nums[slow++];
}
}
return ret == nums.length + 1 ? 0 : ret;
}
推荐题目
四、59. 螺旋矩阵 II
主要代码如下图所示,
核心:控制边界条件判断
public int[][] generateMatrix(int n) {
int startx = 0, starty = 0;
int count = 1;
int[][] ret = new int[n][n];
// 控制列的边界
int offset = 1;
// 循环的圈数
int m = n / 2;
while (m > 0) {
int i = startx;
int j = starty;
for (; j < n - offset; j++) {
ret[i][j] = count++;
}
for (; i < n-offset; i++) {
ret[i][j] = count++;
}
for (; j > starty; j--) {
ret[i][j] = count++;
}
for (; i > startx; i--) {
ret[i][j] = count++;
}
startx++;
starty++;
offset++;
m--;
}
// 奇数的话会有一个中心点
if(n % 2 == 1) {
ret[startx][starty] = count;
}
return ret;
}
推荐题目