二分查找
leetcode链接:leetcode.cn/problems/bi…
能使用二分查找的前提条件:
- 有序数组
- 数组中没有重复的元素
二分查找代码的重难点:
循环不变量,感觉这个从字面上不太好理解,可以直接先记左闭右闭,左闭右开 (之前刷过几道题目,记住了左闭右闭,左闭右开,但是没记住什么意思,不过可以推导出来)
左闭右闭 -> [left, right] -> 对应while循环里面的条件是 left <= right
左闭右开 -> [left, right) -> 对应while循环里面的条件是 left < right
理解了上面的区间,就好理解循环不变量(我自己感觉循环不变区间更容易理解点)
二分查找是一个区间一个区间的搜索,每次迭代区间都是固定的,要么都是左闭右闭,要么都是左闭右开
那么right和left变量的更新就可以根据选择的区间模式去写
左闭右闭 -> [left, right]
当 target < nums[mid] 时,需要更新right,下一个区间的right肯定是要在区间内的,但此时mid已经判断过了,不需要再放入下一个区间了,所以right = mid - 1;
当 target > nums[mid]时,需要更新left,下一个区间的left肯定是要在区间内的,但此时mid已经判断过了,不需要再放入下一个区间了,所以left = mid + 1;
代码贴一下,方便和文字进行理解
// 左闭右闭写法[left, right]
var search = function (nums, target) {
const length = nums.length;
if (length <= 0) return -1;
// 最初的区间定义也要遵循选择的区间模式
let left = 0;
let right = length - 1;
// left可以等于right,对应while循环的条件left <= right
while (left <= right) {
let mid = Math.floor((right - left) / 2) + left;
if (target === nums[mid]) {
return mid;
} else if (target > nums[mid]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
};
左闭右开 -> [left, right)
target < nums[mid] 时,需要更新right,下一个区间的right是肯定不在区间内的,此时mid已经判断过了,符合不在区间内,所以right = mid;
target > nums[mid] 时,需要更新left,下一个区间的left是肯定在区间内的,此时mid已经判断过了,不需要再放入下一个区间了,所以left = mid + 1;
// 左闭右开写法[left,right)
var search = function (nums, target) {
const length = nums.length;
if (length <= 0) return -1;
// 最初的区间定义也要遵循选择的区间模式
let left = 0;
let right = length;
// left不可以等于right,对应while循环的条件left < right
while (left < right) {
let mid = Math.floor((right - left) / 2) + left;
if (target === nums[mid]) {
return mid;
} else if (target > nums[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
};
双指针
leetcode链接:leetcode.cn/problems/re…
这道题目的重点和难点:要理解快指针和慢指针分别代表的作用
快指针:寻找符合新数组的元素
慢指针:更新新数组对应下标的元素
参考链接: