2021-12-07 每日打卡:腾讯精选50题

90 阅读1分钟

2021-12-07 每日打卡:腾讯精选50题

写在前面

“这些事儿在熟练之后,也许就像喝口水一样平淡,但却能给初学者带来巨大的快乐,我一直觉得,能否始终保持如初学者般的热情、专注,决定了在做某件事时能走多远,能做多好。” 该系列文章由python编写,遵循LeetBook 列表/腾讯的刷题顺序,所有代码已通过。每日3道,随缘剖析,希望风雨无阻,作为勉励自己坚持刷题的记录。

148. 排序链表

在这里插入图片描述

  • 递归的归并排序:
class Solution:
    def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 归并排序的合并
        def merge(left,right):
            head = tmp = ListNode(0)
            while left and right:
                if left.val < right.val: 
                    tmp.next, left = left, left.next
                else:
                    tmp.next, right =  right, right.next
                tmp = tmp.next
            tmp.next = left if left else right
            return head.next
        # 空元素,一个元素的情况,直接返回
        if not head or not head.next: return head
        # 通过快慢指针找到中点!
        slow = fast = head
        while fast.next and fast.next.next:
            slow, fast = slow.next, fast.next.next

        # 分成两部分,分别排序+合并
        left, right = head, slow.next
        slow.next = None
        left, right = self.sortList(left), self.sortList(right)

        return merge(left,right)
            
  • 迭代的归并排序【第一遍未写出】:
    在这里插入图片描述
class Solution:
    def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        tmp, lenth, intv = head, 0, 1
        # 统计链表长度
        while tmp:
            tmp, lenth = tmp.next, lenth+1
        # 头结点
        res = ListNode(0)
        res.next = head
        while intv< lenth:
            pre, tmp = res, res.next
            while tmp:
                # 根据i的长度确定每个小块的头部位置
                left, i = tmp, intv
                while i and tmp:
                    tmp, i = tmp.next, i-1
                # 链表长度不够,而不是小块划分完毕:right为空,无须考虑
                if i: break
                # 根据i的长度确定每个小块的头部位置
                right, i = tmp, intv
                while i and tmp:
                    tmp, i = tmp.next, i-1
                len_l, len_r = intv, intv-i
                while len_l and len_r:
                    if left.val <right.val:
                        pre.next, left, len_l = left, left.next, len_l-1
                    else:
                        pre.next, right, len_r = right, right.next, len_r-1
                    pre = pre.next
                # 整个划分小块的过程并没有真正指向next,而是使用长度界定的
                # 所以此处也需要用长度作为循环结束条件
                pre.next = left if len_l else right
                # 将剩余部分顺过去,下一组成对小块需要接上
                while len_l>0 or len_r>0:
                    pre, len_l, len_r = pre.next, len_l-1, len_r-1
                pre.next = tmp 
            intv *= 2
        return res.next
        

33. 搜索旋转排序数组

在这里插入图片描述

  • 有序想二分:
    在这里插入图片描述
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if not nums:
            return -1
        # 排序+旋转数组问题:一定存在某一部分是有序
        # 另一部分无序(无序的部分可以为0个,当K=0时候)
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = (l + r) // 2
            if nums[mid] == target:
                return mid
            if nums[0] <= nums[mid]:
                if nums[0] <= target < nums[mid]:
                    r = mid - 1
                else:
                    l = mid + 1
            else:
                if nums[mid] < target <= nums[len(nums) - 1]:
                    l = mid + 1
                else:
                    r = mid - 1
        return -1

215. 数组中的第K个最大元素

在这里插入图片描述

  • 仿快排,建议熟背!快排中partition的结果就是该数应该插入的下标位置!
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        n = len(nums)
        k = n-k
        def quick_find(start, end):
            # 一定要使用pivot,使得最后比较的数交换过去
            pivot = start
            left, right = start, end
            # 这里的判定条件要加上等号!否则会出现4,6,5(key=5)而排序不正确问题
            while left < right:
                while left < right and nums[right] >= nums[pivot]: right -= 1
                while left < right and nums[left] <= nums[pivot]: left += 1
                nums[left], nums[right] = nums[right], nums[left]
            nums[pivot], nums[right] = nums[right], nums[pivot]

            if right == k:
                return nums[right]
            elif right < k:
                return quick_find(right + 1, end) 
            else:
                return quick_find(start, right - 1)
        return quick_find(0, n - 1)