Jump Search Algorithm - 跳躍搜尋法

Posted by Alan Zhan on Sunday, July 11, 2021

延續猜數字遊戲,1 ~ 100 我們是不是可以換個猜法呢?

如果我們從一開始,只要每次沒猜中,我們就往後面 +10 繼續猜,直到最大值範圍值變成我們所猜的數值後,往回開始找值,這樣做,在數值較小的時候,將會更有效率。

概念

跳躍搜尋 (Jump Search): 這個演算法很像二元搜尋法,被搜尋的清單也是需要事先,先被排序過的,但是在每次查找的過程,如果找不到值,就用一個基值快速地跳到下一個區段查找,直到最大值被變小,再往回開始找值,如果有找到就會回傳元素索引值,否則就會回傳 -1。

上面的敘述可能會有點複雜,以數猜數字為例,假設現在要查找的數值是 30:

  • Step 1: index = 1 ,目標數值並不等於 1 ,先將索引 +10。
  • Step 2: index = 11,目標數值並不等於 11,再將索引 +10。
  • Step 3: index = 21,目標數值並不等於 21,再將索引 +10。
  • Step 4: index = 31,目標數值並不等於 31,但是發現要找數值比 31 還小,所以要開始往回找,將索引 -1。
  • Step 5: index = 30,發現目標索引為 30,回傳索引值。

複雜度

  • 時間複雜度: O(√n)
  • 空間複雜度: O(1)

範例

Go

package main

import (
    "fmt"
    "math"
)

func jumpSearch(list []int, target int) int {
    blockSize := int(math.Sqrt(float64(len(list))))

    i := 0
    for {
        if i > len(list) {
            return -1
        }

        if list[i] >= target {
            break
        }

        i += blockSize
    }

    for j := i; j > 0; j-- {
        if list[j] == target {
            return j
        }
    }

    return -1
}

func main() {
    fmt.Println(jumpSearch([]int{1, 2, 3, 4, 5}, 3)) // 2
    fmt.Println(jumpSearch([]int{1, 2, 3, 4, 5}, 6)) // -1
}

C#

class Algorithm
{
    public static int jumpSearch(int[] list, int target)
    {
        var blockSize = (int)Math.Sqrt(list.Length);

        var i = 0;
        while (true)
        {
            if (i > list.Length)
            {
                return -1;
            }

            if (list[i] >= target)
            {
                break;
            }

            i += blockSize;
        }

        for (var j = i; j > 0; j--) 
        {
            if (list[j] == target)
            {
                return j;
            }
        }

        return -1;
    }

    public static void Main(String[] args)
    {
        Console.WriteLine(jumpSearch(new int[] {1, 2, 3, 4, 5}, 3)); // 2
        Console.WriteLine(jumpSearch(new int[] {1, 2, 3, 4, 5}, 6)); // -1
    }
}

歡迎到我的 Facebook Alan 的筆記本 留言,順手給我個讚吧!你的讚將成為我持續更新的動力,感謝你的閱讀,讓我們一起學習成為更好的自己。