leetcode题解记录 [33, 81]

这些是关联的近似题目,都是查找数字,只是条件略有不同:
0153:找最小值,数组的的值互不相同
0154:找最小值,数组中存在相同值
0033:找目标值,数组中的值互不相同
0081:找目标值,数组中存在相同值
10.03:与81相同, 区别在于返回找的第一个索引

  1. 搜索旋转排序数组
class No_0033_Search:
    """
    题干:
        https://leetcode.cn/problems/search-in-rotated-sorted-array/
        整数数组nums按升序排列,数组中的值互不相同,在 旋转后的数组 中搜索整数target
    解析:
        对“有序数组”,基本思路是二分查找。

        数组轮转后有以下两种情况(*号表示最小值, |表示中间位置),
        通过 当前的边界值 与 当前中间值 对比,可以区分这两种情况:
            • 数组的起始值(最小值)在左半部分: [6, 7, 8 *1, | 2, 3, 4, 5]
              则数组的右半部分保持有序状态
            • 数组的起始值(最小值)在右半部分: [4, 5, 6, 7, | 8, *1, 2, 3]
              则数组的左半部分保持有序状态

        • 判断target是否在被包含在有序区间内,从而收缩查找范围
    """

    def __relative_links__(self):
        """关键字:旋转数组/二分查找"""
        link1 = No_0153_FindMin     # 值互不相同
        link2 = No_0154_FindMin2    # 存在相同值
        link3 = No_0033_Search      # 值互不相同
        link4 = No_0081_Search2     # 存在相同值
        link5 = Job_10_03_loop_list  # 与81基本接近,区别在于返回第一个索引

    @staticmethod
    def sol_01_dichotomy(nums, target):
        n = len(nums)
        left, right = 0, n-1

        # 控制条件取等号,在while中直接return mid。
        while left <= right:
            mid = left + (right - left) // 2

            if nums[mid] == target:
                # 中间值为target,直接返回
                return mid

            if nums[left] <= nums[mid]:
                # 左半部分有序
                if nums[left] <= target < nums[mid]:
                    # target落在左半部分有序区域内
                    right = mid-1
                else:
                    # target落在右半部分无序区域内
                    left = mid+1
            else:
                # 右半部分有序
                if nums[mid] < target <= nums[len(nums)-1]:
                    # target落在右半部分有序区域内
                    left = mid+1
                else:
                    # target落在左半部分无序区域内
                    right = mid-1
        return -1
  1. 搜索旋转排序数组 II
class No_0081_Search2:
    """
    题干:
        https://leetcode.cn/problems/search-in-rotated-sorted-array-ii/
        寻找旋转排序数组中的值
    解析:
        有序数组的基本思路是二分查找。
        对于数组中有重复元素的情况,二分查找时可能会有 a[l]=a[mid]=a[node],
        此时无法判断左区间a[l:mid]和右区间a[mid:node+1]哪个是有序的,譬如:
        [1, 1, 2, 3 *1, 1 | 1, 1, 1, 1, 1, 1]
        对于这种情况,我们将当前二分区间的左边界加一,右边界减一,然后在新区间上继续二分查找。
        1,  [1, 2, 3 *1, 1 | 1, 1, 1, 1, 1] , 1

    """
    
    @staticmethod
    def sol_01_dichotomy(nums, target):
        n = len(nums)
        left, right = 0, n-1

        # 控制条件取等号,在while中直接return mid。
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] == target:
                # 中间值即为target,直接返回
                return True
            
            if nums[left] == nums[mid] == nums[right]:
                # 收缩区间
                left += 1
                right -= 1
                
            elif nums[left] <= nums[mid]:
                # 左半部分有序
                if nums[left] <= target < nums[mid]:
                    # target落在左半部分有序区域内
                    right = mid-1
                else:
                    # target落在右半部分无序区域内
                    left = mid+1
                    
            else:
                # 右半部分有序
                if nums[mid] < target <= nums[len(nums)-1]:
                    # target落在右半部分有序区域内
                    left = mid+1
                else:
                    # target落在左半部分无序区域内
                    right = mid-1
        return False
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值