1. 程式人生 > >LeetCode-33 search-in-rotated-sorted-array 搜尋旋轉排序陣列

LeetCode-33 search-in-rotated-sorted-array 搜尋旋轉排序陣列

題目連結

https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

題意

        對於一個升序排序的陣列,從某個位置截斷,然後直接拼在後面。看題目給的例子,還是比較直白的。

題解

        其實題本身不難,做了一些中等難度的題,其實大部分都沒啥難度,簡單題反而有一些比較騷的。中等題很多都坑在略考驗碼速,有一個大數乘法、螺旋陣列的模擬等等,這個題也一樣,擼一堆程式碼,出一點錯就很蛋疼。

        看評論有人吐槽直接遍歷也能搜出來答案= =因為要求時間複雜度是O(logn),並且是已經升序排序的陣列了,只是中間截斷了而已。那麼反過來,如果從截斷點開始分成兩個陣列,那麼對於單個數組就可以使用二分搜尋了,而二分搜尋恰是O(logn)的時間複雜度。

        問題就是如何找到截斷點。很明顯,如果沒有截斷點的話,直接升序,對於i而言:arr[i-1] < arr[i] < arr[i+1]這個等式是恆成立的,題也說了不存在重複。如果存在i:arr[i - 1] > arr[i] || arr[i] > arr[i+1],那麼i就是截斷點,並且屬於後半陣列。所以,找到截斷點就是比較重要了。for迴圈遍歷就有點蛋疼了,仍然使用二分,可以先找截斷點。找到以後就將陣列分成左右兩部分,分別使用二分搜尋即可。

        這個題情況非常多,所以剪枝能寫很多。例如分開二分搜尋的時候,如果第一個陣列就搜到答案了,那麼第二組就可以不搜尋了。如果在搜截斷點的時候就找到答案,那麼就可以直接結束了。等等。

        另外我的程式碼是忽略了陣列元素小於3的資料,這些單獨拿出來計算了。主要是交的時候發現WA了,所以就拿出來單獨算。可能是搜截斷點的時候,陣列元素是2的時候各種越界吧,懶得寫了,所以就直接判斷了特殊情況= =。

Java 程式碼

class Solution {
    public static int flag;
    public static int len;
    public static int ans;

    public static void search(int left,int right,int[] nums){
        if(left == right) return;
        int mid = (left+right)/2;
        if(mid == 0){
            if(nums[mid] > nums[mid+1]){
                flag = mid;
                return;
            }
        }else{
            if(mid == len-1){
                if(nums[mid] < nums[mid-1]){
                    flag = mid;
                    return;
                }
            }else{
                if(nums[mid] > nums[mid+1] || nums[mid] < nums[mid-1]){
                    flag = mid;
                    return;
                }
            }
        }
        search(left,mid,nums);
        if(flag != -1) return;
        search(mid+1,right,nums);
    }

    public static void brain(int left,int right,int[] nums,int target){
        if(left == right){
            if(target == nums[left]){
                ans = left;
            }
            return;
        }
        int mid = (left+right)/2;
        if(target == nums[mid]){
            ans = mid;
            return;
        }
        if(target > nums[mid]){
            brain(mid+1,right,nums,target);
        }else{
            brain(left,mid,nums,target);
        }
    }

    public int search(int[] nums, int target) {
        flag = -1;
        ans = -1;
        len = nums.length;
        if(len == 0) return -1;
        if(len == 1){
            if(target == nums[0]) return 0;
            return -1;
        }
        if(len == 2){
            for(int i = 0;i < 2;i++){
                if(target == nums[i]) return i;
            }
            return -1;
        }
        search(0,len-1,nums);
        if(flag == -1){
            brain(0,len-1,nums,target);
            return ans;
        }
        if(nums[flag] == target) return flag;
        brain(0,flag,nums,target);
        if(ans != -1) return ans;
        brain(flag+1,len-1,nums,target);
        return ans;
    }
}