LeetCode & 劍指offer 經典題目總結——查找

1.搜索旋轉排序數組

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。

( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。

搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。

你可以假設數組中不存在重複的元素。

你的算法時間複雜度必須是 O(log n) 級別。

示例 1:

輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4

示例 2:

輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1

解法:

  1. 找到旋轉的下標 rotation_index ,也就是數組中最小的元素。二分查找在這裏可以派上用場。
  2. 在選中的數組區域中再次使用二分查找。
    public int search(int[] nums, int target) {
        if(nums.length == 0) return -1;
        if(nums.length == 1){
            return nums[0] == target ? 0:-1;
        }

       int rotate_index = find_rotate_index(nums,0,nums.length-1);

        if(nums[rotate_index] == target){
            return rotate_index;
        }
        if(rotate_index == 0){
            return binarySearch(nums,0,nums.length-1,target);
        }
        if(nums[0] > target){
            return binarySearch(nums,rotate_index,nums.length-1,target);
        }
        return binarySearch(nums,0,rotate_index-1,target);
    }

    public int find_rotate_index(int[] nums,int lo, int hi) {
        //沒有旋轉
        if(nums[lo] < nums[hi]){
            return 0;
        }
        while(lo <= hi){
            int mid=(lo+hi)/2;
            if(nums[mid+1] < nums[mid]){
                return mid+1;
            }else{
                if(nums[mid] < nums[lo]){
                    hi = mid-1;
                }else{
                    lo = mid+1;
                }
            }
        }
        return 0;
    }

    //二分查找
    public int binarySearch(int[] nums,int lo, int hi,int target) {
        while(lo <= hi){
            int mid=(lo+hi)/2;
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] > target){
                hi = mid-1;
            }else {
                lo = mid+1;
            }
        }
        return -1;
    }

2.搜索旋轉排序數組 II

上題的延伸題,本題中的 nums 可能包含重複元素。

示例 1:

輸入: nums = [2,5,6,0,0,1,2], target = 0
輸出: true

示例 2:

輸入: nums = [2,5,6,0,0,1,2], target = 3
輸出: false

解法:
與上題的區別是在尋找旋轉下標時,如果是在重複元素處旋轉的,那麼只能遍歷尋找。

class Solution {
    public boolean search(int[] nums, int target) {
        if(nums.length == 0) return false;
        if(nums.length == 1){
            return nums[0] == target ? true:false;
        }

       int rotate_index = find_rotate_index(nums,0,nums.length-1);

        if(nums[rotate_index] == target){
            return true;
        }
        if(rotate_index == 0){
            return binarySearch(nums,0,nums.length-1,target);
        }
        if(nums[0] > target){
            return binarySearch(nums,rotate_index,nums.length-1,target);
        }
        return binarySearch(nums,0,rotate_index-1,target);
    }

    public int find_rotate_index(int[] nums,int lo, int hi) {
        //沒有旋轉
        if(nums[lo] < nums[hi]){
            return 0;
        }
        while(lo <= hi){
            int mid=(lo+hi)/2;
            //在重複元素處旋轉的情況下,遍歷處理
            if(nums[mid] == nums[lo] && nums[mid] == nums[hi]){
                for(int i = 1;i < nums.length;i++){
                    if(nums[i] < nums[i-1]){
                        return i;
                    }
                }
                return 0;
            }
            if(nums[mid+1] < nums[mid]){
                return mid+1;
            }else{
                if(nums[mid] < nums[lo]){
                    hi = mid-1;
                }else{
                    lo = mid+1;
                }
            }
        }
        return 0;
    }

    //二分查找
    public boolean binarySearch(int[] nums,int lo, int hi,int target) {
        while(lo <= hi){
            int mid=(lo+hi)/2;
            if(nums[mid] == target){
                return true;
            }else if(nums[mid] > target){
                hi = mid-1;
            }else {
                lo = mid+1;
            }
        }
        return false;
    }

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