704.二分查找
状态:已完成
思路:对升序数组使用二分查找能最小时间复杂度找到目标
时间复杂度O(logn),空间复杂度O(1)
想法很简单,不过看完代码随想录的思路后,使用了左闭右闭区间来写该算法,能更清晰while循环及if判断中的条件,以下是代码:
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
let min = 0;
let max = nums.length-1;
let middle = Math.floor((min+max)/2);
while(min<max){
if(nums[middle]==target){
return middle;
}
else if(nums[middle]<target){
min = middle+1;
middle = Math.floor((min+max)/2);
}
else{
max=middle;
middle = Math.floor((min+max)/2);
}
}
return -1;
};
学完之后还举一反三尝试完成了35.搜索插入位置、
34.在排序数组中查找元素的第一个和最后一个位置,还是比较好地掌握了二分法的使用。
27.移除元素
状态:已完成
初始思路:
使用两个指针,p从前往后遍历,
如检测到到当前元素等于val,则用q检查末尾元素是否等于val,
如果相等q就往前挪,直到不相等后,
nums[p]和nums[q]的值互换,并对nums[q]出栈,
不过里面有两个问题:
- 题目不需要对nums出栈,否则反而会不对
- 其实题目表明不需要考虑数组中超出新长度后面的元素,所以nums[q]的值也可以不用处理
时间复杂度O(n),空间复杂度O(1),以下是代码:
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) {
let p = 0;
let q = nums.length-1;
while(p<q){
if(nums[p]==val){
let i = 1;
while(nums[q]==val){
q--;
i++;
}
nums[p] = nums[q];
for(;i>0;i--){
nums.pop();
}
q--;
}
p++;
}
};
看完代码随想录后,重新按文档的快慢指针写了一遍,但仍有问题:
var removeElement = function(nums, val) {
let i = 0;
for(let j = 0;j<nums.length;j++){
if(nums[j]==val){
j++;
}
nums[i]=nums[j];
i++;
}
return i;
};
第二版的问题在于,如果最后一个目标是val,快指针会溢出
因此最终答案为:
//正确答案
var removeElement = function(nums, val) {
const n = nums.length;
let left = 0;
for (let right = 0; right < n; right++) {
if (nums[right] !== val) {
nums[left] = nums[right];
left++;
}
}
return left;
};
今日雷点:
- 不要在for循环里面对循环变量进行修改,容易溢出查找范围
- 自己解题,有思路的情况下只给一个小时(后续慢慢缩短)