【LeetCode】查找数组系列

33. Search in Rotated Sorted Array

题目:在一个被旋转一次的递增数组中找到目标值。

思路:二分法——思路一定要清晰!!!当mid和目标值不等时,判断mid和start的大小,大于说明旋转位置在后面,反之在前面。在后面的时候start-mid是递增的,可以直接判断目标值在不在其中。同理,在前面的时候mid-end是递增的,可以直接判断目标值在不在其中。

public class Solution {
    public int search(int[] nums, int target) {
        int ret = 0, rot = 0;
        if(nums.length < 1) return -1;
        int start = 0, end = nums.length-1;
        while(start <= end){
            int mid = (start+end)/2;
            if(nums[mid] == target) return mid;
            else if(nums[mid] >= nums[start]){
                if(nums[mid] > target && target >= nums[start]){
                    end = mid - 1;
                }
                else{
                    start = mid + 1;
                }
            }
            else{
                if(nums[mid] < target && target <= nums[end]){
                    start = mid + 1; 
                }
                else{
                    end = mid - 1;
                }
            }
        }
        return -1;
    }
}


81. Search in Rotated Sorted Array II

题目:有重复怎么办?

思路:在33题基础上,判断start等于mid时,只能start++遍历移动,因为此时无法判断旋转点在前半段还是后半段。

public class Solution {
    public boolean search(int[] nums, int target) {
        int ret = 0;
        if(nums.length < 1) return false;
        int start = 0, end = nums.length-1;
        while(start <= end){
            int mid = (start+end)/2;
            if(nums[mid] == target) return true;
            else if(nums[mid] > nums[start]){
                if(nums[mid] > target && target >= nums[start]){
                    end = mid - 1;
                }
                else{
                    start = mid + 1;
                }
            }
            else if(nums[mid] < nums[start]){
                if(nums[mid] < target && target <= nums[end]){
                    start = mid + 1; 
                }
                else{
                    end = mid - 1;
                }
            }
            else{
                start++;
            }
        }
        return false;
    }
}


153. Find Minimum in Rotated Sorted Array

题目:在一个旋转数组中找到最小值。

思路:二分法——利用二分法将start和end卡在正好反转的两端,由此只需判断mid与其前后数的关系就可以找到正好旋转的那一点,即找到最小值。

public class Solution {
    public int findMin(int[] nums) {
        if(nums.length < 2) return nums[0];
        int start = 0, end = nums.length-1;
        while(start <= end){
            int mid = (start+end)/2;
            if(mid > 0 && nums[mid] <= nums[mid-1]) return nums[mid];
            if(mid < nums.length-1 && nums[mid] >= nums[mid+1]) return nums[mid+1];
            else if(nums[mid] >= nums[start]){
                start = mid+1;
            }
            else{
                end = mid-1;
            }
        }
        return nums[0];
    }
}

34. Search for a Range

题目:在数组中找到目标值的范围,没有的话用【-1,-1】表示。

思路:二分法——基本的思想是先用二分找到目标值,在分别在【start,mid】以及【mid,start】两个区间内继续利用二分找到上范围和下范围。

public class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] ret = new int[]{-1, -1};
        if(nums.length < 1) return ret;
        int start = 0, end = nums.length-1;
        while(start <= end){
            int mid = (start+end)/2;
            if(nums[mid] == target){
                int mid_cp = mid;
                if(nums[start] == target) ret[0] = start;
                else{
                    while(nums[start] <= nums[mid]){
                        int mid_s = (start+mid)/2;
                        if(nums[mid_s] == target){
                            mid = mid_s-1;
                        }
                        else{
                            start = mid_s+1;
                        }
                    }
                    //ret[0] = nums[start]==target?start:start+1;
                    ret[0] = start;
                }
                mid = mid_cp;
                if(nums[end] == target) ret[1] = end;
                else{
                    while(nums[end] >= nums[mid]){
                        int mid_e = (end+mid)/2;
                        if(nums[mid_e] == target){
                            mid = mid_e+1;
                        }
                        else{
                            end = mid_e-1;
                        }
                    }
                    //ret[1] = nums[end]==target?end:end-1;
                    ret[1] = end;
                }
                return ret;
            }
            else if(nums[mid] > target){
                end = mid-1;
            }
            else{
                start = mid+1;
            }
        }
        return ret;
    }
}


278. First Bad Version

题目:在1到n中找到第一个坏版本。

思路:二分——很简单,但是要注意用start+(end-start)/2,不要用(start+end)/2,不然就TLE。

/* The isBadVersion API is defined in the parent class VersionControl.
      boolean isBadVersion(int version); */

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int start = 1, end = n;
        while(start <= end){
            int mid = start + (end-start)/2;
            if(isBadVersion(mid)){
                end = mid - 1;
            }
            else{
                start = mid + 1;
            }
        }
        return start;
    }
}


374. Guess Number Higher or Lower

题目:猜数字

思路:二分——很简单

/* The guess API is defined in the parent class GuessGame.
   @param num, your guess
   @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
      int guess(int num); */

public class Solution extends GuessGame {
    public int guessNumber(int n) {
        int start = 1, end = n;
        while(start <= end){
            int mid = start + (end-start)/2;
            if(guess(mid) == 0) return mid;
            else if(guess(mid) == 1){
                start = mid+1;
            }
            else{
                end = mid-1;
            }
        }
        return start;
    }
}


35. Search Insert Position

题目:找到目标值或者应该插入的位置

思路:二分法——很简单

public class Solution {
    public int searchInsert(int[] nums, int target) {
        int start = 0, end = nums.length-1;
        while(start <= end){
            int mid = start + (end-start)/2;
            if(nums[mid] == target) return mid;
            else if(nums[mid] > target){
                end = mid - 1;  
            }
            else{
                start = mid + 1;
            }
        }
        return start;
    }
}

41. First Missing Positive

题目:找到数组中第一个不见的正整数

思路:分三步:第一步将负数标记为0,第二步将每位非零数对应的位置上标记为负数,0则标记为该位正整数的负数。第三步统计第一个非负数的位置,返回。

public class Solution {
    public int firstMissingPositive(int[] nums) {
        for(int i = 0; i < nums.length; i++){
            if(nums[i] < 0) nums[i] = 0;
        }
        for(int i = 0; i < nums.length; i++){
            int x = Math.abs(nums[i]);
            if(x <= nums.length && x > 0){
                if(nums[x-1] == 0){
                    nums[x-1] = ~x+1;
                }
                else if(nums[x-1] > 0){
                    nums[x-1] = ~nums[x-1]+1;
                }
            }
        }
        for(int i = 0; i < nums.length; i++){
            if(nums[i] >= 0) return i+1;
        }
        return nums.length+1;
    }
}

其他的解法有将数通过交换放在对应位置上,最后统计如果存在不对应的就返回。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值