[leetcode] Python(26)--寻找旋转排序数组中的最小值 II(154)、寻找重复数(287)、寻找两个有序数组的中位数(4)、找出第 k 小的距离对(719)

从零开始的力扣(第二十六天)~

1.寻找旋转排序数组中的最小值 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

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

与之前不重复翻转那道题一样,只是在相等的时候不知道哪边有最小值,所以进行一次递归
class Solution:
    def findMin(self, nums: List[int]) -> int:
        n = len(nums)
        first = 0
        last = n - 1
        while first < last:
            mid = (first + last + 1) // 2
            if nums[mid - 1] > nums[mid]:
                return nums[mid]
            elif nums[first] == nums[mid]:
                a = self.findMin(nums[0:mid])
                b = self.findMin(nums[mid:])
                return a if a < b else b
            elif nums[first] < nums[mid]:
                first = mid
            else:
                last = mid
        return nums[0]

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:
        li = sorted(nums)
        for i in range(len(li) - 1):
            if li[i] == li[i + 1]:
                return li[i]


不过后来想了一下,sorted算法使用了O(n)的空间复杂度,不符合题意。

应该是唯一解法的快慢指针法,因为当有重复数时,一定在列表内有环(前一位数指向下一位地址)接下来就是找到哪两个数重复就行了
class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        fast = 0
        slow = 0;
        while True:
            fast = nums[nums[fast]]
            slow = nums[slow]
            if slow == fast:
                fast = 0;
                while nums[slow] != nums[fast]:
                    fast = nums[fast]
                    slow = nums[slow]
                return nums[slow]

3.寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0

示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
—————————————————————————————————————————

最开始想法是合并数组,因为时间复杂度要求O(log(m + n)),所以不能使用sorted,只能每一次在数组内去除两个数,直到得到最后一个或者两个数,算出中位数
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        li = nums1 + nums2
        while len(li) > 2:
            li.remove(max(li))
            li.remove(min(li))
        return sum(li) / len(li)


以为此方法使用了remove与max与min几个函数,时间复杂度超了,所以我更改了一下方式

直接在两个数组内分别删值,但是要考虑几种数组为空的情况
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        while (len(nums1) + len(nums2)) > 2:
            if nums1 and nums2:
                if nums1[0] <= nums2[0]:
                    nums1.pop(0)
                else:
                    nums2.pop(0)
                
                if nums1 and nums2:
                    if nums1[-1] >= nums2[-1]:
                        nums1.pop()
                    else:
                        nums2.pop()
                elif nums1 == []:
                    nums2.pop()
                else:
                    nums1.pop()
            
            elif nums1 == []:
                nums2.pop(0)
                nums2.pop()
            else:
                nums1.pop(0)
                nums1.pop()
        return (sum(nums1) + sum(nums2)) / (len(nums1) + len(nums2))


但是其实这种方法中,pop函数当参数为0时,时间复杂度是O(n)的,所以还是不太好,但是基本达到了要求。

4.找出第 k 小的距离对

给定一个整数数组,返回所有数对之间的第 k 个最小距离。一对 (A, B) 的距离被定义为 A 和 B 之间的绝对差值。

示例 1:
输入:
nums = [1,3,1]
k = 1
输出:0
解释:
所有数对如下:
(1,3) -> 2
(1,1) -> 0
(3,1) -> 2
因此第 1 个最小距离的数对是 (1,1),它们之间的距离为 0。

提示:
2 <= len(nums) <= 10000.
0 <= nums[i] < 1000000.
1 <= k <= len(nums) * (len(nums) - 1) / 2.
—————————————————————————————————————————

思路是二分法,因为距离的范围在0(可能距离最小值不是零)与数组内最大数值与最小数值之差中间,所以在这个范围内使用二分法找到第k个最小距离,判断条件是当原数组中距离小于mid的个数与k比较,这个数值大于k时,数组尾就要更改成mid,反之数组头更改成mid + 1
class Solution:
    def smallestDistancePair(self, nums: List[int], k: int) -> int:
        nums.sort()
        n = len(nums)
        first = 0
        last = nums[-1] - nums[0]
        while first < last:
            mid = (first + last) // 2
            i, count = 0, 0
            for j in range(1, n):
                while nums[j] - nums[i] > mid:
                    i += 1
                count += j - i
            if count < k:
                first = mid + 1
            else:
                last = mid
        return first


以上就是今日经验!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值