剑指offer:二分

题目一

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
 
这道题考的是二分法,二分明早再来复盘一下
 
 
 
 
 
 

错误答案:

这是我的错误答案,有好几处

❤:if...elif...else写成了if...if...else

❤:mid的计算方式不对,写成了=right/2,应该是(left+right)作为分子;且式子位置不对,应当写在while里面,因为while里需要用到mid给左右两个值赋值,如果写在外面那么mid就永远不会变了。还有一点就是除法写成//才是向下取整,不然python认为01是浮点数,除出来的结果是浮点型不能作为下标赋值给mid(这个错误经常报)

❤:忘记了给while一个终止return

❤:while条件不应该写等号

❤:还有就是情况考虑不周全,认为下式成立就可以终止条件输出了,其实不是,如果是11101的情况,那么就会输出1而不是0;这种情况只好固定right,让left继续往后走,逐个和固定的right比较,而且因为while left<right才会进行代码块,所以移动过程中是左一直往右和右比较。

rotateArray[mid]=rotateArray[right]
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        if len(rotateArray)==0:
            return 0
        if len(rotateArray)==1:
            return rotateArray[0]
        else:
            left=0
            right=len(rotateArray)-1
            mid=right/2
            while left<=right:
                if rotateArray[mid]<rotateArray[right]:
                    right=mid
                if rotateArray[mid]>rotateArray[right]:
                    left=mid+1
                else:
                    return rotateArray[mid]

所以正确答案如下:

class Solution:
    def minNumberInRotateArray(self, rotateArray):
        if len(rotateArray)==0:
            return 0
        elif len(rotateArray)==1:
            return rotateArray[0]
        else:
            left=0
            right=len(rotateArray)-1
            while left<right:
                mid=(left+right)//2
                if rotateArray[mid]<rotateArray[right]:
                    right=mid
                elif rotateArray[mid]>rotateArray[right]:
                    left=mid+1
                else:
                    left+=1
            return rotateArray[left]

 题目二:

704.给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

错误答案:

❤:做二分涉及到分类的时候不要轻易写else,要多写elif,争取把每种情况都写出来

❤:没有理解while下的return,当条件成立时直接输出代码块里的return,当条件不成立时说明没有找到结果,跳出while,输出-1;这题和上题不一样,上题是left和right一起移动,直到两者相等,找到了最小值,跳出代码块,需要输出找到的最小值的结果。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if len(nums)==0:
            return -1
        else:
            left=0
            right=len(nums)-1
            while left <= right:
                mid=(left+right)//2
                if nums[mid]<target:
                    left=mid+1
                elif nums[mid]>target:
                    right=mid-1
                else :
                    return mid
            return mid

正确答案:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if len(nums)==0:
            return -1
        else:
            left=0
            right=len(nums)-1
            while left <= right:
                mid=(left+right)//2
                if nums[mid]<target:
                    left=mid+1
                elif nums[mid]>target:
                    right=mid-1
                elif nums[mid]==target:
                    return mid
            return -1

 题目三:

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

说真的下面这个代码跟着别人的代码看了很久,就是没找到为什么自己的代码超出了时间限制。下方为错误答案:

class Solution:
    def searchRange (self,nums: List[int], target: int) -> List[int]:
        if not nums:
            return [-1,1]
        else:
            return [self._search_left(nums, target), self._search_right(nums, target)]

    def _search_left(self, nums: List[int], target: int) -> List[int]:
        left=0
        right=len(nums)-1
        while left <=right:
            mid=(left+(right-left))//2
            if nums[mid]>target:
                right=mid-1
            elif nums[mid]<target:
                left=mid+1
            elif nums[mid]==target:#先找左边的边界
                right=mid-1
        if nums[left]!=target or left >= len(nums):
            return -1
        return left
    
    def _search_right(self, nums: List[int], target: int) -> List[int]:
        left=0
        right=len(nums)-1
        while left <=right:
            mid=(left+(right-left))//2
            if nums[mid]>target:
                right=mid-1
            elif nums[mid]<target:
                left=mid+1
            elif nums[mid]==target:#先找右边的边界
                left=mid+1
        if nums[right]!=target or right< 0:
            return -1
        return right

终于改出来了:如下

❤首先是mid的计算多了括号

❤其次题读错了[-1,-1]看成了[-1,1]

❤还有就是最后的if判断,应该先判断是否越界再or。不然的话left容易越界导致在数组中读不出,但是right就没关系,反正nums[-1]也能读

class Solution:
    def searchRange (self,nums: List[int], target: int) -> List[int]:
        if nums==[]:
            return [-1,-1]
        else:
            return [self._search_left(nums, target), self._search_right(nums, target)]

    def _search_left(self, nums ,target) :
        left=0
        right=len(nums)-1
        while left <=right:
            mid=left+(right-left)//2
            if nums[mid]>target:
                right=mid-1
            elif nums[mid]<target:
                left=mid+1
            elif nums[mid]==target:#先找左边的边界
                right=mid-1
        if left >= len(nums) or nums[left] != target:
            return -1
        return left
    
    def _search_right(self, nums ,target) :
        left=0
        right=len(nums)-1
        while left <=right:
            mid=left+(right-left)//2
            if nums[mid]>target:
                right=mid-1
            elif nums[mid]<target:
                left=mid+1
            elif nums[mid]==target:#先找右边的边界
                left=mid+1
        if right < 0 or nums[right] != target:
            return -1
        return right

下面是别人的正确答案:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        # 二分查找,搜索左右边界
        if not nums:
            return [-1, -1]
        return [self._search_left(nums, target), self._search_right(nums, target)]

    def _search_left(self, nums, target):
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] > target:
                right = mid - 1
            elif nums[mid] < target:
                left = mid + 1
            elif nums[mid] == target:
                right = mid - 1                         # 改动这里,使搜索区间向左侧收缩
        if left >= len(nums) or nums[left] != target:   # 判断索引越界情况
            return -1
        return left

    def _search_right(self, nums, target):
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] > target:
                right = mid - 1
            elif nums[mid] < target:
                left = mid + 1
            elif nums[mid] == target:
                left = mid + 1                          # 改动这里,使搜索区间向右侧收缩
        if right < 0 or nums[right] != target:          # 判断索引越界情况
            return -1                                   
        return right

作者:jue-qiang-zha-zha
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/34-zai-pai-xu-shu-zu-zhong-cha-zhao-yuan-irqc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文地址:https://www.cnblogs.com/liuxiangyan/p/14418845.html