面试之 【查找算法】

1 顺序查找

就是简单的从左往右或者从右往左遍历,待查找的数组并不需要有序,查到返回true,否则返回false
时间复杂度:

  • 最优时间复杂度是O(1),需要查找的元素就是第一个或者是最后一个
  • 最差时间复杂度是O(n),待查找的在查找顺序的最优一个位置
  • 平均时间复杂度是O(n)
public class SequenseSearch {
    public boolean search(int[]nums,int target){
        if (nums.length==0)
            return false;
        for (int i = 0; i < nums.length; i++) {
            if (target==nums[i])
                return true;
        }
        return false;
    }

    public static void main(String[] args) {
        int[] nums = new int[20];
        for (int i = 0; i < 20; i++) {
            nums[i] = i + 1;
        }
        SequenseSearch binarySearch = new SequenseSearch();
        for (int i = 1; i < 25; i++) {
            System.out.println(i+"  "+binarySearch.search(nums, i));
        }
    }
}

在这里插入图片描述

2 二分查找

二分查找可以将查找的时间复杂度降低到O(logn),但是前提是待查找的数组必须是有序的数组,当数组有序时,可以使用三个指针,一个左指针和一个右指针以及一个中间指针如果待查找的元素小于中间元素,则将查找范围缩小到数组的前半部分,如果待查找元素大于中间元素,则将查找范围缩小数组后半部分。

left=0right=n-1mid=(left+right)/2
为了防止mid越界,使用right-(right-left)/2或者(right-left)/2+left进行缓冲。
时间复杂度:O(logn)

public class BinarySearch {
    public boolean search(int[] nums, int target) {
        if (nums.length == 0)
            return false;
        int l=0,r=nums.length-1;
        while (l<=r){
            int mid = r-(r-l)/2;
            if (nums[mid]==target)
                return true;
            else if(nums[mid] > target){
                r=mid-1;
            }else{
                l=mid+1;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        int[] nums = new int[20];
        for (int i = 0; i < 20; i++) {
            nums[i] = i + 1;
        }
        BinarySearch binarySearch = new BinarySearch();
        for (int i = 1; i < 25; i++) {
            System.out.println(i+"  "+binarySearch.search(nums, i));
        }

    }
}

3 插值查找

插值查找是二分查找的一种优化,将mid指针的值进行了优化,当待查询数组(有序)的值分布较均匀时,使用插值查找效率较高,但是如果分布不均匀,效率较低。中间指针的公式如下:
mid=left+(target-a[left])/(a[right]-a[left])*(right-left)
其中,target表示待查找的值,a表示待查询数组。

public class InsertSearch {
    public boolean search(int[]nums,int target){
        int n=nums.length;
        if (n==0)
            return false;
        return insertSearch(nums,target,0,n-1);
    }


    public boolean insertSearch(int[]nums,int target,int l,int h){
        //终止递归的条件
        if (l>h||target>nums[h]||target<nums[l])
            return false;
        //当前逻辑
        int mid = l + (target-nums[l])/((nums[h]-nums[l])*(h-l));

        if (nums[mid]==target)
            return true;
        else if (nums[mid]>target){ //向下递归
            return insertSearch(nums,target,l,mid-1);
        }
        else //if (nums[mid]<target) //向下递归
            return insertSearch(nums,target,mid+1,h);
    }


    public static void main(String[] args) {
        int[] nums = new int[20];
        for (int i = 0; i < 20; i++) {
            nums[i] = i + 1;
        }
        InsertSearch insertSearch = new InsertSearch();
        for (int i = 1; i < 25; i++) {
            System.out.println(i+"  "+insertSearch.search(nums, i));
        }
    }

}

4 斐波那契查找

斐波那契查找也是对二分查找的一种改进,改进思路是基于黄金分割点(0.618:1或者1.618:1),我们发现斐波那契数列从第3个数开始,前一个数与后一个数的商随着n的增大,越来越接近于0.618
[借助一张网络图片]
在这里插入图片描述
我们需要先维护一个斐波那契数列的数组,每次指针移动都根据黄金分割比例进行分割,不再是简单的对半分。

  • target>a[mid]k-=1,left=mid+1
  • target<a[mid]k-=2,right=mid-1

时间复杂度分析:

  • 最坏情况下的时间复杂度是O(logn)
  • 且平均时间复杂度也是O(logn)

斐波那契数列一般计算到第20个就差不多,因为第20个数已经很大了。

public class FabonacciSearch {
    public boolean search(int []nums,int target){
        int n=nums.length;
        if (n==0)
            return false;
        int []f=new int[20];
        Fabonacci(f,20);
        int k=0;
        while (n>f[k]-1)
            ++k;
        int []nums2=new int[f[k]];
        System.arraycopy(nums,0,nums2,0,n);
        for (int i = n; i < f[k]; i++) {
            nums2[i]=nums[n-1];
        }

        int l=0,r=f[k]-1;
        while (l<=r){
            int mid = l+f[k]-1;
            if(nums2[mid]>target){
                r=mid-1;
                k-=2;
            }else if(nums2[mid]<target){
                l=mid+1;
                k-=1;
            }else{// if (nums2[mid]==target)
                if (mid>=n){//说明在加长的数组里面,即最后一个元素
                    return true;
                }else{//说明mid小于数组长度,直接返回mid的值
                    return true;
                }
            }
        }
        return false;
    }

    public void Fabonacci(int []f,int size){
        f[0]=1;
        f[1]=1;
        for (int i = 2; i < size; i++) {
            f[i]=f[i-1]+f[i-2];
        }
    }

    public static void main(String[] args) {
        int[] nums = new int[20];
        for (int i = 0; i < 20; i++) {
            nums[i] = i + 1;
        }
        FabonacciSearch fabonacciSearch = new FabonacciSearch();
        for (int i = 1; i < 25; i++) {
            System.out.println(i+"  "+fabonacciSearch.search(nums, i));
        }
    }
}

5 to be contiued…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值