算法篇:查找算法

一、查找算法概述

1. 查找算法
  • 查找:根据给定的值,在查找表中确定一个关键字等于给定值的元素
  • 分类:
    • 静态查找和动态查找
      • 动态查找指查找表中有删除和插入的操作
    • 无序查找和有序查找
      • 无序查找:被查找数列有序无序均可
      • 有序查找:被查找数列必须有序
2. 常见查找算法
  • 顺序查找
  • 二分查找
  • 插值查找
  • 斐波那契查找
二、常见查找算法
1. 顺序查找
  • 思路
    • 一种无序查找算法。从数据结构线性表一端开始,顺序扫描,将扫描得到的结点关键字与给定值进行比较
  • 复杂度:
    • 时间复杂度:O(n)
public boolean sequenceSearch(List<Integer> list, int target){
	int size = list.size();
    for(int i = 0; i < size; i++){
    	if(target == list.get(i)){
    		return true;
    	}
    }
    return false;
}
2. 二分查找
  • 思路
    • 一种有序查找算法。将给定值与中间结点的关键词比较,相等查找成功,不相等则根据比较结果确定查找那个子表,递归进行
  • 时间复杂度
    • 时间复杂度:O(log2n)
  • 特点
    • 适用于有序、静态查找,频繁插入和删除的数据集不适用
// list是升序列表
public boolean binarySearch(List<Integer> list, int target){
	int low = 0, high = list.size() - 1, mid;
	while(low <= high){
		mid = (low + high) / 2;
		if(target == list.get(mid)){
			return true;
		} else if(list.get(mid) < target){
			left = mid + 1;
		} else {
			right = mid - 1;
		}
	}
	return false;
}
3. 插值查找
  • 思路
    • 一种有序查找算法,是对二分查找算法的改进,根据关键字在有序表中所处的位置进行查找,而不是直接一般的位置
    • 二分查找:mid = low + 1/2(high - low)
    • 插值查找:mid = low + (key - a[low])/(a[high] - a[low])*(high - low)
  • 时间复杂度
    • O(log2n)
  • 特点
    • 对于表长较大,关键字分布均匀的查找表,插值查找的平均性能比二分查找好得多;反之则未必
// list是升序列表
public boolean interplotSearch(List<Integer> list, int target){
	if(list.isEmpty()){
		return false;
	}
	int low = 0, high = list.size() - 1, mid;
	while(low <= high){
		mid = low + (target - list.get(low)) / (list.get(high)- list.get(low)) * (high - low);
		if(target == list.get(mid)){
			return true;
		} else if(list.get(mid) < target){
			low = mid + 1;
		} else {
			high = mid - 1;
		}
	}
	return false;
}
4. 斐波那契查找
  • 思路:
    • 一种有序查找算法,也是对二分查找的改进,按照黄金分割比例进行查找
    • 声明斐波那契数列为F(n)
      • 数列为:1,1,2,3,5,8,13,21,34…,随着数列递增,前后两个数的比值越接近0.618
      • 数列满足:F(n) = F(n-1) + F(n-2)
    • 要求查找序列的元素个数为某个斐波那契数 - 1,即n = F(k) - 1
    • 将给定值与F(k-1)位置的记录进行比较,mid = low + F(k-1) - 1
      • 相等即查找成功
      • 给定值大于mid位置的值,low = mid + 1,k = k - 2
      • 给定值小于mid位置的值,high = mid - 1, k = k - 1
        斐波那契查找
  • 时间复杂度
    • O(log2n)
// list是升序列表
public boolean fibonaccSearch(List<Integer> list, int target){
    if(list.isEmpty()){
        return false;
    }
    // 根据list的长度确定斐波那契数组
    int oldLen = list.size();
    List<Integer> fibs = getFibonacc(oldLen);
    // 根据fibs的最大值填充list
    int newLen = fibs.get(fibs.size() - 1) - 1;
    List<Integer> newList = new ArrayList<>(newLen);
    newList.addAll(list);
    for(int i = oldLen; i < newLen; i++){
        // 补充的元素值为list的最后一个元素的值
        newList.add(list.get(oldLen - 1));
    }
    // 开始查找
    int index = fibs.size() - 1, low = 0, high = newLen - 1, mid;
    while(low <= high){
        mid = low + fibs.get(index - 1) - 1;
        // 防止越界
        if(mid >= newLen){
            mid = newLen - 1;
        }
        if(target == newList.get(mid)){
            return true;
        } else if(newList.get(mid) < target){
            low = mid + 1;
            index -= 2;
        } else {
            high = mid - 1;
            index--;
        }
    }
    return false;
}

public List<Integer> getFibonacc(int len){
    List<Integer> fibs = new ArrayList<>();
    int tmp = 1, index = 0;
    while(len > tmp - 1){
        if(index == 0){
            tmp = 1;
        } else if(index == 1){
            tmp = 1;
        } else {
            tmp = fibs.get(index - 1) + fibs.get(index - 2);
        }
        fibs.add(tmp);
        index++;
    }
    return fibs;
}

public static void main(String[] args) {
    Search search = new Search();
    List<Integer> fibonacc = search.getFibonacc(0);
    search.fibonaccSearch(Arrays.asList(1), 1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值