数据结构和算法 十六、指数查找/跳转搜索/鞍背搜索

这篇博客介绍了三种在排序数组中提高搜索效率的算法:指数查找、跳转搜索和鞍背搜索。指数查找通过逐步扩大搜索范围并结合二分搜索来定位目标元素;跳转搜索通过固定步长跳跃,减少不必要的元素比较;鞍背搜索则适用于二维有序数组,通过排除法快速定位目标。这些算法都旨在减少线性搜索的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、指数查找(Exponential Search)

        指数搜索同样需要数组是已经排序。指数搜索包括以下两个步骤:

        1、查找元素存在的范围

        2、在第1步找到的范围内进行二分搜索。

        如何找到元素可能存在的范围? 

        先找到合适的i,依次使用i=1,i=2,i=4,i=8,i=16,i=32,i=64,i=128......,直到使得有 array[i / 2] < x < array[i],x为要搜索的数。

        然后,从i / 2 到 i 之间进行二分查找。

    @Override
    public <T extends Comparable<T>> int find(T[] array, T key) {
        if (array[0] == key) {
            return 0;
        }
        if (array[array.length - 1] == key) {
            return array.length;
        }

        int range = 1;

        while (range < array.length && array[range].compareTo(key) <= -1) {
            range = range * 2;
        }

        return Arrays.binarySearch(array, range / 2, Math.min(range, array.length), key);
    }

二、跳转搜索(Jump Search)

        与二分一样,Jump Search 是一种用于排序数组的搜索算法。基本思想是通过固定步骤向前跳转或跳过某些元素代替搜索所有元素来检查比线性搜索更少的元素。

@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
    int length = array.length;
    /* length of array */
    int blockSize = (int) Math.sqrt(length);
    /* block size to be jumped */

    int limit = blockSize;
    while (key.compareTo(array[limit]) > 0 && limit < array.length - 1) {
        limit = Math.min(limit + blockSize, array.length - 1);
    }

    for (int i = limit - blockSize; i <= limit; i++) {
        if (array[i] == key) {
            /* execute linear search */
                return i;
        }
    }
    return -1;

}

三、鞍背搜索(Saddleback Search)

        用于二维有序数组。从上到下递增,从左到右递增。从左下角第一个元素(当前列值最大,当前行值最小)对比。如果目标值大于当前值,那么这一列的值都可以排除;如果目标值小于当前值,那么这一行的值都可以排除。排除像马鞍式一样。

        时间的复杂度就是O(row + col),就是行数+列数。

//定义二维数组
arr[] = {{ 1, 2, 3},
         { 4, 5, 6},
         { 7, 8, 9}
        }
//需要查找的元素=5
//输出元素的位置坐标 (1, 1).

        参考代码

import java.util.Scanner;

public class SaddlebackSearch {

    private static int[] find(int arr[][], int row, int col, int key) {

        int ans[] = {-1, -1};
        if (row < 0 || col >= arr[row].length) {
            return ans;
        }
        if (arr[row][col] == key) {
            ans[0] = row;
            ans[1] = col;
            return ans;
        } 
        else if (arr[row][col] > key) {
            return find(arr, row - 1, col, key);
        }
        
        return find(arr, row, col + 1, key);
    }

    /**
     * Main method
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        int arr[][];
        int i, j, rows = sc.nextInt(), col = sc.nextInt();
        arr = new int[rows][col];
        for (i = 0; i < rows; i++) {
            for (j = 0; j < col; j++) {
                arr[i][j] = sc.nextInt();
            }
        }
        int ele = sc.nextInt();
        // we start from bottom left corner
        int ans[] = find(arr, rows - 1, 0, ele);
        System.out.println(ans[0] + " " + ans[1]);
        sc.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

坐望云起

如果觉得有用,请不吝打赏

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

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

打赏作者

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

抵扣说明:

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

余额充值