我正在参加「掘金·启航计划」
704.二分查找
自己看到题目的第一想法
看到题目的第一想法就是使用循环,一个一个的遍历,直到找到target或者遍历完。
但是看到题目中的n个元素有序,并且所有元素不重复,这种明显可以用二分法来降低复杂度。
下面是自己调试后写出的代码:
var search = function(nums, target) {
let left = 0,right = nums.length - 1,mid
while(left <= right) {
mid = Math.floor((right - left) / 2) + left;
if(nums[mid] < target) {
left = mid + 1
} else if(nums[mid] > target) {
right = mid - 1
} else {
return mid
}
}
return -1
};
看完代码随想录之后的想法
代码随想录中二分法有两种写法,一种是target是在一个在左闭右闭的区间里,这种时候就像上面的代码,判断时left<=right,同时left = mid + 1、right = mid - 1。
另一种是target 是在一个在左闭右开的区间里,这时候判断循环left<right,同时left = mid、right = mid。
比较值得注意的一点是如果为左闭右开的区间len应该为nums.length而不需要减一了。
二分法对区间的定义很重要,如果不清楚很容易搭配错误。
对于
mid = left + ((right - left) >> 1);
1010>>1 === 0101 十进制由10->5,所以>>1就相当于除以二。为了防止left+right超过基本类型所能容纳的最大值,所以使用位运算,而且位运算更快一些。
自己实现过程中遇到哪些困难
对于right = nums.length - 1,一开始忘记减一,排查了一会。
27.移除元素
数组作为一种连续存储的结构,并不能简单的删除某个位置的元素,只能进行覆盖操作。
自己看到题目的第一想法
暴力解法:如果遇到val就用后面的覆盖val,数组长度减一。
var removeElement = function(nums, val) {
let len = nums.length
for(let i = 0;i < len;i++) {
if(nums[i] === val) {
for(let j = i + 1;j < len;j++) {
nums[j - 1] = nums[j]
}
i--
len--
}
}
return len
};
这种解法时间复杂度很高,为n的平方。
看完代码随想录之后的想法
使用双指针的方式,可以使用一个for循环完成两个for循环的工作。如果遇到目标数,慢指针不加一,可以将非目标数替换到前面的位置。
快指针用来指向新数组所需要的元素,也就是非target的元素。慢指针是新数组的长度。
var removeElement = function(nums, val) {
let k = 0
for(let i = 0;i < nums.length;i++) {
if(nums[i] != val) {
nums[k++] = nums[i]
}
}
return k
};
今日收获,记录一下自己的学习时长
今天的题比较简单,花了两个小时做题+写博客。
今天复习了二分法的使用、位运算的使用以及双指针的使用。