算法学习之三分查找

三分查找(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;
    }

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