zoukankan      html  css  js  c++  java
  • [刷题] Leetcode算法 (2020-3-1)

    1.删除排序链表中的重复元素

    题目:

    给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

    示例:

    输入: 1->1->2->3->3
    输出: 1->2->3

    代码:

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def deleteDuplicates(self, head: ListNode) -> ListNode:
            # 如果head为空,返回None
            if not head:
                return None
            # temp作为前后比较的指针,初始指向head
            temp = head
            # res作为结果链表的指针,初始指向head
            res = head
            # 如果还有下一个节点,则前后比较val
            while temp.next:
                # 如果前后不相等
                if temp.val != temp.next.val:
                    # 让res指向后面那个
                    res.next = temp.next
                    # res移一个节点
                    res = res.next
                temp = temp.next
            # 循环结束的时候可能最后几个是相同的,扔掉最后几个相同的,只取res指向的那个节点
            res.next = None
    
            return head

    2.合并两个有序数组

    题目:

    给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

    说明:

    初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
    你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

    示例:

    输入:
    nums1 = [1,2,3,0,0,0], m = 3
    nums2 = [2,5,6],       n = 3
    
    输出: [1,2,2,3,5,6]

    代码:

    class Solution:
        def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
            """
            Do not return anything, modify nums1 in-place instead.
            """
            
            p1=m-1  # 获取nums1的最大索引
            p2=n-1  # 获取nums2的最大索引
            p=m+n-1  # 获取合并后nums1的最大索引
            # 两个列表都还有值
            while p1>=0 and p2>=0:
                # 谁大,谁放后面
                if nums1[p1]<nums2[p2]:
                    nums1[p]=nums2[p2]
                    p2-=1
                else:
                    nums1[p]=nums1[p1]
                    p1-=1
                # p向前移一格
                p-=1
            # 某个列表没有元素了(假设nums1没有元素了,则剩下的nums2直接拷贝到最前面)(假设nums2没有元素了p2+1=0,所以下面语句不会赋值元素)
            nums1[:p2+1]=nums2[:p2+1]

    总结:

    # 这种in-place合并问题,我们可以找到一个正确的方向来写入值,在写入的同时不影响本身还未使用的元素
    # 这里我们就选择从nums1的最后(合并后总长度)开始向前按顺序存放值,这样在存放的过程中也不会影响nums1和nums2中途未使用的元素

    3.相同的树

    题目:

    给定两个二叉树,编写一个函数来检验它们是否相同。

    如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

    示例:

    输入:       1         1
              /        / 
             2   3     2   3
    
            [1,2,3],   [1,2,3]
    
    输出: true
    
    输入:       1         1
              /        / 
             2   1     1   2
    
            [1,2,1],   [1,1,2]
    
    输出: false

    代码1:

    class Solution:
        def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
            
            """
            :type p: TreeNode
            :type q: TreeNode
            :rtype: bool
            """    
            # 如果都为None,则相等
            if not p and not q:
                return True
            # 如果其中有一个为None,另一个不是None,则不相等
            if not q or not p:
                return False
            # p和q的val不同,不相等
            if p.val != q.val:
                return False
            # p和q的左右子节点分别相同,才相同
            return self.isSameTree(p.right, q.right) and 
                   self.isSameTree(p.left, q.left)

    递归解法。

    时间复杂度 : O(N),其中 N 是树的结点数,因为每个结点都访问一次。

    空间复杂度 : 最优情况(完全平衡二叉树)时为 O(log(N)),最坏情况下(完全不平衡二叉树)时为O(N),用于维护递归栈。

    代码2:

    from collections import deque
    class Solution:
        def isSameTree(self, p, q):
            """
            :type p: TreeNode
            :type q: TreeNode
            :rtype: bool
            """    
            # 定义内部函数,用于判断两个节点是否相同
            def check(p, q):
                # if both are None
                if not p and not q:
                    return True
                # one of p and q is None
                if not q or not p:
                    return False
                if p.val != q.val:
                    return False
                return True
            
            # 使用队列,先将p和q的根节点作为pair元组加入队列(按对加入很重要)
            deq = deque([(p, q),])
            # 当队列中还有pair的时候,就要进行比对,知道队列为空,或者出现不同的对
            while deq:
                # 一对一对拿出来比对
                p, q = deq.popleft()
                # 只要有一对不同,则返回false
                if not check(p, q):
                    return False
                # 只要p树还有节点
                if p:
                    # 将p的左 q的左做成一对加入队列
                    deq.append((p.left, q.left))
                    # 将p的右 q的右做成一对加入队列
                    deq.append((p.right, q.right))
                        
            return True

    迭代解法。

    时间复杂度 : O(N),其中 N 是树的结点数,因为每个结点都访问一次。

    空间复杂度 : 最优情况(完全平衡二叉树)时为 O(log(N)),最坏情况下(完全不平衡二叉树)时为 O(N)。

    总结:

    # 递归做法比较简洁,但是每轮递归都要开辟栈空间。
    # 迭代做法利用了一个队列,由于比较树形结构,所以将其对应节点做为pair是非常好的思想

    4.对称二叉树

    题目:

    给定一个二叉树,检查它是否是镜像对称的。

    说明:

    如果你可以运用递归和迭代两种方法解决这个问题,会很加分。

    示例:

    例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
    
        1
       / 
      2   2
     /  / 
    3  4 4  3
    但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
    
        1
       / 
      2   2
          
       3    3

    代码1:

    class Solution:
        def isSymmetric(self, root: TreeNode) -> bool:
            # 递归,传入判断是否对称的两个节点
            def ismirror(left,right):
                # 如果都为空,表示对称
                if not left and not right:
                    return True
                # 如果只有一个为空,则不对称
                if not left or not right:
                    return False
                # 如果都不为空,但val不同,也不对称
                if left.val != right.val:
                    return False
                # 在当前两个节点对称的情况下,分别在求他们的子节点的是否都对称
                return ismirror(left.left, right.right) and ismirror(left.right,right.left)
    
            return ismirror(root,root)

    递归解法。

    代码2:

    class Solution:
        def isSymmetric(self, root: TreeNode) -> bool:
            from collections import deque
            if not root:
                return True
            deq = deque([(root.left, root.right),])
            # st=[root.left,root.right]
            while deq:
                l,r=deq.popleft()
                if not l and not r:
                    continue
                elif not l or not r:
                    return False
                elif l.val!=r.val:
                    return False
                else:
                    deq.append((l.left,r.right))
                    deq.append((l.right,r.left))
            return True

    迭代做法,和前面的第3题一样,差不多的思路。

    总结:

    # 二叉树是否对称和前面第3题(两个二叉树是否相等)思路基本一致
    # 二叉树是否对称,可以看成 自己和自己的镜像是否完全相等
    # 所以两道题的递归做法和迭代做法都是很相似的

    ###

  • 相关阅读:
    如何改计算机用户名
    解决windows弹出'你可能是盗版软件的受害者...'及去除自动更新图标
    关于复制文件出现“Thumbs:访问被拒绝......”的解决办法和相关知识
    <百度分享平台>透明FLASH模块的方法
    绝对性解决打开我的电脑打开文件夹在新窗口中打开问题
    Git忽略规则(.gitignore配置)不生效原因和解决
    汇编学习笔记18
    汇编学习笔记21
    汇编学习笔记16
    汇编学习笔记22
  • 原文地址:https://www.cnblogs.com/leokale-zz/p/12392387.html
Copyright © 2011-2022 走看看