文章讲解:代码随想录(programmercarl.com)
数组是存放在连续内存空间上的相同类型数据的集合。
注:数组的下标都是从0开始的。
题目链接:LeetCode 704 二分查找
文章讲解:代码随想录(programmercarl.com)
视频讲解:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704 二分查找
此题的题目中提到了该数组是有序的(升序),且在提示中强调数组中的元素是不重复的,所以此题可以使用二分查找法来进行求解。
注:二分查找只能实现单值查找,不能实现多值查找,如果数组中元素有重复,那么二分查找法找到的下标可能不唯一。
二分法容易写乱,主要是没有分清自己定义的区间是左闭右闭[left, right],还是左闭右开[left, right)。这两种区间的定义在做题时都可以使用,但是在一道题目中,只可以选择一种定义方式。
当我们定义target在左闭右闭的区间中,即[left, right],要注意以下两点:
1.因为left == right是有意义的,在while (条件) 循环的条件中我们使用left <= right,而不是left < right,即while (left <= right)。
2.当if (nums[middle] > target)判断条件成立时,我们要给right赋值为middle - 1,而不是middle。因为区间是右闭的,在判断条件中,我们已经知道nums[middle] > target,如果right赋值为middle,就会重复做一次判断。
当我们定义target在左闭右开的区间中,即[left, right),要注意以下两点:
1.因为left == right已经没有意义了,在while (条件) 循环的条件中我们不能让left = right,只可以写left < right,即while (left < right)。
2.当if (nums[middle] > target)判断条件成立时,我们要给right赋值为middle,而不是middle - 1。因为区间是右开的,取不到right的值。所以将right赋值为middle。
Java版本的左闭右开区间的写法
步骤:
a. 判断目标值是否在数组内
b. 定义区间(左闭右开)
c. 进入循环;定义middle;开始判断(3点)
class Solution {
public int search(int[] nums, int target) {
if(target < nums[0] || target > nums[nums.length - 1]){
return -1;
}
int left = 0, right = nums.length;// 左闭右开区间
while (left < right){
int mid = left + ((right - left) >> 1);
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid;
}
return -1;
}
}
在定义middle时,用到了防溢出的方式:
int mid = left + ((right - left) >> 1); //二进制右移
int mid = left + ((right - left) / 2);
二进制右移的运行速度更快。
题目链接:LeetCode 27 移除元素
文章讲解:代码随想录(programmercarl.com)
视频讲解:数组中移除元素并不容易! | LeetCode:27. 移除元素
两层for循环,一个for循环遍历数组元素,另一个for循环更新数组。
双指针法(快慢指针法):需要明确快慢指针的作用分别是什么。
快指针:寻找新数组的元素,新数组就是不含有目标元素的数组。
慢指针:指向更新,新数组下标的位置。、
开始时,fast指针和solw指针都指向0位置;
fast指针先进行判断,判断该位置是否为目标值:
如果不是目标值就将该值赋值给slow指针,然后后移一位;
如果是目标值就后移一位,不进行赋值操作。
Java版本的双指针解法代码
步骤:
a. 定义慢指针
b. 进入循环,并在条件中定义快指针
c. 进行判断
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;
}
}
LeetCode 704 二分查找主要掌握了左闭右闭区间的写法,LeetCode 27 移除元素主要掌握了双指针的解法。