查找元素

在写算法题时经常会遇到在数组中查找元素的情况,当该元素不存在时,会选择比这个元素小的第一个元素,通常采用二分查找来解决,也可以通过一些内置函数解决。

  • 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 是降序状态,不想将其变为升序,只需将判断条件由 >= 变更为 <=
posted @ 2021-12-11 10:32  流光之中  阅读(111)  评论(0编辑  收藏  举报