搜索旋轉的排序數組

原題

  Follow up for 「Search in Rotated Sorted Array」:
  What if duplicates are allowed?
  Would this affect the run-time complexity? How and why?
  Write a function to determine if a given target is in the array.算法

題目大意

  「在旋轉數組中搜索值」的後續,若是數組中的值容許重複寫一個程序肯定一個給定的值是否在數組中。數組

解題思路

  先找最小的數所在的下標,再根據所要找的數字在哪個部分進行查找。this

代碼實現

算法實現類spa

public class Solution {

    public boolean search(int[] nums, int target) {
        if (nums != null && nums.length > 0) {
            // 找最小元素對應的下標
            int minIndex = findMinIndex(nums);

            // 整個數組全局有序
            if (minIndex == 0) {
                return binarySearch(nums, 0, nums.length - 1, target);
            }
            // 有兩個局部有序區間,  如 4 5 6 7 8 9 0 1 2 3
            else {
                // 恬好和後一個有序區間的最後一個元素相等,返回對應的下標
                if (nums[nums.length - 1] == target) {
                    return true;
                }
                // target可能在後一個有序區間中
                else if (nums[nums.length - 1] > target) {
                    return binarySearch(nums, minIndex, nums.length - 1, target);
                }
                // target多是前一個有序區間中
                else {
                    return binarySearch(nums, 0, minIndex - 1, target);
                }
            }
        }

        return false;
    }

    /**
     * 二分搜索
     *
     * @param nums   數組
     * @param start  起始位置
     * @param end    結束位置
     * @param target 搜索目標
     * @return true找到,false沒有找到
     */
    public boolean binarySearch(int[] nums, int start, int end, int target) {

        int mid;
        while (start <= end) {
            mid = start + ((end - start) >> 1);

            if (nums[mid] == target) {
                return true;
            } else if (nums[mid] > target) {
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        }

        return false;
    }


    public int findMinIndex(int[] nums) {
        // 參數校驗
        if (nums == null || nums.length < 1) {
            throw new IllegalArgumentException();
        }

        int lo = 0;
        int hi = nums.length - 1;
        int mid = 0;

        // 能夠排除數組全局有序的狀況
        while (nums[lo] >= nums[hi]) {
            // 若是隻有兩個元素,返回後一個
            if (hi - lo == 1) {
                mid = hi;
                break;
            }

            mid = lo + ((hi - lo) >> 1);

            if (nums[mid] == nums[lo] && nums[mid] == nums[hi]) {
                // 只能採用順序搜索方法,不能採用lo++,hi--的方式
                // 由於lo多是前一個有序數組的最後一個
                // hi也多是後一個有序數組的第一個
                return sequenceSearchMinIndex(nums, lo, hi);
            }

            // 若是mid在前一個有序數組中
            if (nums[mid] >= nums[lo]) {
                lo = mid;
            }
            // 若是mid在後一個有序數組中
            else if (nums[mid] <= nums[hi]) {
                hi = mid;
            }
        }

        return mid;
    }

    /**
     * 順序搜索數組中的最小值的下標,nums是由有序數組按某個軸旋轉得來的
     *
     * @param nums  搜索數組
     * @param start 開始位置
     * @param end   結束位置
     * @return 最小值的下標
     */
    public int sequenceSearchMinIndex(int[] nums, int start, int end) {
        for (int i = start; i < end; i++) {
            if (nums[i] > nums[i + 1]) {
                return i + 1;
            }
        }
        return start;
    }
}
相關文章
相關標籤/搜索