查找元素
在写算法题时经常会遇到在数组中查找元素的情况,当该元素不存在时,会选择比这个元素小的第一个元素,通常采用二分查找来解决,也可以通过一些内置函数解决。
-
java+二分查找
public int q(int t) { int l = 0, r = times.length - 1; // 找到满足 times[l] <= t 的最大的 l while (l < r) { int m = l + (r - l + 1) / 2; if (times[m] <= t) { l = m; } else { r = m - 1; } } return l; }
二分查找模板一致,下面是内置函数
-
python bisect包
bisect.bisect(arr, target) - 1
//查找结果(查找的是插入该元素的位置)落在该位置的右边,所以需要减1
python中bisect包用于有序序列的插入,查找操作,主要方法有
bisect.bisect(arr, target)//等同于调用bisect.bisect_right
bisect_left(a, x, lo=0, hi=None)//查找该数值将会插入的位置并返回,而不会插入。如果x存在在a中则返回x左边的位置
bisect_right(a, x, lo=0, hi=None)//查找该数值将会插入的位置并返回,而不会插入。如果x存在在a中则返回x右边的位置
insort(a,x)//列表a中插入元素x,并在排序后保持排序。如果x已经在a中,把它插入右x的右边。等同于调用 insort_right
insort_left(a, x, lo=0, hi=None)//在列表a中插入元素x,并在排序后保持排序。如果x已经在a中,把它插入右x的左边。
insort_right(a, x, lo=0, hi=None)//在列表a中插入元素x,并在排序后保持排序。如果x已经在a中,把它插入右x的右边。
- C++ upper_bound
//查找[first, last)区域中第一个大于 val 的元素。
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last,
const T& val);
//查找[first, last)区域中第一个不符合 comp 规则的元素
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last,
const T& val, Compare comp);
//查找[first, last)区域中第一个大于等于val 的元素。
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
const T& val);
//在 [first, last) 区域内查找第一个不符合 comp 规则的元素
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
const T& val, Compare comp);
- Golang sort库
该包实现了四种基本排序算法:插入排序、归并排序、堆排序和快速排序。 sort 包会根据实际数据自动选择高效的排序算法。
sort 包提供了对[]int 切片、[]float64 切片和[]string 切片完整支持,主要包括:
- 对基本数据类型切片的排序支持
- 基本数据元素查找
- 判断基本数据类型切片是否已经排好序
- 对排好序的数据集合逆序
对数据集合(包括自定义数据类型的集合)排序需要实现 sort.Interface 接口的三个方法
type Interface interface {
// 获取数据集合元素个数
Len() int
// 如果 i 索引的数据小于 j 索引的数据,返回 true,且不会调用下面的 Swap(),即数据升序排序。
Less(i, j int) bool
// 交换 i 和 j 索引的两个元素的位置
Swap(i, j int)
}
reverse实现
// 定义了一个 reverse 结构类型,嵌入 Interface 接口
type reverse struct {
Interface
}
//reverse 结构类型的 Less() 方法拥有嵌入的 Less() 方法相反的行为
//Len() 和 Swap() 方法则会保持嵌入类型的方法行为
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i)
}
// 返回新的实现 Interface 接口的数据类型
func Reverse(data Interface) Interface {
return &reverse{data}
}
search函数,会根据二分查找计算,搜索元素 x 是否在已经升序排好的切片 s 中
x := 11
s := []int{3, 6, 8, 11, 45} // 注意已经升序排序
pos := sort.Search(len(s), func(i int) bool { return s[i] >= x })
if pos < len(s) && s[pos] == x {
fmt.Println(x, " 在 s 中的位置为:", pos)
} else {
fmt.Println("s 不包含元素 ", x)
}
sort包原生支持[]int、[]float64 和[]string 三种内建数据类型切片的排序操作,不必我们自己实现相关的 Len()、Less() 和 Swap() 方法。
type IntSlice []int
func (p IntSlice) Len() int { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
//IntSlice 类型定义了 Sort() 方法,包装了 sort.Sort() 函数
func (p IntSlice) Sort() { Sort(p) }
//IntSlice 类型定义了 SearchInts() 方法,包装了 SearchInts() 函数
func (p IntSlice) Search(x int) int { return SearchInts(p, x) }
//对int[]排序
sort.Ints(s)
Sort(IntSlice(a))
//逆序
sort.Sort(sort.Reverse(sort.IntSlice(s)))
//查找整数 x 在切片 a 中的位置,切片必须是升序的
sort.SearchInts(s, 2)
对于string对象,是基于字典序排序的
[]interface 排序与查找
func Slice(slice interface{}, less func(i, j int) bool) //排序
func SliceStable(slice interface{}, less func(i, j int) bool) //稳定排序
func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool //判断是否有序
func Search(n int, f func(int) bool) int//判断 []interface 是否存在指定元素
//升序情况,判断条件必须为 >=
a := []int{2, 3, 4, 200, 100, 21, 234, 56}
x := 21
sort.Slice(a, func(i, j int) bool { return a[i] < a[j] }) // 升序排序
index := sort.Search(len(a), func(i int) bool { return a[i] >= x }) // 查找元素//index=3
//slice 是降序状态,不想将其变为升序,只需将判断条件由 >= 变更为 <=