和你一起刷算法-LeetCode刷题之二分查找训练营(九)

第一题快速导航:154. 寻找旋转排序数组中的最小值 II

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

请找出其中最小的元素。

注意数组中可能存在重复的元素。

示例 1:

输入: [1,3,5]
输出: 1

示例 2:

输入: [2,2,2,0,1]
输出: 0

说明:

  • 这道题是 寻找旋转排序数组中的最小值 的延伸题目。
  • 允许重复会影响算法的时间复杂度吗?会如何影响,为什么?

和你一起刷算法-LeetCode刷题之二分查找训练营(九)_第1张图片和你一起刷算法-LeetCode刷题之二分查找训练营(九)_第2张图片和你一起刷算法-LeetCode刷题之二分查找训练营(九)_第3张图片和你一起刷算法-LeetCode刷题之二分查找训练营(九)_第4张图片和你一起刷算法-LeetCode刷题之二分查找训练营(九)_第5张图片

class Solution {
    public int findMin(int[] nums) {
        /**
        每次进入无序的那部分找出最小值
        但是由于有重复值的情况, 需要加入 mid 元素等于 hi 元素的情况
        此时应该将 hi 减 1 防止重复数字是最小元素
        **/
        int lo = 0, hi = nums.length-1;
        while(lo < hi) {
            int mid = lo+(hi-lo)/2;
            if(nums[mid] > nums[hi])
                lo = mid+1;
            else if(nums[mid] < nums[hi])
                hi = mid;
            else
                hi--;
        }
        return nums[lo];
    }
}

和你一起刷算法-LeetCode刷题之二分查找训练营(九)_第6张图片

第二题快速导航:540. 有序数组中的单一元素

给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。

示例 1:

输入: [1,1,2,3,3,4,4,8,8]
输出: 2

示例 2:

输入: [3,3,7,7,10,11,11]
输出: 10

题解:本题解题的关键句是目标值出现一次  非目标值出现两次    也就是二分之后需要进行个数的奇偶判断,很明显,目标值存在奇数一侧。

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while(left < right){
            int mid = left + (right - left)/2;
            if(nums[mid] == nums[mid-1]){
                //中点和左边相等 判断中点左侧有几位数
                if((mid - left)%2 == 0){
                    //偶数位则单数的在左边[1,1,2,3,3,4,4,5,5]  mid = 4
                    right = mid - 2;
                }else{
                    left = mid + 1;
                }
            }else if(nums[mid] == nums[mid+1]){
                //中点和右边相等 判断个数
                if((right - mid)%2 == 0){
                    //偶数位则目标值的在左边[1,1,2,2,3,3,4,4,5,6,6]  mid = 5
                    left = mid + 2;
                }else{
                    right = mid -1;
                }
            }else{
                return nums[mid];
            }
        }
        //思考为啥是nums[right]  而不是   nums[left]呢?
        return nums[right]; 
    }
}

和你一起刷算法-LeetCode刷题之二分查找训练营(九)_第7张图片

进阶难度快速导航:4. 寻找两个正序数组的中位数

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。

进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

示例 3:

输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000

示例 4:

输入:nums1 = [], nums2 = [1]
输出:1.00000

示例 5:

输入:nums1 = [2], nums2 = []
输出:2.00000

题解:需要对两个数组同时进行二分搜索。看了下这个解法很精妙,自愧不如。

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/

 

 

 

 

你可能感兴趣的:(和你一起刷算法,算法,柿子,leetcode,算法,数据结构,二分查找,java)