【Leetcode】随笔

🌈你好呀!我是 山顶风景独好
🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊
🌸愿您在此停留的每一刻,都沐浴在轻松愉悦的氛围中。
📖这里不仅有丰富的知识和趣味横生的内容等您来探索,更是一个自由交流的平台,期待您留下独特的思考与见解。🌟
🚀让我们一起踏上这段探索与成长的旅程,携手挖掘更多可能,共同进步!💪✨

题目一:二叉树的层序遍历(LeetCode 102)

题目分析:

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。例如:输入root = [3,9,20,null,null,15,7],输出[[3],[9,20],[15,7]]。

解题思路:

广度优先搜索(BFS):利用队列辅助实现逐层遍历,记录每一层的节点值。
步骤:

  1. 若根节点为空,返回空列表。
  2. 初始化队列,将根节点加入队列。
  3. 循环处理每一层:
    • 记录当前层的节点数量(队列长度)。
    • 遍历当前层的所有节点,收集节点值,并将左右子节点加入队列(若存在)。
    • 将当前层的节点值列表加入结果集。
  4. 返回结果集。

示例代码:

from collections import deque

# 二叉树节点定义
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def levelOrder(root):
    if not root:
        return []
    
    result = []
    q = deque([root])  # 初始化队列
    
    while q:
        level_size = len(q)  # 当前层的节点数
        level = []  # 存储当前层的节点值
        
        for _ in range(level_size):
            node = q.popleft()
            level.append(node.val)
            
            # 加入下一层节点
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        
        result.append(level)
    
    return result

# 辅助函数:构建二叉树
def build_tree(values):
    if not values:
        return None
    root = TreeNode(values[0])
    queue = [root]
    i = 1
    while queue and i < len(values):
        node = queue.pop(0)
        if values[i] is not None:
            node.left = TreeNode(values[i])
            queue.append(node.left)
        i += 1
        if i < len(values) and values[i] is not None:
            node.right = TreeNode(values[i])
            queue.append(node.right)
        i += 1
    return root

# 测试示例
if __name__ == "__main__":
    # 构建示例树:[3,9,20,null,null,15,7]
    root = build_tree([3,9,20,None,None,15,7])
    print("层序遍历结果:", levelOrder(root))  # 输出:[[3],[9,20],[15,7]]

代码解析:

使用队列存储每一层的节点,通过level_size控制每层的遍历范围,确保每次只处理当前层的节点。
遍历当前层节点时,将其左右子节点加入队列,为下一层遍历做准备,实现逐层访问。
结果集中每个子列表对应一层的节点值,顺序为从左到右。
时间复杂度为O(n)(n为节点总数,每个节点访问一次),空间复杂度为O(n)(队列最多存储一层节点,最坏情况为满二叉树的最后一层)。

题目二:有效的括号(LeetCode 20)

题目分析:

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
    例如:输入s = “()”,输出true;输入s = “()[]{}”,输出true;输入s = “(]”,输出false。

解题思路:

栈:利用栈的先进后出特性匹配括号,遇到左括号入栈,遇到右括号则与栈顶元素比较,若匹配则出栈,否则无效。
步骤:

  1. 初始化栈,创建括号映射字典(右括号对应左括号)。
  2. 遍历字符串中的每个字符:
    • 若为左括号,入栈。
    • 若为右括号:
      • 若栈为空或栈顶元素与当前右括号不匹配,返回false。
      • 否则,栈顶元素出栈。
  3. 遍历结束后,若栈为空(所有左括号都匹配),返回true;否则返回false。

示例代码:

def isValid(s):
    stack = []
    # 右括号到左括号的映射
    bracket_map = {')': '(', '}': '{', ']': '['}
    
    for char in s:
        if char in bracket_map:
            # 处理右括号:检查栈顶是否匹配
            top_element = stack.pop() if stack else '#'
            if bracket_map[char] != top_element:
                return False
        else:
            # 左括号入栈
            stack.append(char)
    
    # 栈为空说明所有括号都匹配
    return not stack

# 测试示例
if __name__ == "__main__":
    s1 = "()"
    print("字符串{}是否有效:".format(s1), isValid(s1))  # 输出:True
    
    s2 = "()[]{}"
    print("字符串{}是否有效:".format(s2), isValid(s2))  # 输出:True
    
    s3 = "(]"
    print("字符串{}是否有效:".format(s3), isValid(s3))  # 输出:False

代码解析:

通过栈存储左括号,当遇到右括号时,必须与最后一个未匹配的左括号(栈顶)匹配,否则字符串无效。
bracket_map字典用于快速查找右括号对应的左括号,简化匹配逻辑。
遍历结束后,若栈中仍有元素,说明存在未匹配的左括号,返回false;否则返回true。
时间复杂度为O(n)(n为字符串长度,每个字符处理一次),空间复杂度为O(n)(栈最多存储n/2个左括号)。

题目三:合并两个有序链表(LeetCode 21)

题目分析:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。例如:输入l1 = [1,2,4], l2 = [1,3,4],输出[1,1,2,3,4,4]。

解题思路:

迭代法:使用虚拟头节点简化边界处理,通过双指针遍历两个链表,每次选择较小的节点连接到结果链表。
步骤:

  1. 创建虚拟头节点dummy和当前指针current,current初始指向dummy。
  2. 当两个链表都不为空时:
    • 若l1节点值 <= l2节点值,current的next指向l1,l1后移。
    • 否则,current的next指向l2,l2后移。
    • current后移。
  3. 将剩余非空的链表连接到current的next。
  4. 返回dummy.next(新链表的头节点)。

示例代码:

# 链表节点定义
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def mergeTwoLists(l1, l2):
    # 创建虚拟头节点
    dummy = ListNode(0)
    current = dummy
    
    # 遍历两个链表,选择较小的节点连接
    while l1 and l2:
        if l1.val <= l2.val:
            current.next = l1
            l1 = l1.next
        else:
            current.next = l2
            l2 = l2.next
        current = current.next
    
    # 连接剩余节点
    current.next = l1 if l1 else l2
    
    return dummy.next

# 辅助函数:将列表转换为链表
def list_to_linkedlist(lst):
    dummy = ListNode(0)
    current = dummy
    for val in lst:
        current.next = ListNode(val)
        current = current.next
    return dummy.next

# 辅助函数:将链表转换为列表
def linkedlist_to_list(head):
    result = []
    current = head
    while current:
        result.append(current.val)
        current = current.next
    return result

# 测试示例
if __name__ == "__main__":
    l1 = list_to_linkedlist([1,2,4])
    l2 = list_to_linkedlist([1,3,4])
    merged = mergeTwoLists(l1, l2)
    print("合并后的链表:", linkedlist_to_list(merged))  # 输出:[1,1,2,3,4,4]

代码解析:

虚拟头节点dummy避免了单独处理头节点的情况,current指针用于构建结果链表。
通过比较l1和l2的当前节点值,选择较小的节点加入结果链表,确保升序特性。
当其中一个链表遍历完毕后,直接将另一个链表的剩余部分连接到结果链表末尾,无需逐个处理。
时间复杂度为O(m + n)(m、n分别为两个链表的长度,每个节点访问一次),空间复杂度为O(1)(仅使用常数变量)。


✨ 这就是今天要分享给大家的全部内容了,我们下期再见!😊
🏠 我在CSDN等你哦!我的主页😍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山顶风景独好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值