数据结构和算法三个“二分查找”练习
Posted 秘法鞋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构和算法三个“二分查找”练习相关的知识,希望对你有一定的参考价值。
关于二分查找算法的总结和三个LeetCode练习题,简单或中等难度,编号就是LeetCode的题号,Swift语言编码解答。如有错误或需优化处,欢迎交流指正
/*
* 二分查找要点介绍
* 69. x 的平方根
* 33. 搜索旋转排序数组
* 167. 两数之和 II - 输入有序数组
*/
二分查找介绍
二分查找主要用于有序数据集合元素查找,其时间复杂度为O(logN)
写二分查找代码的要点
-
退循环条件为low <= high -
mid 最佳取值公式为 mid = low+((high-low)>>1 -
两端更新方式为 low = mid+1 或 high = mid-1
二分查找适用场景
-
适合顺序表(数组),不适合链表 -
需要连续的内存空间 -
数据量不宜太大,GB量级的就不适合了
二分查找变题
-
查找第一个值等于给定值的元素 -
查找最后一个值等于给定值的元素 -
查找第一个大于等于给定值的元素 -
查找最后一个小于等于给定值的元素
69. x 的平方根
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
适合用二分查找法,如求8的平方根可转换为找数组[1,2,3,4,5,6,7,8]数组中平方最接近8的数字, 二分查找过程如下
[1,2,3,4,5,6,7,8]
[1,2,3,4]
[2,4]
[2,3]
[2]
实现代码如下(swift)
class Solution {
func mySqrt(_ x: Int) -> Int {
if x == 0 {
return 0
}
var low = 1
var high = x/2 + 1
while high - low > 1 {
let mid = (low + high)/2
if mid * mid > x {
high = mid
} else {
low = mid
}
}
return low
}
}
33. 搜索旋转排序数组
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例1
输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例2
输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1
提出一种解法,先找出翻转点,再判断target所在区间分区间查找。
class Solution {
func search(_ nums: [Int], _ target: Int) -> Int
{
// 1.0
guard nums.count > 0 else {
return -1
}
var low = 0, high = nums.count-1
var mid = low + (high-low)>>1
// 先找分割点
var minFlag = 0
// 先判断是否翻转点是否在数组中间(最后一个元素翻转,对数组顺序无影响)
// 若翻转则nums[low] > nums[high]
if nums[low] > nums[high] {
while low < high {
if nums[mid] > nums[low] {
low = mid
} else {
high = mid
}
mid = low + (high-low)>>1
}
minFlag = mid+1
}
// 二分查找
if target <= (nums.last ?? 0) {
low = minFlag
high = nums.count - 1
} else {
low = 0
high = minFlag - 1
}
mid = low + (high-low)>>1
while low <= high {
if nums[mid] > target{
high = mid - 1
} else if nums[mid] < target {
low = mid + 1
} else {
return mid
}
mid = low + (high-low)>>1
}
return -1
}
}
167. 两数之和 II - 输入有序数组
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:
输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
这题并没有用折半查找,但用到有序的特性来进行遍历。思路相对简单:双指针分别从头尾遍历。swift代码实现如下
class Solution {
func twoSum(_ numbers: [Int], _ target: Int) -> [Int] {
var low = 0
var high = numbers.count - 1
while low < high
{
if (numbers[low] + numbers[high]) == target{
return [low+1, high+1]
} else if (numbers[low] + numbers[high]) < target {
low += 1
} else {
high -= 1
}
}
return []
}
}
最后欢迎同学们交流关注~~
以上是关于数据结构和算法三个“二分查找”练习的主要内容,如果未能解决你的问题,请参考以下文章