704.二分查找
今日学习文章链接
第一想法
题目要求在nums中寻找与target相等的元素的下标,首次想法是暴力解法,代码如下:
var search = function(nums, target) {
for(let i=0;i<nums.length;i++){
if(nums[i]<target) continue
if(nums[i]===target) return i
if(nums[i]>target) return -1
}
return -1
};
代码质量:
之后觉得二分查找也可以,代码如下(也是左闭右闭的写法)
var search = function(nums, target) {
let left=0;
let right=nums.length-1
while(left<=right){
let middle=~~((left+right)/2)
if(nums[middle]<target) left=middle+1
if(nums[middle]>target) right=middle-1
if(nums[middle]==target) return middle
}
return -1
};
代码质量
看完文章讲解后的想法
通过代码随想录中关于二分查找的讲解,发现有两种写法,分类为左闭右开和左闭右闭。以前我常用左闭右闭的写法,今日来学习一下左闭右开的写法(本人正在学习ts,所以左闭右开的写法为ts
function search(nums: number[], target: number): number {
let left:number =0
let right:number=nums.length
while(left<right){//此时是左闭右开的写法
let middle:number=~~((left+right)/2)//向下取整
if(nums[middle]<target) left=middle+1
if(nums[middle]>target) right=middle //这里是因为按照左闭右开的写法,可能解的范围为left~right-1
if(nums[middle]==target) return middle
}
return -1
};
代码质量
思考
二分查找主要为两种写法,左闭右闭和左闭右开,区别在于区间的范围和缩小范围是右边界
左闭右闭的写法:
while(left<=right){//左闭右闭
...
if(nums[middle]>target) right=middle-1 //这里之所以是middle-1,原因是左右都是闭区间,所以right取middle是由判断条件可知是不成立的,所以right取middle-1
...
}
左闭右开写法:
while(left<right){ //这里是左闭右开的写法
...
if(nums[middle]>target) right=middle//这里是middle的原因是右边界是开区间,所以middle取不到,如果是middle-1的话middle-1这个下标的元素就无法取到,可能就错过了目标结果
...
}
27.移除元素
文章学习链接
第一想法
利用js自带的splice方法解决以上问题,代码如下:
var removeElement = function(nums, val) {
for(let i=0;i<nums.length;i++){
if(nums[i]==val){
nums.splice(i,1)
i-- //因为splice会改变原数组,所以删除元素后,刚刚删除元素的下标会被后面一位元素占据,所以这里i--需要重新判断当前下标是否等于val
}
}
return nums.length
};
代码质量:
看完文章讲解后的想法
看完代码随想录后,发现这道题可以用暴力和双指针的解法,于是尝试用这两种解法解决问题
暴力解法:
//暴力写法
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-- //这里i--的原因是重新判断移到这一位的元素是否等于val
len--
}
}
return len
};
代码质量:
双指针解法:
//双指针
var removeElement = function(nums, val) {
let slow=0
//慢指针用于确定新数组的下标 快指针用于寻找非val的元素
for(let i=0;i<nums.length;i++){
if(nums[i]!=val){
nums[slow]=nums[i]
slow++
}
}
return slow
};
代码质量:
思考
这道题的主要思路为用后方的元素把等于val的元素覆盖掉(逐一覆盖),所以暴力法应该是最先想到的,遇到等于val的则将当前下标之后的往前移动一位。两层for循环时间复杂度为O()
优化:
两层for循环的目的就是让不等于val的元素往前移,所以双指针完全可以解决问题,快指针用于寻找非val元素,slow用于确定新数组下标。
今日总结
今天是参加代码随想录算法营的第一天,之前零零散散刷过一些题,这是第一次系统的学习算法。今日花费时间约2h,算是中规中矩吧。二分查找一般能想到,但是对于双指针有点想不到,还得继续努力