diff --git a/.idea/algorithm020.iml b/.idea/algorithm020.iml new file mode 100644 index 00000000..0117fde1 --- /dev/null +++ b/.idea/algorithm020.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dictionaries/bigheadlu.xml b/.idea/dictionaries/bigheadlu.xml new file mode 100644 index 00000000..579f2d71 --- /dev/null +++ b/.idea/dictionaries/bigheadlu.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..af69ba38 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + Buildout + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..137444ae --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 00000000..0f0a3a1d --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,532 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1605966230842 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Week1/README.md b/Week1/README.md index 50de3041..07483e99 100644 --- a/Week1/README.md +++ b/Week1/README.md @@ -1 +1,3 @@ -学习笔记 \ No newline at end of file +学习笔记 +在python中,queue是基于deque实现的。deque拥有queue的全部特性,所以queue的实现相当于只利用了deque的部分特性。 +在python中,heapq基于堆的特性来实现的,其中堆则直接借助list来实现。其中,算法的核心就是维护这个堆。 \ No newline at end of file diff --git a/Week1/deque_add.py b/Week1/deque_add.py new file mode 100644 index 00000000..25798232 --- /dev/null +++ b/Week1/deque_add.py @@ -0,0 +1,14 @@ +"""用 add first 或 add last 这套新的 API 改写 Deque 的代码""" +## 不太明白题意 + +from collections import deque + +# initiate a deque of python +test_deq = deque([1,2,3,4,5]) +# 相当于java里的add_last +test_deq.append(6) +# 相当于java里的add_first +test_deq.appendleft(0) + +print(test_deq) + diff --git a/Week1/easy/__init__.py b/Week1/easy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week1/easy/dedupe_array.py b/Week1/easy/dedupe_array.py new file mode 100644 index 00000000..864969b6 --- /dev/null +++ b/Week1/easy/dedupe_array.py @@ -0,0 +1,26 @@ +# ============================================ +# Leetcode 26. 删除排序数组中的重复项 +# 审题: 1. 原地删除,空间复杂度为O(1); 2.数组已为排序过的数组; 3)只需返回新数组的长度。 +# seen before +# 解体思路: 快慢指针 +# time complexity: O(n) +# ============================================ + + +class Solution(object): + def removeDuplicates(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + slow = 0 + fast = 1 + while (fast <= len(nums) - 1): + if nums[slow] == nums[fast]: + fast += 1 + else: + slow += 1 + nums[slow] = nums[fast] + fast += 1 + return slow+1 + diff --git a/Week1/easy/move_zero.py b/Week1/easy/move_zero.py new file mode 100644 index 00000000..cab09150 --- /dev/null +++ b/Week1/easy/move_zero.py @@ -0,0 +1,28 @@ +# ============================================ +# Leetcode 283. 移动零 +# 审题: 1.必须在原数组上操作 +# seen before +# 解体思路: 快慢指针 +# time complexity: O(n) +# ============================================ + +class Solution(object): + def moveZeroes(self, nums): + """ + :type nums: List[int] + :rtype: None Do not return anything, modify nums in-place instead. + """ + slow = 0 + fast = 1 + while (fast <= len(nums) - 1): + if nums[slow] != 0: + slow += 1 + fast += 1 + else: + if nums[fast] != 0: + nums[slow], nums[fast] = nums[fast], nums[slow] + slow += 1 + fast += 1 + else: + fast += 1 + return nums \ No newline at end of file diff --git a/Week1/hard/__init__.py b/Week1/hard/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week1/hard/trapping_rain_water.py b/Week1/hard/trapping_rain_water.py new file mode 100644 index 00000000..1b3fbc9f --- /dev/null +++ b/Week1/hard/trapping_rain_water.py @@ -0,0 +1,39 @@ +# ============================================ +# Leetcode 283. 移动零 +# 审题: 1.non-negative integers +# seen similar one before: nextGreaterNumber, largest rectangle? +# 解体思路: 有序stack +# time complexity: O(n) +# ============================================ + + +class Solution(object): + def trap(self, height): + """ + :type height: List[int] + :rtype: int + """ + stack = [] + # record block value + memo = 0 + # record total trapped rainy water + total = 0 + for i, ele in enumerate(height[::-1]): + while (len(stack) != 0) and (stack[-1][1] < ele): + memo += stack.pop()[1] + # current ele as left bound, s.top() as right bound + if len(stack) != 0: + volume = ele * (stack[-1][0] - i - 1) - memo + if volume > 0: + total += volume + # stack.pop() + stack.append((i, ele)) + memo = 0 + return total + + + + + + + diff --git a/Week1/medium/__init__.py b/Week1/medium/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week2/README.md b/Week2/README.md index 50de3041..a608f8b9 100644 --- a/Week2/README.md +++ b/Week2/README.md @@ -1 +1,8 @@ -学习笔记 \ No newline at end of file +学习笔记 + +2. 为什么和树相关的问题一般会使用递归的方式? + 1) 树的结构决定了树在大多数情况下是不适合用循环的方法: 如果树的每个节点除了有可以储存值的数据域,还有两个分别指向左孩子和右孩子的指针,这两个指针可以类比链表里的单指针,但是它们只能遍历子树的一个孩子一下的一些节点, + 由于树的这种特性也就决定了树在大多数情况下是不适合用循环的方法去解决问题的;但是这里也有一种可能树的结构和链表单指针结构是一样的,就是树的所有节点的度(即孩子的个数只为1). + 2) 树的节点 + (左子树) + (右子树), 左子树 = 左子树节点 + (subleftroot.left) + (subleftroot.right), 右子树 = 右子树节点 + (subrightroot.left) + (subrightroot.right), + 而所有节点都是同一属性的TreeNode, 这就是一个层层嵌套的结构,一个树是含有重复嵌套结构或者说重复子问题的结构。 + 3)在实际的一些应用场景,解决树的一些问题例如插入、删除操作需要先遍历再做访问,在这里可以使用循环的方法,但是要借助栈做缓存保留遍历的记忆,这个本质上还是和递归里层层走进嵌入的模式是一样的。 diff --git a/Week2/__init__.py b/Week2/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week2/easy/__init__.py b/Week2/easy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week2/easy/isAnagram.py b/Week2/easy/isAnagram.py new file mode 100644 index 00000000..9a2fbc67 --- /dev/null +++ b/Week2/easy/isAnagram.py @@ -0,0 +1,53 @@ +# ============================================ +# Leetco 242. 有效的字母异位词 +# 审题: 1. 进阶的情况: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况 +# not seen before +# 解体思路: 字典形式储存词频 +# time complexity: O(2n)≈O(n) +# ============================================ + + +# TODO Solution1 +#执行用时:48 ms, 在所有 Python 提交中击败了51.42%的用户 +#内存消耗:14.9 MB, 在所有 Python 提交中击败了11.08%的用户 +class Solution1(object): + def isAnagram(self, s, t): + """ + :type s: str + :type t: str + :rtype: bool + """ + # record the frequency/count of letters in s by key-value data structure + dict_ct = {} + if len(s) != len(t): + return False + for i in range(len(s)): + if s[i] not in dict_ct: + dict_ct[s[i]] = 0 + dict_ct[s[i]] += 1 + for i in range(len(t)): + if t[i] in dict_ct: + dict_ct[t[i]] -= 1 + else: + return False + + if dict_ct[t[i]] == 0: + del dict_ct[t[i]] + + return (not dict_ct) + + +# TODO 内存还是没有上来 +class Solution2(object): + def isAnagram(self, s, t): + """ + :type s: str + :type t: str + :rtype: bool + """ + if len(s) != len(s): + return False + if sorted(s) == sorted(t): + return True + else: + return False \ No newline at end of file diff --git a/Week2/easy/preorder.py b/Week2/easy/preorder.py new file mode 100644 index 00000000..e5e48f2b --- /dev/null +++ b/Week2/easy/preorder.py @@ -0,0 +1,51 @@ +# ============================================ +# Leetco 242. 有效的字母异位词 +# 审题: 1. 对一个node的定义,判断一个node,直接可以if node,无需node.val, 不然会有'NoneType has no attribute of val'。 +# not seen before +# 解体思路: 1.递归;2.stack 迭代 +# time complexity: 1.recursive: O(n), n=Tree.size +# ============================================ + +""" +# Definition for a Node. +class Node(object): + def __init__(self, val=None, children=None): + self.val = val + self.children = children +""" + + +class Solution(object): + + def preorder(self, root): + """ + :type root: Node + :rtype: List[int] + """ + vec = [] + if not root: + return vec + + def preorder_helper(node): + vec.append(node.val) + if node.children: + for child in node.children: + preorder_helper(child) + return vec + return preorder_helper(root) + +class Solution(object): + def preorder(self, root): + """ + :type root: Node + :rtype: List[int] + """ + vec = [] + if not root: + return vec + # root first + vec.append(root.val) + # preorder in children + for child in root.children: + vec.extend(self.preorder(child)) + return vec diff --git a/Week2/medium/__init__.py b/Week2/medium/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week2/medium/topK.py b/Week2/medium/topK.py new file mode 100644 index 00000000..bd48a382 --- /dev/null +++ b/Week2/medium/topK.py @@ -0,0 +1,8 @@ +# ============================================ +# Leetco 347. 前 K 个高频元素 +# 审题: 1. 对一个node的定义,判断一个node,直接可以if node,无需node.val, 不然会有'NoneType has no attribute of val'。 +# not seen before +# 解体思路: 1.哈希表储存,再进行排序;2.heapq(堆) (O(NlogK)); 3.sort (O(NlogN)) +# time complexity: 1.O(NlogN); +# ============================================ + diff --git a/Week3/README.md b/Week3/README.md index 50de3041..08043643 100644 --- a/Week3/README.md +++ b/Week3/README.md @@ -1 +1,11 @@ -学习笔记 \ No newline at end of file +学习笔记 +1. 树的递归: + - 要掌握树的三种遍历方法,前序、中序和后序遍历 + - 树的节点插入与删除 (要巩固时间复杂度) + + +2. 本周涉及到的分治、回溯 (其中回溯相关的内容我还需自己要加强理解): + + 自己结合超哥总结,动态规划、分治、回溯其实本质是属于同一类型的问题。它们都可以用递归的方法去解决。 + 分治 (分而治之) 可归纳为一个算法问题,回溯可归纳为一个算法技术,而动态规划就像是这同一类问题中的算法思想。 + 它们三者都会涉及到一个根本性的问题,就是要解决重复子问题。(而动态规划还要考虑到一个最优子结构的问题)。 \ No newline at end of file diff --git a/Week3/medium/__init__.py b/Week3/medium/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week3/medium/buildTree_preorder_inorder.py b/Week3/medium/buildTree_preorder_inorder.py new file mode 100644 index 00000000..04baf85b --- /dev/null +++ b/Week3/medium/buildTree_preorder_inorder.py @@ -0,0 +1,42 @@ +# ============================================ +# 105. Construct Binary Tree from Preorder and Inorder Traversal +# 审题: You may assume that duplicates do not exist in the tree. +# not seen before, not solved alone, idea following the solutions proposed in leetcode +# 解体思路: 1.递归;2.迭代 +# time complexity: 1.recursive: O(n), n=Tree.size +# ============================================ + + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +# TODO, 不是最优解法,还需改进内存与速度 +class Solution(object): + def buildTree(self, preorder, inorder): + """ + :type preorder: List[int] + :type inorder: List[int] + :rtype: TreeNode + """ + # recursion terminator + if (len(preorder) <= 0) or (len(inorder) <= 0): + return None + + # process current level + root = TreeNode() + root.val = preorder[0] + in_pointer = inorder.index(root.val) + + # drill down + # in_pointer also means the number of left nodes here + root.left = self.buildTree(preorder[1:in_pointer + 1], inorder[0:in_pointer]) + root.right = self.buildTree(preorder[in_pointer + 1:], inorder[in_pointer + 1:]) + # reverse + # merge + return root \ No newline at end of file diff --git a/Week3/medium/lca.py b/Week3/medium/lca.py new file mode 100644 index 00000000..0e0334f3 --- /dev/null +++ b/Week3/medium/lca.py @@ -0,0 +1,58 @@ +# ============================================ +# 236. Lowest Common Ancestor of a Binary Tree +# 审题: +# not seen before, not solved alone, idea following the solutions proposed in leetcode +# 解体思路: 1.递归;2.迭代 +# time complexity: 1.recursive: O(n), n=Tree.size +# ============================================ + +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +# TODO, this solution is not efficient +class Solution1(object): + def lowestCommonAncestor(self, root, p, q): + """ + :type root: TreeNode + :type p: TreeNode + :type q: TreeNode + :rtype: TreeNode + """ + if (root == None) or (root == p) or (root == q): + return root + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + + if (left) and (right): + return root + else: + if left: + return left + elif right: + return right + + +class Solution2(object): + def lowestCommonAncestor(self, root, p, q): + """ + :type root: TreeNode + :type p: TreeNode + :type q: TreeNode + :rtype: TreeNode + """ + if root in (None, p, q): + return root + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + + if all((left, right)): + return root + else: + if left: + return left + elif right: + return right diff --git a/Week4/easy/__init__.py b/Week4/easy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Week4/easy/assign_cookies.py b/Week4/easy/assign_cookies.py new file mode 100644 index 00000000..beb5afa9 --- /dev/null +++ b/Week4/easy/assign_cookies.py @@ -0,0 +1,27 @@ +# ============================================ +# 455. Assign Cookies +# 审题: 1.每个孩子最多只能给一块饼干。2.你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 +# not seen before, not solved alone, idea following the solutions proposed in leetcode +# 解体思路: 1.贪心思想。 +# time complexity: 1.O(nlongn) + O(n) ≈ O(nlogn) +# ============================================ + + +class Solution(object): + def findContentChildren(self, g, s): + """ + :type g: List[int] + :type s: List[int] + :rtype: int + """ + if (len(g) == 0) or (len(s) == 0): + return 0 + g.sort(reverse=False) + s.sort(reverse=False) + child = 0 + bisc = 0 + while (bisc <= len(s)-1) and (child <= len(g)-1): + if (s[bisc] >= g[child]): + child += 1 + bisc += 1 + return child diff --git a/Week4/easy/lemon_change.py b/Week4/easy/lemon_change.py new file mode 100644 index 00000000..69116693 --- /dev/null +++ b/Week4/easy/lemon_change.py @@ -0,0 +1,39 @@ +# ============================================ +# 860. Lemonade Change +# 审题: 1. 一开始你手头没有任何零钱; 2. 只有5, 10, 20三种类型。 +# not seen before, not solved alone, idea following the solutions proposed in leetcode +# 解体思路: 1.枚举所有可能的找零方式; 2.找零时贪心思想。 +# time complexity: 1.O(n) +# ============================================ + + +# TODO, 内存消耗太大 +class Solution(object): + def lemonadeChange(self, bills): + """ + :type bills: List[int] + :rtype: bool + """ + cash_5 = 0 + cash_10 = 0 + ct = 0 + for ele in bills: + if ele == 5: + cash_5 += 1 + elif ele == 10: + if cash_5 < 1: + return False + cash_10 += 1 + cash_5 -= 1 + # ele == 20 + else: + if (cash_10 > 0) and (cash_5 > 0): + cash_10 -= 1 + cash_5 -= 1 + elif (cash_5 >= 3): + cash_5 -= 3 + else: + return False + return True + +