算法基础篇-03-查找(顺序查找和二分法查找)

1.查找

  • 查找:在一些数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程;
  • 列表查找(线性表查找):从列表中查找指定元素;
    • 输入: 列表,待查找元素
    • 输出:元素下标(未找到元素时一般返回None或-1)
  • 内置列表查找函数:index of ()

2. 顺序查找(Linear Search)

顺序查找:也叫线性查找,从列表第一个元素开始,顺序进行搜索,直到找到元素或搜索到列表最后一个元素为止;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 线性查找/顺序查找
 *
 * @author wql
 * @date 2022/12/7 21:44
 */
public class LinearSearch {
    public static void main(String[] args) {
        List<String> asList = Arrays.asList("A", "AB", "AC");
        int index = handLinearSearch(asList, "AC");
        System.out.println("index = " + index);
    }
    
    /**
     * 顺序查找(线性查找)
     *
     * @param arr         待查找列表
     * @param targetValue 目标值
     * @return 目标值所处位置索引下标
     */
    public static int handLinearSearch(List<String> arr, String targetValue) {
        for (int i = 0; i < arr.size(); i++) {
            if (Objects.equals(targetValue, arr.get(i))) {
                return i;
            }
        }
        return -1;
    }
}

在这里插入图片描述
如上图所示:分析算法时间复杂度三部曲:寻找规模n,是否存在循环减半过程,k层关于n的循环;从代码中,我们可以看出不存在循环减半和k层n循环的过程,问题规模是n,那么这个顺序查找的
时间复杂度为: O(n)

3. 二分查找(Binary Search)

二分查找:又叫折半查找,从有序列表的初始候选区li[0:n] 开始,通过对待查找的值与候选区中间值的比较,可以是候选区减少一半;

案例:
在这里插入图片描述
我们要从列表里面寻找3的位置,问题规模是n,目标值是3,那么在使用二分查找的时候,我们的关键是如何为维护候选区,候选区指的是目标值所在区域;假设初始的时候left是0,right是n-1,其实就是下标;
那么我们求中间值就是left + right 之和,再除以2,也就是mid;

如上图所示,第一步中间值是5,5大于3,则要维护候选区,就是将right指针移动到mid-1的位置,如下图所示
在这里插入图片描述
第二步:重新计算新的mid下标,此时0+3 除以2 等于1,那么mid光标在 2上面
在这里插入图片描述
再比较2和3,发现2比3小,所以移动left,left的下一个位置等于mid位置+1
在这里插入图片描述
第三步:left=2,right=3,那么2+3=5,除以2,等于2,所以mid等于left,也就是3上面
在这里插入图片描述
最后一步:判断当mid值等于3时,输出mid值,也就是3的下标,如果left 大于right ,那么候选区没有值了,也就是找不到,返回-1

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 二分查找
 *
 * @author wql
 * @date 2022/12/7 22:01
 */
public class BinarySearch {

    public static void main(String[] args) {
        List<Integer> asList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        int index = handBinarySearch(asList, 3);
        System.out.println("index = " + index);
    }

    /**
     * 二分查找
     * <p>
     * 列表首先默认时排好序的
     *
     * @param arr         待查找列表
     * @param targetValue 目标值
     * @return 目标值所处位置索引下标
     */
    public static int handBinarySearch(List<Integer> arr, Integer targetValue) {
        //定义left right mid
        int left = 0;
        int right = arr.size() - 1;
        //当left<=right时,表示候选区有值
        while (left <= right) {
            //获取中间值的下标
            int mid = (left + right) / 2;
            if (Objects.equals(targetValue, arr.get(mid))) {
                return mid;
            } else if (arr.get(mid) > targetValue) {
                //如果中间值大于目标值,说明候选区在左侧
                right = mid - 1;
            } else if (arr.get(mid) < targetValue) {
                //如果中间值小于目标值,说明候选区在右侧
                left = mid + 1;
            }
        }
        return -1;
    }
}

在这里插入图片描述
时间复杂度:O(logn)

4. 顺序查找和二分查找对比

二分查找效率远远大于 线性查找,那为啥jdk里面的 index of 函数不使用二分查找,因为使用二分查找的前提是列表必须是有序的;所以在不能保证列表有序的情况下,使用线性查找;因为排序也可能消耗大量的时间;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alan0517

感谢您的鼓励与支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值