704.二分查找
题目链接:https://leetcode.cn/problems/binary-search/
我的解题代码:
class Solution {
public int search(int[] nums, int target) {
int left = 0, rihgt = nums.length;
while (left < rihgt) {
int mid = left + ((rihgt - left) / 2);
if (nums[mid] == target)
return mid;
else if (nums[mid] > target)
rihgt = mid;
else if (nums[mid] < target)
left = mid + 1;
}
return -1;
}
}
对于二分法,重要的还是对区间的定义
-
左闭右闭,即:[left, right]
-
while (left <= right) {
// 当 left==right,区间[left, right]依然有效,所以用 <= -
right = middle - 1;
// target 在左区间,所以[left, middle - 1]
-
-
左闭右开,即:[left, right)
-
while (left < right) {
// 因为 left == right 的时候,在[left, right)是无效的空间,所以使用 <
-
27.移除元素
题目链接:https://leetcode.cn/problems/remove-element/
我的解题代码
class Solution {
public int removeElement(int[] nums, int val) {
int size = 0;
int rightIndex = nums.length - 1;
while (leftIndex <= rightIndex) {
if (nums[rightIndex] == val) {
rightIndex--;
} else if (nums[size] == val) {
int temp = nums[rightIndex];
nums[rightIndex] = nums[leftIndex];
nums[leftIndex] = temp;
rightIndex--;
} else {
size++;
}
}
return size;
}
}
因为提示二分法,所以我解这道题的时候也尝试着用二分法。 这里的区间是左闭右闭,所以循环条件用的是 while (leftIndex <= rightIndex)
。
思路是把有意义的值留在左边,需要删除的值放在右边,如果左边有需要删除的值,就挑选最右边的有意义的值做个替换。这样后面都是删除的值,最后返回数组大小就行了。主要在循环中思考了三种情况:
- 右边的值等于要删除的值,那就刚好,直接右边索引 -1,然后进入下一轮循环。
- 左边的值等于要删除的值,那就跟右边索引的值做一个替换,因为我们是 if else ,可以确保此时替换的右边的值不是要删除的值。
- 以上两个条件都不满足,说明左边索引前面的值都有意义,那就左边索引+1,检索下一个。
快慢指针解法
做完题后,去看了下代码随想录的解析,才发现还有 快慢指针 这种方式,这种方法真的很好理解。贴上代码:
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
总结
我在做 移除元素 这道题的时候完全没有想到 快慢指针 这一种更简单的方式,只是在一开始觉得我的双向指针想法可行,然后死磕了一个多小时,才慢慢琢磨出来。刚弄出来成功了,我自己都还没有彻底理清思路。做的时候就是哪个用例报错了,就针对这个用例自己模拟计算一下,发现问题解决问题。写总结还是有利于梳理思路和方法的。