zoukankan      html  css  js  c++  java
  • leetcode(二分)

    https://leetcode-cn.com/leetbook/read/binary-search/xexoac/

     这 3 个模板的不同之处在于:

        左、中、右索引的分配。
        循环或递归终止条件。
        后处理的必要性。

    模板 #1 和 #3 是最常用的,几乎所有二分查找问题都可以用其中之一轻松实现。模板 #2 更 高级一些,用于解决某些类型的问题。

    这 3 个模板中的每一个都提供了一个特定的用例:

    模板 #1 (left <= right)

        二分查找的最基础和最基本的形式。
        查找条件可以在不与元素的两侧进行比较的情况下确定(或使用它周围的特定元素)。
        不需要后处理,因为每一步中,你都在检查是否找到了元素。如果到达末尾,则知道未找到该元素。

    模板 #2 (left < right)

        一种实现二分查找的高级方法。
        查找条件需要访问元素的直接右邻居。
        使用元素的右邻居来确定是否满足条件,并决定是向左还是向右。
        保证查找空间在每一步中至少有 2 个元素。
        需要进行后处理。 当你剩下 1 个元素时,循环 / 递归结束。 需要评估剩余元素是否符合条件。

    模板 #3 (left + 1 < right)

        实现二分查找的另一种方法。
        搜索条件需要访问元素的直接左右邻居。
        使用元素的邻居来确定它是向右还是向左。
        保证查找空间在每个步骤中至少有 3 个元素。
        需要进行后处理。 当剩下 2 个元素时,循环 / 递归结束。 需要评估其余元素是否符合条件。

    时间:O(log n) —— 算法时间

    空间:O(1) —— 常量空间

    '''
    153寻找旋转排序数组中的最小值
    
    假设按照升序排序的数组在预先未知的某个点上进行了旋转。
    
    ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
    
    请找出其中最小的元素。
    
    你可以假设数组中不存在重复元素。
    
    示例 1:
    
    输入: [3,4,5,1,2]
    输出: 1
    示例 2:
    
    输入: [4,5,6,7,0,1,2]
    输出: 0
    
    '''
    #思路:获取第一个元素,因为数组前半部分是递增的,那么可以通过二分直到左节点到最大值
    class Solution(object):
        def find_rotate(self, nums):
            target = nums[0]
            lo = 1
            hi = len(nums)
            while lo < hi:
                mid = (lo + hi) // 2
                if nums[mid] > target:
                    lo = mid + 1
                else:
                    hi = mid
            return lo
        
        def findMin(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            
            rotate = self.find_rotate(nums)
            
            if rotate == len(nums):
                return nums[0]
            
            return nums[rotate]



    class Solution:
        def findMin(self, nums: List[int]) -> int:
            # 思路:对于这道题来说,nums升序排序的数组,那么可以利用其特性,第0个元素与最后的一个元素进行比较,是否进行了翻转,如果有,使用二分法的第三种方式,mid与第一个位置的元素进行比较.最后会剩下两个元素,然后进行后处理
            left=0
            right=len(nums)-1
            if nums[0]<nums[right]:
                return nums[0]
            while left+1<right:
                mid=(left+right)//2
                if nums[mid]>nums[left]:
                    left=mid
                else:
                    right=mid
            if nums[left]>nums[right]:
                return nums[right]
            else:
                return nums[left]
                
    两个数组的交集
    
    给定两个数组,编写一个函数来计算它们的交集。
    
     
    
    示例 1:
    
    输入:nums1 = [1,2,2,1], nums2 = [2,2]
    输出:[2]
    
    示例 2:
    
    输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    输出:[9,4]
    
     
    
    说明:
    
        输出结果中的每个元素一定是唯一的。
        我们可以不考虑输出结果的顺序。

    class Solution:
        def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
            return_=[]
            for i in  nums1:
                if i  in nums2 and i not in return_:
                    return_.append(i)
            return return_
    
    
    class Solution:
        def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
            # 二分法:查找元素是针对有序的,因而对一个数组进行排序,在将另一个数组一次遍历,在排序好的数组中进行查询
            # 并且该二分法,不需要与周围元素进行比较,因而使用第一种二分法
            nums2.sort()
            return_list=[]
            for target in nums1:
                if self.search_num(target,nums2) and target not in return_list:
                    return_list.append(target)
            return return_list
        def search_num(self,target,nums2):
            left=0
            right=len(nums2)-1
            while left<=right:
                mid=(left+right)//2
                print(mid)
                if nums2[mid]>target:
                    right=mid-1
                elif nums2[mid]<target:
                    left=mid+1
                else:
                    return True
            return False
     
    剑指 Offer 53 - II. 0~n-1中缺失的数字
    
    一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
    
     
    
    示例 1:
    
    输入: [0,1,3]
    输出: 2
    
    示例 2:
    
    输入: [0,1,2,3,4,5,6,7,9]
    输出: 8
    
     
    
    限制:
    
    1 <= 数组长度 <= 10000

    class Solution:
        def missingNumber(self, nums: List[int]) -> int:
            # 思路:二分,nums是从0开始的,且为递增
            left=0
            right=len(nums)-1
            while left<=right:
                mid=(left+right)//2
                if nums[mid]==mid:
                    left=mid+1
                else:
                    right=mid-1
                
            return left
    二分查找
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    输入: nums = [-1,0,3,5,9,12], target = 9
    输出: 4
    解释: 9 出现在 nums 中并且下标为 4
    输入: nums = [-1,0,3,5,9,12], target = 2
    输出: -1
    解释: 2 不存在 nums 中因此返回 -1


    模板:
    以下全部代码都是该模板

    初始条件:left = 0, right = length-1
    终止:left > right
    向左查找:right = mid-1
    向右查找:left = mid+1

    class Solution:
        def search(self, nums: List[int], target: int) -> int:
            # 思路:二分查找
            left=0
            right=len(nums)-1
            while left<=right:
                min_=(left+right)//2
                if nums[min_]>target:
                    right=min_-1
                elif nums[min_]<target:
                    left=min_+1
                else:
                    return min_
            if left>right:
                return -1

      

    剑指 Offer 53 - I. 在排序数组中查找数字 I
    
    统计一个数字在排序数组中出现的次数。
    
     
    
    示例 1:
    
    输入: nums = [5,7,7,8,8,10], target = 8
    输出: 2
    
    示例 2:
    
    输入: nums = [5,7,7,8,8,10], target = 6
    输出: 0

    class Solution:
        def search(self, nums: List[int], target: int) -> int:
            #思路:先通过二分法找到相等的点,然后往两边延伸
            left=0
            right=len(nums)-1
            count=0
            while left<=right:
                mid=(left+right)//2
                if nums[mid]==target:
                    left1,right1=mid-1,mid+1
                    count+=1
                    while left1!=-1 or right1!=-1:
                        if left1>=0 and nums[left1]==target:
                            count+=1
                            left1-=1
                        else:
                            left1=-1
                        if right1<=len(nums)-1 and nums[right1]==target:
                            count+=1
                            right1+=1
                        else:
                            right1=-1
                    break
                elif nums[mid]>target:
                    right=mid-1
                else:
                    left=mid+1
            return count
    
    
    
     
     稀疏数组搜索
    
    稀疏数组搜索。有个排好序的字符串数组,其中散布着一些空字符串,编写一种方法,找出给定字符串的位置。
    
    示例1:
    
     输入: words = ["at", "", "", "", "ball", "", "", "car", "", "","dad", "", ""], s = "ta"
     输出:-1
     说明: 不存在返回-1。
    
    示例2:
    
     输入:words = ["at", "", "", "", "ball", "", "", "car", "", "","dad", "", ""], s = "ball"
     输出:4
    
    提示:
    
        words的长度在[1, 1000000]之间

    class Solution:
        def findString(self, words: List[str], s: str) -> int:
            # copy 大佬的思路,首先对words进行二分法,进行判断,如果words[mid]为空值,则mid+1,
            left=0
            right=len(words)-1
            while left<=right:
                mid=(left+right)//2
                # 如果当前的mid为空字符,且小于右边界,则进行mid+1
                while words[mid] =='' and mid<right:
                    mid+=1
                # 这里即我右边界也是为空,这时我就可以将right的进行往右移了.
                if words[mid]=='':
                    right=mid-1
                    continue
                # 下面就是正常的二分法进行判断元素是否存在
                if words[mid]==s:
                    return mid
                elif s<words[mid]:
                    right=mid-1
                else:
                    left=mid+1
            return -1
    寻找比目标字母大的最小字母
    
    给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。
    
    在比较时,字母是依序循环出现的。举个例子:
    
        如果目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a'
    
    
    
    提示:
    
        letters长度范围在[2, 10000]区间内。
        letters 仅由小写字母组成,最少包含两个不同的字母。
        目标字母target 是一个小写字母。

    
    
    class Solution:
        def nextGreatestLetter(self, letters: List[str], target: str) -> str:
            # 思路1:直接扫描:复杂度为0(n),空间为0(1)
            for i in letters:
                if i > target:
                    return i
            return letters[0]
    
    
    
    
    
    
    
    class Solution:
        def nextGreatestLetter(self, letters: List[str], target: str) -> str:
            #思路:这里使用二分法的第一种形式,因为不存在对mid的邻居进行判断.
            left=0
            right=len(letters)-1
            while left<=right:
                mid=(left+right)//2
                if letters[mid]>target:
                    right=mid-1
                else: 
                    left=mid+1
            if left==len(letters):
                return letters[0]
            else:
                return letters[left]
    
    
    
     
    寻找峰值
    
    峰值元素是指其值大于左右相邻值的元素。
    
    给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
    
    数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
    
    你可以假设 nums[-1] = nums[n] = -∞。
    
    示例 1:
    
    输入: nums = [1,2,3,1]
    输出: 2
    解释: 3 是峰值元素,你的函数应该返回其索引 2。
    
    示例 2:
    
    输入: nums = [1,2,1,3,5,6,4]
    输出: 1 或 5 
    解释: 你的函数可以返回索引 1,其峰值元素为 2;
         或者返回索引 5, 其峰值元素为 6class Solution:
        def findPeakElement(self, nums: List[int]) -> int:
            # 思路:二分法,不过该二分法与其他的二分法是不同的,因为这里的判断条件是与后一位元素进行判断
            left=0
            right=len(nums)-1
            while left<right:
                mid=(left+right)//2
                if nums[mid]>nums[mid+1]:
                    right=mid
                else:
                    left=mid+1
            return left
                
    两个数组的交集 II
    
    给定两个数组,编写一个函数来计算它们的交集。
    
     
    
    示例 1:
    
    输入:nums1 = [1,2,2,1], nums2 = [2,2]
    输出:[2,2]
    
    示例 2:
    
    输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    输出:[4,9]
    
     
    
    说明:
    
        输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
        我们可以不考虑输出结果的顺序。
    
    进阶:
    
        如果给定的数组已经排好序呢?你将如何优化你的算法?
        如果 nums1 的大小比 nums2 小很多,哪种方法更优?
        如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

    class Solution:
        def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
            #方法与其I的类似度很高只不过添加删除操作
            nums2.sort()
            return_list=[]
            for target in nums1:
                if self.search_num(target,nums2):
                    return_list.append(target)
            return return_list
        def search_num(self,target,nums2):
            left=0
            right=len(nums2)-1
            while left<=right:
                mid=(left+right)//2
                if nums2[mid]>target:
                    right=mid-1
                elif nums2[mid]<target:
                    left=mid+1
                else:
                    nums2.pop(mid)
                    return True
            return False
    
    
    
     
    两数之和 II - 输入有序数组
    
    给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
    
    函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
    
    说明:
    
        返回的下标值(index1 和 index2)不是从零开始的。
        你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
    
    示例:
    
    输入: numbers = [2, 7, 11, 15], target = 9
    输出: [1,2]
    解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

    class Solution:
        def twoSum(self, numbers: List[int], target: int) -> List[int]:
            # 双指针思路:numbers前后一起判断
            left=0
            right=len(numbers)-1
            while left<right:
                if numbers[left]+numbers[right]>target:
                    right-=1
                elif numbers[left]+numbers[right]<target:
                    left+=1
                else:
                    return [left+1,right+1]
            return -1


    寻找两个正序数组的中位数
    
    给定两个大小为 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

    class Solution:
        def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
            # 思路:遍历nums1,在通过二分法,添加到Nums2中   复杂度为0(nlogm)  空间复杂度0(1)
            # 二分法使用第一种,原因是:第一种二分法最终可以找到恰好比target大的点,下面的代码,可以进行进一步优化,如,当i>nums2[right],则不用进行二分法,直接在nums2后天面进行添加nums1的元素即可
    
            for i in nums1:
                left=0
                right=len(nums2)-1
                while left<=right:
                    mid=(left+right)//2
                    if nums2[mid]>i:
                        right=mid-1
                    else:
                        left=mid+1
                nums2.insert(left,i)
            if len(nums2)%2:
                return nums2[len(nums2)//2]
            else:
                return (nums2[len(nums2)//2-1]+nums2[len(nums2)//2])/2
    
    
            
    寻找重复数
    
    给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
    
    示例 1:
    
    输入: [1,3,4,2,2]
    输出: 2
    
    示例 2:
    
    输入: [3,1,3,4,2]
    输出: 3
    
    说明:
    
        不能更改原数组(假设数组是只读的)。
        只能使用额外的 O(1) 的空间。
        时间复杂度小于 O(n2) 。
        数组中只有一个重复的数字,但它可能不止重复出现一次。

    class Solution:
        def findDuplicate(self, nums: List[int]) -> int:
            # 思路1:直接排序,遍历
            nums.sort()
            for i in range(1,len(nums)):
                if nums[i]==nums[i-1]:
                    return nums[i]
            return -1 

     
    在排序数组中查找元素的第一个和最后一个位置
    
    给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
    
    你的算法时间复杂度必须是 O(log n) 级别。
    
    如果数组中不存在目标值,返回 [-1, -1]。
    
    示例 1:
    
    输入: nums = [5,7,7,8,8,10], target = 8
    输出: [3,4]
    
    示例 2:
    
    输入: nums = [5,7,7,8,8,10], target = 6
    输出: [-1,-1]
    
    
    class Solution:
        def searchRange(self, nums: List[int], target: int) -> List[int]:
            # 思路:利用二分法,找到相等的值,然后进行forfor循环,分别向前进行遍历,获取第一个相等的值,向后遍历获取最后一个相等的值,最后进行返回
            left=0
            right=len(nums)-1
            return_list=[]
            mid_=0
            while left<=right:
                mid=(left+right)//2
                if nums[mid]==target:
                    return_list.append(mid)
                    break
                elif nums[mid]>target:
                    right=mid-1
                else:
                    left=mid+1
            
            if len(return_list)==0:
                return [-1,-1]
            mid_=return_list[0]
            return_list=[]
            for i in range(mid_,-1,-1):
                if i==0 and nums[0]==target:
                    return_list.append(0)
                if nums[i]!=target:
                    return_list.append(i+1)
                    break
            for j in range(mid_,len(nums),1):
                if j==len(nums)-1 and nums[-1]==target:
                    return_list.append(len(nums)-1)
                if nums[j]!=target:
                    return_list.append(j-1)
                    break
            return return_list
    猜数字大小
    
    猜数字游戏的规则如下:
    
        每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
        如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
    
    你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
    
        -1:我选出的数字比你猜的数字小 pick < num
        1:我选出的数字比你猜的数字大 pick > num
        0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
    输入:n = 10, pick = 6
    输出:6
    输入:n = 1, pick = 1
    输出:1
    输入:n = 2, pick = 2
    输出:2
    
    
    # The guess API is already defined for you.
    # @param num, your guess
    # @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
    # def guess(num: int) -> int:
    
    class Solution:
        def guessNumber(self, n: int) -> int:
            # 思路:二分法,只不过上下区间改为1和n,因为n的取值为1-n,
            left=1
            right=n
            while left<=right:
                min_=(left+right)//2
                guess_num=guess(min_)
                if guess_num==-1:
                    right=min_-1
                elif guess_num==1:
                    left=min_+1
                else:
                    return min_
    搜索旋转排序数组
    给你一个整数数组 nums ,和一个整数 target 。
    
    该整数数组原本是按升序排列,但输入时在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
    
    请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
    
    示例 1:
    
    输入:nums = [4,5,6,7,0,1,2], target = 0
    输出:4
    
    示例 2:
    
    输入:nums = [4,5,6,7,0,1,2], target = 3
    输出:-1
    
    示例 3:
    
    输入:nums = [1], target = 0
    
    思路和算法:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/sou-suo-xuan-zhuan-pai-xu-shu-zu-by-leetcode-solut/class Solution:
        def search(self, nums: List[int], target: int) -> int:
            left=0
            right=len(nums)-1
            while(left<=right):
                mid_=(left+right)//2
                if target==nums[mid_]:
                    return mid_
                # 左半段  有序mid_
                if nums[left]<=nums[mid_]:
                    if nums[left]<=target and nums[mid_]>=target:
                        right=mid_-1
                    else:
                        left=mid_+1
                # 右半段有序
                else:
                    if nums[right]>=target and nums[mid_]<=target:
                        left=mid_+1
                    else:
                        right=mid_-1
            return -1

    class Solution:
        def search(self, nums: List[int], target: int) -> int:
            #思路: 顺带回顾下两种二分法的用法,首先通过第二种二分法找到 反转点,在通过二分法对两个有序的进行二分
            left=0
            right=len(nums)-1
            while left+1<right:
                mid=(left+right)//2
                if nums[mid]>nums[left]:
                    left=mid
                else:
                    right=mid
            if nums[left]>nums[right]:
                index=right
            else:
                index=left
            ind=self.binary_search(nums[:index],target)
            if ind!=-1:
                return ind
            ind=self.binary_search(nums[index:],target)
            if ind!=-1:
                return ind+index
            return -1


        def binary_search(self,nums,target):
            left=0
            right=len(nums)-1
            while left<=right:
                mid=(left+right)//2
                if nums[mid]>target:
                    right=mid-1
                elif nums[mid]<target:
                    left=mid+1
                else:
                    return mid
            return -1
    找到 K 个最接近的元素
    
    给定一个排序好的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。
    
    整数 a 比整数 b 更接近 x 需要满足:
    
        |a - x| < |b - x| 或者
        |a - x| == |b - x| 且 a < b
    
     
    
    示例 1:
    
    输入:arr = [1,2,3,4,5], k = 4, x = 3
    输出:[1,2,3,4]
    
    示例 2:
    
    输入:arr = [1,2,3,4,5], k = 4, x = -1
    输出:[1,2,3,4]
    
     
    
    提示:
    
        1 <= k <= arr.length
        1 <= arr.length <= 104
        数组里的每个元素与 x 的绝对值不超过 104
    class Solution:
        def findClosestElements(self, arr: List[int], k: int, x: int) -> List[int]:
            # 思路1:直接通过对差值进行排序获取前kk个元素,在对k个元素进行排序
            arr_=sorted(arr,key=lambda q :abs(q-x))[:k]
            arr_.sort()
            return arr_
    class Solution:
        def findClosestElements(self, arr: List[int], k: int, x: int) -> List[int]:
            # 思路2:双指针从两端进行遍历,一个一个删除直到最后剩下k个元素
    
            left=0
            right=len(arr)-1
            if arr[0]>x:
                return arr[:k]
            if arr[-1]<x:
                return arr[-k:]
            while right-left+1!=k:
                if abs(x-arr[left]) <= abs(x-arr[right]):
                    right-=1
                else:
                    left+=1
            return arr[left:right+1]
    寻找峰值
    
    峰值元素是指其值大于左右相邻值的元素。
    
    给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
    
    数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
    
    你可以假设 nums[-1] = nums[n] = -∞。
    
    示例 1:
    
    输入: nums = [1,2,3,1]
    输出: 2
    解释: 3 是峰值元素,你的函数应该返回其索引 2。
    
    示例 2:
    
    输入: nums = [1,2,1,3,5,6,4]
    输出: 1 或 5 
    解释: 你的函数可以返回索引 1,其峰值元素为 2;
         或者返回索引 5, 其峰值元素为 6。
    
    说明:
    
    你的解法应该是 O(logN) 时间复杂度的。
    class Solution:
        def findPeakElement(self, nums: List[int]) -> int:
            # 思路1:直接遍历
            if len(nums)<=1:
                return 0
            for i in range(1,len(nums)):
                if nums[i]>nums[i-1]:
                    continue
                else:
                    return i-1
            return len(nums)-1
    
    
    class Solution:
        def findPeakElement(self, nums: List[int]) -> int:
            # 二分法,第二种方式进行遍历,因为他要使用到mid的左右邻居进行判断,但是存在一个问题就是,当他还剩下2个元素的时候就已经退出循环了,这时,我们在最后的对其进行后处理.
            left=0
            right=len(nums)-1
            while left+1<right:
                mid=(left+right)//2
                if nums[mid]<nums[mid+1]:
                    left=mid
                else:
                    right=mid
            if nums[left]>nums[right]:
                return left
            else:
                return right
           



     1 '''
     2 假设按照升序排序的数组在预先未知的某个点上进行了旋转。
     3 
     4 ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
     5 
     6 请找出其中最小的元素。
     7 
     8 注意数组中可能存在重复的元素。
     9 
    10 示例 1:
    11 
    12 输入: [1,3,5]
    13 输出: 1
    14 示例 2:
    15 
    16 输入: [2,2,2,0,1]
    17 输出: 0
    18 '''
    19 
    20 class Solution(object):
    21     def findMin(self, nums):
    22         """
    23         :type nums: List[int]
    24         :rtype: int
    25         """
    26 #         与第一个一样,只不过存在重复元素.
    27         def find_min(nums):
    28             target=nums[0]
    29             l0=1
    30             r0=len(nums)
    31             for i in range(1,len(nums)):
    32                 if nums[i]==target:
    33                     l0+=1
    34                 else:
    35                     break
    36             while l0<r0:
    37                 mid=(l0+r0)/2
    38                 if nums[mid]>target:
    39                     l0=mid+1
    40                 else:
    41                     r0=mid
    42             return l0
    43         rotaion=find_min(nums)
    44         if rotaion==len(nums):
    45             return nums[0]
    46         return nums[rotaion]
    154寻找旋转排序数组中的最小值2
  • 相关阅读:
    file_zilla 通过key连接远程服务器
    git 恢复丢失的文件
    花括号中的json数据--->转为数组array
    3种日志类型,微信付款反馈-->写入txt日志
    清空数据库中所有表--连表删除
    冒泡排序, 使用最低票价.---双重循环,一重移动次数.二重移动
    navicat 连接远程mysql
    付款前.检查状态.防止重复付款,需要ajax设置为同步,等待ajax返回结果再使用
    反射
    设计模式六大原则
  • 原文地址:https://www.cnblogs.com/liuyicai/p/9856598.html
Copyright © 2011-2022 走看看