704. 二分查找
二分查找的一般写法有左闭右闭和左闭右开。而区分这两种写法的一般是看右指针所指是否是包含在区间内的,即【letf, right】 还是 【left, right)。而由于区间的范围不同,也会影响在收缩边界时right和left的赋值。 左闭右闭写法:
var search = function(nums, target) {
// 区别点一: 因为右指针在区间内,所以我们从最后一个index开始
let left = 0, right = nums.length - 1;
// 区别点二:因为我们是从nums.length - 1开始为右节点,类比(i = 0; i <= nums.length - 1; i++)
while (left <= right) {
let mid = left + Math.floor((right - left)/2);
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
// 区别点三:因为我们排除了mid不是target,所以【left,mid-1】是下一个搜索范围
right = mid - 1;
} else {
return mid;
}
}
return -1;
};
左闭右开写法:
var search = function(nums, target) {
// 区别点一:因为右指针是右边界,所以我们从length开始
let left = 0, right = nums.length;
// 区别点二:因为我们是从nums.length开始为右边界,类比(i = 0; i < nums.length - 1; i++)
while (left < right) {
let mid = left + Math.floor((right - left)/2);
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
// 区别点三:因为我们排除了mid是不可能为target的,所以target在【left,mid)中间,收缩右边界。
right = mid;
} else {
return mid;
}
}
return -1;
};
27. 移除元素
我们可以用双指针的技巧来实现O(n)的时间复杂度:
var removeElement = function(nums, val) {
let read = 0, write = 0
// 因为read永远比write走得快,所以我们可以直接检查read然后赋值给write
while (read < nums.length) {
if (nums[read] !== val) {
nums[write] = nums[read]
write += 1
}
read += 1
}
return write
};