二分查找算法之Golang代码简释

写在前面:本文侧重诠释对算法的思考记录过程,忽略其他诸如代码简洁、字符编码等细节问题。

package main

//二分查找算法,针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,
//将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0为止
//时间复杂度:O(logn)
func Divide2Select(nums []int, target int) int {
	return DivideSelect(nums, target, 0, len(nums)-1)
}
func DivideSelect(nums []int, target, start, end int) int {
	if start > end {
		return -1
	}

	middle := (start + end) / 2
	if target < nums[middle] {
		return DivideSelect(nums, target, 0, middle-1)
	} else if target > nums[middle] {
		return DivideSelect(nums, target, middle+1, end)
	} else {
		return middle
	}
}

//二分法查找的变形版本:在一个给定排序序列中查找第一个等于给定值的元素
//(待查找的元素在序列中有多个)
func Divide2SelectFirst(nums []int, target int) int {
	return DivideSelectFirst(nums, target, 0, len(nums)-1)
}
func DivideSelectFirst(nums []int, target, start, end int) int {
	if start > end {
		return -1
	}

	middle := (start + end) / 2
	if target < nums[middle] {
		return DivideSelectFirst(nums, target, 0, middle-1)
	} else if target > nums[middle] {
		return DivideSelectFirst(nums, target, middle+1, end)
	} else {
		if middle == 0 || nums[middle-1] != target {
			return middle
		} else {
			return DivideSelectFirst(nums, target, 0, middle-1)
		}
	}
}

//二分法查找的变形版本:在给定已排序序列中查找最后一个等于给定值的元素
//(待查找的元素在序列中有多个)
func Divide2SelectLast(nums []int, target int) int {
	return DivideSelectLast(nums, target, 0, len(nums)-1)
}
func DivideSelectLast(nums []int, target, start, end int) int {
	if start > end {
		return -1
	}

	middle := (start + end) / 2
	if target < nums[middle] {
		return DivideSelectLast(nums, target, 0, middle-1)
	} else if target > nums[middle] {
		return DivideSelectLast(nums, target, middle+1, end)
	} else {
		if middle == len(nums)-1 || nums[middle+1] != target {
			return middle
		} else {
			return DivideSelectLast(nums, target, middle+1, end)
		}
	}
}

//二分法查找的变形版本:在给定排序序列中查找第一个大于等于给定值的元素
func Divide2SelectLargeFirst(nums []int, target int) int {
	return DivideSelectLargeFirst(nums, target, 0, len(nums)-1)
}
func DivideSelectLargeFirst(nums []int, target, start, end int) int {
	if start > end {
		return -1
	}

	middle := (start + end) / 2
	if target <= nums[middle] {
		if middle == 0 || nums[middle-1] < target {
			return middle
		} else {
			return DivideSelectLargeFirst(nums, target, 0, middle-1)
		}
	} else {
		return DivideSelectLargeFirst(nums, target, middle+1, end)
	}
}

//二分法查找的变形版本:在给定序列中查找最后一个小于等于给定值的元素
func Divide2SelectSmallLast(nums []int, target int) int {
	return DivideSelectSmallLast(nums, target, 0, len(nums)-1)
}
func DivideSelectSmallLast(nums []int, target, start, end int) int {
	if start > end {
		return -1
	}

	middle := (start + end) / 2
	if target < nums[middle] {
		return DivideSelectSmallLast(nums, target, 0, middle-1)
	} else {
		if middle == len(nums)-1 || nums[middle+1] > target {
			return middle
		} else {
			return DivideSelectSmallLast(nums, target, middle+1, end)
		}

	}
}

参考来源:https://xueyuanjun.com/books/data-structure-and-algorithms

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值