算法學習之三分查找

三分查找(Ternary Search),查找一次就可以排除整個有序線性表的2/3,查找效率更高。最差時間複雜度O(log3 n),最優時間複雜度

O(1),空間複雜度O(1)。

Java代碼示例:

/**
     * 使用遞歸的方法
     * 三分數組搜索
     * @param arr 數組
     * @param key 目標數值
     * @param s 數組下標開始位置
     * @param e 數組下標結束位置
     * @return 目標下標位
     */
    public int ternaryFind(int[] arr, int key, int s, int e){
        if (s < e){
            return -1;
        }
        // 第一個範圍點數組長度的1/3
        int midPos1 = s + (e - s)/3;
        // 第二個範圍點數組長度的2/3
        int midPos2 = s + 2*(e - s)/3;

        if (key == arr[midPos1]){
            return midPos1;
        }else if (key == arr[midPos2]){
            return midPos2;
        }else if (key < arr[midPos1]){
            return ternaryFind(arr, key, s, midPos1-1);
        }else if (key > arr[midPos2]){
            return ternaryFind(arr, key, midPos2 + 1, e);
        }else {
            return ternaryFind(arr, key, midPos1 + 1, midPos2 - 1);
        }
    }

    public<T extends Comparable<T>> int ternaryFind(T[] arr, T key, int s, int e){
        if (s > e){
            return -1;
        }
        int midPos1 = s + (e - s)/3;
        int midPos2 = s + 2*(e - s)/3;
        int cmpResult1 = key.compareTo(arr[midPos1]);
        int cmpResult2 = key.compareTo(arr[midPos2]);

        if (cmpResult1 == 0){
            return midPos1;
        }else if (cmpResult2 == 0){
            return midPos2;
        }else if (cmpResult1 < 0){
            return ternaryFind(arr, key, s, midPos1 - 1);
        }else if (cmpResult2 > 0){
            return ternaryFind(arr, key, midPos2 + 1, e);
        }else {
            return ternaryFind(arr, key, midPos1 + 1, midPos2 - 1);
        }
    }

    /**
     * 三分搜索法
     * 迭代循環
     * @param arr 數組
     * @param key 目標對象
     * @param s 數組下標開始位
     * @param e 數組下標結束位
     * @param <T> 泛型
     * @return 目標下標位置
     */
    public<T extends Comparable<T>> int ternaryFindCycle(T[] arr, T key, int s, int e){

        /**
         * 1、一次循環排除2/3
         * 推薦
         */
        while (s >=0 && e >= s){
            int midPos1 = s + (e - s)/3;
            int midPos2 = s + 2*(e - s)/3;
            int cmpResult1 = key.compareTo(arr[midPos1]);
            int cmpResult2 = key.compareTo(arr[midPos2]);

            if (cmpResult1 == 0){
                return midPos1;
            }else if (cmpResult2 == 0){
                return midPos2;
            }else if (cmpResult1 < 0){
                e = midPos1 - 1;
            }else if (cmpResult2 > 0){
                s = midPos2 + 1;
            }else {
                s = midPos1 + 1;
                e = midPos2 - 1;
            }
        }

        /**
         * 2、一次循環排除1/3或者2/3
         * 不推薦
         */
        while (s >=0 && e >= s){
            int midPos1 = s + (e - s)/3;
            int cmpResult1 = key.compareTo(arr[midPos1]);
            if (cmpResult1 == 0){
                return midPos1;
            }else if (cmpResult1 < 0){
                e = midPos1 - 1;
            }else {
                s = midPos1 + 1;
            }
        }
        return -1;
    }

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章