leetcode - 刷题记录

2020年1月29日正式开始刷题之路。

  1. 不再像之前那样随机做题,按照leetcode初级算法,中级算法,高级算法的设定循序渐进的开始。
  2. 因为已经开始了算法简介-递归的学习,就先把这个弄完,然后开始初级算法。
  • 递归之反转字符串:
    • 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

      不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

      你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

    • class Solution(object):
          def reverseString(self, s):
              """
              :type s: List[str]
              :rtype: None Do not return anything, modify s in-place instead.
              """
              if len(s)==0:
                  return s
              else:
                  s[0],s[-1] = s[-1],s[0]
                  if len(s) <= 3:
                      return s
                  else:
                      s[1:-1]=self.reverseString(s[1:-1])
                      return s

      提交代码后显示:477/478个通过测试用例,总是说超出内存限制,不知道该怎么改进了。。。哭哭

  • 递归之两两交换链表中的节点:

    • 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

      你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

    • # Definition for singly-linked list.
      # class ListNode(object):
      #     def __init__(self, x):
      #         self.val = x
      #         self.next = None
      
      class Solution(object):
          def swapPairs(self, head):
              """
              :type head: ListNode
              :rtype: ListNode
              """
              if head is None or head.next is None:
                  return head
              else:
                  tmp = head.next.next
                  h = head.next
                  h.next = head
                  if tmp is None:
                      h.next.next = None
                      return h
                  else:
                      h.next.next = self.swapPairs(tmp)
                      return h

      通过

  • 递归之杨辉三角:

    • 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

    • class Solution(object):
          def generate(self, numRows):
              """
              :type numRows: int
              :rtype: List[List[int]]
              """
              if  numRows == 0:
                  return []
              elif numRows == 1:
                  return [[1]]
              elif numRows == 2:
                  return [[1],[1,1]]
              else:
                  res_1 = self.generate(numRows-1)
                  last_e = res_1[-1]
                  new = [1]
                  for i in range(len(last_e)-1):
                      new.append(last_e[i]+last_e[i+1])
                  new.append(1)
                  res_1.append(new)
                  return res_1

      通过

  • 递归之杨辉三角II:

    • 给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 行。

    • class Solution(object):
          def getRow(self, rowIndex):
              """
              :type rowIndex: int
              :rtype: List[int]
              """
              if rowIndex == 0:
                  return [1]
              elif rowIndex == 1:
                  return [1,1]
              else:
                  last_e = self.getRow(rowIndex-1)
                  last_e_1 = last_e[1:]
                  new = [1] + [sum(x) for x in zip(last_e,last_e_1)] + [1]
                  return new

      通过

  • 递归之反转链表:

    • 反转一个单链表。可以迭代或递归地反转链表

    • # Definition for singly-linked list.
      # class ListNode(object):
      #     def __init__(self, x):
      #         self.val = x
      #         self.next = None
      
      class Solution(object):
          def reverseList(self, head):
              """
              :type head: ListNode
              :rtype: ListNode
              """
              #print('head',head)
              if head is None or head.next is None:
                  return head
              else:
                  # recursion
                  last = self.reverseList(head.next)
                  head.next.next = head
                  head.next = None
                  return last
                  # iteration
                  p = head
                  q = head.next
                  p.next = None
                  while q is not None:
                      r = q.next
                      q.next = p
                      p = q
                      q = r
                  return p

      通过

      • 这是很经典,也花了很长时间理解的一个题目,对于理解递归帮助很大。递归的精髓在于:理解递归函数的输出,或是定义。例如反转链表时,首先确认好,函数返回的会是一个反转好的链表的head,那么,调用self.reverseList(head.next)获得的就是一个已经反转好的链表,最后一个element是head.next!!!

  • 递归的重复计算问题:记忆化

    • 递归之斐波那契数:

      • 斐波那契数,给定 N,计算 F(N)

      • class Solution(object):
            def fib(self, N):
                """
                :type N: int
                :rtype: int
                """
                # original
                if N == 0:
                    return 0
                elif N == 1:
                    return 1
                else:
                    return self.fib(N-1)+self.fib(N-2)
                
                # memorization
                dic_fib = {0:0,1:1}
                def save_fib(N):
                    print(dic_fib)
                    if N in dic_fib:
                        return dic_fib[N]
                    else:
                        s = save_fib(N-1)+save_fib(N-2)
                        dic_fib[N] = s
                        return s
                return save_fib(N)
                

        通过

    • 递归之爬楼梯:

      • 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

        每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

        注意:给定 n 是一个正整数。

      • class Solution(object):
            def climbStairs(self, n):
                """
                :type n: int
                :rtype: int
                """
                if n==1:
                    return 1
                elif n==2:
                    return 2
                else:
                    return self.climbStairs(n-1)+self.climbStairs(n-2)
                # 以上是没有采用记忆化技术的实现,在n=18时,就已经超过代码运行时间限制。
                
                save_dic = {1:1,2:2}
                def save_sta(n):
                    if n in save_dic:
                        return save_dic[n]
                    else:
                        s = save_sta(n-1)+save_sta(n-2)
                        save_dic[n]=s
                        return s
                return save_sta(n)
                # 采用记忆化技术后,可以通过全部测试样例。
                
                def pos_des(i,n):
                    if i>n:
                        return 0
                    elif i==n:
                        return 1
                    else:
                        return pos_des(i+1,n) + pos_des(i+2,n)
                return pos_des(0,n)
                # 最后这种是暴力法,没有通过全部测试用例。
                # pos_des中,i代表了当前位置,n代表了目标位置。
                # 当前位置可以走一个台阶或者两个台阶 是一开始都会想到,但是无法很好实现。

        通过

  • 递归的复杂度分析

    • 递归之二叉树最大深度:

      • 给定一个二叉树,找出其最大深度。

        二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

        说明: 叶子节点是指没有子节点的节点。

      • class Solution(object):
            def maxDepth(self, root):
                """
                :type root: TreeNode
                :rtype: int
                """
                
                # recursion
                if not root:
                    return 0
                else:
                    if root.left is not None and root.right is not None:
                        depth = max(self.maxDepth(root.right),self.maxDepth(root.left)) + 1
                    elif root.left is None and root.right is not None:
                        depth = self.maxDepth(root.right) + 1
                    elif root.left is not None and root.right is None:
                        depth = self.maxDepth(root.left) + 1
                    #elif root.left is None and root.right is None:
                    else:
                        depth = 1
                return depth
                
                #  iteration
                depth_root = []
                if root is not None:
                    depth_root.append((1,root))
                depth = 0
                while depth_root != []:
                    current_depth,root = depth_root.pop()
                    if root is not None:
                        depth = max(depth,current_depth)
                        depth_root.append((current_depth+1,root.left))
                        depth_root.append((current_depth+1,root.right))
                return depth           

        通过,迭代的方法值得好好学习。

    • 递归之Pow(x, n):

      • 实现 pow(xn) ,即计算 x 的 n 次幂函数。

      • class Solution(object):
            def myPow(self, x, n):
                """
                :type x: float
                :type n: int
                :rtype: float
                """
                # violence
                if x==1 or n==0:
                    return 1
                if n<0:
                    x = 1/x
                    n = abs(n)
                return x*self.myPow(x, n-1)
                
                # square
                if x == 1 or n == 0:
                    return 1.0
                
                if n<0:
                    x = 1/x
                    n = abs(n)
                
                if n % 2 == 1:
                    return x*float(self.myPow(x, n/2)**2)
                else:
                    return float(self.myPow(x, n/2)**2)

        无脑递归的实现无法通过所以测试用例,会出现runtime error之类的。需要利用x^n = (x^(n/2))^2减少递归次数。

  • 递归之总结

    • 递归之合并两个有序链表:

      • 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

      • # Definition for singly-linked list.
        # class ListNode(object):
        #     def __init__(self, x):
        #         self.val = x
        #         self.next = None
        
        class Solution(object):
            def mergeTwoLists(self, l1, l2):
                """
                :type l1: ListNode
                :type l2: ListNode
                :rtype: ListNode
                """
                
                # recursion
                if l1 is None:
                    return l2
                elif l2 is None:
                    return l1
                
                if l1.val < l2.val:
                    sub_list = self.mergeTwoLists(l1.next, l2)
                    l1.next = sub_list
                    return l1
                else:
                    sub_list = self.mergeTwoLists(l1, l2.next)
                    l2.next = sub_list
                    return l2
                
                # iteration
                if l1 is None:
                    return l2
                elif l2 is None:
                    return l1
                
                if l1.val<l2.val:
                    p = l1
                    l1 = l1.next
                else:
                    p = l2
                    l2 = l2.next
                res = p
                while l1 is not None and l2 is not None:
                    if l1.val<l2.val:
                        p.next = l1
                        l1 = l1.next
                    else:
                        p.next = l2
                        l2 = l2.next
                    p = p.next
                if l1 is None and l2 is not None:
                    p.next = l2
                elif l1 is not None and l2 is None:
                    p.next = l1
                return res

        通过

    • 递归之第K个语法符号:

      • 在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为011替换为10

        给定行数 N 和序数 K,返回第 N 行中第 K个字符。(K从1开始)

      • class Solution(object):
            def kthGrammar(self, N, K):
                """
                :type N: int
                :type K: int
                :rtype: int
                """
                # recursion
                if N==1:
                    return 0
                elif N==2 and K==1:
                    return 0
                elif N==2 and K==2:
                    return 1
                sub_res = self.kthGrammar(N-1, K/2) if K % 2 == 0 else self.kthGrammar(N-1, (K+1)/2)
                # 0-->01 1-->10
                res = 1 if (sub_res==0 and K%2==0) or (sub_res==1 and K%2==1) else 0
                return res
                
                # memorize
                dic_n_k = {11:0,12:0,21:0,22:1}
                def sub_kthGrammar(n,k):
                    if 10*n+k in dic_n_k:
                        return dic_n_k[10*n+k]
                    else:
                        sub_res = sub_kthGrammar(n-1, k/2) if k % 2 == 0 else sub_kthGrammar(n-1, (k+1)/2)
                        if k % 2 == 0:
                            dic_n_k [10*(n-1)+(k/2)] = sub_res
                        else:
                             dic_n_k [10*(n-1)+((k+1)/2)] = sub_res
                    res = 1 if (sub_res==0 and k%2==0) or (sub_res==1 and k%2==1) else 0
                    return res
                return sub_kthGrammar(N,K)

        通过 原始递归方法耗时24ms完成全部测试用例,记忆化技术方法耗时16ms.

发布了45 篇原创文章 · 获赞 1 · 访问量 8565

猜你喜欢

转载自blog.csdn.net/qq_32110859/article/details/104103956
今日推荐