算法binary search系列2

  1. Search in Rotated Sorted Array II
    rotated数组里出现重复的情况。比起没有重复的数组,这里需要比较nums[low]与nums[mid],如果两者相同则需要low++,向右移动。同理nums[high],比较后如果相同则high–,向左移动。直到两个数不相同,然后情况就跟 Search in Rotated Sorted Array l是一样的了。
class Solution {
    public boolean search(int[] nums, int target) {
        if(nums == null || nums.length == 0) {
            return false;
        }
        int low = 0;
        int high = nums.length - 1;
        int mid;
        while(low <= high) {
            mid = low + (high - low) / 2;
            if(nums[mid] == target) {
                return true;
            }
            if(nums[mid] < nums[high]) {
                if(nums[mid] < target && nums[high] >= target) {
                    low = mid + 1;
                } else {
                    high = mid - 1;//it's either target smaller than both or larger than both. either case target is on the left part of mid.
                }
            } else if (nums[mid] > nums[low]) {
                if(nums[mid] > target && nums[low] <= target) {
                    high = mid - 1;
                } else {
                    low = mid + 1; //either larger than both nums[low] and nums[mid], or smaller than both, target is on the right side of mid.
                }
            } else if (nums[mid] == nums[high]) {
                high--;
            } else if (nums[mid] == nums[low]) {
                low++;
            }
        }
        return false;
    }
}

153 Find Minimum in Rotated Sorted Array
跟基本的二分法一样,但是要注意出循环的条件是left<right,不是left<=right,因为当nums[mid] < nums[right],我们不能确定mid是否已经是最小当数了,所以不能将right设为mid+1。这样子如果出循环条件是left<=right,则会出现left = mid = right而永远出不了循环。

class Solution {
    public int findMin(int[] nums) {
         if(nums == null || nums.length == 0) {
             return -1;   
        int left = 0;
        int right = nums.length - 1;
        int mid;
        
        while(left < right) {
            mid = left + (right - left) / 2;
            
            if(nums[mid] > nums[right]) {
                left = mid + 1;
            } else if(nums[mid] < nums[right]) {
                right = mid;
            } 
        }
        return nums[left];
    }
}
  1. Find Minimum in Rotated Sorted Array II
    跟上一题几乎一样,只是出现了重复的情况,(参考Search in Rotated Sorted Array II)在这里出loop的条件可以为left<=right,因为当出现left = mid = right的情况的时候,right会减一,所以不会出现死循环。
class Solution {
    public int findMin(int[] nums) {
                //base case
         if(nums == null || nums.length == 0) {
             return -1;
         }
      
        
        int left = 0;
        int right = nums.length - 1;
        int mid;
        
        while(left < right) {//也可以是left<=right
            mid = left + (right - left) / 2;
            
            if(nums[mid] > nums[right]) {
                left = mid + 1;
            } else if(nums[mid] < nums[right]) {
                right = mid;
            } else {
                right--;
            }
        }
        return nums[left];
    }
}
  1. Find Peak Element
class Solution {
    public int findPeakElement(int[] nums) {
        if(nums == null || nums.length == 0) {
            return -1;
        }
        if(nums.length == 1) {
            return 0;
        }
        int left = 0;
        int right = nums.length - 1;
        int mid;
        //be careful of index out of bound
        while(left <= right) {
            mid = left + (right - left) / 2;
            if((mid == 0 && nums[mid] > nums[mid + 1]) || (mid == nums.length - 1 && nums[mid] > nums[mid - 1])) {
                return mid;
            }
            if(mid > 0 && mid < nums.length - 1 && nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]) {
                return mid;
            }
            if(nums[mid] < nums[mid + 1]) {
                left = mid + 1;
            } else if(nums[mid] > nums[mid + 1]) {
                right = mid - 1;
            }
        }
        return -1;
    }
}
  1. Search a 2D Matrix II
    key idea是从右上角出发,如果该元素大于target向左走,小于该元素向下走。同时while loop里保证不要出界(row < matrix.length, col >=0)
class Solution {
    
    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }
        int r = 0;
        int c = matrix[0].length - 1;
        while(r < matrix.length && c >= 0) {
            if(matrix[r][c] == target) {
                return true;
            } else if(matrix[r][c] < target) {
                r++;
            } else {
                c--;
            }
        }
        return false;
    }
}
  1. H-Index II
    key idea跟找first position of element一样,即使发现了符合条件的元素,也只是right = mid,尽量往左边搜索。返回的条件也是一样,left,right相邻就可以了,然后看左边是否符合条件,符合就返回左边,否则返回右边。
class Solution {
    public int hIndex(int[] citations) {
        //we are look for element that  than its N - index 
        //left-most
        if(citations == null || citations.length == 0) {
            return 0;
        }
        
        int N = citations.length;
        
        if(citations[N -1] == 0) {//mark
            return 0;
        }
        
        int left = 0;
        int right = N - 1;
        int mid;
        while(left < right - 1) {//mark
            mid = left + (right - left) / 2;
            if(citations[mid] >= N - mid) {
                right = mid;
            } else {
                left = mid;
            }
        }
        if(citations[left] >= N - left) {
            return N - left;
        } else {
            return N - right;
        }
    }
}
  1. Find the Duplicate Number
    read only array。
    time complexity o(nlog(n))
    将array分成三段[low,mid),[mid,mid],(mid,high],每次都数一次每段里数字都个数,如果该段出现都数字大于两个index之差就证明重复的数出现在该段,将left/right相应的移动。
class Solution {
    //time complexitynlog(n)
    public int findDuplicate(int[] nums) {
        int low = 1;
        int high = nums.length;
        int mid;
        int lowCount;
        int midCount;
        int highCount;
        while(low < high) {//low <= high is also ok
            mid = low + (high - low) / 2;
            lowCount = 0;
            midCount = 0;
            highCount = 0;
            //linear scan, count # of nums in each range
            for(int i = 0; i < nums.length; i++) {
                if(nums[i] == mid) {
                    midCount++;
                } else if (nums[i] < mid && nums[i] >= low) {
                    lowCount++;
                } else if (nums[i] > mid && nums[i] < high) {
                    highCount++;
                }
            }
            //narrow range
            if(midCount > 1) {
                return mid;
            } else if (lowCount > mid - low) {
                high = mid - 1;//mark
            } else {
                low = mid + 1;
            }
        }
        return low;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值