704.二分查找
时间复杂度 O(logn) 空间复杂度 O(1)
要求: 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
思路
本题为有序无重复元素数组,适用于二分法思想,如果有重复元素,使用二分法返回的元素下表可能不是唯一的。 二分法的难点在于区间的定义,区间定义分为两种,左闭右闭[left, right]和左闭右开[left, right)。
左闭右闭区间[left, right],即left=0, right=n-1, 此时这个right是可以取到的,所以while(left<=right)是正确的写法;而左闭右开[left, right), 即left=0, right=n, 此时这个right我们无法取到,所以while(left<right)是正确的,这就是循环不变量规则。
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
let left = 0, right = nums.length-1
while(left<=right){
let mid = left + Math.floor((right-left)/2)
if(nums[mid]<target){
// left++
left = mid+1
}else if(nums[mid]>target){
// right--
right = mid-1
}else{
return mid
}
}
return -1
};
27.移除元素
要求: 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
思路
首先想到的是用splice方法删除数组元素
var removeElement = function(nums, val) {
for(let i=0; i<nums.length; i++){
if(nums[i] == val){
nums.splice(i, 1)
i--
}
}
return nums.length
};
本题暴力解法超出时间限制
- 暴力解法:两层for循环,一层遍历数组元素,第二层for循环更新数组。
时间复杂度 O(n^n) 空间复杂度 O(1)
var removeElement = function(nums, val) {
let len = nums.length
for(let i=0; i<nums.length; i++){
if(nums[i] == val){
for(let j=i+1; j<nums.length;j++){
nums[j-1] = nums[j]
}
i--
len--
}
}
return len //暴力超出时间限制
};
- 双指针法(快慢指针法):快指针在for循环中遍历数组元素,慢指针用于更新新数组下标的位置
时间复杂度 O(n) 空间复杂度 O(1)
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) {
//快慢指针法
let j=0
for(let i = 0; i<nums.length; i++){
if(nums[i]!=val){
nums[j++] = nums[i]
}
}
return j
};