提示:努力生活,开心、快乐的一天
题目链接:704.二分查找
有序数组+无重复元素
[left,right]和[left,right)
循环不变量
原则,此题中的不变量就是区间
[left,right]
:nums[mid]>target时,需要更新右边界的值,right = middle-1(此处!=middle的原因是:遵循区间不变原则,右区间为闭区间,则nums[mid]可能等于target,但进入该判断条件的前提是nums[mid]>target,两者相悖,所以!=middle);
nums[mid]
[left,right)
nums[mid]>target时,此时需要更新右边界的值,right = middle(此处=middle的原因是:遵循区间不变原则,右区间为开区间,则nums[mid]不可能等于target,但进入该判断条件的前提是nums[mid]>target,两者一致,所以=middle);
nums[mid]
mid的取值问题,(left+right)/2 会产生溢出情况
解决方案:使用 >>
运算符
边界处理上,一看就会,一些就废,眼高手低啦
[left,right]
var search = function (nums, target) {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
let mid = (right + left) >> 1
if (nums[mid] > target) {
right = mid - 1
} else if (nums[mid] < target) {
left = mid + 1
} else {
return mid
}
}
return -1;
};
[left,right)
var search = function (nums, target) {
let left = 0;
let right = nums.length;
while (left < right) {
let mid = (right + left) >> 1
if (nums[mid] > target) {
right = mid
} else if (nums[mid] < target) {
left = mid + 1
} else {
return mid
}
}
return -1;
};
二分查找的条件
确定查找的区间,是[left,right]还是[left,right)
>>
运算符 [left,right]
right
值就是数组最后一位的下标 while
循环的条件遵循区间不变规则, left<=right
nums[mid] > target
:target值在左区间,更新右区间值为[left,mid-1] nums[mid] < target
:target值在右区间,更新右区间值为[mid+1,right] nums[mid] = target
:return mid[left,right)
right
值就是数组的长度 while
循环的条件遵循区间不变规则, left
判断条件分3种情况:
nums[mid] > target
:target值在左区间,更新右区间值为[left,mid)
nums[mid] < target
:target值在右区间,更新右区间值为[mid+1,right)
nums[mid] = target
:return mid
不满足循环,return -1
题目链接:27.移除元素
原地
移除元素,所以不能new一个新的数组双层for循环
,第一层,遍历数组;某元素与val值相同时,进行第二层循环,将其后的元素往前移动,时间复杂度: O(N^2),空间复杂度:O ( 1 )fast
指针代表新数组的元素,slow
指针代表新数组的下标,当fast
指针遇到val时,直接跳过,等待 slow
指针将其覆盖,从而达到删除元素的效果;如果 fast
指针遇到值不等于val
的元素,将其值赋值给 slow
指针,然后让 slow
指针前进一步。暴力解法
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;
};
双指针解法
var removeElement = function (nums, val) {
//双指针
let slow = 0
for (let i = 0; i < nums.length; i++){
if (nums[i] !== val) {
nums[slow] = nums[i]
slow++
}
}
return slow;
};
双指针经常用于处理数组和链表相关问题,主要利用了数组连序性
的特点。优点是降低算法的时间复杂度,因为使用两个指针可以避免多层循环。双指针技巧主要分为两类:左右指针
和快慢指针
。本题使用到了快慢指针。
一边上班一边刷题,先看题,发散思维,梳理自己的思路,再看视频,再看文字版解析,再编码,最后写博客(第一次写,很浪费时间)。时间比较散,因为偶尔对需求,偶尔改bug,偶尔开会。但还是完成了。欣崽棒棒哒