练习时长两年半的小趴菜开始的算法之路
leetcode 704.二分查找
题目链接: 704.二分查找
题目分析
该题目是在有序数组中,寻找一个数字,然后返回其对应要求的值 使用
二分法效率比较高
解法:左闭右开
左闭右开即 [left, right)
function search(nums: number[], target: number): number {
let left = 0
let right = nums.length // 注意
while (left < right) { // 注意
const mid =left + ((right - left) >> 1)
if(target < nums[mid]) {
right = mid // 注意
} else if (target > nums[mid]) {
left = mid + 1
} else if (target == nums[mid]) {
return right = mid
}
}
return nums[left] == target ? left : -1 // 注意边界问题
};
解法:左闭右闭,也称为两端闭合
两端闭合即 [left, right]
function search(nums: number[], target: number): number {
const len = nums.length
let left = 0
let right = len - 1
while (left <= right) {
const mid = Math.floor(left + (right - left) / 2)
if(target == mums[mid]) {
return mid
} else if(target < nums[mid]) {
right = mid - 1
} else if (target > nums[mid]) {
left = mid + 1
}
}
return -1
};
对比
| 左闭右开 | 两端闭合 | |
|---|---|---|
| right取值 | 数组长度 | 数组长度-1 |
| while | < | <= |
| 数组不存在目标元素时 | 需要判断边界问题 | 直接return -1 |
| target < nums[mid] | right = mid | right = mid - 1 |
leetcode 27.移除元素
题目链接:27.移除元素
题目分析
数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖
所以该题目不能删除只有做覆盖
解法:暴力双循环
function removeElement(nums: number[], val: number): number {
let len = nums.length
for( let i = 0; i< len; i++) {
if(val === nums[i]) {
for (let j = i+1; j <len; j++) {
nums[j-1] = nums[j]
}
i--
len--
}
}
return len
};
解法:双指针
function removeElement(nums: number[], val: number): number {
let slow = 0
for( let fast = 0; fast <nums.length; fast++) {
if(val !== nums[fast]) {
nums[slow] = nums[fast]
slow++
}
}
return slow
};
总结&注意
总结
之前也断断续续的刷过几道二分法的题,只理解了两端闭合的写法,这次巩固了左闭右开的写法,下去也得多多练习
1. 二分法
- 二分法整体思路不难,难在
mid(中间值) 是 +1 还是 -1; while 中用<=还是< - 取中间值用
left + (right -left) / 2或left + (right -left) >> 1, 不要用(left + right) / 2在计算中可能会产生溢出问题,即上述可以改为 - 逻辑运算符(
+``-``*``/) 优先级在 位运算 之前,即上述使用位运算时需要加上括号left + ((right-left) >> 1)
2. 双指针
- 快慢指针法:
fast快指针用来查找元素,slow慢指针用来处理操作 - 数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖
参考资料:
1.数组理论基础
2.位运算 >>
![]()
最后,文章有不对的地方请各位大佬指出!!!