返回

LeetCode选讲 第十四期:链表、搜索、数列、括号专题

前端

一、K个一组翻转链表

这道题要求我们以K个一组的形式翻转一个给定的单向链表。比如,对于链表1->2->3->4->5->6->7->8->9,当K=3时,翻转后的链表为3->2->1->6->5->4->9->8->7。

本题的难点在于如何高效地翻转链表。我们可以采用「分治法」的思想,将链表分成若干个子链表,然后分别对这些子链表进行翻转。最后,将这些翻转后的子链表连接起来即可得到最终结果。

代码实现:

def reverseKGroup(head, k):
    if not head or k == 1:
        return head

    # 将链表分成k个一组
    dummy = ListNode(0)
    dummy.next = head
    prev = dummy

    while True:
        # 找到k个一组的尾节点
        tail = prev
        for i in range(k):
            tail = tail.next
            if not tail:
                return dummy.next

        # 翻转k个一组的链表
        new_head = reverseList(prev.next, tail)

        # 将翻转后的链表连接到前一个子链表
        prev.next = new_head
        prev = tail

    return dummy.next


def reverseList(head, tail):
    prev = tail.next
    p = head
    while p != tail:
        next_node = p.next
        p.next = prev
        prev = p
        p = next_node

    return prev

二、搜索插入位置

这道题要求我们在一个排序数组中搜索一个给定的目标值,并返回该目标值在数组中的插入位置。如果目标值已经存在于数组中,则返回其索引。

本题的难点在于如何高效地找到目标值的位置。我们可以采用「二分搜索」的思想,将数组分成两半,然后比较目标值与中间元素的大小。如果目标值小于中间元素,则继续在数组的前半部分搜索;如果目标值大于中间元素,则继续在数组的后半部分搜索。如此反复,直到找到目标值或搜索到数组的末尾。

代码实现:

def searchInsert(nums, target):
    left, right = 0, len(nums) - 1

    while left <= right:
        mid = (left + right) // 2

        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    # 如果没有找到目标值,则返回其插入位置
    return left

三、外观数列

这道题要求我们生成一个「外观数列」。外观数列是一个奇怪的数列,其第n项是其第n-1项的「外观」。比如,外观数列的前几项如下:

  1. 1
  2. 11
  3. 21
  4. 1211
  5. 111221

外观数列的生成规则如下:

  1. 从第一个数1开始,
  2. 对于外观数列的第n项,将它分解为一组连续的数字,
  3. 然后将这些数字的个数及其值组合起来,得到外观数列的第n+1项。

代码实现:

def countAndSay(n):
    if n == 1:
        return '1'

    prev = countAndSay(n - 1)
    result = []
    count = 1

    for i in range(len(prev)):
        if i < len(prev) - 1 and prev[i] == prev[i + 1]:
            count += 1
        else:
            result.append(str(count))
            result.append(prev[i])
            count = 1

    return ''.join(result)

四、最长有效括号

这道题要求我们在一个由左右括号组成的字符串中找到最长有效括号的长度。有效括号是指成对的括号,例如「()」和「[]」。

本题的难点在于如何高效地找到最长有效括号。我们可以采用「栈」的数据结构来解决这个问题。栈是一种后进先出的数据结构,我们可以利用它来记录括号的匹配情况。当遇到左括号时,我们将它压入栈中;当遇到右括号时,我们将它与栈顶的左括号进行匹配。如果匹配成功,则将这两个括号从栈中弹出;否则,继续遍历字符串。如此反复,直到遍历完整个字符串。

代码实现:

def longestValidParentheses(s):
    stack = []
    max_length = 0

    for i in range(len(s)):
        if s[i] == '(':
            stack.append(i)
        else:
            if stack:
                stack.pop()
                if not stack:
                    max_length = max(max_length, i + 1)
                else:
                    max_length = max(max_length, i - stack[-1])

    return max_length