2020年1月29日正式开始刷题之路。
- 不再像之前那样随机做题,按照leetcode初级算法,中级算法,高级算法的设定循序渐进的开始。
- 因为已经开始了算法简介-递归的学习,就先把这个弄完,然后开始初级算法。
- 递归之反转字符串:
-
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组
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,返回杨辉三角的第 k 行。
-
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(x, n) ,即计算 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
替换为01
,1
替换为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.
-
-