diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 000000000..0569ad13d
Binary files /dev/null and b/.DS_Store differ
diff --git a/Summary.md b/Summary.md
new file mode 100644
index 000000000..b1ec0cedf
--- /dev/null
+++ b/Summary.md
@@ -0,0 +1,8 @@
+与我而言 训练营是一段督促自己学习的过程
+有些东西 确实我们都学过,但是就是容易忘记
+而且学了也不一定做的了题 在训练营的时间 主要就是过遍数
+五毒神掌 往往是有些基础题 我还没有做到 有些题目 看着无比熟悉 却还是没法10min解决
+目前209道题 慢慢往后做吧 刷题这件事 对于没有上岸的人 真不是一朝一夕能完成的任务
+道阻且长 我将继续前行
+另外 我总结了一些 常见的套路题 放在另外的仓库了
+[部分面试题总结](https://github.com/mqray/leetcode)
\ No newline at end of file
diff --git a/Week01/.DS_Store b/Week01/.DS_Store
new file mode 100644
index 000000000..4eb4a7a45
Binary files /dev/null and b/Week01/.DS_Store differ
diff --git a/Week01/.idea/Week01.iml b/Week01/.idea/Week01.iml
new file mode 100644
index 000000000..7c9d48f0f
--- /dev/null
+++ b/Week01/.idea/Week01.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml
new file mode 100644
index 000000000..274582e1b
--- /dev/null
+++ b/Week01/.idea/leetcode/editor.xml
@@ -0,0 +1,185 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week01/.idea/misc.xml b/Week01/.idea/misc.xml
new file mode 100644
index 000000000..399908725
--- /dev/null
+++ b/Week01/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week01/.idea/modules.xml b/Week01/.idea/modules.xml
new file mode 100644
index 000000000..8c762a0d7
--- /dev/null
+++ b/Week01/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week01/.idea/vcs.xml b/Week01/.idea/vcs.xml
new file mode 100644
index 000000000..6c0b86358
--- /dev/null
+++ b/Week01/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml
new file mode 100644
index 000000000..0f8fff7a4
--- /dev/null
+++ b/Week01/.idea/workspace.xml
@@ -0,0 +1,823 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1591629823930
+
+
+ 1591629823930
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week01/2Sum.py b/Week01/2Sum.py
new file mode 100644
index 000000000..688b0e591
--- /dev/null
+++ b/Week01/2Sum.py
@@ -0,0 +1,48 @@
+# 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
+#
+# 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
+#
+#
+#
+# 示例:
+#
+# 给定 nums = [2, 7, 11, 15], target = 9
+#
+# 因为 nums[0] + nums[1] = 2 + 7 = 9
+# 所以返回 [0, 1]
+#
+# Related Topics 数组 哈希表
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def twoSum(self, nums, target):
+ """
+ :type nums: List[int]
+ :type target: int
+ :rtype: List[int]
+ """
+ # 只用找到一组解的下标即可
+ # 1.暴力解法:两重循环
+ # 2.hash表记录 两次hash
+ # 3.一次hash表
+ # 击败18%
+ # for i in range(len(nums)-1):
+ # for j in range(i + 1, len(nums)):
+ # if nums[i] + nums[j] == target:
+ # return [i, j]
+ # 击败53%
+ # dict = {}
+ # for ind, num in enumerate(nums): # 创建hash表
+ # dict[num] = ind
+ # for ind, num in enumerate(nums): # 遍历hash表
+ # j = dict.get(target - num)
+ # if j and ind != j: # 排除[2,3] 4这种情况
+ # return [ind, j]
+ # 击败78%
+ dict = {}
+ for ind, num in enumerate(nums):
+ if dict.get(target - num) is not None:
+ return [dict.get(target - num), ind]
+ dict[num] = ind
+# leetcode submit region end(Prohibit modification and deletion)
diff --git a/Week01/3Sum.py b/Week01/3Sum.py
new file mode 100644
index 000000000..be458e530
--- /dev/null
+++ b/Week01/3Sum.py
@@ -0,0 +1,103 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/11 2:20 PM
+
+# 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复
+# 的三元组。
+#
+# 注意:答案中不可以包含重复的三元组。
+#
+#
+#
+# 示例:
+#
+# 给定数组 nums = [-1, 0, 1, 2, -1, -4],
+#
+# 满足要求的三元组集合为:
+# [
+# [-1, 0, 1],
+# [-1, -1, 2]
+# ]
+#
+# Related Topics 数组 双指针
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def threeSum(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: List[List[int]]
+ """
+ # 1.暴力法,三重循环
+ # nums.sort()
+ # res = set()
+ # for i in range(len(nums)-2):
+ # for j in range(i+1,len(nums)-1):
+ # for m in range(j+1,len(nums)):
+ # if nums[i] + nums[j] + nums[m] == 0:
+ # res.add((nums[i],nums[j],nums[m]))
+ # return list([list(item) for item in res])
+ # 2.hash表+两重循环 击败5%
+ hashmap = {}
+ nums.sort()
+ res = set()
+ for ind, num in enumerate(nums):
+ hashmap[num] = ind
+ for i in range(len(nums)):
+ for j in range(i + 1, len(nums)):
+ target = 0 - nums[i] - nums[j]
+ if hashmap.get(target) is not None and hashmap[target] > j:
+ # Only need to check if the target value on the right side of (j)
+ res.add((nums[i], nums[j], target))
+ return list(res)
+
+ # 外层循环+双指针 击败7%
+ # nums.sort()
+ # res = set()
+ # for i in range(len(nums)):
+ # left, right = i + 1, len(nums) - 1
+ # while left < right:
+ # if nums[left] == nums[left+1]:#[0,0,0]会报错
+ # left += 1
+ # continue
+ # tmp = nums[i] + nums[left] + nums[right]
+ # if tmp < 0:
+ # left += 1
+ # elif tmp > 0:
+ # right -= 1
+ # else:
+ # res.add((nums[i], nums[left], nums[right]))
+ # left, right = left + 1, right - 1
+ # return list(res)
+
+ # 外层循环+双指针 + 预处理去重 击败76%
+ nums.sort()
+ res = []
+ for i in range(len(nums)-2):
+ if nums[i]>0:#plus this line ,you can beat 93%
+ break
+ if i > 0 and nums[i] == nums[i - 1]:
+ continue
+ left, right = i + 1, len(nums) - 1
+ while (left < right):
+ tmp = nums[i] + nums[left] + nums[right]
+ if tmp < 0:
+ left = left + 1
+ elif tmp > 0:
+ right = right - 1
+ else:
+ res.append((nums[i], nums[left], nums[right]))
+ while (left < right) and nums[left] == nums[left + 1]:
+ left = left + 1
+ while (left < right) and nums[right] == nums[right - 1]:
+ right = right - 1
+ left = left + 1 #put the two lines, you can
+ right = right - 1
+ return res
+
+ # leetcode submit region end(Prohibit modification and deletion)
+s = Solution()
+# res = s.threeSum([-4,-1,-1,0,1,2])
+res = s.threeSum([0,0,0])
+print(res)
\ No newline at end of file
diff --git a/Week01/NOTE.md b/Week01/NOTE.md
index 50de30414..c31ebd77f 100644
--- a/Week01/NOTE.md
+++ b/Week01/NOTE.md
@@ -1 +1,413 @@
-学习笔记
\ No newline at end of file
+学习笔记
+
+#### 两数之和
+1.暴力解法 两次遍历枚举出所有可能的数的配对 时间复杂度是O(N^2)
+ 两重循环的标准写法:
+
+```python
+for i in range(len(nums)-1):#给第二个指针预留一个位置
+for j in range(i + 1, len(nums)):#这里从第一个指针的下一个位置开始
+ if nums[i] + nums[j] == target:
+ return [i, j]
+```
+
+2.两次hash表 第一次遍历数组,将所有元素的对应解`target-nums[i]`作为`key`存入hash表中
+ 下一次遍历此数组时,查询hash表中的内容
+
+```python
+dict = {}
+for ind, num in enumerate(nums): # 创建hash表
+ dict[num] = ind
+for ind, num in enumerate(nums): # 遍历hash表
+ j = dict.get(target - num)
+ if j and ind != j: # 排除[2,3] 4这种情况
+ return [ind, j]
+```
+3.一次hash表 上面的两次hash表中,会存表示同样一组解的情形,比如`{'2':4}`和`{'4':2}`,所以可以在一次遍历时,先判断是否在hash表中,不在则加入;在即返回对应结果
+
+```python
+dict = {}
+for ind, num in enumerate(nums):
+ if dict.get(target - num) is not None:
+ return [dict.get(target - num), ind]
+ dict[num] = ind
+```
+
+--
+
+#### 三数之和
+1.同样可以采用暴力解法,三重循环枚举出所有可能的三元组,时间复杂度是O(N^3)
+ 三重循环的标准写法:
+
+```python
+nums.sort()
+res = set()
+for i in range(len(nums)-2):
+ for j in range(i+1,len(nums)-1):
+ for m in range(j+1,len(nums)):
+ if nums[i] + nums[j] + nums[m] == 0:
+ res.add((nums[i],nums[j],nums[m]))
+return list([list(item) for item in res])
+```
+
+2. 排序+set去重+两次循环+二重循环+hash表
+ 第一次遍历时,构建hash表 `{'nums[i]':ind}`
+ 第二次循环,枚举可能的二元组,同时查询hash表检测是否存在
+
+```python
+hashmap = {}
+nums.sort()
+res = set()
+for ind, num in enumerate(nums):
+ hashmap[num] = ind
+for i in range(len(nums)):
+ for j in range(i + 1, len(nums)):
+ target = 0 - nums[i] - nums[j]
+ if hashmap.get(target) is not None and hashmap[target] > j:
+ # Only need to check if the target value on the right side of (j)
+ res.add((nums[i], nums[j], target))
+return list(res)
+```
+
+3. 排序+set去重+双指针+过滤解+排序数组首元素过滤正数优化
+
+```python
+nums.sort()
+res = []
+for i in range(len(nums)-2):
+ if nums[i]>0:#plus this line ,you can beat 93%
+ break
+ if i > 0 and nums[i] == nums[i - 1]:
+ continue
+ left, right = i + 1, len(nums) - 1
+ while (left < right):
+ tmp = nums[i] + nums[left] + nums[right]
+ if tmp < 0:
+ left = left + 1
+ elif tmp > 0:
+ right = right - 1
+ else:
+ res.append((nums[i], nums[left], nums[right]))
+ while (left < right) and nums[left] == nums[left + 1]:
+ left = left + 1
+ while (left < right) and nums[right] == nums[right - 1]:
+ right = right - 1
+ left = left + 1 #put the two lines, you can
+ right = right - 1
+return res
+```
+
+--
+
+#### 移动0
+1.暴力解法 遇到则将0移动到数组末尾
+ 每次遇到0,先加入到末尾,再删除这个0以调整数组,时间复杂度O(N^2)
+
+```python
+for num in nums:
+if num == 0:
+ nums.append(0)
+ nums.remove(0)
+```
+
+2.统计0的个数 同时删除这个0 如果不为0 则将它放到前面那个0的位置
+ 最后返回数组时,将count个0放到数组的末尾len-count开始的count个位置
+
+```python
+count = 0
+for i in range(len(nums)):
+ if nums[i]==0:
+ count = count + 1
+ else:#[0,1,0,3,12]
+ nums[i-count] = nums[i]
+for i in range(len(nums)-count,len(nums)):
+ nums[i] = 0
+```
+
+3.用指针记录当前0的个数 遇上不为0的数,则将它与前面记录的0的位置的元素进行交换
+
+```python
+index_0 = 0
+for i in range(len(nums)):
+ if nums[i] != 0:
+ nums[index_0], nums[i] = nums[i], nums[index_0]
+ index_0 = index_0 + 1
+return nums
+```
+
+--
+
+#### 爬楼梯
+1.蠢递归
+
+```python
+if n == 1: return 1
+if n == 2: return 2
+return self.climbStairs(n - 1) + self.climbStairs(n - 2)
+```
+
+2.递归+数组备忘录
+
+```python
+if n == 1: return 1
+tmp = [0 for _ in range(n)] # 开辟额外数组空间
+tmp[0], tmp[1] = 1, 2
+for i in range(2, n):
+ tmp[i] = tmp[i - 1] + tmp[i - 2]
+return tmp[-1]
+```
+
+3.递归+变量缓存
+
+```python
+if n == 1: return 1
+a, b = 1, 2
+for i in range(2, n):
+ a, b = b, a + b
+return b
+```
+
+--
+
+#### 容器的最大面积
+1.暴力枚举所有可能的面积 时间复杂度O(N^2)
+
+```python
+max_area = 0
+ for i in range(len(height)):
+ for j in range(i, len(height)):
+ area = (j - i) * min(height[j], height[i])
+ if max_area < area: max_area = area
+ return max_area
+```
+
+2.双指针
+
+```python
+left,right,area = 0,len(height)-1,0
+while left ListNode:
+ fast = slow = finder = head
+ while fast and fast.next:
+ fast, slow = fast.next.next, slow.next
+ if fast == slow:
+ while slow != finder:
+ slow, finder = slow.next, finder.next
+ return slow
+ return None
+```
+
+2. hash表
+
+```python
+hashtable = {}
+while head:
+ # if not in the hashtable
+ if not hashtable.get(head):
+ hashtable[head] = head
+ # must move back the head pointer, so it can continue while loop
+ head = head.next
+ else:
+ # if the node in hashtable, it must be the loop header
+ return head
+# if walk here head==None, so we just return None
+return None
+```
+
+--
+
+#### 加一
+判断进位,如果末位是9->末位修改为0 继续判断
+如果不为0,则该位置+1后return即可
+如果出现999这种情形,那循环只会讲digits处理为000,需要在前面添1
+
+```python
+for i in range(len(digits)-1,-1,-1):
+ if digits[i] != 9:
+ digits[i] += 1
+ return digits
+ digits[i] = 0 #[9,9,9,9]的情况处理完再返回
+return [1]+digits
+```
+
+
+--
+
+#### 旋转数组
+1. 切片后重新赋值
+
+```python
+#tmp = nums[len(nums) - k:] + nums[:len(nums) - k]
+#for i in range(len(tmp)):#这种赋值就比较傻
+# nums[i] = tmp[i]
+
+k = k % len(nums)#要考虑k大于数组长度的情形
+nums[:] = nums[len(nums) - k:] + nums[:len(nums) - k]
+```
+
+2.暴力解法 类似于bubble排序,k轮交换(从后往前),每一轮中交换len(nums)次
+
+```python
+for i in range(k%len(nums)): # 旋转k次
+ for j in range(len(nums) - 1, 0, -1):#反序调转
+ nums[j - 1], nums[j] = nums[j], nums[j - 1]
+```
+
+3.reverse三次,先reverse整个List,再reverse List[:k] 第三次reverse List[k:]
+
+
+4. 最大公约数解法,还未掌握
+
+--
+
+#### 合并两个有序数组
+1.暴力解法 将两个数组合并后重新排序
+
+```python
+nums1[:] = sorted((nums1[:m] + nums2))
+```
+2.两个指针分别指向数组的最小元素,将较小的元素放入nums1中
+
+```python
+tmp = nums1[:m]
+nums1[:] = []#注意这里要重新赋值,而不能只是传递引用
+i, j = 0, 0
+while i < m and j < n:
+ if tmp[i] < nums2[j]:
+ nums1.append(tmp[i])
+ i = i + 1
+ else:
+ nums1.append(nums2[j])
+ j = j + 1
+if i < m:#tmp数组中还有剩余元素
+ nums1[i+j:] = tmp[i:]
+if j < n:
+ nums1[i+j:] = nums2[j:]
+```
+3.两个指针指向数组的最大元素,将较大的元素插入到nums1末尾,无需额外的开辟数组空间
+
+```python
+i, j = m-1, n-1
+ind = m+n-1
+while i >= 0 and j >= 0:
+ if nums1[i] > nums2[j]:
+ nums1[ind] = nums1[i]
+ ind, i = ind-1, i-1
+ else:
+ nums1[ind] = nums2[j]
+ ind, j = ind-1, j-1
+#如果nums1中还有元素不需要处理
+#而如果是nums2中还有元素,那么说明nums1中前面的元素需要被替换
+nums1[:j+1] = nums2[:j+1]
+return nums1
+```
+
+--
+
+#### 合并两个有序链表
+
+```python
+def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
+ if not l1:#如果l1为空,直接返回l2
+ return l2
+ if not l2:#如果l2为空,直接返回l1
+ return l1
+ rhead = ListNode(None)#用来返回最后的结果的节点
+ pre = rhead #用来添加比较过的节点
+ while l1 and l2:#循环直到某链表没有值结束,刚开始这里写的是l1.next and l2.next 返回的结果是[1,1,2,4]
+ if l1.val <= l2.val:
+ tmp,l1 = l1,l1.next#
+ pre.next = tmp
+ pre = tmp
+ else:
+ tmp,l2 = l2,l2.next
+ pre.next = tmp
+ pre = tmp
+ if not l1:
+ pre.next = l2
+ if not l2:
+ pre.next = l1
+ return rhead.next
+```
+
+#### 删除排序数组中的重复数
+1.双指针 用指针记录不同元素的个数 思路比较天马行空 但是有迹可循 就是 用一个指针记录当前不同元素的个数,每次不相同时,就将这个指针更新,并且将num[i+1]赋值给指针指向的地址
+
+```python
+point = 0 # 指向前一个重复的数值
+for i in range(len(nums) - 1):
+ if nums[i] == nums[i + 1]:
+ continue
+ else:
+ point = point + 1
+ nums[point] = nums[i+1]
+return point+1
+```
+
+#### 最长公共前缀
+1. 先确定列表中最短字符串的长度size LCP应该小于等于它 然后外层循环遍历size长度,内层循环取每个字符的前size位,如果所有的都相匹配,则返回
+
+```python
+if not strs: return ''
+min_size = min([len(x) for x in strs]) # 公共前缀最长只会这么长
+for i in range(min_size, 0, -1):
+ tmp = strs[0][:i] # 当前待比较的公共前缀子串
+ if all(s[:i] == tmp for s in strs):
+ return tmp
+return ''
+```
+改进版
+```python
+prefix = strs[0] if strs else ''
+while True:
+ if all(s.startswith(prefix) for s in strs):
+ return prefix
+ prefix = prefix[:-1]
+```
diff --git "a/Week01/[239]\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274.py" "b/Week01/[239]\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274.py"
new file mode 100644
index 000000000..8c518d19f
--- /dev/null
+++ "b/Week01/[239]\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274.py"
@@ -0,0 +1,82 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/13 10:04 AM
+# 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
+#
+#
+# 返回滑动窗口中的最大值。
+#
+#
+#
+# 进阶:
+#
+# 你能在线性时间复杂度内解决此题吗?
+#
+#
+#
+# 示例:
+#
+# 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
+# 输出: [3,3,5,5,6,7]
+# 解释:
+#
+# 滑动窗口的位置 最大值
+# --------------- -----
+# [1 3 -1] -3 5 3 6 7 3
+# 1 [3 -1 -3] 5 3 6 7 3
+# 1 3 [-1 -3 5] 3 6 7 5
+# 1 3 -1 [-3 5 3] 6 7 5
+# 1 3 -1 -3 [5 3 6] 7 6
+# 1 3 -1 -3 5 [3 6 7] 7
+#
+#
+#
+# 提示:
+#
+#
+# 1 <= nums.length <= 10^5
+# -10^4 <= nums[i] <= 10^4
+# 1 <= k <= nums.length
+#
+# Related Topics 堆 Sliding Window
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+from collections import deque
+
+
+class Solution:
+ def maxSlidingWindow(self, nums: 'List[int]', k: 'int') -> 'List[int]':
+ # 超时了 时间复杂度是O(KN),空间复杂度是O(K)
+ # if not nums or k == 0: return []
+ # if k == 1: return nums
+ # res = []
+ # for i in range(len(nums)-k+1):
+ # cur = nums[i:i+k]
+ # res.append(max(cur))
+ # return res
+ if not nums or k == 0: return []
+ if k == 1: return nums
+ res = []
+ quene = deque()
+ for i in range(len(nums)):
+ while quene and nums[i] > nums[quene[-1]]:
+ quene.pop()
+ # 使用双端队列 考虑何时进何时出
+ # 进的规则是,如果队列里没有元素,直接进
+ # 如果队列里有元素,如果此时的元素大,就把队列里的元素抛出,再把这个值入对
+ # 如果一直都是更大的进来,队列首部的应该移除
+ quene.append(i) # 把这个元素的下标记录下来
+ if i - quene[0] == k:
+ quene.popleft()
+ if i + 1 >= k: # 有k个元素了,把nums[i-k:i]的最大值放进res,也就是quene[0]
+ res.append(nums[quene[0]]) # 应该把此时队首的值放入res中
+ return res
+
+
+# leetcode submit region end(Prohibit modification and deletion)
+
+
+s = Solution()
+res = s.maxSlidingWindow([1,3,-1,-3,5,3,6,7],3)
+print(res)
\ No newline at end of file
diff --git "a/Week01/[42]\346\216\245\351\233\250\346\260\264.py" "b/Week01/[42]\346\216\245\351\233\250\346\260\264.py"
new file mode 100644
index 000000000..256b9ae71
--- /dev/null
+++ "b/Week01/[42]\346\216\245\351\233\250\346\260\264.py"
@@ -0,0 +1,46 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/18 4:27 PM
+from typing import List
+class Solution:
+ def trap(self, height: List[int]) -> int:
+ if not height: return 0
+ size = len(height)-1
+ dp0 = [0] * (size + 1)
+ dp1 = [0] * (size + 1)
+ dp0[0] = height[0]
+ dp1[size] = height[-1]
+ for i in range(1,size):
+ dp0[i] = max(dp0[i-1],height[i])
+ for i in range(size-1,-1,-1):
+ dp1[i] = max(dp1[i+1],height[i])
+ res = 0
+ for i in range(size):
+ res += min(dp0[i],dp1[i]) - height[i]
+ return res
+
+class SolutionI:
+ def trap(self, height: List[int]) -> int:
+ # 这里的标准解法肯定是 单调栈
+ # 什么情况下能够接到雨水,当前height比左小,也比右小
+ # 也就是说 维护一个单调递减栈,遇到比栈顶元素小的,就入栈,遇到比栈顶元素大的,将栈顶元素出栈
+ # 计算刚才出栈元素下标出能接的水量
+ if not height: return 0
+ size = len(height)-1
+ stack = []
+ area = 0
+ for i in range(size+1):#[2,0,2]如果下标只遍历到1,就没有用到右边的2,输出是0
+ while stack and height[i] > height[stack[-1]]:
+ top = stack.pop()
+ if not stack: break#栈中只有一个元素的话,左边比当前元素还要小,存不住水
+ # 注意在计算高度的时候,top原本是有高度的
+ h = min(height[i],height[stack[-1]])-height[top]
+ w = i - stack[-1] -1
+ area += h*w
+ stack.append(i)
+ return area
+
+s = SolutionI()
+nums = [2,0,2]
+res = s.trap(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week01/[75]\350\215\267\345\205\260\345\233\275\346\227\227\351\227\256\351\242\230.py" "b/Week01/[75]\350\215\267\345\205\260\345\233\275\346\227\227\351\227\256\351\242\230.py"
new file mode 100644
index 000000000..beb274152
--- /dev/null
+++ "b/Week01/[75]\350\215\267\345\205\260\345\233\275\346\227\227\351\227\256\351\242\230.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/13 1:32 AM
+
+class Solution:
+ def sortColors(self, nums: List[int]) -> None:
+ """
+ Do not return anything, modify nums in-place instead.
+ """
+ left, right = 0, len(nums)-1
+ cur = 0
+ while cur<=right:#注意这里的循环条件
+ if nums[cur] == 0:
+ nums[left], nums[cur] = nums[cur], nums[left]
+ cur += 1
+ left += 1
+ elif nums[cur] == 2:
+ nums[cur],nums[right] = nums[right],nums[cur]
+ right -= 1
+ else:
+ cur += 1
+ # return nums
\ No newline at end of file
diff --git "a/Week01/k\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250.py" "b/Week01/k\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250.py"
new file mode 100644
index 000000000..14cf3415a
--- /dev/null
+++ "b/Week01/k\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250.py"
@@ -0,0 +1,77 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/12 6:33 PM
+
+# 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
+#
+# k 是一个正整数,它的值小于或等于链表的长度。
+#
+# 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
+#
+#
+#
+# 示例:
+#
+# 给你这个链表:1->2->3->4->5
+#
+# 当 k = 2 时,应当返回: 2->1->4->3->5
+#
+# 当 k = 3 时,应当返回: 3->2->1->4->5
+#
+#
+#
+# 说明:
+#
+#
+# 你的算法只能使用常数的额外空间。
+# 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
+#
+# Related Topics 链表
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for singly-linked list.
+class ListNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+
+class Solution(object):
+ def reverseKGroup(self, head, k):
+ """
+ :type head: ListNode
+ :type k: int
+ :rtype: ListNode
+ """
+
+ dummy = ListNode(-1)#dummy是用来返回最后的链表
+ dummy.next = head
+ pre = dummy#pre记录翻转过程每次翻转链表的前一个元素
+
+ while head:
+ tail = pre# last用以记录k个node的最后一个
+ for i in range(k):
+ tail = tail.next
+ if not tail:
+ return dummy.next#说明在取元素的时候没能够取到K个元素,返回的应该是头节点
+ next_head = tail.next#记录下个K组的首节点
+ head, tail = self.reverseList(head, tail)
+ # 将翻转后的链表接到原始链表上
+ pre.next = head
+ tail.next = next_head
+ # 调整此时的head和pre
+ head = next_head
+ pre = tail
+ return dummy.next
+
+ # 记录这K个node的第一个元素,最后将它作为尾元素返回 以连接到原始链表中
+ def reverseList(self, head, tail):
+ prev = tail.next
+ tail_node = head
+ while prev != tail:
+ tmp = head.next
+ head.next = prev
+ prev = head
+ head = tmp
+ return tail, tail_node
+# leetcode submit region end(Prohibit modification and deletion)
diff --git a/Week01/linkListTest.py b/Week01/linkListTest.py
new file mode 100644
index 000000000..845babe61
--- /dev/null
+++ b/Week01/linkListTest.py
@@ -0,0 +1,100 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/12 8:51 PM
+
+class ListNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+class LinkList:
+ def __init__(self):
+ self.head = None
+
+ def initList(self,data):
+ self.head = ListNode(data[0])#链表头
+ r,p = self.head,self.head
+ for i in data[1:]:#循环创建链表
+ node = ListNode(i)
+ p.next = node
+ p = p.next
+ return r#返回头指针
+
+ def printLinkList(self,head):
+ if not head:
+ return
+ node = head
+ while node != None:
+ print(node.val,'->',end='')
+ node = node.next
+class Solution(object):
+ def reverseKGroup(self, head, k):
+ dummy = ListNode(-1) #dummy是用来返回最后的链表
+ dummy.next = head
+ pre = dummy#pre记录翻转过程每次翻转链表的前一个元素
+ while head:
+ tail = pre# last用以记录k个node的最后一个
+ # 取出k个node
+ for i in range(k):
+ tail = tail.next
+ if tail is None:#说明在取元素的时候没能够取到K个元素,返回的应该是头节点
+ return dummy.next
+ next_head = tail.next#记录下个K组的首节点
+ head,tail = self.reverseLinkList(head, tail)#这里传next_head,当做最后一个节点
+ #将翻转后的链表接到原始链表上
+ pre.next = head
+ tail.next = next_head
+ #调整此时的head和pre
+ pre = tail
+ head = next_head
+ return dummy.next
+ def reverseLinkList(self,head,tail):
+ prev = tail.next
+ tail_node = head#记录这K个node的第一个元素,最后将它作为尾元素返回 以连接到原始链表中
+ while prev != tail:
+ tmp = head.next
+ head.next = prev
+ prev = head
+ head = tmp
+ return tail, tail_node
+# leetcode submit region end(Prohibit modification and deletion)
+
+class Solution1:
+ # 翻转一个子链表,并且返回新的头与尾
+ def reverse(self, head: ListNode, tail: ListNode):
+ prev = tail.next
+ p = head
+ while prev != tail:
+ nex = p.next
+ p.next = prev
+ prev = p
+ p = nex
+ return tail, head
+
+ def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
+ hair = ListNode(0)
+ hair.next = head
+ pre = hair
+
+ while head:
+ tail = pre
+ # 查看剩余部分长度是否大于等于 k
+ for i in range(k):
+ tail = tail.next
+ if not tail:
+ return hair.next
+ nex = tail.next
+ head, tail = self.reverse(head, tail)
+ # 把子链表重新接回原链表
+ pre.next = head
+ tail.next = nex
+ pre = tail
+ head = tail.next
+
+ return hair.next
+
+ll = LinkList()
+a = ll.initList([1,2,3,4,5,6])
+# ll.printLinkList(a)
+s = Solution()
+res = s.reverseKGroup(a,2)
+ll.printLinkList(res)
\ No newline at end of file
diff --git a/Week01/plusOne.py b/Week01/plusOne.py
new file mode 100644
index 000000000..fc52d2945
--- /dev/null
+++ b/Week01/plusOne.py
@@ -0,0 +1,46 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/14 10:23 PM
+# 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
+#
+# 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
+#
+# 你可以假设除了整数 0 之外,这个整数不会以零开头。
+#
+# 示例 1:
+#
+# 输入: [1,2,3]
+# 输出: [1,2,4]
+# 解释: 输入数组表示数字 123。
+#
+#
+# 示例 2:
+#
+# 输入: [4,3,2,1]
+# 输出: [4,3,2,2]
+# 解释: 输入数组表示数字 4321。
+#
+# Related Topics 数组
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def plusOne(self, digits):
+ """
+ :type digits: List[int]
+ :rtype: List[int]
+ """
+ #击败99%
+ for i in range(len(digits)-1,-1,-1):
+ if digits[i] != 9:
+ digits[i] += 1
+ return digits
+ digits[i] = 0 #[9,9,9,9]的情况处理完再返回
+ # digits.insert(0, 1)#这个击败89%
+ # return digits #往第0个位置插入1
+ return [1]+digits
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+res = s.plusOne([1,9])
+print(res)
diff --git "a/Week01/quene_deque_heap\345\210\206\346\236\220.md" "b/Week01/quene_deque_heap\345\210\206\346\236\220.md"
new file mode 100644
index 000000000..a2e7efa28
--- /dev/null
+++ "b/Week01/quene_deque_heap\345\210\206\346\236\220.md"
@@ -0,0 +1,418 @@
+ 1. 谷歌搜索[python quene](https://docs.python.org/3/library/queue.html)
+ 2. 点开第一个连接[A synchronized queue class](https://docs.python.org/3/library/queue.html)
+ 3. 能看到关于quene的代码都被保存在**Lib/queue.py**,可以下载python源码进行查阅。
+
+这个模块中实现了三种类型的队列
+
+```
+class queue.Queue(maxsize=0)#FIFO队列
+class queue.LifoQueue(maxsize=0)#LIFO队列
+class queue.PriorityQueue(maxsize=0)#优先级队列,通常需要借助heapq模块
+```
+>队列模块实现了多生产者、多使用者队列。当信息必须在多个线程之间安全地交换时,它在线程编程中特别有用。这个模块中的Queue类实现了所有所需的锁定语义。
+除此之外,还实现了名为`class queue.SimpleQueue`,它是最基本的FIFO队列,缺少任务追踪等功能。
+
+
+### `Quene()`
+
+#### __init__()
+实例方法,定义了队列相关操作需要的锁、标识符等
+
+```
+def __init__(self, maxsize=0):
+ self.maxsize = maxsize
+ self._init(maxsize)
+
+ # mutex must be held whenever the queue is mutating. All methods
+ # that acquire mutex must release it before returning. mutex
+ # is shared between the three conditions, so acquiring and
+ # releasing the conditions also acquires and releases mutex.
+ self.mutex = threading.Lock()
+
+ # Notify not_empty whenever an item is added to the queue; a
+ # thread waiting to get is notified then.
+ self.not_empty = threading.Condition(self.mutex)
+
+ # Notify not_full whenever an item is removed from the queue;
+ # a thread waiting to put is notified then.
+ self.not_full = threading.Condition(self.mutex)
+
+ # Notify all_tasks_done whenever the number of unfinished tasks
+ # drops to zero; thread waiting to join() is notified to resume
+ self.all_tasks_done = threading.Condition(self.mutex)
+ self.unfinished_tasks = 0
+```
+
+
+#### task_done 标识前面的入队任务已完成
+由队列使用者线程使用。对于用于获取任务的每个`get()`,后续调用`task_done()`告诉队列任务的处理已完成。
+
+```
+ def task_done(self):
+ '''Indicate that a formerly enqueued task is complete.
+
+ Used by Queue consumer threads. For each get() used to fetch a task,
+ a subsequent call to task_done() tells the queue that the processing
+ on the task is complete.
+
+ If a join() is currently blocking, it will resume when all items
+ have been processed (meaning that a task_done() call was received
+ for every item that had been put() into the queue).
+
+ Raises a ValueError if called more times than there were items
+ placed in the queue.
+ '''
+ with self.all_tasks_done:
+ unfinished = self.unfinished_tasks - 1
+ if unfinished <= 0:
+ if unfinished < 0:
+ raise ValueError('task_done() called too many times')
+ self.all_tasks_done.notify_all()
+ self.unfinished_tasks = unfinished
+```
+
+#### join 阻塞直到队列中所有元素被处理
+
+每当有任务添加到队列中时,未完成的任务count计数增加;当消费者进程调用`task_done()`标识任务已被释放所有工作已完成时,任务计数减少。
+```
+ def join(self):
+ '''Blocks until all items in the Queue have been gotten and processed.
+
+ The count of unfinished tasks goes up whenever an item is added to the
+ queue. The count goes down whenever a consumer thread calls task_done()
+ to indicate the item was retrieved and all work on it is complete.
+
+ When the count of unfinished tasks drops to zero, join() unblocks.
+ '''
+ with self.all_tasks_done:
+ while self.unfinished_tasks:
+ self.all_tasks_done.wait()
+```
+
+#### qsize 返回队列的大致大小
+```
+def qsize(self):
+ '''Return the approximate size of the queue (not reliable!).'''
+ with self.mutex:
+ return self._qsize()
+```
+#### empty 判断队列是否为空
+```
+def empty(self):
+ '''Return True if the queue is empty, False otherwise (not reliable!).
+
+ This method is likely to be removed at some point. Use qsize() == 0
+ as a direct substitute, but be aware that either approach risks a race
+ condition where a queue can grow before the result of empty() or
+ qsize() can be used.
+
+ To create code that needs to wait for all queued tasks to be
+ completed, the preferred technique is to use the join() method.
+ '''
+ with self.mutex:
+ return not self._qsize()
+```
+
+#### full 判断队列是否已满
+```
+def full(self):
+ '''Return True if the queue is full, False otherwise (not reliable!).
+
+ This method is likely to be removed at some point. Use qsize() >= n
+ as a direct substitute, but be aware that either approach risks a race
+ condition where a queue can shrink before the result of full() or
+ qsize() can be used.
+ '''
+ with self.mutex:
+ return 0 < self.maxsize <= self._qsize()
+```
+
+#### put 入队列
+```
+def put(self, item, block=True, timeout=None):
+ '''Put an item into the queue.
+
+ If optional args 'block' is true and 'timeout' is None (the default),
+ block if necessary until a free slot is available. If 'timeout' is
+ a non-negative number, it blocks at most 'timeout' seconds and raises
+ the Full exception if no free slot was available within that time.
+ Otherwise ('block' is false), put an item on the queue if a free slot
+ is immediately available, else raise the Full exception ('timeout'
+ is ignored in that case).
+ '''
+ with self.not_full:
+ if self.maxsize > 0:
+ if not block:
+ if self._qsize() >= self.maxsize:
+ raise Full
+ elif timeout is None:
+ while self._qsize() >= self.maxsize:
+ self.not_full.wait()
+ elif timeout < 0:
+ raise ValueError("'timeout' must be a non-negative number")
+ else:
+ endtime = time() + timeout
+ while self._qsize() >= self.maxsize:
+ remaining = endtime - time()
+ if remaining <= 0.0:
+ raise Full
+ self.not_full.wait(remaining)
+ self._put(item)
+ self.unfinished_tasks += 1
+ self.not_empty.notify()
+```
+
+#### get 从队列中取出元素
+```
+def get(self, block=True, timeout=None):
+ '''Remove and return an item from the queue.
+
+ If optional args 'block' is true and 'timeout' is None (the default),
+ block if necessary until an item is available. If 'timeout' is
+ a non-negative number, it blocks at most 'timeout' seconds and raises
+ the Empty exception if no item was available within that time.
+ Otherwise ('block' is false), return an item if one is immediately
+ available, else raise the Empty exception ('timeout' is ignored
+ in that case).
+ '''
+ with self.not_empty:
+ if not block:
+ if not self._qsize():
+ raise Empty
+ elif timeout is None:
+ while not self._qsize():
+ self.not_empty.wait()
+ elif timeout < 0:
+ raise ValueError("'timeout' must be a non-negative number")
+ else:
+ endtime = time() + timeout
+ while not self._qsize():
+ remaining = endtime - time()
+ if remaining <= 0.0:
+ raise Empty
+ self.not_empty.wait(remaining)
+ item = self._get()
+ self.not_full.notify()
+ return item
+
+ def put_nowait(self, item):
+ '''Put an item into the queue without blocking.
+
+ Only enqueue the item if a free slot is immediately available.
+ Otherwise raise the Full exception.
+ '''
+ return self.put(item, block=False)
+```
+#### put_nowait 在不阻塞的情况下入队列
+```
+ def put_nowait(self, item):
+ '''Put an item into the queue without blocking.
+
+ Only enqueue the item if a free slot is immediately available.
+ Otherwise raise the Full exception.
+ '''
+ return self.put(item, block=False)
+```
+#### get_nowait 不阻塞的情况下出队列
+```
+ def get_nowait(self):
+ '''Remove and return an item from the queue without blocking.
+
+ Only get an item if one is immediately available. Otherwise
+ raise the Empty exception.
+ '''
+ return self.get(block=False)
+```
+#### 被继承时,必须重写的方法
+`_init()`方法中默认使用`deque`实现队列
+
+```
+# Initialize the queue representation
+ def _init(self, maxsize):
+ self.queue = deque()
+
+ def _qsize(self):
+ return len(self.queue)
+
+ # Put a new item in the queue
+ def _put(self, item):
+ self.queue.append(item)
+
+ # Get an item from the queue
+ def _get(self):
+ return self.queue.popleft()
+```
+
+### PriorityQueue(Queue)
+继承自`Quene`,`deque`使用`[]`实现;但是注意到入队和出队操作实际调用的是`heappush`和`heappop `,显然内部实现优先级队列的时候是采用的`heapq`实现的
+
+
+```
+class PriorityQueue(Queue):
+ '''Variant of Queue that retrieves open entries in priority order (lowest first).
+
+ Entries are typically tuples of the form: (priority number, data).
+ '''
+
+ def _init(self, maxsize):
+ self.queue = []
+
+ def _qsize(self):
+ return len(self.queue)
+
+ def _put(self, item):
+ heappush(self.queue, item)
+
+ def _get(self):
+ return heappop(self.queue)
+```
+
+### LifoQueue(Queue)
+继承自`Quene`,`deque`使用`[]`实现;内部入队出队操作调用的是`List`的`append`和`pop`方法。
+
+```
+class LifoQueue(Queue):
+ '''Variant of Queue that retrieves most recently added entries first.'''
+
+ def _init(self, maxsize):
+ self.queue = []
+
+ def _qsize(self):
+ return len(self.queue)
+
+ def _put(self, item):
+ self.queue.append(item)
+
+ def _get(self):
+ return self.queue.pop()
+```
+
+### heapq
+链接在此[heapq](https://docs.python.org/2/library/heapq.html),可以看到对应的源码在`Lib/heapq.py`文件下
+
+>python中的优先级队列是使用`heapq`(默认小根堆)来实现的,而`堆`的实现方式多种多样,这里是用数组存储的`二叉树`实现的。
+
+堆是二叉树,每个父节点的值小于或等于其子节点的值。使用数组`List`实现`heap[k] <= heap[2*k+1] `和 `heap[k] <= heap[2*k+2]`(k从0计数)以满足堆的结构
+其内部实现的方法较多,这里捡几个常用的说
+
+#### heappush 往堆里插入元素
+```
+def heappush(heap, item):
+ """Push item onto heap, maintaining the heap invariant."""
+ heap.append(item)
+ _siftdown(heap, 0, len(heap)-1)
+```
+
+#### heappop 从堆顶出元素
+```
+def heappop(heap):
+ """Pop the smallest item off the heap, maintaining the heap invariant."""
+ lastelt = heap.pop() # raises appropriate IndexError if heap is empty
+ if heap:
+ returnitem = heap[0]
+ heap[0] = lastelt
+ _siftup(heap, 0)
+ return returnitem
+ return lastelt
+```
+
+#### heapreplace 替换元素
+等价于`heappop`+`heappush`,更推荐使用。
+```
+def heapreplace(heap, item):
+ """Pop and return the current smallest value, and add the new item.
+
+ This is more efficient than heappop() followed by heappush(), and can be
+ more appropriate when using a fixed-size heap. Note that the value
+ returned may be larger than item! That constrains reasonable uses of
+ this routine unless written as part of a conditional replacement:
+
+ if item > heap[0]:
+ item = heapreplace(heap, item)
+ """
+ returnitem = heap[0] # raises appropriate IndexError if heap is empty
+ heap[0] = item
+ _siftup(heap, 0)
+ return returnitem
+```
+
+#### heappushpop
+等价于`heappush` + `heappop`
+```
+def heappushpop(heap, item):
+ """Fast version of a heappush followed by a heappop."""
+ if heap and heap[0] < item:
+ item, heap[0] = heap[0], item
+ _siftup(heap, 0)
+ return item
+```
+
+#### heapify 堆化
+原地将List转化为堆,内部调用`_siftup`和`_siftdown`实现,建堆时,无需考虑叶子节点,所以只用考察数组头、中部之间的元素
+```
+def heapify(x):
+ """Transform list into a heap, in-place, in O(len(x)) time."""
+ n = len(x)
+ # Transform bottom-up. The largest index there's any point to looking at
+ # is the largest with a child index in-range, so must have 2*i + 1 < n,
+ # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so
+ # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is
+ # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.
+ for i in reversed(range(n//2)):
+ _siftup(x, i)
+```
+
+#### _siftup
+```
+def _siftup(heap, pos):
+ endpos = len(heap)
+ startpos = pos
+ newitem = heap[pos]
+ # Bubble up the smaller child until hitting a leaf.
+ childpos = 2*pos + 1 # leftmost child position
+ while childpos < endpos:
+ # Set childpos to index of smaller child.
+ rightpos = childpos + 1
+ if rightpos < endpos and not heap[childpos] < heap[rightpos]:
+ childpos = rightpos
+ # Move the smaller child up.
+ heap[pos] = heap[childpos]
+ pos = childpos
+ childpos = 2*pos + 1
+ # The leaf at pos is empty now. Put newitem there, and bubble it up
+ # to its final resting place (by sifting its parents down).
+ heap[pos] = newitem
+ _siftdown(heap, startpos, pos)
+```
+
+#### _siftdown
+```
+def _siftdown(heap, startpos, pos):
+ newitem = heap[pos]
+ # Follow the path to the root, moving parents down until finding a place
+ # newitem fits.
+ while pos > startpos:
+ parentpos = (pos - 1) >> 1
+ parent = heap[parentpos]
+ if newitem < parent:
+ heap[pos] = parent
+ pos = parentpos
+ continue
+ break
+ heap[pos] = newitem
+```
+
+
+
+### deque 双端队列
+连接在此[deque](https://docs.python.org/2/library/collections.html),支持从两端插入和删除元素。源代码在`Lib/collections/__init__.py`。
+`deque`是线程安全且内存搞笑的插入和删除操作,从两端插入删除的时间复杂度可视作O(1)
+
+常见的操作有:
+
+`append、appendleft、clear、copy、count、extend、extendleft`
+`pop、popleft、remove、reverse、rotate`
+
+
+
+
diff --git "a/Week01/\344\270\213\344\270\200\344\270\252\346\216\222\345\210\227.py" "b/Week01/\344\270\213\344\270\200\344\270\252\346\216\222\345\210\227.py"
new file mode 100644
index 000000000..44fc189a2
--- /dev/null
+++ "b/Week01/\344\270\213\344\270\200\344\270\252\346\216\222\345\210\227.py"
@@ -0,0 +1,39 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/29 11:40 PM
+
+from typing import List
+class Solution:
+ def nextPermutation(self, nums: List[int]) -> None:
+ """
+ Do not return anything, modify nums in-place instead.
+ """
+ # 1.从后往前,找到第一个nums[i] nums[p1]:
+ nums[i], nums[p1] = nums[p1], nums[i]
+ break
+ return self.my_reverse(nums,p1+1,size)
+
+ def my_reverse(self, nums, left, right):
+ while left <= right:
+ nums[left], nums[right] = nums[right], nums[left]
+ left, right = left + 1, right - 1
+ return nums
+
+s = Solution()
+nums = [1,2,5,4,1]
+# nums = [1,2,4,8,5,2,1]
+# nums = [3,2,1]
+res = s.nextPermutation(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week01/\344\270\244\344\270\252\346\255\243\345\272\217\346\225\260\347\273\204\347\232\204\344\270\255\344\275\215\346\225\260.py" "b/Week01/\344\270\244\344\270\252\346\255\243\345\272\217\346\225\260\347\273\204\347\232\204\344\270\255\344\275\215\346\225\260.py"
new file mode 100644
index 000000000..17de72b04
--- /dev/null
+++ "b/Week01/\344\270\244\344\270\252\346\255\243\345\272\217\346\225\260\347\273\204\347\232\204\344\270\255\344\275\215\346\225\260.py"
@@ -0,0 +1,73 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/27 2:45 AM
+
+from typing import List
+
+class Solution:
+ def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
+ def getKthElement(k):
+ """
+ - 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
+ - 这里的 "/" 表示整除
+ - nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个
+ - nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个
+ - 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
+ - 这样 pivot 本身最大也只能是第 k-1 小的元素
+ - 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
+ - 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
+ - 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
+ """
+
+ p1, p2 = 0, 0
+ while True:
+ # 特殊情况
+ if p1 == m:#如果一个数组为空
+ return nums2[p2 + k - 1]
+ if p2 == n:
+ return nums1[p1 + k - 1]
+ if k == 1:
+ return min(nums1[p1], nums2[p2])
+
+ # 正常情况
+ ind1 = min(p1 + k // 2 - 1, m - 1)#原数组a的第k//2个元素
+ ind2 = min(p2 + k // 2 - 1, n - 1)#原数组b的第k//2个元素
+ pivot1, pivot2 = nums1[ind1], nums2[ind2]
+ if pivot1 <= pivot2:#删除较小数组的左侧k//2个元素,更新k值
+ k -= ind1 - p1 + 1
+ p1 = ind1 + 1
+ else:
+ k -= ind2 - p2 + 1
+ p2 = ind2 + 1
+
+ m, n = len(nums1), len(nums2)
+ totalLength = m + n
+ if totalLength & 1:
+ return getKthElement((totalLength + 1) // 2)
+ else:
+ return (getKthElement(totalLength // 2) + getKthElement(totalLength // 2 + 1)) / 2
+
+ #归并法 时间复杂度O(M+N)
+ # nums = []
+ # m, n = len(nums1), len(nums2)
+ # size = m + n
+ # i, j = 0, 0
+ # while i < m and j < n:
+ # if nums1[i] <= nums2[j]:
+ # nums.append(nums1[i])
+ # i = i + 1
+ # else:
+ # nums.append(nums2[j])
+ # j = j + 1
+ # while i < m:
+ # nums.append(nums1[i])
+ # i = i + 1
+ # while j int:
+ #区分 两数的符号问题
+ sign = (dividend>0) ^ (divisor>0) #异号为1
+ dividend, divisor= abs(dividend), abs(divisor)
+ res = 0
+ while divisor <= dividend:
+ tmp_divisor, count = divisor, 1 # 当不能被倍增后的整除时,将除数重置
+ while tmp_divisor <= dividend:
+ dividend -= tmp_divisor
+ res += count
+ count <<= 1
+ tmp_divisor <<= 1
+ res_value = -res if sign else res # 给结果加上符号
+ return max(min(res_value, 2**31-1), -2**31)
+
+s = Solution()
+res = s.divide(11,2)
+print(res)
+
+
diff --git "a/Week01/\344\270\262\350\201\224\346\211\200\346\234\211\345\215\225\350\257\215\347\232\204\345\255\220\344\270\262.py" "b/Week01/\344\270\262\350\201\224\346\211\200\346\234\211\345\215\225\350\257\215\347\232\204\345\255\220\344\270\262.py"
new file mode 100644
index 000000000..db72ebe42
--- /dev/null
+++ "b/Week01/\344\270\262\350\201\224\346\211\200\346\234\211\345\215\225\350\257\215\347\232\204\345\255\220\344\270\262.py"
@@ -0,0 +1,54 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/30 12:19 AM
+
+from typing import List
+from collections import Counter
+
+class Solution:
+ def findSubstring(self, strs: str, words: List[str]) -> List[int]:
+ if not words: return []
+ size = len(words[0])#单词长度
+ if size > len(strs): return []
+ res, tmp = [], {}
+ for word in words:
+ tmp[word] = tmp.get(word, 0) + 1
+ #利用words全部元素构造为strs的一个连续串
+ for i in range(len(strs)):
+ j = i
+ hashmap = tmp.copy()
+ # 这里可以考虑用两个hashmap来做,匹配的时候先将words长度的字符串搞出来
+ while strs[j:j+size] in hashmap:
+ cur = strs[j:j+size]
+ hashmap[cur] -= 1
+ if hashmap.get(cur) == 0:
+ hashmap.pop(cur)
+ j = j+size
+ if len(hashmap) == 0:#现在判断条件需要修改 不再是长度为0,而是字典里面value全是0
+ res.append(i)
+ return res
+ def findSubstringII(self, s, words):
+ if not words: return []
+ k = len(words[0])
+ res = []
+ tmp = Counter(words)
+ for left in range(k):#k组
+ hashmap = tmp.copy()
+ for right in range(left + k, len(s) + 1, k):#滑动k
+ word = s[right - k: right]#截取出原串中的部分
+ hashmap[word] -= 1#这句话不会报错么????
+ while hashmap[word] < 0:
+ hashmap[s[left:left + k]] += 1
+ left += k
+ if left + k * len(words) == right:
+ res.append(left)
+ return res
+
+
+s = Solution()
+# strs = "wordgoodgoodgoodbestword"
+# words = ["word","good","best","word"]
+strs = "barfoothefoobarman"
+words = ["foo","bar"]
+res = s.findSubstringII(strs,words)
+print(res)
\ No newline at end of file
diff --git "a/Week01/\344\272\244\346\215\242\351\223\276\350\241\250\347\233\270\351\202\273\350\212\202\347\202\271.py" "b/Week01/\344\272\244\346\215\242\351\223\276\350\241\250\347\233\270\351\202\273\350\212\202\347\202\271.py"
new file mode 100644
index 000000000..e621a9b42
--- /dev/null
+++ "b/Week01/\344\272\244\346\215\242\351\223\276\350\241\250\347\233\270\351\202\273\350\212\202\347\202\271.py"
@@ -0,0 +1,79 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/11 4:13 PM
+
+# 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
+#
+# 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
+#
+#
+#
+# 示例:
+#
+# 给定 1->2->3->4, 你应该返回 2->1->4->3.
+#
+# Related Topics 链表
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# 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
+ """
+ # 1. 迭代
+ # preparing listnode
+ # dummy node for return the list head
+ # beat 9%
+ # dummy = ListNode(-1)
+ # dummy.next = head
+ # pre = dummy
+ #
+ # while head and head.next:
+ # # prepare the two node
+ # first_node = head
+ # second_node = head.next
+ #
+ # # swap the two node
+ # pre.next = second_node
+ # first_node.next = second_node.next
+ # second_node.next = first_node
+ #
+ # # reset the pre and head point for next swap
+ # pre = first_node
+ # head = first_node.next
+ # return dummy.next
+
+ # 击败49%
+ # dummy = prev = ListNode(0)
+ # prev.next = head
+ #
+ # while prev.next and prev.next.next:
+ # a, b = prev.next, prev.next.next
+ # prev.next, a.next, b.next = b, b.next, a
+ # prev = a
+ #
+ # return dummy.next
+
+ # trying recursive 击败6%
+ # 递归无非是 地递归过程中的操作,以及每层递归要返回的
+ # 1.
+ if not head or not head.next:
+ return head
+ first_node = head
+ second_node = head.next
+
+ # 递归过程
+ # 相邻元素倒置,以及外加一条向外连接的线
+ first_node.next = self.swapPairs(second_node.next)
+ second_node.next = first_node
+
+ return second_node
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week01/\345\216\237\345\234\260\345\210\240\351\231\244\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\346\225\260.py" "b/Week01/\345\216\237\345\234\260\345\210\240\351\231\244\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\346\225\260.py"
new file mode 100644
index 000000000..32144a47f
--- /dev/null
+++ "b/Week01/\345\216\237\345\234\260\345\210\240\351\231\244\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\346\225\260.py"
@@ -0,0 +1,73 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/15 5:13 PM
+
+# 给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
+#
+# 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
+#
+#
+#
+# 示例 1:
+#
+# 给定数组 nums = [1,1,2],
+#
+# 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
+#
+# 你不需要考虑数组中超出新长度后面的元素。
+#
+# 示例 2:
+#
+# 给定 nums = [0,0,1,1,1,2,2,3,3,4],
+#
+# 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
+#
+# 你不需要考虑数组中超出新长度后面的元素。
+#
+#
+#
+#
+# 说明:
+#
+# 为什么返回数值是整数,但输出的答案是数组呢?
+#
+# 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
+#
+# 你可以想象内部操作如下:
+#
+# // nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
+# int len = removeDuplicates(nums);
+#
+# // 在函数里修改输入数组对于调用者是可见的。
+# // 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
+# for (int i = 0; i < len; i++) {
+# print(nums[i]);
+# }
+#
+# Related Topics 数组 双指针
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def removeDuplicates(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ point = 0# 指向前一个重复的数值
+ for i in range(len(nums) - 1):
+ # if nums[i] == nums[i + 1]:
+ # continue
+ # else:
+ # point = point + 1
+ # nums[point] = nums[i+1]
+ if nums[i]!=nums[i+1]: #击败99.7%
+ point = point+1
+ nums[point] = nums[i+1]
+ # return nums[:point+1]
+ return point + 1#需要的返回值是不相同的元素个数
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+res = s.removeDuplicates([0,0,1,1,1,2,2,3,3,4])
+print(res)
\ No newline at end of file
diff --git "a/Week01/\345\220\210\345\271\266k\344\270\252\346\216\222\345\272\217\351\223\276\350\241\250.py" "b/Week01/\345\220\210\345\271\266k\344\270\252\346\216\222\345\272\217\351\223\276\350\241\250.py"
new file mode 100644
index 000000000..0ba4abd93
--- /dev/null
+++ "b/Week01/\345\220\210\345\271\266k\344\270\252\346\216\222\345\272\217\351\223\276\350\241\250.py"
@@ -0,0 +1,60 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/28 11:57 PM
+
+# Definition for singly-linked list.
+class ListNode:
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+
+from typing import List
+class Solution:
+ # 分治算法,每次归并链各个链表01-0,23-2 步长倍增
+ # 下次就归并02-0 46-4
+ def mergeKLists(self, lists: List[ListNode]) -> ListNode:
+ if not lists: return None
+ if len(lists) == 1: return lists[0]
+ size = len(lists)
+ step = 1
+ while step < size:
+ for i in range(0,size-step,step*2):
+ lists[i] = self.merge2list(lists[i],lists[i+step])
+ step = step * 2
+ return lists[0]
+
+ def merge2list(self,l1,l2):
+ pre = head = ListNode(-1)
+ while l1 and l2:
+ if l1.val <= l2.val:
+ head.next = l1
+ l1 = l1.next
+ else:
+ head.next = l2
+ l2 = l2.next
+ head = head.next
+ if not l1:
+ head.next = l2
+ if not l2:
+ head.next = l1
+ return pre.next
+from queue import PriorityQueue
+class SolutionII:
+ # 使用优先级队列 省去每次链表头结点的大小比较
+ # 这段代码在python3中不过,应为优先级队列
+ def mergeKLists(self, lists: List[ListNode]) -> ListNode:
+ pre = head = ListNode(-1)
+ pq = PriorityQueue()
+ for l in lists:
+ if l:
+ pq.put((l.val,l))#优先级在前
+ while pq:
+ val, node = pq.get()
+ head.next = node
+ node = node.next
+ head = head.next
+ if node:
+ pq.put((node.val,node))#优先级队列中加入一个
+ return pre.next
+
+
diff --git "a/Week01/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.py" "b/Week01/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.py"
new file mode 100644
index 000000000..db7f2a052
--- /dev/null
+++ "b/Week01/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.py"
@@ -0,0 +1,73 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/15 4:13 PM
+
+# 给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
+#
+#
+#
+# 说明:
+#
+#
+# 初始化 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]
+# Related Topics 数组 双指针
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def merge(self, nums1, m, nums2, n):
+ """
+ :type nums1: List[int]
+ :type m: int
+ :type nums2: List[int]
+ :type n: int
+ :rtype: None Do not return anything, modify nums1 in-place instead.
+ """
+ #击败99.9% 占用额外空间
+ # nums1[:] = sorted((nums1[:m] + nums2))
+ #击败70% 双指针+ 额外空间 从头开始比较
+ # tmp = nums1[:m]
+ # nums1[:] = []
+ # i, j = 0, 0
+ # while i < m and j < n:
+ # if tmp[i] < nums2[j]:
+ # nums1.append(tmp[i])
+ # i = i + 1
+ # else:
+ # nums1.append(nums2[j])
+ # j = j + 1
+ # if i < m:#tmp数组中还有剩余元素
+ # nums1[i+j:] = tmp[i:]
+ # if j < n:
+ # nums1[i+j:] = nums2[j:]
+ #时间复杂度是O(m+n),空间开销是常数级
+ i, j = m-1, n-1
+ ind = m+n-1
+ while i >= 0 and j >= 0:#从后往前比较,将较大的值存入nums1末尾中
+ if nums1[i] > nums2[j]:
+ nums1[ind] = nums1[i]
+ ind, i = ind-1, i-1
+ else:
+ nums1[ind] = nums2[j]
+ ind, j = ind-1, j-1
+ #如果nums1中还有元素不需要处理
+ #而如果是nums2中还有元素,那么说明nums1中前面的元素需要被替换
+ nums1[:j+1] = nums2[:j+1]
+ return nums1
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+res = s.merge([1,2,3,0,0,0],3,[0,1,5],3)
+print(res)
\ No newline at end of file
diff --git "a/Week01/\345\220\210\345\271\266\344\270\244\344\270\252\351\223\276\350\241\250.py" "b/Week01/\345\220\210\345\271\266\344\270\244\344\270\252\351\223\276\350\241\250.py"
new file mode 100644
index 000000000..41bb99e5f
--- /dev/null
+++ "b/Week01/\345\220\210\345\271\266\344\270\244\344\270\252\351\223\276\350\241\250.py"
@@ -0,0 +1,49 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/15 5:37 PM
+
+# 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
+#
+# 示例1:
+#
+# 输入:1->2->4, 1->3->4
+# 输出:1->1->2->3->4->4
+#
+# 限制:
+#
+# 0 <= 链表长度 <= 1000
+#
+# 注意:本题与主站 21 题相同:https://leetcode-cn.com/problems/merge-two-sorted-lists/
+# Related Topics 分治算法
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# 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: ListNode, l2: ListNode) -> ListNode:
+ if not l1: # 如果l1为空,直接返回l2
+ return l2
+ if not l2: # 如果l2为空,直接返回l1
+ return l1
+ rhead = ListNode(None) # 用来返回最后的结果的节点
+ pre = rhead # 用来添加比较过的节点
+ while l1 and l2: # 循环直到某链表没有值结束,刚开始这里写的是l1.next and l2.next 返回的结果是[1,1,2,4]
+ if l1.val <= l2.val:
+ tmp, l1 = l1, l1.next #
+ pre.next = tmp
+ pre = tmp
+ else:
+ tmp, l2 = l2, l2.next
+ pre.next = tmp
+ pre = tmp
+ if not l1:
+ pre.next = l2
+ if not l2:
+ pre.next = l1
+ return rhead.next
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week01/\345\233\233\346\225\260\344\271\213\345\222\214.py" "b/Week01/\345\233\233\346\225\260\344\271\213\345\222\214.py"
new file mode 100644
index 000000000..7ba630cae
--- /dev/null
+++ "b/Week01/\345\233\233\346\225\260\344\271\213\345\222\214.py"
@@ -0,0 +1,41 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/28 10:49 PM
+
+from typing import List
+class Solution:
+ def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
+ size = len(nums)#[-2,-1,0,0,1,2]
+ if size < 4: return []
+ res = []
+ nums.sort()
+ for i in range(size - 2):
+ if i>0 and nums[i] == nums[i-1]: continue#确保不会和前面产生的结果重复
+ if nums[i] * 4 > target: break
+ for j in range(i + 1, size - 1):
+ if j > i+1 and nums[j] == nums[j-1]: continue
+ if nums[i] + nums[j]*3 > target: break
+ left, right = j + 1, size - 1
+ while left < right:
+ cur = nums[i] + nums[j] + nums[left] + nums[right]
+ if cur == target:#注意下面的是while条件而不是if
+ while left < right and nums[left] == nums[left+1]: left = left + 1
+ while left < right and nums[right] == nums[right-1]: right = right -1
+ tmp =[nums[i],nums[j],nums[left],nums[right]]
+ res.append(tmp)
+ left, right = left + 1, right - 1
+ elif cur < target:
+ left += 1
+ else:
+ right -= 1
+ return res
+
+s = Solution()
+# nums = [1, 0, -1, 0, -2, 2]
+# nums = [-3,-2,-1,0,0,1,2,3]
+nums = [4,-9,-2,-2,-7,9,9,5,10,-10,4,5,2,-4,-2,4,-9,5]
+res = s.fourSum(nums,-13)
+print(res)
+
+
+
diff --git "a/Week01/\345\256\236\347\216\260strStr.py" "b/Week01/\345\256\236\347\216\260strStr.py"
new file mode 100644
index 000000000..f3e3d336d
--- /dev/null
+++ "b/Week01/\345\256\236\347\216\260strStr.py"
@@ -0,0 +1,37 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/29 12:34 AM
+
+class Solution:
+ def strStr(self, haystack: str, needle: str) -> int:
+ if not needle: return 0
+ m, n = len(haystack), len(needle)
+ for i in range(0,m-n+1):#5-2=3
+ if haystack[i:i+n] == needle:
+ return i
+ return -1
+ #刚开始想的时候就是用滑动窗口做,但是没写出来,反倒是这种直接暴力的反而简单
+ # 滑动窗口关键在于 回溯
+ # if not needle: return 0
+ # m, n = len(haystack), len(needle)
+ # p1 = p2 = 0
+ # curr_len = 0
+ # while p1 <= m - n:
+ # while p1 < m and haystack[p1] == needle[p2]:
+ # curr_len += 1
+ # p1 += 1
+ # p2 += 1
+ # if curr_len == n:
+ # return p1 - n
+ # # 回溯,移动pn到开始位置的后一位。重置其他变量
+ # p1 = p1 - curr_len + 1
+ # p2 = 0
+ # curr_len = 0
+ # return -1
+
+
+s = Solution()
+haystack = "hello"
+needle = "lo"
+res = s.strStr(haystack,needle)
+print(res)
\ No newline at end of file
diff --git "a/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/QuickLook/Preview.jpg" "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/QuickLook/Preview.jpg"
new file mode 100644
index 000000000..3be4a83f9
Binary files /dev/null and "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/QuickLook/Preview.jpg" differ
diff --git "a/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/contents.xml" "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/contents.xml"
new file mode 100644
index 000000000..bc7c1cda0
Binary files /dev/null and "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/contents.xml" differ
diff --git "a/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/contents.xml" "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/contents.xml"
new file mode 100644
index 000000000..73d4e289d
--- /dev/null
+++ "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/contents.xml"
@@ -0,0 +1,274 @@
+
+
+
+
+ allowNodeStrokeColorVariation
+
+ backgroundColor
+ {0.933333, 0.933333, 0.952941, 1.000000}
+ baseSubnode
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {0.392157, 0.784314, 0.803922, 1.000000}
+ dash
+ 0
+ width
+ 6
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+ shapeType
+ 0
+
+ strokeStyle
+
+ color
+ {0.392157, 0.784314, 0.803922, 1.000000}
+ dash
+ 0
+ width
+ 6
+
+ titleStyle
+
+ alignment
+ 0
+ bold
+
+ color
+ {0.428090, 0.428100, 0.428094, 1.000000}
+ fontName
+ Helvetica
+ fontSize
+ 20
+ italic
+
+
+
+ crossConnections
+
+
+ arrowStyle
+
+ endArrow
+ 1
+ startArrow
+ 0
+
+ pathStyle
+
+ strokeStyle
+
+ color
+ {0.366349, 0.366358, 0.366353, 1.000000}
+ dash
+ 1
+ width
+ 1
+
+
+ titleStyle
+
+ alignment
+ 1
+ bold
+
+ color
+ {1.000000, 1.000000, 1.000000, 1.000000}
+ fontName
+ HelveticaNeue
+ fontSize
+ 14
+ italic
+
+
+
+
+ mainNodes
+
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {1.000000, 1.000000, 1.000000, 1.000000}
+ dash
+ 0
+ width
+ 1
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+ shapeType
+ 2
+
+ strokeStyle
+
+ color
+ {0.294118, 0.294118, 0.294118, 1.000000}
+ dash
+ 0
+ width
+ 4
+
+ titleStyle
+
+ alignment
+ 1
+ bold
+
+ color
+ {0.292470, 0.292477, 0.292473, 1.000000}
+ fontName
+ Helvetica
+ fontSize
+ 24
+ italic
+
+
+
+
+ subnodeColors
+
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {1.000000, 0.588235, 0.352941, 1.000000}
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+
+ strokeStyle
+
+ color
+ {1.000000, 0.588235, 0.352941, 1.000000}
+
+ titleStyle
+
+ color
+ {0.428090, 0.428100, 0.428094, 1.000000}
+
+
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {0.450980, 0.784314, 1.000000, 1.000000}
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+
+ strokeStyle
+
+ color
+ {0.450980, 0.784314, 1.000000, 1.000000}
+
+ titleStyle
+
+ color
+ {0.428090, 0.428100, 0.428094, 1.000000}
+
+
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {0.686275, 0.313725, 0.784314, 1.000000}
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+
+ strokeStyle
+
+ color
+ {0.686275, 0.313725, 0.784314, 1.000000}
+
+ titleStyle
+
+ color
+ {0.428090, 0.428100, 0.428094, 1.000000}
+
+
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {1.000000, 0.803922, 0.235294, 1.000000}
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+
+ strokeStyle
+
+ color
+ {1.000000, 0.803922, 0.235294, 1.000000}
+
+ titleStyle
+
+ color
+ {0.428090, 0.428100, 0.428094, 1.000000}
+
+
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {1.000000, 0.372549, 0.411765, 1.000000}
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+
+ strokeStyle
+
+ color
+ {1.000000, 0.372549, 0.411765, 1.000000}
+
+ titleStyle
+
+ color
+ {0.428090, 0.428100, 0.428094, 1.000000}
+
+
+
+ shapeStyle
+
+ borderStrokeStyle
+
+ color
+ {0.392157, 0.784314, 0.803922, 1.000000}
+
+ fillColor
+ {1.000000, 1.000000, 1.000000, 1.000000}
+
+ strokeStyle
+
+ color
+ {0.392157, 0.784314, 0.803922, 1.000000}
+
+ titleStyle
+
+ color
+ {0.428090, 0.428100, 0.428094, 1.000000}
+
+
+
+ subnodeLevels
+
+
+
diff --git "a/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/metadata.plist" "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/metadata.plist"
new file mode 100644
index 000000000..378b0eb8e
--- /dev/null
+++ "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/metadata.plist"
@@ -0,0 +1,14 @@
+
+
+
+
+ author
+ MindNode
+ id
+ 514DD5D6-7C79-481B-8CB1-A08FA9F5D3DF
+ title
+ Tropical
+ version
+ 3
+
+
diff --git "a/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/viewState.plist" "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/viewState.plist"
new file mode 100644
index 000000000..327fb2bcd
Binary files /dev/null and "b/Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/viewState.plist" differ
diff --git "a/Week01/\346\225\260\347\273\204\345\220\221\345\217\263\347\247\273\345\212\250k\346\254\241.py" "b/Week01/\346\225\260\347\273\204\345\220\221\345\217\263\347\247\273\345\212\250k\346\254\241.py"
new file mode 100644
index 000000000..dea4e1af0
--- /dev/null
+++ "b/Week01/\346\225\260\347\273\204\345\220\221\345\217\263\347\247\273\345\212\250k\346\254\241.py"
@@ -0,0 +1,64 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/14 11:03 PM
+
+# 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
+#
+# 示例 1:
+#
+# 输入: [1,2,3,4,5,6,7] 和 k = 3
+# 输出: [5,6,7,1,2,3,4]
+# 解释:
+# 向右旋转 1 步: [7,1,2,3,4,5,6]
+# 向右旋转 2 步: [6,7,1,2,3,4,5]
+# 向右旋转 3 步: [5,6,7,1,2,3,4]
+#
+#
+# 示例 2:
+#
+# 输入: [-1,-100,3,99] 和 k = 2
+# 输出: [3,99,-1,-100]
+# 解释:
+# 向右旋转 1 步: [99,-1,-100,3]
+# 向右旋转 2 步: [3,99,-1,-100]
+#
+# 说明:
+#
+#
+# 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
+# 要求使用空间复杂度为 O(1) 的 原地 算法。
+#
+# Related Topics 数组
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def rotate(self, nums, k):
+ """
+ 要求原地置换
+ :type nums: List[int]
+ :type k: int
+ :rtype: None Do not return anything, modify nums in-place instead.
+ """
+ # 击败81%
+ # k = k % len(nums)#要考虑k大于数组长度的情形
+ # nums[:] = nums[len(nums) - k:] + nums[:len(nums) - k]
+ # 击败64%
+ tmp = nums[len(nums) - k:] + nums[:len(nums) - k]
+ for i in range(len(tmp)):
+ nums[i] = tmp[i]
+
+ #暴力解法 超出时间限制
+ for i in range(k%len(nums)): # 旋转k次
+ for j in range(len(nums) - 1, 0, -1):#反序调转
+ nums[j - 1], nums[j] = nums[j], nums[j - 1]
+
+ # nums.reverse()
+ # nums[:len(nums)-k].reverse()
+#
+# leetcode submit region end(Prohibit modification and deletion)
+
+s =Solution()
+a = [1,2,3,4,5,6,7]
+s.rotate(a,2)
+print(a)
\ No newline at end of file
diff --git "a/Week01/\346\225\264\346\225\260\345\217\215\350\275\254.py" "b/Week01/\346\225\264\346\225\260\345\217\215\350\275\254.py"
new file mode 100644
index 000000000..db487b473
--- /dev/null
+++ "b/Week01/\346\225\264\346\225\260\345\217\215\350\275\254.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/28 12:49 AM
+
+class Solution:
+ def reverse(self, x: int) -> int:
+ # 迭代反转数字
+ flag = 0
+ if x<0:
+ x = abs(x)
+ flag = 1
+ res = 0
+ while x>0:
+ res = 10 * res + x % 10
+ x = x//10
+ res = -1 * res if flag==1 else res
+ return res if -1*2**31<=res<=2**31-1 else 0
+ #当然也可以使用栈来做,但要提前判断是否越界
+
+s = Solution()
+res = s.reverse(123)
+print(res)
\ No newline at end of file
diff --git "a/Week01/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262.py" "b/Week01/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262.py"
new file mode 100644
index 000000000..71e298b51
--- /dev/null
+++ "b/Week01/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262.py"
@@ -0,0 +1,38 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/26 10:57 PM
+
+class Solution:
+ def lengthOfLongestSubstring(self, strs: str) -> int:
+ # [a,b,c,a,b,c,d]
+ # if not strs: return 0
+ # quene = []
+ # max_len, cur_len = 0,0
+ # for ch in strs:
+ # while ch in quene:#O(N)
+ # quene.pop(0)#双端队列
+ # cur_len -= 1
+ # if ch not in quene:
+ # quene.append(ch)
+ # cur_len += 1
+ # max_len = max(max_len,cur_len)
+ # return max_len
+ # 很明显,记录长度的时候可以不需要使用队列,而是直接用右指针记录下一次的起始
+ if not strs: return 0
+ visited = set()
+ max_len, cur_len, left = 0, 0, 0
+ for i in range(len(strs)):
+ while strs[i] in visited:
+ visited.remove(strs[left])
+ left = left + 1
+ cur_len -= 1
+ visited.add(strs[i])
+ cur_len += 1
+ max_len = max(max_len, cur_len)
+ return max_len
+
+
+s = Solution()
+strs = "abcabcbb"
+res = s.lengthOfLongestSubstring(strs)
+print(res)
\ No newline at end of file
diff --git "a/Week01/\346\230\257\345\220\246\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267.py" "b/Week01/\346\230\257\345\220\246\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267.py"
new file mode 100644
index 000000000..2564acc30
--- /dev/null
+++ "b/Week01/\346\230\257\345\220\246\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267.py"
@@ -0,0 +1,66 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/12 11:22 PM
+
+# 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
+#
+# 有效字符串需满足:
+#
+#
+# 左括号必须用相同类型的右括号闭合。
+# 左括号必须以正确的顺序闭合。
+#
+#
+# 注意空字符串可被认为是有效字符串。
+#
+# 示例 1:
+#
+# 输入: "()"
+# 输出: true
+#
+#
+# 示例 2:
+#
+# 输入: "()[]{}"
+# 输出: true
+#
+#
+# 示例 3:
+#
+# 输入: "(]"
+# 输出: false
+#
+#
+# 示例 4:
+#
+# 输入: "([)]"
+# 输出: false
+#
+#
+# 示例 5:
+#
+# 输入: "{[]}"
+# 输出: true
+# Related Topics 栈 字符串
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def isValid(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ #击败96%
+ stack = []
+ dic = {')':'(',']':'[','}':'{'}
+ for item in s:
+ if item not in dic:#如果是左括号,入栈
+ stack.append(item)
+ else:#如果是右括号
+ top = stack.pop() if stack else '#'#判断是否与当前栈顶元素相匹配
+ if top != item:#不匹配,则返回False
+ return False
+ #如果刚开始是左括号,入栈后就结束了,明显是不匹配的,所以最终结果需要根据stack是否空来返回
+ return not stack
+ # leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week01/\346\234\200\345\244\247\347\232\204\347\237\251\345\275\242\351\235\242\347\247\257.py" "b/Week01/\346\234\200\345\244\247\347\232\204\347\237\251\345\275\242\351\235\242\347\247\257.py"
new file mode 100644
index 000000000..92c2dc0e2
--- /dev/null
+++ "b/Week01/\346\234\200\345\244\247\347\232\204\347\237\251\345\275\242\351\235\242\347\247\257.py"
@@ -0,0 +1,105 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/13 12:59 AM
+
+# 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
+#
+# 求在该柱状图中,能够勾勒出来的矩形的最大面积。
+#
+#
+#
+#
+#
+# 以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
+#
+#
+#
+#
+#
+# 图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
+#
+#
+#
+# 示例:
+#
+# 输入: [2,1,5,6,2,3]
+# 输出: 10
+# Related Topics 栈 数组
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# class Solution(object):
+# def largestRectangleArea(self, heights):
+# """
+# :type heights: List[int]
+# :rtype: int
+# """
+ # 1.暴力解 超出时间限制
+ # size = len(heights)
+ # res = 0
+ # for i in range(size):
+ # left = i
+ # cur_height = heights[i]
+ # while left > 0 and heights[left - 1] >= cur_height:
+ # left -= 1
+ #
+ # right = i
+ # while right < size - 1 and heights[right + 1] >= cur_height:
+ # right += 1
+ # res = max(res, (right - left + 1) * cur_height)
+ # return res
+from typing import List
+
+class Solution:
+ def largestRectangleArea(self, heights: List[int]) -> int:
+ size = len(heights)#[2,1,5,6,2,3]
+ res = 0
+ stack = []
+ for i in range(size):
+ while len(stack) > 0 and heights[i] < heights[stack[-1]]:
+ # 如果当前height的右边height严格小于height,则确定了此轮的height
+ cur_height = heights[stack.pop()]
+
+ # while len(stack) > 0 and cur_height == heights[stack[-1]]:
+ # stack.pop()
+
+ if len(stack) > 0:
+ cur_width = i - stack[-1] - 1
+ else:
+ cur_width = i
+
+ res = max(res, cur_height * cur_width)
+ stack.append(i)#记录的是heights的下标
+
+ while len(stack) > 0 is not None:#处理还未出栈的高度
+ cur_height = heights[stack.pop()]
+ # while len(stack) > 0 and cur_height == heights[stack[-1]]:#处理相邻高度一致的情形
+ # stack.pop()
+
+ if len(stack) > 0:
+ cur_width = size - stack[-1] - 1
+ else:
+ cur_width = size
+ res = max(res, cur_height * cur_width)
+ return res
+
+
+class SolutionI:
+ #哨兵优化 击败73%
+ def largestRectangleArea(self, heights: List[int]) -> int:
+ heights = [0] + heights + [0]
+ size = len(heights)
+ stack, res = [], 0
+ for i in range(size):
+ while len(stack) > 0 and heights[i] < heights[stack.pop()]:
+ cur_height = heights[stack.pop()]
+ res = max(res, cur_height * (i - stack[-1] - 1))
+ stack.append(i)
+ return res
+
+
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+res = s.largestRectangleArea([2,1,5,6,2,3])
+print(res)
\ No newline at end of file
diff --git "a/Week01/\346\234\200\345\260\217\346\240\210.py" "b/Week01/\346\234\200\345\260\217\346\240\210.py"
new file mode 100644
index 000000000..3d2116b89
--- /dev/null
+++ "b/Week01/\346\234\200\345\260\217\346\240\210.py"
@@ -0,0 +1,94 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/13 12:08 AM
+# 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
+#
+#
+# push(x) —— 将元素 x 推入栈中。
+# pop() —— 删除栈顶的元素。
+# top() —— 获取栈顶元素。
+# getMin() —— 检索栈中的最小元素。
+#
+#
+#
+#
+# 示例:
+#
+# 输入:
+# ["MinStack","push","push","push","getMin","pop","top","getMin"]
+# [[],[-2],[0],[-3],[],[],[],[]]
+#
+# 输出:
+# [null,null,null,null,-3,null,0,-2]
+#
+# 解释:
+# MinStack minStack = new MinStack();
+# minStack.push(-2);
+# minStack.push(0);
+# minStack.push(-3);
+# minStack.getMin(); --> 返回 -3.
+# minStack.pop();
+# minStack.top(); --> 返回 0.
+# minStack.getMin(); --> 返回 -2.
+#
+#
+#
+#
+# 提示:
+#
+#
+# pop、top 和 getMin 操作总是在 非空栈 上调用。
+#
+# Related Topics 栈 设计
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+
+class MinStack:
+
+ def __init__(self):
+ """
+ initialize your data structure here.
+ """
+ self.stack = []
+ self.min_stack = []
+ #击败92%
+ def push(self, x: int) -> None:
+ self.stack.append(x)
+ #如果当前元素比最小栈中的元素小,则将此元素放入最小栈中
+ #如果当前最小栈为空,将此元素放入最小栈中
+ if not self.min_stack :
+ self.min_stack.append(x)
+ elif x <= self.min_stack[-1]:
+ self.min_stack.append(x)
+
+ def pop(self) -> None:
+ if self.stack.pop() == self.min_stack[-1]:
+ return self.min_stack.pop()
+
+ def top(self) -> int:
+ return self.stack[-1]
+
+ def getMin(self) -> int:
+ return self.min_stack[-1]
+
+
+
+# Your MinStack object will be instantiated and called as such:
+# obj = MinStack()
+# obj.push(x)
+# obj.pop()
+# param_3 = obj.top()
+# param_4 = obj.getMin()
+
+
+
+
+
+# Your MinStack object will be instantiated and called as such:
+# obj = MinStack()
+# obj.push(x)
+# obj.pop()
+# param_3 = obj.top()
+# param_4 = obj.getMin()
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_13_\347\210\254\346\245\274\346\242\257.py" "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_13_\347\210\254\346\245\274\346\242\257.py"
new file mode 100644
index 000000000..32d88e296
--- /dev/null
+++ "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_13_\347\210\254\346\245\274\346\242\257.py"
@@ -0,0 +1,29 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/13 11:59 AM
+
+class Solution:
+ def climbStairs(self, n: int) -> int:
+ # 1.无脑递归 未通过
+ # if n==1: return 1
+ # if n==2: return 2
+ # return self.climbStairs(n-1)+self.climbStairs(n-2)
+ # 2.递归+备忘录,记录climbstairs(n)
+ # 击败39%
+ # mem = [0,1,2]
+ # if n==1:return mem[1]
+ # if n==2:return mem[2]
+ # for i in range(3,n+1):
+ # mem.append(mem[i-1]+mem[i-2])
+ # return mem[-1]
+ # 3. 备忘录解法中相当于是存了1-n所有的结果,但是没有必要
+ # 优化 击败83%
+ a, b = 1, 2
+ if n == 1: return 1
+ if n == 2: return 2
+ for i in range(3, n + 1):
+ a, b = b, a + b
+ return b
+
+
+
diff --git "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py"
new file mode 100644
index 000000000..96465f027
--- /dev/null
+++ "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py"
@@ -0,0 +1,19 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/14 5:32 PM
+from typing import List
+class Solution:
+ def findBestValue(self, arr: List[int], target: int) -> int:
+ #这种接法就是应该是贪心吧??如果匹配过程中,该元素都与均值匹配,那么就替换
+ #每次都是与期望的均值作比较
+ arr.sort()
+ size = len(arr)
+ for i in range(size):
+ average = target / (size-i)#
+ if arr[i] <= average:#如果当前元素小于平均值,那么再下次匹配时,希望的平均值就应当大一些
+ target = target - arr[i]
+ else:#如果当前的元素大于average,那么这个值就是可以修改的
+ return int(average+0.49)
+ #如果遍历完之后还没有返回这个value,说明整个数组整体的值都偏小,导致没法匹配到average值
+ # 这个时候就返回排序数组最后的元素
+ return arr[-1]
\ No newline at end of file
diff --git "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_15_\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py" "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_15_\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py"
new file mode 100644
index 000000000..66ef8433b
--- /dev/null
+++ "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_15_\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py"
@@ -0,0 +1,54 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/15 5:40 PM
+
+# 编写一个函数来查找字符串数组中的最长公共前缀。
+#
+# 如果不存在公共前缀,返回空字符串 ""。
+#
+# 示例 1:
+#
+# 输入: ["flower","flow","flight"]
+# 输出: "fl"
+#
+#
+# 示例 2:
+#
+# 输入: ["dog","racecar","car"]
+# 输出: ""
+# 解释: 输入不存在公共前缀。
+#
+#
+# 说明:
+#
+# 所有输入只包含小写字母 a-z 。
+# Related Topics 字符串
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def longestCommonPrefix(self, strs):
+ """
+ :type strs: List[str]
+ :rtype: str
+ """
+ #击败59%
+ # if not strs: return ''
+ # min_size = min([len(x) for x in strs]) # 公共前缀最长只会这么长
+ # for i in range(min_size, 0, -1):
+ # tmp = strs[0][:i] # 当前待比较的公共前缀子串
+ # if all(s[:i] == tmp for s in strs):
+ # return tmp
+ # return ''
+ #击败78%
+ prefix = strs[0] if strs else ''
+ while True:
+ if all(s.startswith(prefix) for s in strs):
+ return prefix
+ prefix = prefix[:-1]
+
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+res = s.longestCommonPrefix(["dog","racecar","car"])
+print(res)
diff --git "a/Week01/\347\210\254\346\245\274\346\242\257.py" "b/Week01/\347\210\254\346\245\274\346\242\257.py"
new file mode 100644
index 000000000..cc9013ece
--- /dev/null
+++ "b/Week01/\347\210\254\346\245\274\346\242\257.py"
@@ -0,0 +1,70 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/9 11:55 PM
+
+# 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
+#
+# 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
+#
+# 注意:给定 n 是一个正整数。
+#
+# 示例 1:
+#
+# 输入: 2
+# 输出: 2
+# 解释: 有两种方法可以爬到楼顶。
+# 1. 1 阶 + 1 阶
+# 2. 2 阶
+#
+# 示例 2:
+#
+# 输入: 3
+# 输出: 3
+# 解释: 有三种方法可以爬到楼顶。
+# 1. 1 阶 + 1 阶 + 1 阶
+# 2. 1 阶 + 2 阶
+# 3. 2 阶 + 1 阶
+#
+# Related Topics 动态规划
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def climbStairs(self, n):
+ """
+ :type n: int
+ :rtype: int
+ 最大的误区做题只做一遍
+ 优化:升维、空间换时间
+ 参考连接:https://leetcode.com/problems/climbing-stairs/discuss/25313/Python-different-solutions-(bottom-up-top-down).
+ """
+ # 傻递归,时间复杂度是O(2^N)
+ # if n == 1: return 1
+ # if n == 2: return 2
+ # return self.climbStairs(n - 1) + self.climbStairs(n - 2)
+
+ # 击败39% 开辟数组像备忘录记录递归结果
+ # if n == 1: return 1
+ # tmp = [1, 2] + [0 for _ in range(n - 2)] # 开辟额外数组空间
+ # for i in range(2, n):
+ # tmp[i] = tmp[i - 1] + tmp[i - 2]
+ # return tmp[-1]
+
+ # 击败98% 优化 开辟数组过程
+ # if n == 1: return 1
+ # tmp = [0 for _ in range(n)] # 开辟额外数组空间
+ # tmp[0], tmp[1] = 1, 2
+ # for i in range(2, n):
+ # tmp[i] = tmp[i - 1] + tmp[i - 2]
+ # return tmp[-1]
+
+ # 击败98.5% 只要一个额外的if判断
+ if n == 1: return 1
+ a, b = 1, 2
+ for i in range(2, n):
+ a, b = b, a + b
+ return b
+
+
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week01/\347\233\233\346\260\264\346\234\200\345\244\232\347\232\204\345\256\271\345\231\250.py" "b/Week01/\347\233\233\346\260\264\346\234\200\345\244\232\347\232\204\345\256\271\345\231\250.py"
new file mode 100644
index 000000000..046bf00ec
--- /dev/null
+++ "b/Week01/\347\233\233\346\260\264\346\234\200\345\244\232\347\232\204\345\256\271\345\231\250.py"
@@ -0,0 +1,51 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/9 10:23 PM
+
+# 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i,
+# ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
+#
+# 说明:你不能倾斜容器,且 n 的值至少为 2。
+#
+#
+#
+#
+#
+# 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
+#
+#
+#
+# 示例:
+#
+# 输入:[1,8,6,2,5,4,8,3,7]
+# 输出:49
+# Related Topics 数组 双指针
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def maxArea(self, height):
+ """
+ :type height: List[int]
+ :rtype: int
+ """
+ # 暴力 时间复杂度O(N^2) 运行不通过
+ # max_area = 0
+ # for i in range(len(height)):
+ # for j in range(i, len(height)):
+ # area = (j - i) * min(height[j], height[i])
+ # if max_area < area: max_area = area
+ # return max_area
+ #击败84%的人
+ left,right,area = 0,len(height)-1,0
+ while left int:
+ left, size = 0, len(nums)
+ for i in range(size):
+ if nums[i] != val:
+ nums[left] = nums[i]
+ left += 1
+ return left
+
+
+s = Solution()
+nums = [0,1,2,2,3,0,4,2]
+res = s.removeElement(nums,2)
+print(nums)
\ No newline at end of file
diff --git "a/Week01/\347\277\273\350\275\254\351\223\276\350\241\250.py" "b/Week01/\347\277\273\350\275\254\351\223\276\350\241\250.py"
new file mode 100644
index 000000000..3e52977b8
--- /dev/null
+++ "b/Week01/\347\277\273\350\275\254\351\223\276\350\241\250.py"
@@ -0,0 +1,50 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/11 3:55 PM
+
+# 反转一个单链表。
+#
+# 示例:
+#
+# 输入: 1->2->3->4->5->NULL
+# 输出: 5->4->3->2->1->NULL
+#
+# 进阶:
+# 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
+# Related Topics 链表
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# 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
+ """
+ # pre = None#击败97%
+ # while head:
+ # tmp = head.next
+ # head.next = pre
+ # pre, head = head, tmp
+ # return pre
+
+ #递归解法 重要的是边界条件和每层递归要做的事情
+ # 这里要做什么?node->next,以及存储上一层的节点以便连接
+ # 边界是什么,如果node为空,返回pre
+ return self._reverse(head)
+
+ def _reverse(self,node,pre=None):#击败38%
+ if not node:#如果节点不存在了
+ return pre
+ tmp = node.next
+ node.next = pre
+ return self._reverse(tmp,node)
+
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week01/\351\223\276\350\241\250\346\230\257\345\220\246\346\234\211\347\216\257.py" "b/Week01/\351\223\276\350\241\250\346\230\257\345\220\246\346\234\211\347\216\257.py"
new file mode 100644
index 000000000..0fda587b2
--- /dev/null
+++ "b/Week01/\351\223\276\350\241\250\346\230\257\345\220\246\346\234\211\347\216\257.py"
@@ -0,0 +1,80 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/11 8:23 PM
+
+# 给定一个链表,判断链表中是否有环。
+#
+# 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
+#
+#
+#
+# 示例 1:
+#
+# 输入:head = [3,2,0,-4], pos = 1
+# 输出:true
+# 解释:链表中有一个环,其尾部连接到第二个节点。
+#
+#
+#
+#
+# 示例 2:
+#
+# 输入:head = [1,2], pos = 0
+# 输出:true
+# 解释:链表中有一个环,其尾部连接到第一个节点。
+#
+#
+#
+#
+# 示例 3:
+#
+# 输入:head = [1], pos = -1
+# 输出:false
+# 解释:链表中没有环。
+#
+#
+#
+#
+#
+#
+# 进阶:
+#
+# 你能用 O(1)(即,常量)内存解决此问题吗?
+# Related Topics 链表 双指针
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for singly-linked list.
+# class ListNode(object):
+# def __init__(self, x):
+# self.val = x
+# self.next = None
+
+class Solution(object):
+ def hasCycle(self, head):
+ """
+ :type head: ListNode
+ :rtype: bool
+ """
+ # 双指针解法 击败40%
+ # if not head or not head.next:
+ # return False
+ # fast, slow = head.next, head
+ # while fast != slow: # 相遇的时候退出此while返回True
+ # if fast == None or fast.next == None:
+ # return False
+ # fast = fast.next.next
+ # slow = slow.next
+ # return True
+ # hashtable 击败73%
+ hashtable = {}
+ if not head or not head.next:
+ return False
+ while head: # 如果遍历完链表,则返回False
+ if hashtable.get(head):
+ return True
+ else: # 如果该节点没有出现过,则将其存入hashtable中
+ hashtable[head] = True
+ head = head.next
+ return False
+ # leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week01/\351\223\276\350\241\250\347\216\257\345\205\245\345\217\243.py" "b/Week01/\351\223\276\350\241\250\347\216\257\345\205\245\345\217\243.py"
new file mode 100644
index 000000000..2ef05f687
--- /dev/null
+++ "b/Week01/\351\223\276\350\241\250\347\216\257\345\205\245\345\217\243.py"
@@ -0,0 +1,119 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/12 4:47 PM
+
+
+# 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
+#
+# 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
+#
+# 说明:不允许修改给定的链表。
+#
+#
+#
+# 示例 1:
+#
+# 输入:head = [3,2,0,-4], pos = 1
+# 输出:tail connects to node index 1
+# 解释:链表中有一个环,其尾部连接到第二个节点。
+#
+#
+#
+#
+# 示例 2:
+#
+# 输入:head = [1,2], pos = 0
+# 输出:tail connects to node index 0
+# 解释:链表中有一个环,其尾部连接到第一个节点。
+#
+#
+#
+#
+# 示例 3:
+#
+# 输入:head = [1], pos = -1
+# 输出:no cycle
+# 解释:链表中没有环。
+#
+#
+#
+#
+#
+#
+# 进阶:
+# 你是否可以不用额外空间解决此题?
+# Related Topics 链表 双指针
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for singly-linked list.
+class ListNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+
+class Solution(object):
+ # def detectCycle(self, head):
+ # """
+ # :type head: ListNode
+ # :rtype: ListNode
+ # """
+ # # 1.hashtable beat 97%
+ # hashtable = {}
+ # while head:
+ # # if not in the hashtable
+ # if not hashtable.get(head):
+ # hashtable[head] = head
+ # # must move back the head pointer, so it can continue while loop
+ # head = head.next
+ # else:
+ # # if the node in hashtable, it must be the loop header
+ # return head
+ # # if walk here head==None, so we just return None
+ # return None
+ # 击败28%
+ # def detectCycle(self, head: ListNode) -> ListNode:
+ # if not head:
+ # return None
+ # intersect_node = self.interseet(head)
+ # if not intersect_node: # if interset is None
+ # return None
+ # tmp = head
+ # while tmp != intersect_node:
+ # tmp, intersect_node = tmp.next, intersect_node.next
+ # return intersect_node
+ #
+ # def interseet(self, head: ListNode) -> ListNode:
+ # fast, slow = head, head
+ # while fast and fast.next:
+ # fast = fast.next.next
+ # slow = slow.next
+ # if slow == fast:
+ # return slow # return the intersect
+ # return None
+ #击败47%
+ # def detectCycle(self, head: ListNode) -> ListNode:
+ # slow = fast = head
+ # while fast and fast.next:
+ # slow, fast = slow.next, fast.next.next
+ # if slow == fast:
+ # break
+ # else:
+ # return None
+ # while head != slow:
+ # slow, head = slow.next, head.next
+ # return head
+ #击败65%
+ def detectCycle(self, head: ListNode) -> ListNode:
+ fast = slow = finder = head
+ while fast and fast.next:
+ fast, slow = fast.next.next, slow.next
+ if fast == slow:
+ while slow != finder:
+ slow, finder = slow.next, finder.next
+ return slow
+ return None
+
+
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git a/Week02/.DS_Store b/Week02/.DS_Store
new file mode 100644
index 000000000..8125e1414
Binary files /dev/null and b/Week02/.DS_Store differ
diff --git a/Week02/.idea/Week02.iml b/Week02/.idea/Week02.iml
new file mode 100644
index 000000000..7c9d48f0f
--- /dev/null
+++ b/Week02/.idea/Week02.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week02/.idea/leetcode/editor.xml b/Week02/.idea/leetcode/editor.xml
new file mode 100644
index 000000000..0d23ff760
--- /dev/null
+++ b/Week02/.idea/leetcode/editor.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week02/.idea/misc.xml b/Week02/.idea/misc.xml
new file mode 100644
index 000000000..399908725
--- /dev/null
+++ b/Week02/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week02/.idea/modules.xml b/Week02/.idea/modules.xml
new file mode 100644
index 000000000..feb2b8699
--- /dev/null
+++ b/Week02/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week02/.idea/vcs.xml b/Week02/.idea/vcs.xml
new file mode 100644
index 000000000..6c0b86358
--- /dev/null
+++ b/Week02/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week02/.idea/workspace.xml b/Week02/.idea/workspace.xml
new file mode 100644
index 000000000..ac110c3b0
--- /dev/null
+++ b/Week02/.idea/workspace.xml
@@ -0,0 +1,737 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1592220835707
+
+
+ 1592220835707
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/Week02/2\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py" "b/Week02/2\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..fdd95a9bc
--- /dev/null
+++ "b/Week02/2\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,65 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/15 8:40 PM
+
+# 给定一个二叉树,返回它的中序 遍历。
+#
+# 示例:
+#
+# 输入: [1,null,2,3]
+# 1
+# \
+# 2
+# /
+# 3
+#
+# 输出: [1,3,2]
+#
+# 进阶: 递归算法很简单,你可以通过迭代算法完成吗?
+# Related Topics 栈 树 哈希表
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for a binary tree node.
+class TreeNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+from typing import List
+class Solution(object):
+ #1.递归实现 击败 67%
+ # def inorderTraversal(self, root):
+ # """
+ # #中序遍历 左根右
+ # :type root: TreeNode
+ # :rtype: List[int]
+ # """
+ # res = []
+ # if root:
+ # self.inorder(root, res)
+ # return res
+ # def inorder(self, root, res):
+ # if root.left:
+ # self.inorder(root.left, res)
+ # if root:
+ # res.append(root.val)
+ # if root.right:
+ # self.inorder(root.right, res)
+ # 击败21%
+ def inorderTraversal(self, root: TreeNode) -> List[int]:
+ if not root: return []
+ stack, res = [], []
+ while root or stack:
+ while root:
+ stack.append(root)
+ root = root.left
+ root = stack.pop()
+ res.append(root.val)
+ root = root.right
+ return res
+
+
+
+
+ # leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week02/2\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" "b/Week02/2\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..b021f1b3f
--- /dev/null
+++ "b/Week02/2\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,65 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/16 8:56 PM
+
+# 给定一个二叉树,返回它的 前序 遍历。
+#
+# 示例:
+#
+# 输入: [1,null,2,3]
+# 1
+# \
+# 2
+# /
+# 3
+#
+# 输出: [1,2,3]
+#
+#
+# 进阶: 递归算法很简单,你可以通过迭代算法完成吗?
+# Related Topics 栈 树
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for a binary tree node.
+class TreeNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+
+from typing import List
+class Solution(object):
+ # 递归方式,击败96%
+ # def preorderTraversal(self, root: TreeNode) -> List[int]:
+ # res = []
+ # if root:
+ # self.preorder(root, res)
+ # return res
+ #
+ # def preorder(self, root, res): # 前序遍历 根左右
+ # if root:
+ # res.append(root.val)
+ # if root.left:
+ # self.preorder(root.left, res)
+ # if root.right:
+ # self.preorder(root.right, res)
+ #非递归方式 击败86%
+ def preorderTraversal(self, root: TreeNode) -> List[int]:
+ # 前序遍历的迭代实现
+ if root is None: return []
+ stack = [root]
+ res = []
+ while stack:
+ cur = stack.pop()
+ if cur is not None:
+ res.append(cur.val)
+ # 考虑到入栈的顺序,所以先右后左
+ if cur.right is not None:
+ stack.append(cur.right)
+ if cur.left is not None:
+ stack.append(cur.left)
+ return res
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week02/2\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py" "b/Week02/2\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..d236468cb
--- /dev/null
+++ "b/Week02/2\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,38 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/16 9:37 PM
+
+class Solution(object):
+ # def postorderTraversal(self,root):
+ # res = []
+ # if root is not None:
+ # self.postorder(root, res)
+ # return res
+ # def postorder(self,root,res):
+ # if root.left is not None:
+ # self.postorder(root.left)
+ # if root is not None:
+ # res.append(root.val)
+ # if root.right is not None:
+ # self.postorder(root.right)
+ def postorderTraversal(self, root):
+ #用两个栈实现后序遍历的非递归实现
+ if root is None:
+ return False
+ stack1, stack2 = [root], []
+ while stack1: # 找出后序遍历的逆序,存放在 stack2中
+ node = stack1.pop()
+ if node.left:
+ stack1.append(node.left)
+ if node.right:
+ stack1.append(node.right)
+ stack2.append(node.val)
+ return stack2[::-1]
+
+
+
+
+
+
+
+
diff --git "a/Week02/2\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" "b/Week02/2\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..3402a8528
--- /dev/null
+++ "b/Week02/2\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,32 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/16 10:54 PM
+
+class Solution(object):
+ def levelTraversal(self,root):
+ # if root is None:
+ # return False
+ # stack1, stack2 = [root], []
+ # while stack1: # 找出后序遍历的逆序,存放在 stack2中
+ # node = stack1.pop(0)#抛出第一个元素
+ # if node.left:
+ # stack1.append(node.left)
+ # if node.right:
+ # stack1.append(node.right)
+ # stack2.append(node.val)
+ # return stack2#这里是层序遍历就不用反转了
+
+ if not root: return []
+ res, depth = [], 0
+ self.dfs(root, res, depth)
+ return res
+
+ def dfs(self, root, res, depth):
+ if not root: return
+ if len(res) == depth: res.append([]) # 每当进入到一个新的depth,就创建一个[]
+ res[depth].append(root.val)
+ if root.left:
+ self.dfs(root.left, res, depth + 1)
+ if root.right:
+ self.dfs(root.right, res, depth + 1)
+
diff --git a/Week02/NOTE.md b/Week02/NOTE.md
index 50de30414..fcf849569 100644
--- a/Week02/NOTE.md
+++ b/Week02/NOTE.md
@@ -1 +1,760 @@
-学习笔记
\ No newline at end of file
+学习笔记
+
+[TOC]
+
+#### 有效的异位词
+1.直接对两个字符串进行排序,判断排序后的结果是否一致
+```
+return sorted(s) == sorted(t)
+```
+2.根据两个字符串构建hash表,判断两个hash表是否一致
+```python
+dic1, dic2 = {}, {}
+for item in s:
+ dic1[item] = dic1.get(item, 0) + 1
+for item in t:
+ dic2[item] = dic2.get(item, 0) + 1
+return dic1 == dic2
+
+```
+3.只需要使用一个hash表,前一次遍历增加值,后一次遍历减少值
+最后判断hash表中的值是否为0
+```python
+if len(s) != len(t): return False
+hashmap = {}
+for substr in s:
+ if not hashmap.get(substr):
+ hashmap[substr] = 1
+ else:
+ hashmap[substr] += 1
+for substr in t:
+ if hashmap.get(substr):
+ hashmap[substr] -= 1
+ else:
+ return False
+for value in hashmap.values():
+ if value != 0:
+ return False
+return True
+
+```
+4.使用python内置的count函数,统计字符出现的个数 原理与方法2一致
+
+```python
+if len(s) != len(t):
+ return False
+for i in set(s):
+ if s.count(i) != t.count(i):
+ return False
+return True
+```
+优化
+```python
+
+if len(s)!=len(t):return False
+tmp = set(s)
+if tmp == set(t):#如果两个字符串的set相同进行深入判断
+ for i in tmp:
+ if s.count(i) != t.count(i): return False
+ return True
+return False
+```
+
+#### 异位词分组
+对于给定包含多个字符串的列表,将其按照是否异位词分组输出
+1.由于异位词都是由相同字母集组成的,可以在遍历列表时,根据其字母排序是否一致,作为异位词分组的根据
+具体的 根据字母排序是否一致,构建hash表,以字母排序作为key(当然也可以使用字母的tuple序),以原字符串作为键
+由于涉及到排序 所以时间复杂度为O(NKlogK),空间复杂度为O(NK)
+```python
+dic = {}
+for item in strs:
+ # key = tuple(sorted(item))#字母的键也可以用字母排序对应的tuple
+ key = ''.join(sorted(item))#sorted返回的是list,不能作为dict的键
+ if key in dic:
+ dic[key].append(item)
+ else:
+ dic[key] = [item]
+# return [x for x in dic.values()]#击败94%
+return [dic[x] for x in dic]#击败97%
+```
+这种写法很直观,但是判断当前字符是否存在hash表中,有简简洁写法
+dict.get()获取不到时,返回[]
+获取到时 + [item]可以直接在原list中拼接
+```python
+dic = {}
+for item in strs:
+ key = ''.join((sorted(item)))
+ dic[key] = dic.get(key, []) + [item]
+return [dic[x] for x in dic]
+```
+当然也可以使用defaultdict实现
+```angular2html
+dic = collections.defaultdict(list)
+for item in strs:
+ dic[tuple(sorted(item))].append(item)
+return [dic[item] for item in dic]
+```
+
+2.根据字符串中字符出现的次数作为hash表的键
+对于每次遍历到的字符串,都需要维护一个长度为26的list,并要将其转化为tuple
+时间复杂度是O(NK),空间复杂度为O(NK)
+```python
+dic = {}
+for item in strs:
+ count = [0] * 26
+ for char in item:
+ count[ord(char) - ord('a')] += 1
+ # res[tuple(count)].append(item)
+ dic[tuple(count)] = dic.get(tuple(count),[]) + [item]
+return [dic[x] for x in dic]
+```
+对应的defaultdict实现如下
+```python
+dic = collections.defaultdict(list)
+for item in strs:
+ count = [0] * 26
+ for char in item:
+ count[ord(char) - ord('a')] += 1
+ dic[tuple(count)].append(item)
+return [dic[x] for x in dic]
+```
+
+### 二叉树的深度优先遍历
+递归实现都比较简单,也比较容易理解,不赘述
+
+#### 二叉树的前序遍历 根左右
+
+1.递归实现
+```python
+def preorderTraversal(self, root: TreeNode) -> List[int]:
+ res = []
+ if root:
+ self.preorder(root, res)
+ return res
+
+def preorder(self, root, res): # 前序遍历 根左右
+ if root:
+ res.append(root.val)
+ if root.left:
+ self.preorder(root.left, res)
+ if root.right:
+ self.preorder(root.right, res)
+```
+2.非递归实现
+前序遍历的非递归实现应该是这三中遍历方式中最简单的
+首先将根节点置于stack中,在栈不为空的前提下,遍历整个二叉树
+每次先取出stack顶元素,如果栈顶元素不为None,就可以直接存入res中
+然后判断其左右子节点是否存在,并对他们进行入栈操作
+最后返回res
+
+```python
+def preorderTraversal(self, root: TreeNode) -> List[int]:
+ # 前序遍历的迭代实现
+ if root is None: return []
+ stack = [root]
+ res = []
+ while stack:
+ cur = stack.pop()
+ if cur is not None:
+ res.append(cur.val)
+ # 考虑到入栈的顺序,所以先右后左
+ if cur.right is not None:
+ stack.append(cur.right)
+ if cur.left is not None:
+ stack.append(cur.left)
+ return res
+```
+
+#### 二叉树的中序遍历 左根右
+1.递归实现
+```python
+def inorderTraversal(self, root):
+ """
+ #中序遍历 左根右
+ :type root: TreeNode
+ :rtype: List[int]
+ """
+ res = []
+ if root:
+ self.inorder(root, res)
+ return res
+def inorder(self, root, res):
+ if root.left:
+ self.inorder(root.left, res)
+ if root:
+ res.append(root.val)
+ if root.right:
+ self.inorder(root.right, res)
+```
+
+2.非递归实现
+中序遍历的非递归实现就复杂一些了,因为每次并不是先将根节点的值输出,而是优先的找到树的最左子树
+所以要确保能一直往最左节点找 同时入栈 如果已经找到最左节点,
+那么首先应当将这个元素出栈存入res中 其次应判断当前栈顶元素是是否有右孩子 将cur指向栈顶元素的右孩子
+```python
+def inorderTraversal(self, root: TreeNode) -> List[int]:
+ if root is None: return []
+ res, stack = [], []
+ cur = root
+ while cur is not None or stack:
+ while cur is not None: # 确保了能一直往左走
+ stack.append(cur)
+ cur = cur.left
+ cur = stack.pop() # 相当于等到这次的根节点
+ res.append(cur.val)
+ cur = cur.right
+ return res
+```
+
+#### 二叉树的后序遍历 左右根
+1.递归实现
+```python
+def postorderTraversal(self,root):
+ res = []
+ if root is not None:
+ self.postorder(root, res)
+ return res
+def postorder(self,root,res):
+ if root.left is not None:
+ self.postorder(root.left)
+ if root is not None:
+ res.append(root.val)
+ if root.right is not None:
+ self.postorder(root.right)
+```
+2.非递归实现
+后续遍历的非递归方式应该是最难的,因为在入栈过程中还需要额外的指针标识是否已经访问过左子树的右孩子节点
+这里取巧使用两个栈,根节点不用在一个单独的栈中出入并用指针记录访问元素
+
+```python
+def postorderTraversal(self, root):
+ #用两个栈实现后序遍历的非递归实现
+ if root is None:
+ return False
+ stack1,stack2 = [root], []
+ while stack1: # 找出后序遍历的逆序,存放在 stack2中
+ node = stack1.pop()#每次取出的都是右子树节点值,进而在stack2中就相当于存储的是
+ if node.left:
+ stack1.append(node.left)
+ if node.right:
+ stack1.append(node.right)
+ stack2.append(node.val)
+ return stack2[::-1]
+```
+
+#### 二叉树的层序遍历
+写着写着,才发现二叉树的层序遍历和我上面后序遍历是真的像
+```python
+class Solution(object):
+ def levelTraversal(self,root):
+ if root is None:
+ return False
+ stack1, stack2 = [root], []
+ while stack1: # 找出后序遍历的逆序,存放在 stack2中
+ node = stack1.pop(0)#抛出第一个元素
+ if node.left:
+ stack1.append(node.left)
+ if node.right:
+ stack1.append(node.right)
+ stack2.append(node.val)
+ return stack2#这里是层序遍历就不用反转了
+```
+
+
+#### N叉树的层序遍历
+刚开始是这么写的,看起来算法逻辑没什么问题,但是这里我相当于是将cur当做一个list在做
+而实际上cur只是一个Node,哪怕它是root.children它也是个Node,所以没法将其进行迭代
+```python
+def levelOrder(self, root: 'Node') -> List[List[int]]:
+ if root is None: return []
+ quene,res = [root],[]
+ while quene:
+ cur = quene.pop()
+ if cur is not None:
+ print(type(cur))#cur is Node
+ #tmp = []
+ #for item in cur:
+ # tmp.append(item.val)
+ #res.append(tmp)
+ res.append([item.val for item in cur])
+ for child in cur.children:
+ quene.append(child)
+ return res
+```
+改进之后,这里 实际上quene每次存储的都是每一层的所有节点,
+每次都将quene所有元素记录到tmp中,将所有节点合并为list之后存入res
+同时,在加入的过程中,用tmp_quene记录下一层的节点值,
+在遍历完上层节点后,将下层节点赋给quene
+```python
+def levelOrder(self,root):
+ #击败55%
+ if root is None: return []
+ quene,res = [root],[]
+ while quene:
+ #将当前层的所有元素出队列,记录其值存入res中,由于输出格式的限制,要用tmp先存放
+ #并且将其孩子全部记录在下一个quene中,这样保证了上层节点全部被加入到res中,而不会发生交替现象
+ tmp, tmp_quene = [], []#这个tmp_quene是为了暂存下一层的所有节点
+ for node in quene:
+ tmp.append(node.val)
+ for child in node.children:
+ tmp_quene.append(child)
+ res.append(tmp)
+ quene = tmp_quene
+ return res
+```
+
+#### N叉树的前序遍历
+```python
+class Solution:
+ def preorder(self, root: 'Node') -> List[int]:
+ #dfs
+ # if not root: return []
+ # res = []
+ # self.dfs(root,res)
+ # return res
+ # def dfs(self,root,res):
+ # res.append(root.val)
+ # for node in root.children:
+ # self.dfs(node,res)
+ #bfs 根左右
+ if not root: return[]
+ stack, res = [root], []
+ while stack:
+ cur = stack.pop()
+ res.append(cur.val)
+ for node in cur.children[::-1]:
+ stack.append(node)
+ return res
+
+```
+
+#### N叉树的后序遍历
+```python
+class Solution:
+ def postorder(self, root: 'Node') -> List[int]:
+ # #dfs
+ # if not root: return []
+ # stack, res = [root],[]
+ # while stack:
+ # cur = stack.pop()
+ # for node in cur.children:
+ # stack.append(node)
+ # res.append(cur.val)
+ # return res[::-1]
+ #dfs
+ if not root: return []
+ res = []
+ self.dfs(root,res)
+ return res
+ def dfs(self, root, res):
+ for node in root.children:
+ self.dfs(node,res)
+ res.append(root.val)
+```
+
+#### N叉树的最大深度
+```python
+class Solution:
+ def maxDepth(self, root: 'Node') -> int:
+ #DFS
+ # if not root: return 0
+ # if not root.children: return 1
+ # tmp = [self.maxDepth(node) for node in root.children]
+ # return max(tmp) + 1
+ #bfs
+ if not root: return 0
+ # if not root.children: return 1
+ stack, depth = [root], 0
+ while stack:
+ depth += 1
+ for i in range(len(stack)):
+ cur = stack.pop(0)
+ for node in cur.children:
+ stack.append(node)
+ return depth
+```
+
+#### 二叉树的最大深度
+```python
+# Definition for a binary tree node.
+# class TreeNode:
+# def __init__(self, x):
+# self.val = x
+# self.left = None
+# self.right = None
+
+class Solution:
+ def maxDepth(self, root: TreeNode) -> int:
+ #bfs
+ if not root: return 0
+ stack, depth = [root], 0
+ while stack:
+ for i in range(len(stack)):
+ cur = stack.pop(0)#注意到这里和后序遍历 层序遍历一致 都是pop(0)
+ if cur.left: stack.append(cur.left)
+ if cur.right: stack.append(cur.right)
+ depth += 1
+ return depth
+ #dfs
+ # if not root: return 0
+ # return max(self.maxDepth(root.left),self.maxDepth(root.right)) + 1
+
+```
+
+#### 二叉树的最小深度
+```python
+
+```
+
+
+#### 数组中最小的k个数
+1.暴力解法 对数组进行排序,返回前k个
+```python
+arr.sort()
+return arr[:k]
+```
+2.小根堆 借助python内置的heapq实现
+```angular2html
+if k == 0:
+ return []
+heap = [-x for x in arr[:k]] # 只用维护一个大小为k的小根堆
+heapq.heapify(heap) # 这k个元素一定满足三角顶最小的原则
+for i in range(k, len(arr)):
+ if -heap[0] > arr[i]:
+ heapq.heappop(heap) # 如果堆中的元素大于入堆元素,则将原堆顶元素出堆
+ heapq.heappush(heap, -arr[i]) # 将这个元素放入小根堆中,heappop中调用了siftup调整了堆
+res = [-x for x in heap]
+return res
+```
+3.快排思想
+```python
+def partition(self, nums, left, right):
+ pivot = nums[left]
+ while left < right:
+ while left < right and pivot <= nums[right]:
+ right -= 1
+ nums[left] = nums[right]
+ while left < right and nums[left] <= pivot:
+ left += 1
+ nums[right] = nums[left]
+ nums[left] = pivot
+ return left
+
+def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
+ # 快速排序法:
+ size = len(arr)
+ if size == 0 or k > size: return
+ if size == 1 or size == k:
+ return arr
+ left, right = 0, size - 1
+ while left <= right: # 这里其实也相当于是二分法
+ pivot = self.partition(arr, left, right) # left, right, split_ind 都是原始 index
+ if pivot == k: # 在 split_ind 左边有 k 个元素,全部不大于 pivot
+ break
+ elif pivot > k:
+ right = pivot - 1 # 不-1 会陷入死循环
+ else:
+ left = pivot + 1 # 不 +1 会陷入死循环
+ return arr[:k]
+```
+
+#### 堆排序
+堆排序的过程主要包括 建堆以及对每一个小三角形进行堆化处理,使之满足小根堆或者大根堆的情形
+建堆是指,对于给定的元素,从下往上考虑(从最后一个非叶节点开始)使之满足nums_i>(nums_2xi+1,nums_2i+2)
+然后对于每一个元素 逆序遍历时 与堆的根节点进行调换 对树进行从上往下的堆化比较过程
+对于有节点值交换的情形 进一步考量它的下一层是否符合小根堆或大根堆的条件
+建堆之后 堆顶的元素应该是最大的(大根堆),此时将它与末尾元素调换就会使得最大元素到最后位置,对现今的堆顶元素进行堆化
+这个过程就完成了对一个元素的排序,目前堆中的最大元素已经到了末尾,下一次进行调整时就无须再处理此元素
+```python
+
+#时间复杂度为NlogN,logN为建立大根堆/小根堆的时间复杂度,
+#heapify的时间复杂度是O(logN)的因为,最坏情况下,每一层都需要判断
+#N为对已经构成的堆排序反向遍历的时间复杂度
+
+def heapify(self, nums, size, i):#heapify过程就是递归考量三角是否满足条件
+ max_index = i
+ left, right = 2*i+1,2*i+2
+ if left < size and nums[left] > nums[max_index]:
+ max_index = left
+ if right < size and nums[right] > nums[max_index]:
+ max_index = right
+ if max_index != i:#存在交换的情形
+ nums[i], nums[max_index] = nums[max_index], nums[i]
+ self.heapify(nums, size, max_index)
+
+def heap_sort(self,nums):
+ size = len(nums)
+ for i in range(size//2-1,-1,-1):
+ self.heapify(nums,size,i)
+ print(nums)
+
+ for i in range(size-1,0,-1):#排序需要对整个堆进行调整
+ nums[i], nums[0] = nums[0], nums[i]#交换末尾元素与堆顶元素
+ self.heapify(nums,i,0)#交换之后,要确定这个堆是否合乎条件,进行堆化,
+ #要注意到,每次堆化时,就已经把一个元素排好了,放在最末尾了,以后就不许要再考虑这个元素了
+```
+
+
+#### 判断是否是丑数
+如果一个数是丑数那肯定满足这种定义num = 2^i*3^j*5^k
+```python
+if num == 0: return False
+while num % 5 == 0: num /= 5
+while num % 3 == 0: num /= 3
+while num % 2 == 0: num /= 2
+return num == 1#击败98%,省去了迭代的过程
+```
+当然也可以简化为如下,但是就要多一部分迭代过程
+```angular2html
+for item in [2,3,5]:
+ while num%item==0:#依次除尽2,3,5
+ num = num/item
+# return True if num==1 else False #击败50%
+# return num==1#击败87%
+```
+
+#### 求第n个丑数
+动态规划的题,解法分 动态转移方程和动态转移矩阵
+后面整理一套解法
+```python
+# 1、2、3、5、4、6、8、9、10
+if n==0:
+ return 0
+res = [1]*n
+p2,p3,p5 = 0,0,0#指向三个队列的指针
+for i in range(1,n):
+ res[i] = min(res[p2]*2,res[p3]*3,res[p5]*5)
+ if res[i] == res[p2]*2: p2 = p2+1
+ if res[i] == res[p3]*3: p3 = p3+1
+ if res[i] == res[p5]*5: p5 = p5+1
+return res[-1]
+```
+
+#### 验证字符串是否是回文串
+1.翻转字符串 看是否相同 击败81%
+```python
+tmp = "".join(char.lower() for char in s if ch.isalnum())
+return tmp == tmp[::-1]
+```
+2.双指针 击败61%
+```angular2html
+tmp = "".join(char.lower() for char in s if ch.isalnum())
+n = len(tmp)
+left, right = 0, n - 1
+while left < right:
+ if tmp[left] != tmp[right]:
+ return False
+ left, right = left + 1, right - 1
+return True
+```
+
+#### 正则表达式匹配
+1.递归解法
+是超出时间限制的,时间复杂度是O(3^N)
+```python
+def isMatch(self, s: str, pattern: str) -> bool:
+ # 特殊情况处理
+ if len(s) == 0 and len(pattern) == 0: return True
+ if len(s) > 0 and len(pattern) == 0: return False
+ # 如果pattern形如 a*####,检查这个*能匹配几次
+ if len(pattern) > 1 and pattern[1] == '*':#击败80%
+ # s和pattern首字母相同
+ if len(s) > 0 and (pattern[0] == s[0] or pattern[0] == '.'):
+ # s能和pattern匹配的情形
+ # 1.*匹配0次,则需要递归的对s和pattern[2:]进行匹配
+ # 2.*匹配1次,需要递归的对s[1:]和pattern[2:]进行匹配
+ # 3.*匹配n次,需要递归的对s[1:]和pattern进行匹配
+ return self.isMatch(s, pattern[2:]) or self.isMatch(s, pattern[2:]) or self.isMatch(s[1:], pattern)
+ else: # 如果首字母不相同,就相当于*匹配0次,继续匹配s和pettern[2:]
+ return self.isMatch(s, pattern[2:])
+ # pattern以.开头
+ if len(s) > 0 and (pattern[0] == '.' or s[0] == pattern[0]):
+ return self.isMatch(s[1:], pattern[1:])
+ return False
+```
+python中有装饰器优化迭代过程@lru_cache
+所以在函数前使用装饰器即可通过
+```python
+@lru_cache
+def isMatch(self, s: str, pattern: str) -> bool:
+ pass
+```
+上面的代码比较复杂,可以优化代码
+```angular2html
+if not pattern: return not s#这句话真的优秀
+match_first = bool(s) and (pattern[0] == s[0] or pattern[0] == '.')
+if len(pattern) > 1 and pattern[1] == '*':
+ return (self.isMatch(s, pattern[2:]) or match_first and self.isMatch(s[1:], pattern))
+else:
+ return match_first and self.isMatch(s[1:], pattern[1:])
+```
+2.动态规划
+```python
+pass
+```
+
+
+#### 只出现一次的数字 时间复杂度为O(N),空间复杂度为O(N)
+除一个数外,所有元素都出现了两次,求这个只出现一次的元素
+1.两次hash表 遍历list,用hash表统计每个值出现的次数,根据出现次数返回key
+```python
+# 1.hash表记录出现次数,以num为key,以出现次数为value 击败42%
+dic = {}
+for num in nums:
+ dic[num] = dic.get(num,0)+1
+for key, value in dic.items():
+ if value == 1:
+ return key
+```
+2.题目要求用常数级的空间复杂度实现,则不能用hash表实现
+```python
+#位运算,击败97%
+# 由于每个元素都出现了两次,根据异或运算可以消去这两个元素
+#最后保留的就是带求值key和初始值1的异或
+res = 0
+for num in nums:
+ res ^= num
+return res
+```
+
+#### 只出现一次的数字II
+1. 数学计算
+```python
+tmp = set(nums)
+return (3*sum(tmp) - sum(nums))//2
+```
+给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
+1.python解法 使用count函数 但是count函数本身的时间复杂度就是O(N)的,导致算法时间复杂度是O(N^2)
+```python
+for num in nums:
+ if nums.count(num)==1:
+ return num
+```
+对应的优化是采用collections中的Counter模块
+```python
+from collections import Counter
+dic = Counter(nums)
+for key in dic.keys():
+ if dic[key] == 1:
+ return key
+```
+2.hash表法 通用解
+```python
+dic = {}
+for num in nums:
+ dic[num] = dic.get(num,0)+1
+for key, value in dic.items():
+ if value == 1:
+ return key
+```
+3. 借助逻辑电路,构造这样的逻辑门状态
+1x1x1->1 1->0,这个数可以出现0次、1次、2次,需要两位来表示其状态
+构造真值表 写出逻辑表达式 并化简
+参考连接[电路逻辑通俗解](https://leetcode-cn.com/problems/single-number-ii/solution/luo-ji-dian-lu-jiao-du-xiang-xi-fen-xi-gai-ti-si-l/)
+```python
+x,y = 0,0
+for z in nums:
+ tmp = ~x&(y^z)
+ x = (x&~y&~z)|(~x&y&z)
+ y = tmp
+return y
+```
+根据两个表达式同构的性质,可以优化更新x的逻辑表达式
+```python
+x, y = 0, 0
+for num in nums:#num means input
+ y = ~x & (y^num)
+ x = ~y & (x^num)
+return y
+```
+
+#### 只出现一次的数字III
+1.使用Counter
+```python
+from collections import Counter #{'num':count}
+dic = Counter(nums)
+return [key for key in dic if dic[key]==1 ]
+```
+给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
+2.hash表法
+```python
+dic,res = {}, []
+for num in nums:
+ dic[num] = dic.get(num,0) + 1
+for key,value in dic.items():
+ if value == 1:
+ res.append(key)
+return res
+```
+3.接上一题的思路,如果对这些元素进行异或,得到的结果就是待求元素的异或值,如何从结果中分离这两个元素呢?
+异或得到的结果不能直接分离出待求元素,但是我们可以根据这个异或值的第一个1将原数组分类,
+由于其余元素都是出现两次的,所以对这两个数组分别求异或即可得到结果。
+```python
+tmp = 0
+for num in nums:
+ tmp ^= num
+#找到第一位不相同的数字
+count = 0
+while tmp&1 !=1:
+ tmp>>=1#右移1位
+ count += 1
+tmp1,tmp2 = [],[]
+for num in nums:
+ if num>>count & 1 == 0:#将该数向右移动count位
+ tmp1.append(num)
+ else:
+ tmp2.append(num)
+res = []
+t1,t2 = 0,0
+for num in tmp1:
+ t1 ^= num
+res.append(t1)
+for num in tmp2:
+ t2^= num
+res.append(t2)
+return res
+
+```
+上面的方式可以优化,其一,找第一位不同,第二,不需要用数组存放元素,直接根据此位是否为1,直接进行计算
+```python
+tmp= 0
+for num in nums:
+ tmp ^= num
+# rightmost 1-bit diff between x and y
+diff = tmp & (-tmp)#这个找到第一位不相同的方式厉害
+x = 0
+for num in nums:
+ if num & diff:#结果大于0执行,此位为1为一组,直接计算
+ x ^= num
+return [x, tmp^x]#tmp是两个数的异或值,一个值已经找到了
+```
+
+#### 二叉树的最大路径和
+比较自然的想法是递归,计算上层节点的最大路径时,只需要考虑左右子树最大值
+路径: 左->中->再上
+ 左->中
+ 左->中->右
+```python
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+#路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
+class Solution:
+ def __init__(self):
+ self.maxpath_sum = float("-inf")#节点值可能为负值
+
+ def maxPathSum(self, root: TreeNode) -> int:
+ self.maxGain(root)
+ return self.maxpath_sum
+
+ def maxGain(self,node):
+ if not node: return 0
+ left_gain = max(self.maxGain(node.left),0)#将空值、负值过滤掉了
+ right_gain = max(self.maxGain(node.right),0)
+ path_sum = node.val + left_gain + right_gain #左根右
+ self.maxpath_sum = max(path_sum, self.maxpath_sum)#更新self.maxpath_sum,过滤负值
+ return node.val + max(left_gain, right_gain)#对于更上层的元素,它的最大路径值,只可能向左或向右到达此节点,所以取最大值
+```
diff --git "a/Week02/[108]\346\234\211\345\272\217\346\225\260\347\273\204\351\207\215\345\273\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.py" "b/Week02/[108]\346\234\211\345\272\217\346\225\260\347\273\204\351\207\215\345\273\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.py"
new file mode 100644
index 000000000..5408328b5
--- /dev/null
+++ "b/Week02/[108]\346\234\211\345\272\217\346\225\260\347\273\204\351\207\215\345\273\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.py"
@@ -0,0 +1,21 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/18 11:37 AM
+
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Solution:
+ def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
+ def buildTree(left,right):
+ if left>right: return None
+ mid = left + ((right-left)>>1)
+ root = TreeNode(nums[mid])
+ root.left = buildTree(left,mid-1)
+ root.right = buildTree(mid+1,right)
+ return root
+ return buildTree(0,len(nums)-1)
\ No newline at end of file
diff --git "a/Week02/[109]\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" "b/Week02/[109]\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py"
new file mode 100644
index 000000000..01d4d1680
--- /dev/null
+++ "b/Week02/[109]\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py"
@@ -0,0 +1,35 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/18 11:13 AM
+
+
+# Definition for singly-linked list.
+class ListNode:
+ def __init__(self, val=0, next=None):
+ self.val = val
+ self.next = next
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, val=0, left=None, right=None):
+ self.val = val
+ self.left = left
+ self.right = right
+class Solution:
+ # 时间复杂度O(nlogn),空间复杂度O(logn)
+ def sortedListToBST(self, head: ListNode) -> TreeNode:
+ # 找到根节点,左右子树继续找根节点
+ def findroot(left,right):
+ fast = slow = left
+ while fast != right and fast.next != right:
+ fast = fast.next.next
+ slow = slow.next
+ return slow
+
+ def buildBST(left,right):
+ if left == right: return None
+ node = findroot(left,right)
+ root = TreeNode(node.val)#产生空间开销
+ root.left = buildBST(left,node)#注意这里是分治的过程,左右子树继续找根节点,
+ root.right = buildBST(node.next,right)
+ return root
+ return buildBST(head,None)
diff --git "a/Week02/[125]\346\257\217\346\227\245\344\270\200\351\242\2306_19_\351\252\214\350\257\201\346\230\257\345\220\246\345\233\236\346\226\207\344\270\262.py" "b/Week02/[125]\346\257\217\346\227\245\344\270\200\351\242\2306_19_\351\252\214\350\257\201\346\230\257\345\220\246\345\233\236\346\226\207\344\270\262.py"
new file mode 100644
index 000000000..e54994c89
--- /dev/null
+++ "b/Week02/[125]\346\257\217\346\227\245\344\270\200\351\242\2306_19_\351\252\214\350\257\201\346\230\257\345\220\246\345\233\236\346\226\207\344\270\262.py"
@@ -0,0 +1,42 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/20 11:03 PM
+
+# 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
+#
+# 说明:本题中,我们将空字符串定义为有效的回文串。
+#
+# 示例 1:
+#
+# 输入: "A man, a plan, a canal: Panama"
+# 输出: true
+#
+#
+# 示例 2:
+#
+# 输入: "race a car"
+# 输出: false
+#
+# Related Topics 双指针 字符串
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def isPalindrome(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ #1. 翻转字符串 看是否相同 击败81%
+ # tmp = "".join(ch.lower() for ch in s if ch.isalnum())
+ # return tmp == tmp[::-1]
+ #2.双指针 击败61%
+ tmp = "".join(ch.lower() for ch in s if ch.isalnum())
+ n = len(tmp)
+ left, right = 0, n - 1
+ while left < right:
+ if tmp[left] != tmp[right]:
+ return False
+ left, right = left + 1, right - 1
+ return True
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week02/\345\207\272\347\216\260\351\242\221\347\216\207\346\234\200\351\253\230\347\232\204k\344\270\252\346\225\260.py" "b/Week02/\345\207\272\347\216\260\351\242\221\347\216\207\346\234\200\351\253\230\347\232\204k\344\270\252\346\225\260.py"
new file mode 100644
index 000000000..1778a7128
--- /dev/null
+++ "b/Week02/\345\207\272\347\216\260\351\242\221\347\216\207\346\234\200\351\253\230\347\232\204k\344\270\252\346\225\260.py"
@@ -0,0 +1,20 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/19 8:41 PM
+from typing import List
+class Solution:
+ # : List[int], k: int
+ def topKFrequent(self, nums) -> List[int]:
+ dic = {}
+ for num in nums:
+ if not dic.get(num):
+ dic[num] = 1
+ else:
+ dic[num] += 1
+ res = sorted(dic.items(),key=lambda item:item[1])
+ return res
+
+nums = [1,1,1,2,2,3]
+s = Solution()
+res = s.topKFrequent(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week02/\345\240\206\346\216\222\345\272\217.py" "b/Week02/\345\240\206\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..5262551bc
--- /dev/null
+++ "b/Week02/\345\240\206\346\216\222\345\272\217.py"
@@ -0,0 +1,88 @@
+# # -*- coding:utf-8 -*-
+# # Author : Ray
+# # Data : 2020/6/18 7:06 PM
+#
+# # !/usr/bin/env python
+# # -*- coding: utf-8 -*-
+# # @Time : 2019/12/2 18:25
+# # @Author : mqray
+# # @File : 选择排序之堆排序#
+#
+class HeapSort():
+ '''
+ 时间复杂度为NlogN,logN为建立大根堆/小根堆的时间复杂度,
+ heapify的时间复杂度是O(logN)的因为,最坏情况下,每一层都需要判断
+ N为对已经构成的堆排序反向遍历的时间复杂度
+ '''
+ def heapify(self, nums, size, i):#heapify过程就是递归考量三角是否满足条件
+ max_index = i
+ left, right = 2*i+1,2*i+2
+ if left < size and nums[left] > nums[max_index]:
+ max_index = left
+ if right < size and nums[right] > nums[max_index]:
+ max_index = right
+ if max_index != i:#存在交换的情形
+ nums[i], nums[max_index] = nums[max_index], nums[i]
+ self.heapify(nums, size, max_index)
+
+ def heap_sort(self,nums):
+ size = len(nums)
+ for i in range(size//2-1,-1,-1):
+ self.heapify(nums,size,i)
+
+ for i in range(size-1,0,-1):#排序需要对整个堆进行调整
+ nums[i], nums[0] = nums[0], nums[i]#交换末尾元素与堆顶元素
+ self.heapify(nums,i,0)#交换之后,要确定这个堆是否合乎条件,进行堆化,
+ #要注意到,每次堆化时,就已经把一个元素排好了,放在最末尾了,以后就不许要再考虑这个元素了
+
+
+#
+# def heapify(self, nums, n, i):
+# '''
+# 堆化操作,将数组转化为小根堆
+# :param nums: 完全二叉树对应的数组
+# :param n: 元素个数
+# :param i: 进行堆化的数组下标
+# '''
+# #取当前节点,将其与左右孩子中较大的元素进行调换
+# if i >= n:
+# return
+# c1, c2 = 2 * i + 1, 2 * i + 2
+# max = i # 暂存最大数对应index
+# if c1 < n and nums[c1] > nums[max]:
+# max = c1
+# if c2 < n and nums[c2] > nums[max]:
+# max = c2
+# print(nums)
+# if max != i:
+# nums[i], nums[max] = nums[max], nums[i]
+# self.heapify(nums, n, max)
+#
+# def build_heap(self, nums, n):
+# last_node = n - 1 # 堆化过程只需要考虑最后一个节点的父节点及其之前的节点
+# parent = (last_node - 1) // 2
+# for i in range(parent, -1, -1):
+# self.heapify(nums, n, i)
+#
+# def heap_sort(self, nums, n):
+# self.build_heap(nums, len(nums))
+# print('build finished')
+# for i in range(n-1, -1, -1):
+# nums[i], nums[0] = nums[0], nums[i] # 交换堆顶与最后一个元素,将交换后得到的最大数砍断
+# self.heapify(nums, i, 0) # 后续操作一样,只不过后续的最大索引值变小了
+#
+#
+nums = [4, 10, 3, 5, 1, 2]
+s = HeapSort()
+s.heap_sort(nums)
+print(nums)
+
+
+
+
+
+
+
+
+
+
diff --git "a/Week02/\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py" "b/Week02/\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py"
new file mode 100644
index 000000000..cf7ba6f87
--- /dev/null
+++ "b/Week02/\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py"
@@ -0,0 +1,69 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/15 9:40 PM
+
+# 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
+#
+# 示例:
+#
+# 输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
+# 输出:
+# [
+# ["ate","eat","tea"],
+# ["nat","tan"],
+# ["bat"]
+# ]
+#
+# 说明:
+#
+#
+# 所有输入均为小写字母。
+# 不考虑答案输出的顺序。
+#
+# Related Topics 哈希表 字符串
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def groupAnagrams(self, strs):
+ """
+ :type strs: List[str]
+ :rtype: List[List[str]]
+ """
+ #击败74%
+ # from collections import defaultdict
+ # ans = defaultdict(list)
+ # #根据异位词分组 {('a','b','c'):['abc']}
+ # for s in strs:
+ # ans[tuple(sorted(s))].append(s)
+ # return list(ans.values())
+
+ #击败36%
+ # ans = collections.defaultdict(list)
+ # for s in strs:
+ # count = [0] * 26
+ # for c in s:
+ # count[ord(c) - ord('a')] += 1
+ # ans[tuple(count)].append(s)
+ # return list(ans.values())
+
+ #击败50%
+
+ # d = {}
+ # for w in sorted(strs):
+ # key = tuple(sorted(w))
+ # d[key] = d.get(key, []) + [w]
+ # return list(d.values())
+
+ dic = {}
+ for string in strs:
+ s = ''.join(sorted(string))
+ if s in dic:
+ dic[s].append(string)
+ else:
+ dic[s] = [string]
+ # return [x for x in dic.values()]#击败94%
+ return [dic[x] for x in dic]#击败97%
+
+
+# leetcode submit region end(Prohibit modification and deletion)
\ No newline at end of file
diff --git "a/Week02/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.pdf" "b/Week02/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.pdf"
new file mode 100644
index 000000000..b1fde4b34
Binary files /dev/null and "b/Week02/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.pdf" differ
diff --git "a/Week02/\346\234\211\346\225\210\345\255\227\346\257\215\347\232\204\345\274\202\344\275\215\350\257\215.py" "b/Week02/\346\234\211\346\225\210\345\255\227\346\257\215\347\232\204\345\274\202\344\275\215\350\257\215.py"
new file mode 100644
index 000000000..53cbb817d
--- /dev/null
+++ "b/Week02/\346\234\211\346\225\210\345\255\227\346\257\215\347\232\204\345\274\202\344\275\215\350\257\215.py"
@@ -0,0 +1,84 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/15 7:42 PM
+
+# 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
+#
+# 示例 1:
+#
+# 输入: s = "anagram", t = "nagaram"
+# 输出: true
+#
+#
+# 示例 2:
+#
+# 输入: s = "rat", t = "car"
+# 输出: false
+#
+# 说明:
+# 你可以假设字符串只包含小写字母。
+#
+# 进阶:
+# 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
+# Related Topics 排序 哈希表
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def isAnagram(self, s, t):
+ """
+ 异位词的概念是 字符串中出现的字母都是一样的且对应字母其次数也一致
+ :type s: str
+ :type t: str
+ :rtype: bool
+ """
+ #1.对这两个字符串进行排序,如果排序结果一致,说明是异位词
+ #击败22%
+ # return sorted(s) == sorted(t)
+ #2.遍历两个字符串,检查生成的hash表是否一致
+ #击败32%
+ # dic1, dic2 = {}, {}
+ # for item in s:
+ # dic1[item] = dic1.get(item, 0) + 1
+ # for item in t:
+ # dic2[item] = dic2.get(item, 0) + 1
+ # return dic1 == dic2
+ #2.只需使用一个hash表 hash表记录每个字母出现的次数
+ #击败58%
+ #hash表的key也可以使用ord(item)-ord('a')
+ # if len(s) != len(t): return False
+ # hashmap = {}
+ # for substr in s:
+ # if not hashmap.get(substr):
+ # hashmap[substr] = 1
+ # else:
+ # hashmap[substr] += 1
+ # for substr in t:
+ # if hashmap.get(substr):
+ # hashmap[substr] -= 1
+ # else:
+ # return False
+ # for value in hashmap.values():
+ # if value != 0:
+ # return False
+ # return True
+ #4.python中使用count函数统计出现的次数
+ #击败90%
+ # if len(s) != len(t):
+ # return False
+ # for i in set(s):
+ # if s.count(i) != t.count(i):
+ # return False
+ # return True
+
+ #击败95%
+ if len(s) != len(t): return False
+ tmp = set(s)
+ if tmp == set(t):#如果两个字符串的set相同进行深入判断
+ for i in s:
+ if s.count(i) != t.count(i): return False
+ return True
+ return False
+ #
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_16_N\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_16_N\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..924a129bd
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_16_N\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,70 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/16 11:31 PM
+
+# 给定一个二叉树,返回它的 前序 遍历。
+#
+# 示例:
+#
+# 输入: [1,null,2,3]
+# 1
+# \
+# 2
+# /
+# 3
+#
+# 输出: [1,2,3]
+#
+#
+# 进阶: 递归算法很简单,你可以通过迭代算法完成吗?
+# Related Topics 栈 树
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for a binary tree node.
+# class TreeNode(object):
+# def __init__(self, x):
+# self.val = x
+# self.left = None
+# self.right = None
+
+class Solution(object):
+ #击败86%
+ def preorderTraversal(self, root):
+ """
+ :type root: TreeNode
+ :rtype: List[int]
+ """
+ # 击败95%
+ if not root: return []
+ res = []
+ res.append(root.val)
+ for child in root.children:
+ res += self.preorderTraversal(child)
+ return res
+
+ #击败86%
+ # res = []
+ # if root:
+ # self.Npreorder(root, res)
+ # return res
+ # def Npreorder(self, root, res):
+ # if root is None:
+ # return
+ # res.append(root.val)#先序遍历 先将值存入res,再依次访问子节点
+ # for child in root.children:
+ # self.Npreorder(child, res)
+
+ #击败69%
+ def traversal(self,root):
+ if not root: return []
+ stack, res = [root], []
+ while stack:
+ node = stack.pop()
+ res.append(node.val)
+ for item in node.children[::-1]:
+ stack.append(item)
+ return res
+
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_17_N\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_17_N\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..3150f2cba
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_17_N\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,46 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/16 9:30 PM
+
+# 给定一个 N 叉树,返回其节点值的后序遍历。
+#
+# 例如,给定一个 3叉树 :
+#
+#
+#
+#
+#
+#
+#
+# 返回其后序遍历: [5,6,3,2,4,1].
+#
+#
+#
+# 说明: 递归法很简单,你可以使用迭代法完成此题吗? Related Topics 树
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+"""
+# Definition for a Node.
+class Node(object):
+ def __init__(self, val=None, children=None):
+ self.val = val
+ self.children = children
+"""
+
+
+class Solution(object):
+ def postorder(self, root):
+ """
+ :type root: Node
+ :rtype: List[int]
+ """
+ # 击败48%
+ if not root: return []
+ res = []
+ for child in root.children:
+ res += self.postorder(child)
+ res.append(root.val)
+ return res
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_17_N\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_17_N\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..5edb59310
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_17_N\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,29 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/17 10:27 PM
+
+"""
+# Definition for a Node.
+class Node:
+ def __init__(self, val=None, children=None):
+ self.val = val
+ self.children = children
+"""
+
+class Solution:
+ # def levelOrder(self, root: 'Node') -> List[List[int]]:
+ def levelOrder(self,root):
+ #击败55%
+ if root is None: return []
+ quene,res = [root],[]
+ while quene:
+ #将当前层的所有元素出队列,记录其值存入res中,由于输出格式的限制,要用tmp先存放
+ #并且将其孩子全部记录在下一个quene中,这样保证了上层节点全部被加入到res中,而不会发生交替现象
+ tmp, tmp_quene = [], []#这个tmp_quene是为了暂存下一层的所有节点
+ for node in quene:
+ tmp.append(node.val)
+ for child in node.children:
+ tmp_quene.append(child)
+ res.append(tmp)
+ quene = tmp_quene
+ return res
\ No newline at end of file
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_18_\346\234\200\345\260\217\347\232\204k\344\270\252\346\225\260.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_18_\346\234\200\345\260\217\347\232\204k\344\270\252\346\225\260.py"
new file mode 100644
index 000000000..113feeb8d
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_18_\346\234\200\345\260\217\347\232\204k\344\270\252\346\225\260.py"
@@ -0,0 +1,91 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/17 11:06 PM
+
+from typing import List
+import heapq
+# class Solution:
+# def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
+# #暴力破解 击败64%
+# arr.sort()
+# return arr[:k]
+# #
+# # #击败59%
+# if k == 0:
+# return []
+# heap = [-x for x in arr[:k]] # 只用维护一个大小为k的小根堆
+# heapq.heapify(heap) # 这k个元素一定满足三角顶最小的原则
+# for i in range(k, len(arr)):
+# if -heap[0] > arr[i]:
+# heapq.heappop(heap) # 如果堆中的元素大于入堆元素,则将原堆顶元素出堆
+# heapq.heappush(heap, -arr[i]) # 将这个元素放入小根堆中,heappop中调用了siftup调整了堆
+# res = [-x for x in heap]
+# return res
+
+class Solution:
+ def partition(self, nums, left, right):
+ pivot = nums[left]
+ while left < right:
+ while left < right and pivot <= nums[right]:
+ right -= 1
+ nums[left] = nums[right]
+ while left < right and nums[left] <= pivot:
+ left += 1
+ nums[right] = nums[left]
+ nums[left] = pivot
+ return left
+
+ def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
+ # 快速排序法:
+ size = len(arr)
+ if size == 0 or k > size: return
+ if size == 1 or size == k:
+ return arr
+ left, right = 0, size - 1
+ while left <= right: # 这里其实也相当于是二分法
+ pivot = self.partition(arr, left, right) # left, right, split_ind 都是原始 index
+ if pivot == k: # 在 split_ind 左边有 k 个元素,全部不大于 pivot
+ break
+ elif pivot > k:#如果左边还有大于k个数,继续在左边找
+ right = pivot - 1 # 不-1 会陷入死循环
+ else:
+ left = pivot + 1 # 不 +1 会陷入死循环
+ return arr[:k]
+
+
+
+import heapq
+
+class SolutionII:
+ #如果 是要求最小的k个数,那么应该是维护一个大小为k的大根堆,如果元素值小于堆顶元素,
+ # 将此元素放到数组末尾,进行heapify,那么每次就相当于将原始数组中的大数全部推出,只留下最后k个,那他就是最小值
+ # 判断当前元素是否小于堆顶元素,如果小,就入堆
+
+ # 同理 如果要求最大的k个数,那么就需要维护小根堆,一致删除较小的元素,直到元素组只剩k个值,就是最大的k个数
+ # 但是由于python中的heapq是小根堆,所以我们在维护堆之前先将符号调换一下
+ # 小根堆 如果当前值大于堆顶元素 才能入堆
+ def getLeastNumbers(self, nums, k):
+ if k == 0: return []
+ my_heap = [-x for x in nums[:k]]#维护大小为k的小顶堆
+ heapq.heapify(my_heap)
+ for i in range(k,len(nums)):
+ if -nums[i] > my_heap[0]:#小根堆最后留下的是最大的k个值,所以只有大于堆顶才能进
+ heapq.heappop(my_heap)
+ heapq.heappush(my_heap,-nums[i])
+ res = [-x for x in my_heap]
+ return res
+
+ # heapq.heapify(my_heap)#维护大小为k的小根堆
+ # for i in range(k,len(nums)):
+ # if nums[i] < my_heap[-1]:#如果比栈顶元素小,将当前栈顶元素
+
+
+
+
+
+
+s = SolutionII()
+# nums = [1, 4, 2, 5, 10, 3, -1]
+nums = [0,0,1,2,4,2,2,3,1,4]
+res = s.getLeastNumbers(nums,8)
+print(res)
\ No newline at end of file
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\345\210\244\346\226\255\346\230\257\345\220\246\344\270\221\346\225\260.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\345\210\244\346\226\255\346\230\257\345\220\246\344\270\221\346\225\260.py"
new file mode 100644
index 000000000..5196535f3
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\345\210\244\346\226\255\346\230\257\345\220\246\344\270\221\346\225\260.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/19 8:07 PM
+
+class Solution:
+ def isUgly(self, num: int) -> bool:
+ #如果一个数是丑数那肯定满足这种定义num = 2^i*3^j*5^k
+ # for item in [2,3,5]:
+ # while num%item==0:#依次除尽2,3,5
+ # num = num/item
+ # # return True if num==1 else False #击败50%
+ # return num==1#击败87%
+ if num == 0: return False
+ while num % 5 == 0: num /= 5
+ while num % 3 == 0: num /= 3
+ while num % 2 == 0: num /= 2
+ return num == 1#击败98%,省去了迭代的过程
+
+
+s = Solution()
+res = s.isUgly(7)
+print(res)
\ No newline at end of file
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\346\261\202\347\254\254n\344\270\252\344\270\221\346\225\260.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\346\261\202\347\254\254n\344\270\252\344\270\221\346\225\260.py"
new file mode 100644
index 000000000..2890e1325
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\346\261\202\347\254\254n\344\270\252\344\270\221\346\225\260.py"
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/19 12:33 AM
+
+class Solution:
+ def nthUglyNumber(self, n: int) -> int:
+ # 1、2、3、5、4、6、8、9、10
+ if n==0:
+ return 0
+ res = [1]*n
+ p2,p3,p5 = 0,0,0#指向三个队列的指针
+ for i in range(1,n):
+ res[i] = min(res[p2]*2,res[p3]*3,res[p5]*5)
+ if res[i] == res[p2]*2: p2 = p2+1
+ if res[i] == res[p3]*3: p3 = p3+1
+ if res[i] == res[p5]*5: p5 = p5+1
+ return res[-1]
\ No newline at end of file
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_20_\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_20_\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py"
new file mode 100644
index 000000000..b047e2380
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_20_\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py"
@@ -0,0 +1,98 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/20 10:11 PM
+
+# 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
+#
+# '.' 匹配任意单个字符
+# '*' 匹配零个或多个前面的那一个元素
+#
+#
+# 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
+#
+# 说明:
+#
+#
+# s 可能为空,且只包含从 a-z 的小写字母。
+# p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
+#
+#
+# 示例 1:
+#
+# 输入:
+# s = "aa"
+# p = "a"
+# 输出: false
+# 解释: "a" 无法匹配 "aa" 整个字符串。
+#
+#
+# 示例 2:
+#
+# 输入:
+# s = "aa"
+# p = "a*"
+# 输出: true
+# 解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
+#
+#
+# 示例 3:
+#
+# 输入:
+# s = "ab"
+# p = ".*"
+# 输出: true
+# 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
+#
+#
+# 示例 4:
+#
+# 输入:
+# s = "aab"
+# p = "c*a*b"
+# 输出: true
+# 解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
+#
+#
+# 示例 5:
+#
+# 输入:
+# s = "mississippi"
+# p = "mis*is*p*."
+# 输出: false
+# Related Topics 字符串 动态规划 回溯算法
+
+from functools import lru_cache
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+
+ #1.将复杂问题进行拆解 递归 但是明显是超出时间限制的,时间复杂度是O(3^N)
+ # s="aaaaaaaaaaaaab"
+ # pattern="a*a*a*a*a*a*a*a*a*a*c" 但是python中可以使用@lru_cache装饰器优化递归过程
+ @lru_cache
+ def isMatch(self, s: str, pattern: str) -> bool:
+ # # 特殊情况处理
+ # if len(s) == 0 and len(pattern) == 0: return True
+ # if len(s) > 0 and len(pattern) == 0: return False
+ # # 如果pattern形如 a*####,检查这个*能匹配几次
+ # if len(pattern) > 1 and pattern[1] == '*':#击败80%
+ # # s和pattern首字母相同
+ # if len(s) > 0 and (pattern[0] == s[0] or pattern[0] == '.'):
+ # # s能和pattern匹配的情形
+ # # 1.*匹配0次,则需要递归的对s和pattern[2:]进行匹配
+ # # 2.*匹配1次,需要递归的对s[1:]和pattern[2:]进行匹配
+ # # 3.*匹配n次,需要递归的对s[1:]和pattern进行匹配
+ # return self.isMatch(s, pattern[2:]) or self.isMatch(s, pattern[2:]) or self.isMatch(s[1:], pattern)
+ # else: # 如果首字母不相同,就相当于*匹配0次,继续匹配s和pettern[2:]
+ # return self.isMatch(s, pattern[2:])
+ # # pattern以.开头
+ # if len(s) > 0 and (pattern[0] == '.' or s[0] == pattern[0]):
+ # return self.isMatch(s[1:], pattern[1:])
+ # return False
+ #击败86%
+ if not pattern: return not s
+ match_first = bool(s) and (pattern[0] == s[0] or pattern[0] == '.')
+ if len(pattern) > 1 and pattern[1] == '*':
+ return (self.isMatch(s, pattern[2:]) or match_first and self.isMatch(s[1:], pattern))
+ else:
+ return match_first and self.isMatch(s[1:], pattern[1:])
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\350\267\257\345\276\204\345\222\214.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\350\267\257\345\276\204\345\222\214.py"
new file mode 100644
index 000000000..39f8ec6a0
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\350\267\257\345\276\204\345\222\214.py"
@@ -0,0 +1,30 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/21 4:23 PM
+
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+#路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
+class Solution:
+ def __init__(self):
+ self.maxpath_sum = float("-inf")
+
+ def maxPathSum(self, root: TreeNode) -> int:
+ self.maxGain(root)
+ return self.maxpath_sum
+
+ def maxGain(self,node):
+ if not node: return 0
+ left_gain = max(self.maxGain(node.left),0)#将空值、负值过滤掉了
+ right_gain = max(self.maxGain(node.right),0)
+ path_sum = node.val + left_gain + right_gain #左根右
+ self.maxpath_sum = max(path_sum, self.maxpath_sum)#更新self.maxpath_sum,过滤负值
+ return node.val + max(left_gain, right_gain)#返回此节点的最大贡献值,方便上层节点计算
+
+
+
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227.py"
new file mode 100644
index 000000000..897e8b817
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227.py"
@@ -0,0 +1,25 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/21 10:24 AM
+
+from typing import List
+class Solution:
+ def singleNumber(self, nums: List[int]) -> int:
+ # # 1.hash表记录出现次数,以num为key,以出现次数为value 击败42%
+ # dic = {}
+ # for num in nums:
+ # dic[num] = dic.get(num,0)+1
+ # for key, value in dic.items():
+ # if value == 1:
+ # return key
+ #位运算,击败97%
+ # 由于每个元素都出现了两次,根据异或运算可以消去这两个元素
+ res = 0
+ for num in nums:
+ res ^= num
+ return res
+
+
+s = Solution()
+res = s.singleNumber([4,1,2,1,2])
+print(res)
\ No newline at end of file
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227II.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227II.py"
new file mode 100644
index 000000000..3a40d34c2
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227II.py"
@@ -0,0 +1,23 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/21 11:31 AM
+from typing import List
+class Solution:
+ def singleNumber(self, nums: List[int]) -> int:
+ # dic = {}#击败87%
+ # for num in nums:
+ # dic[num] = dic.get(num,0)+1
+ # for key, value in dic.items():
+ # if value == 1:
+ # return key
+ # x, y = 0, 0#击败74%
+ # for z in nums:#num means input
+ # y = ~x & (y^z)
+ # x = ~y & (x^z)
+ # return y
+ x,y = 0,0#击败57%
+ for z in nums:
+ tmp = ~x&(y^z)
+ x = (x&~y&~z)|(~x&y&z)
+ y = tmp
+ return y
\ No newline at end of file
diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227III.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227III.py"
new file mode 100644
index 000000000..d98f06879
--- /dev/null
+++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_21_\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\346\225\260\345\255\227III.py"
@@ -0,0 +1,25 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/21 11:40 AM
+from typing import List
+class Solution:
+ def singleNumber(self, nums: List[int]) -> List[int]:
+ #击败64%
+ # dic,res = {}, []
+ # for num in nums:
+ # dic[num] = dic.get(num,0) + 1
+ # for key,value in dic.items():
+ # if value == 1:
+ # res.append(key)
+ # return res
+ tmp = 0
+ for num in nums:
+ tmp ^= num
+ # rightmost 1-bit diff between x and y
+ diff = tmp & (-tmp) # 这个找到第一位不相同的方式厉害
+ x = 0
+ for num in nums:
+ if num & diff: # 结果大于0执行,此位为1为一组,直接计算
+ x ^= num
+ return [x, tmp ^ x] # tmp是两个数的异或值,一个值已经找到了
+
diff --git a/Week03/.idea/Week03.iml b/Week03/.idea/Week03.iml
new file mode 100644
index 000000000..7c9d48f0f
--- /dev/null
+++ b/Week03/.idea/Week03.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week03/.idea/leetcode/editor.xml b/Week03/.idea/leetcode/editor.xml
new file mode 100644
index 000000000..20fc4c471
--- /dev/null
+++ b/Week03/.idea/leetcode/editor.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week03/.idea/misc.xml b/Week03/.idea/misc.xml
new file mode 100644
index 000000000..399908725
--- /dev/null
+++ b/Week03/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week03/.idea/modules.xml b/Week03/.idea/modules.xml
new file mode 100644
index 000000000..1191ab715
--- /dev/null
+++ b/Week03/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week03/.idea/vcs.xml b/Week03/.idea/vcs.xml
new file mode 100644
index 000000000..6c0b86358
--- /dev/null
+++ b/Week03/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week03/.idea/workspace.xml b/Week03/.idea/workspace.xml
new file mode 100644
index 000000000..b8da57564
--- /dev/null
+++ b/Week03/.idea/workspace.xml
@@ -0,0 +1,968 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1592831728412
+
+
+ 1592831728412
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/组合.py
+ 9
+
+
+
+ file://$PROJECT_DIR$/组合.py
+ 10
+
+
+
+ file://$PROJECT_DIR$/组合.py
+ 14
+
+
+
+ file://$PROJECT_DIR$/组合.py
+ 12
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 42
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 43
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 44
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 45
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 46
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 47
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 48
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列.py
+ 54
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 27
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 28
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 29
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 31
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 34
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 35
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 36
+
+
+
+ file://$PROJECT_DIR$/每日一题6_27_全排列II.py
+ 39
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week03/NOTE.md b/Week03/NOTE.md
index 50de30414..1d51e17be 100644
--- a/Week03/NOTE.md
+++ b/Week03/NOTE.md
@@ -1 +1,716 @@
-学习笔记
\ No newline at end of file
+学习笔记
+
+
+
+#### 翻转二叉树
+1.递归
+我刚开始的想法是,考虑左右孩子节点,这个连接指向修改了就好了
+然后写的代码如下
+```python
+def invertTree(self, root: TreeNode) -> TreeNode:
+ #recursive terminator
+ if root is None: return
+ #current process
+ if root.right:
+ root.left = self.invertTree(root.right)
+ if root.left:
+ root.right = self.invertTree(root.left)
+ #drill down
+ #reverse states
+ return root
+```
+上述代码的问题在于,if root.right:执行过后,左孩子已经修改了;在想要执行if root.left:时已经是同一个指向了
+所以需要修改
+```python
+def invertTree(self, root: TreeNode) -> TreeNode:
+ # recursive terminator
+ #击败70%
+ if root is None: return
+ # current process
+ left = self.invertTree(root.right)
+ right = self.invertTree(root.left)
+ root.left = left
+ root.right = right
+ # drill down
+ # reverse states
+ return root
+
+```
+2.迭代 类似层序遍历,将每一层访问到的节点存到quene中
+如果quene不为空,取出队尾元素 对于当前节点,交换左右孩子后,将其添加到quene中,继续进行判断
+```python
+def invertTree(self, root: TreeNode) -> TreeNode:
+ if root is None: return None
+ quene = [root]
+ while quene:
+ cur = quene.pop()
+ cur.left, cur.right = cur.right, cur.left
+ if cur.left is not None: quene.append(cur.left)
+ if cur.right is not None: quene.append(cur.right)
+ return root
+```
+
+#### 验证是否搜索二叉树
+1.递归,判断左子树是否小于根,右子树是否大于根
+```python
+if root is None: return True
+#确定左子树是否符合排序二叉树,如果不满足,就返回False
+if not self.isValidBST(root.left): return False
+if root.val <= self.pre_val: return False#不满足左子树小于根节点
+self.pre_val = root.val#记录上一个访问的节点的值
+#访问右子树 # drill down
+return self.isValidBST(root.right)
+```
+2.迭代 由于二叉搜索树的特性 中序遍历比较方便 这里就借用二叉树的中序遍历的非递归实现完成
+```python
+stack, pre_val = [], float('-inf')
+cur = root
+while stack or cur is not None:
+ while cur is not None:#一直往下找,到左叶节点
+ stack.append(cur)
+ cur = cur.left
+ cur = stack.pop()
+ if cur.val <= pre_val: return False#判断左节点值与根节点的大小关系
+ pre_val = cur.val#修改当前的根节点大小
+ cur = cur.right
+return True
+```
+
+#### 二叉树的最大深度
+1.递归代码 这个代码我真的印象超级深
+```python
+if root is None: return 0
+return max(self.maxDepth(root.left),self.maxDepth(root.right))+1
+```
+2.迭代 借助DFS思想,借助栈,每次入栈时 记录当前节点的深度
+将遍历左右孩子时,将节点和当前深度+1压入栈中
+```python
+if root is None: return 0
+stack = [(1, root)]#栈中记录当前节点和此时的高度
+depth = 0
+while stack != []:
+ current_depth, root = stack.pop()#这里pop(0)和pop()都可以
+ if root is not None:
+ depth = max(depth, current_depth)#记录当前节点的高度
+ stack.append((current_depth + 1, root.left))#当前深度+1
+ stack.append((current_depth + 1, root.right))
+return depth
+```
+上述代码可以优化
+``` python
+ quene, depth = [root], 0
+ while quene:
+ # cur_layer = []
+ for _ in range(len(quene)):
+ root = quene.pop(0)#要确保将这一层的元素加入到quene中
+ if root.left: quene.append(root.left)
+ if root.right: quene.append(root.right)
+ depth += 1
+ return depth
+```
+
+#### 二叉树的最小深度
+最小深度是从根节点到最近叶子节点的最短路径上的节点数量
+1.递归 递归时需要弄清楚递归的结束条件
+```python
+def minDepth(self, root: TreeNode) -> int:
+ #1.根节点为空 return 0
+ #2. 左右节点为空 return 1
+ #3.左节点或右节点为空 return 左/右+1
+ #4.左右节点都不为空 return min(left,right)+1
+ if root is None: return 0
+ if root.left is None and root.right is None: return 1
+ left_height, right_height = self.minDepth(root.left),self.minDepth(root.right)
+ if root.left is None or root.right is None: return left_height+right_height+1#有一个为0
+ #其余情况 返回较小值+1
+ return min(left_height,right_height) + 1#+1是加的根那一层
+```
+2.借助层序遍历 不需要遍历所有节点 只需要遍历到第一个叶子节点就能返回
+```python
+if not root: return 0
+quene = [(1, root)]
+while quene:
+ #[3,9,20,null,null,15,7]
+ depth, root = quene.pop(0) # 保证从左往右看,如果是pop(),那么可能往右看的过程中返回了,而丢失了应有的最小值
+ if not root.left and not root.right: return depth # 如果此节点左右为空 返回当前depth
+ if root.left: quene.append((depth + 1, root.left))
+ if root.right: quene.append((depth + 1, root.right))
+```
+这里和上面最大深度逻辑一致,只要提前判断子树就可以返回深度了
+``` python
+if not root: return 0
+quene, depth = [root], 1
+while quene:
+ for _ in range(len(quene)):
+ root = quene.pop(0)
+ if not root.left and not root.right: return depth#提前判断是否叶节点即可,由于depth是后加的,所以初值depth=1
+ if root.left: quene.append(root.left)
+ if root.right: quene.append(root.right)
+ depth += 1
+```
+
+#### 二进制求和
+1.进制转换后求解
+```python
+return bin(int(a, 2)+int(b, 2))[2:]
+```
+2. 如果不能使用加减乘除
+```angular2html
+#2.如果不能使用加减乘除运算,则使用位运算
+x, y = int(a, 2), int(b, 2)
+while y:
+ res = x ^ y #无进位相加结果
+ carry = (x & y) << 1#计算x+y的进位
+ x, y = res, carry
+return bin(x)[2:]
+```
+
+
+#### 单词拆分
+1.动态规划 时间复杂度O(N^2),空间复杂度O(N)
+```python
+#动态规划 用大小为len(s)+1的数组保存转态结果
+#dp[i]表示s的前i位是否能被worddict中的元素表示,最后只需要取转移数组的最后一位即可知道是否能够拆分
+#如何转移呢?
+#外层i从[0,len(s)),内层j[i+1,n]
+ #如何从i转移到j? 如果dp[i]=True并且s[i:j]在worddict中,即可转移
+def wordBreak(self, s: str, wordDict: List[str]) -> bool:
+ dp = [False for _ in range(len(s)+1)]
+ dp[0] = True
+ for i in range(len(s)):
+ for j in range(i+1,len(s)+1):
+ if dp[i]==True and s[i:j] in wordDict:
+ dp[j] = True
+ return dp[-1]
+```
+2.备忘录回溯
+```python
+#备忘录回溯
+def wordBreak(self, s: str, wordDict: List[str]) -> bool:
+ import functools
+ @functools.lru_cache
+ def backtrace(s):
+ if not s: return True#s已经考察结束
+ res = False
+ for i in range(1, len(s)+1):#
+ if s[:i] in wordDict:
+ res = backtrace(s[i:]) or res#记录递归过程中的res
+ return res#最后返回的相当于是dp[-1]or(dp[-2]or(dp[-n])) 其实只用看最后一层的res即可
+ return backtrace(s)
+```
+
+#### 最接近的三数之和
+1.枚举所有组合 枚举过程中 使用双指针优化 枚举过程
+这里最后是要返回最接近target的三个数的和 min_closer 用来记录最接近的三数之和
+首先对数组排序 然后 写出标准的三指针遍历模式 对于left int:
+ nums.sort() # 先排序
+ # [-4,-1,1,2],1
+ min_closer = float('inf')
+ for i in range(len(nums) - 2): # 为双指针留出位置
+ if i > 0 and nums[i] == nums[i - 1]: # 保证前后两个数字不一,因为只有一组解
+ continue
+ left, right = i + 1, len(nums) - 1
+ while left < right:
+ tmp = nums[i] + nums[left] + nums[right] # 先记录当前遍历得到的三数之和
+ if abs(min_closer - target) > abs(tmp - target):
+ min_closer = tmp
+ # min_closer = min(abs(target-tmp),min_closer)
+ if tmp < target: # 如果还没有找到相等的 ,j右移
+ left = left + 1
+ # cur_diff = abs()
+ elif tmp > target: # 如果找着找着 大于target了,就需要和之前记录的min_diff比较
+ right = right - 1
+ else: # tmp==target:
+ return min_closer
+ return min_closer
+```
+
+#### 最长回文子串
+1.暴力解法
+遍历出所有长度的子串,判断它是否是回文串,从结果中挑出最长的返回 时间复杂度是O(N^3)
+```python
+def longestPalindrome(self, s: str) -> str:
+ res,max_length = '',0
+ for i in range(len(s)):
+ for j in range(i+1,len(s)+1):
+ cur_string = s[i:j]
+ if self.isPalidrome(cur_string) and len(cur_string)>max_length:
+ res = cur_string
+ max_length = max(max_length,len(res))
+ return res
+
+def isPalidrome(self,cur_string):
+ #判断是否回文字符
+ left,right = 0,len(cur_string)-1
+ while left str:
+ size = len(s)
+ dp = [[False] * size for _ in range(size)] # 为什么是一个二维数组
+ res = ""
+ # 枚举子串的长度 l+1
+ for L in range(size):
+ # 枚举子串的起始位置 i,这样可以通过 j=i+l 得到子串的结束位置
+ for i in range(size):
+ j = i + L
+ if j >= len(s):
+ break
+ if L == 0: # 如果当前字符长度为0
+ dp[i][j] = True#i==j,为True
+ elif L == 1: # 如果当前字符长度为1
+ dp[i][j] = (s[i] == s[j])
+ else: #
+ dp[i][j] = (dp[i + 1][j - 1] and s[i] == s[j])
+ if dp[i][j] and L + 1 > len(res):
+ res = s[i:j + 1]
+ return res
+```
+#### 序列话和反序列化二叉树
+遍历二叉树有深度和广度,但是由于要重建二叉树,我们普通的遍历结果是连在一起的,无法确定None节点在哪里,
+所以如果想要用一次遍历的结果推导出其二叉树的构型 需要为叶节点的孩子打上标记
+1.BFS 层序遍历实现
+ - 1 序列化 层序遍历的二叉树
+ ```python
+def serialize(self, root):#层序遍历中使用deque是最简单的
+ #手写一个二叉树的层寻遍历
+ if not root: return []
+ dquene,res = [root],''
+ while dquene:
+ cur = dquene.pop(0)#使用了双端队列
+ if cur != None:
+ res += str(cur.val)+','
+ dquene.append(cur.left)
+ dquene.append(cur.right)
+ else:
+ res += '#,'#标识None
+ return res
+```
+ - 2 重建时,如果遍历到的元素是#,那我们就不对它进行处理
+ ```python
+def deserialize(self, data):
+ if not data: return None
+ data = data.split(',')
+ root = TreeNode(data.pop(0))
+ dquene = [root]
+ while dquene:
+ cur = dquene.pop(0)
+ if data:
+ cur_left = data.pop(0)
+ if cur_left != '#':#反序列化时,如果节点值为#就不处理
+ cur.left = TreeNode(cur_left)
+ dquene.append(cur.left)
+ # if data:
+ cur_right = data.pop(0)
+ if cur_right != '#':
+ cur.right = TreeNode(cur_right)
+ dquene.append(cur.right)
+ return root
+```
+
+2.前序遍历 递归解
+ - 1 序列化 前序遍历
+```python
+def serialize(self, root):
+ #手写一个二叉树的层寻遍历
+ if root == None: return '#,'
+ leftserilized = self.serialize(root.left)
+ rightserilized = self.serialize(root.right)
+ return str(root.val) + ',' + leftserilized + rightserilized
+```
+ - 2 反序列化
+```python
+def deserialize(self, data):
+ data = data.split(',')
+ root = self.deserializeCore(data)
+ return root
+
+def deserializeCore(self,data):
+ root_val = data.pop(0)
+ if root_val == '#': return None
+ root = TreeNode(root_val)
+ root.left = self.deserializeCore(data)
+ root.right = self.deserializeCore(data)
+ return root
+```
+
+#### 二叉树的最近公共祖先
+1.递归
+class Solution:
+```python
+#1.递归 分析出找到最近公共祖先节点的情形,如果p,q由同一祖先节点 则p、q要么位于某棵树的左右子树
+ #要么在同一棵树上,在同一棵树上又有 p或q为根 另外存在p或q在其左右子树中
+ res = None
+ def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
+ self.dfs(root,p,q)
+ return self.res
+
+ def dfs(self,root,p,q):
+ # recursive terminator
+ if root is None: return False
+ #current process
+ #drill down
+ root_left = self.dfs(root.left,q,p)#判断这颗树的子树中是否含有q节点或者q节点
+ root_right = self.dfs(root.right,p,q)
+ #要判断p、q的最近公共祖先,我们从根节点开始寻找,查探root的左子树和右子树是否包含q节点或p节点,此时最近公共最先就是root;另外的,如果p或q为子树根节点,且p或q处在这棵子树下面,则最进公共祖先就是p或q节点
+ if root_left and root_right or ((root.val==p.val or root.val==q.val) and(root_left or root_right) ):#对于5,1这种情况,这是后就要返回p为true给上层递归
+ self.res = root#那么就返回当前树的根节点
+ #reverse states
+ return root_left or root_right or(root.val==p.val or root.val==q.val)
+```
+写的更简洁一点
+```python
+def lowestCommonAncestor(self, root, p, q):
+ if not root or p==root or q==root:
+ return root
+ left = self.lowestCommonAncestor(root.left, p, q)
+ right = self.lowestCommonAncestor(root.right, p, q)
+ if left and right:
+ return root
+ return left if left else right
+```
+
+2.记录父节点
+```python
+class Solution:
+ # ,然后我们就可以利用节点的父节点信息从p结点开始不断往上跳,并记录已经访问过的节点,再从q节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。
+ all_parents = {}
+ p_parents = {}
+
+ def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
+ self.all_parents[root.val] = None
+ self.dfs(root) # 用哈希表存储所有节点的父节点
+ # 在all_parents找p的根节点,并且记录找到的父节点
+ while p != None:
+ self.p_parents[p.val] = True
+ p = self.all_parents.get(p.val)
+ while q != None: # 因为p、q是必有公共父节点的,所以一定能在p_parents里面找到父节点
+ if self.p_parents.get(q.val): # 如果如果在p的parent中找到
+ return q
+ q = self.all_parents.get(q.val) # 如果没找到,说明q可能还要向上一层才能找到
+ return None
+
+ def dfs(self, root): # 从root开始遍历子节点 记录子节点值作为key,值为root节点
+ if root.left is not None:
+ self.all_parents[root.left.val] = root
+ self.dfs(root.left)
+ if root.right is not None:
+ self.all_parents[root.right.val] = root
+ self.dfs(root.right)
+```
+
+#### 根据二叉树的前中序列重建二叉树
+手动模拟根据二叉树的前中序列生成二叉树的过程,不难发现每次都是先确定根节点,以根节点划分出左右子树
+对应到两个序列,递归的进行确定根节点,左右子树序列
+所以我们在重建时,先确定根节点、然后为其分配左右子树,
+处理左右子树时,先确定并对应其前中序列,进行相同的处理
+```python
+def buildTree(self, pre: List[int], inorder: List[int]) -> TreeNode:
+ if not pre or not inorder:
+ return None
+ root = TreeNode(pre[0])
+ index = inorder.index(root.val)#记录root在中序序列中的位置
+ root.left = self.buildTree(pre[1:index+1],inorder[:index])
+ root.right = self.buildTree(pre[index+1:],inorder[index+1:])
+ return root
+```
+
+
+#### 删除未排序链表中的重复元素
+1.使用set实现存储未重复元素,然后重建 (超时)尽管时间复杂度是O(N),但是相当于遍历了两次
+```python
+if head is None or head.next is None: return head
+ once = set()
+ while head is not None:
+ if head.val not in once:
+ once.add(head.val)
+ head = head.next
+ head = pre = ListNode(None)
+ while once:
+ head.next = ListNode(once.pop())
+ head = head.next
+ return pre.next
+```
+可以知道,如果当前元素已经出现过,那么如果遍历时记录了前一个指针,那么可以直接删除掉这个节点元素
+```python
+if not head: return head
+ once = {head.val}
+ pre = head
+ while head.next:#如果有下一个节点
+ cur = head.next
+ if not cur.val in once:
+ once.add(cur.val)
+ head = head.next
+ else:#如果这个元素已经出现,那就直接删除掉
+ head.next = head.next.next
+ return pre
+```
+
+#### 括号生成
+1.因为括号类别已经确定,可以想象为左右括号最多N个
+左括号出现次数小于N即可,右括号小于左括号个数
+```python
+def generateParenthesis(self,n):
+ result = []
+ self._generate_parenthesis(0, 0, n, '',result)
+ return result
+
+def _generate_parenthesis(self, left, right, n, res, result):
+ # recursive terminator
+ if left == n and right == n:
+ result.append(res)
+ return
+ # current process
+ if left < n: self._generate_parenthesis(left + 1, right, n, res + '(', result)
+ if left > right: self._generate_parenthesis(left, right + 1, n, res + ')', result)
+
+ # drill down
+
+ # reverse state
+```
+上面这种解法,由于最后要返回res,所以在递归时传入的参数较多,可以简化一下
+```python
+def generateParenthesis(self,n):
+ result = []
+ def _generate_parenthesis( left, right, n, res):
+ # recursive terminator
+ if left == n and right == n:
+ result.append(res)
+ return
+ # current process
+ if left < n: _generate_parenthesis(left + 1, right, n, res + '(')
+ if left > right: _generate_parenthesis(left, right + 1, n, res + ')')
+ _generate_parenthesis(0, 0, n, '')
+ return result
+```
+
+#### 组合
+碰到组合、全排列、括号生成这种打印类的题,一般都是 回溯算法,回溯算法有一个基本模板:
+```python
+def backtracing(路径,可选路径):
+ #触发结束条件
+ #for i in range():
+ #处理不符合条件的
+ #执行当前选择 路径+,可选路径-
+ #进入下一层决策
+ #进行有必要的撤销选择以进行回溯
+
+```
+
+```python
+def combine(self, n, k):
+ def backtracing(first=1, tmp=[]):
+ #触发结束条件
+ if len(tmp) == k: # 如果当前元素 已经有k个,就将它加入res中
+ res.append(tmp[:])
+ for i in range(first, n + 1): # 如果当前元素个数小于k,则加入cur中
+ # 做选择
+ tmp.append(i)
+ # 进入下一层决策
+ backtracing(i + 1, tmp)
+ # 撤销刚才的选择
+ tmp.pop()
+ res = []
+ backtracing()
+ return res
+```
+
+
+#### 组合II
+
+#### 全排列
+```python
+def permute(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums, tmp):
+ #触发结束条件
+ if not nums:
+ res.append(tmp[:])
+ for i in range(len(nums)):
+ #排除不合法或已存在的
+ if nums[i] in tmp: continue
+ #做选择 修改已选路径和能选择的路径
+ #进入下一次决策、回溯之前的决策
+ backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径
+ res = []
+ backtrace(nums, [])
+ return res
+```
+
+#### 全排列II
+```python
+class SolutionII:
+ def permuteUnique(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums,tmp):
+ if len(tmp) == size:
+ res.append(tmp[:])
+ for i in range(len(nums)):
+ backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]])
+ res, size = [], len(nums)
+ backtrace(nums,[])
+ return res
+```
+上面在判重的时候,是在写入res时手动遍历判重,其实可以直接用set记录中间结果
+```python
+def permuteUnique(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: List[List[int]]
+ """
+ def backtrace(nums, tmp):
+ if not nums:
+ res.append(tmp[:])
+ visited = set()
+ for i in range(len(nums)):
+ if nums[i] in visited: continue
+ visited.add(nums[i])
+ backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径
+
+ res = []
+ backtrace(nums, [])
+ return res
+```
+
+#### Pow(x,n)
+1.遍历n次,时间复杂度O(N)
+```angular2html
+if n==0: return 1
+flag=False if n< 0 else True
+times,res = abs(n),1
+while times>0:
+ res *= x
+ times -= 1
+return res if flag else 1/res
+```
+递归形式如下 但是都超出时间限制
+```angular2html
+if n == 1: return x
+if n < 0:
+ return 1 / self.myPow(x, -n)
+return self.myPow(x, n // 2) * self.myPow(x, n - n // 2)
+```
+
+2.我们可以将这个问题的时间复杂度缩减到O(logN),求x的N次方 我们可以化简为计算两次x的N/2次(判断奇偶)
+```angular2html
+if n == 1: return x
+if n < 0:
+ return 1 / self.myPow(x, -n)
+return self.myPow(x*x, n // 2) if n%2==0 else x*self.myPow(x, n-1)
+```
+
+#### 子集
+1.递归
+```python
+def subsets(self, nums: List[int]) -> List[List[int]]:
+ res = [[]]
+ for num in nums:
+ res += [tmp + [num] for tmp in res]
+ return res
+```
+2.回溯
+```python
+def subsets(self, nums: List[int]) -> List[List[int]]:
+ def backtrack(first=0, tmp=[]):
+ #处理结束条件
+ if len(tmp) == k:
+ res.append(tmp[:])
+ for i in range(first, size):
+ #选择
+ tmp.append(nums[i])
+ # print(curr)
+ #下一层决策
+ backtrack(i + 1, tmp)
+ tmp.pop()
+ res = []
+ size = len(nums)
+ for k in range(size + 1):
+ backtrack()
+ return res
+
+```
+3.位运算
+```python
+def subsets(self, nums: List[int]) -> List[List[int]]:
+ size = len(nums)
+ res = []
+ for i in range(2 ** size, 2 ** (size + 1)):
+ # generate bitmask, from 0..00 to 1..11
+ bitmask = bin(i)[3:]
+ # append subset corresponding to that bitmask
+ res.append([nums[j] for j in range(size) if bitmask[j] == '1'])
+ return res
+```
+
+#### 字符串相加
+手动模拟数字进位加法,如果两个数长度不一致,就在将其作为0处理
+```python
+def addStrings(self, num1, num2):
+ """
+ :type num1: str
+ :type num2: str
+ :rtype: str
+ """
+ #1.转数字计算
+ # return str(int(num1)+int(num2))
+ # 2.手动模拟加法运算
+ res = ''
+ i, j, carry = len(num1) - 1,len(num2) - 1, 0
+ while i >= 0 or j >= 0:
+ n1 = int(num1[i]) if i >= 0 else 0
+ n2 = int(num2[j]) if j >= 0 else 0
+ tmp = n1 + n2 + carry
+ carry = tmp // 10
+ res = str(tmp % 10) + res
+ i, j = i - 1, j - 1
+ return '1' + res if carry else res
+```
+
+#### 长度最小的子数组
+1.枚举出长度为1,2,3...的数组,查看其值是否大于s,如果大于则可以直接返回 此时的枚举长度 但是时间复杂度高 O(N^2)
+```python
+def minSubArrayLen(self, s, nums):
+# 1. 穷举 超出时间限制
+ for i in range(1, len(nums) + 1):
+ # 长度为1,2,3,穷举可能的解,找到则返回
+ for j in range(len(nums) - i + 1):
+ if sum(nums[j:i + j]) >= s: return i
+ return 0
+```
+2.穷举的过程中,有很多不必要的开销,比如每次指定长度的窗口,但是大多数窗口都是无效的
+就像窗口为1时 计算和之后 判断了一次 如果不符合规定 就往后挪了一位 不符合需要继续后移
+窗口值为2时,又计算了前面的过程
+所以我们可以使用双指针 来界定是否是最短子数组
+双指针开始时指向 数组头 如果当前窗口和 小于s,end右移 以达到期望的s,如果此时已经到达s,记录下当前的窗口值
+将当前窗口往右移动 继续判断窗口值与s的关系,如果小了,就右移end;如果还是大于s,窗口继续右移
+```python
+def minSubArrayLen(self, s, nums):
+ if not nums: return 0
+ size, res = len(nums), len(nums) + 1
+ start, end = 0, 0
+ tmp = 0 # 记录窗口和
+ while end < size:
+ tmp = tmp + nums[end]
+ while tmp >= s: # 如果当前窗口和值大于s,收缩窗口
+ res = min(res, end - start + 1)
+ tmp = tmp - nums[start]
+ start = start + 1
+ end = end + 1 # 窗口扩张
+ return 0 if end == size + 1 else res
+```
diff --git "a/Week03/[104]\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py" "b/Week03/[104]\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py"
new file mode 100644
index 000000000..492d38aad
--- /dev/null
+++ "b/Week03/[104]\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py"
@@ -0,0 +1,28 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/23 7:58 PM
+
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Solution:
+ def maxDepth(self, root: TreeNode) -> int:
+ #1.递归 击败50%
+ # if root is None: return 0
+ # return max(self.maxDepth(root.left),self.maxDepth(root.right))+1
+ #2.迭代 击败77% BFS
+ if root is None: return 0
+ stack = [(1, root)]#栈中记录当前节点和此时的高度
+ depth = 0
+ while stack:
+ current_depth, root = stack.pop()
+ if root is not None:
+ depth = max(depth, current_depth)#记录当前节点的高度
+ stack.append((current_depth + 1, root.left))
+ stack.append((current_depth + 1, root.right))
+ return depth
+
diff --git "a/Week03/[105]\346\257\217\346\227\245\344\270\200\351\242\2306_26\345\211\215\344\270\255\345\272\217\345\210\227\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py" "b/Week03/[105]\346\257\217\346\227\245\344\270\200\351\242\2306_26\345\211\215\344\270\255\345\272\217\345\210\227\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py"
new file mode 100644
index 000000000..c5ef59f31
--- /dev/null
+++ "b/Week03/[105]\346\257\217\346\227\245\344\270\200\351\242\2306_26\345\211\215\344\270\255\345\272\217\345\210\227\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py"
@@ -0,0 +1,20 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/26 5:29 PM
+
+from typing import List
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Solution:
+ def buildTree(self, pre: List[int], inorder: List[int]) -> TreeNode:
+ if not pre or not inorder:
+ return None
+ root = TreeNode(pre[0])
+ index = inorder.index(root.val)#记录root在中序序列中的位置
+ root.left = self.buildTree(pre[1:index+1],inorder[:index])
+ root.right = self.buildTree(pre[index+1:],inorder[index+1:])
+ return root
\ No newline at end of file
diff --git "a/Week03/[106]\344\270\255\345\272\217\345\220\216\345\272\217\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py" "b/Week03/[106]\344\270\255\345\272\217\345\220\216\345\272\217\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py"
new file mode 100644
index 000000000..bf416f3e9
--- /dev/null
+++ "b/Week03/[106]\344\270\255\345\272\217\345\220\216\345\272\217\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py"
@@ -0,0 +1,16 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/12 11:17 PM
+
+
+class Solution:
+ def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
+ if not inorder and not postorder: return
+ val = postorder[-1]
+ root_ind = inorder.index(val)
+ root = TreeNode(val)
+ left = self.buildTree(inorder[:root_ind],postorder[:root_ind])
+ right = self.buildTree(inorder[root_ind+1:],postorder[root_ind:-1])
+ root.left = left
+ root.right = right
+ return root
\ No newline at end of file
diff --git "a/Week03/[111]\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py" "b/Week03/[111]\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py"
new file mode 100644
index 000000000..0e7497cc4
--- /dev/null
+++ "b/Week03/[111]\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py"
@@ -0,0 +1,38 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/23 8:52 PM
+
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Solution:
+ def minDepth(self, root: TreeNode) -> int:
+ #击败21%
+ #recursive terminator
+ #1.根节点为空 return 0
+ #2. 左右节点为空 return 1
+ #3.左节点或右节点为空 return 左/右+1
+ #4.左右节点都不为空 return min(left,right)+1
+ # if root is None: return 0
+ # if root.left is None and root.right is None: return 1
+ # left_height, right_height = self.minDepth(root.left),self.minDepth(root.right)
+ # if root.left is None or root.right is None: return left_height+right_height+1#有一个为0
+ # #其余情况 返回较小值+1
+ # return min(left_height,right_height)+1
+
+ # 2.深度优先搜索
+
+ # 3.广度优先搜索
+ #借助双端队列 击败86%
+ if not root: return 0
+ quene = [(1, root)]
+ while quene:
+ #[3,9,20,null,null,15,7]
+ depth, root = quene.pop(0) # 保证从左往右看,如果是pop(0),那么可能往右看的过程中返回了,而丢失了应有的最小值
+ if not root.left and not root.right: return depth # 如果此节点左右为空 返回当前depth
+ if root.left: quene.append((depth + 1, root.left))
+ if root.right: quene.append((depth + 1, root.right))
\ No newline at end of file
diff --git "a/Week03/[216]\347\273\204\345\220\210\346\200\273\345\222\214III.py" "b/Week03/[216]\347\273\204\345\220\210\346\200\273\345\222\214III.py"
new file mode 100644
index 000000000..5be24645d
--- /dev/null
+++ "b/Week03/[216]\347\273\204\345\220\210\346\200\273\345\222\214III.py"
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 2:37 AM
+
+class Solution:
+ def combinationSum3(self, k: int, target: int) -> List[List[int]]:
+ def dfs(cur, k, tmp, start):
+ if k < 0: return
+ if cur == target and k==0 : res.append(tmp)
+ # visited = set()
+ for i in range(start, 10):
+ # if i in visited: continue
+ # visited.add(i)
+ dfs(cur+i,k-1,tmp+[i],i+1)
+ res = []
+ dfs(0,k,[],1)
+ return res
\ No newline at end of file
diff --git "a/Week03/[232]\347\224\250\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.py" "b/Week03/[232]\347\224\250\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.py"
new file mode 100644
index 000000000..4c6d7a548
--- /dev/null
+++ "b/Week03/[232]\347\224\250\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.py"
@@ -0,0 +1,46 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/16 2:03 PM
+
+
+class MyQueue:
+ #用栈实现队列,最要考虑的就是抛出的时候该怎么做
+ # 抛出首先检查栈2是否为空,如果不为空,就抛出栈2顶元素
+ # 如果为空 就将栈1中的元素全部转移到栈2中,抛出栈2顶元素
+ # 如果栈1也为空,就抛出 异常
+ def __init__(self):
+ self.stack1 = []
+ self.stack2 = []
+
+ def push(self, x: int) -> None:
+ self.stack1.append(x)
+
+ def pop(self) -> int:
+ if self.stack2:#如果栈2中有元素,直接从栈2中抛出
+ return self.stack2.pop()
+ while self.stack1:#如果栈2中没有元素了,那就将栈1中的元素全部转移到栈2
+ self.stack2.append(self.stack1.pop())
+ return self.stack2.pop()
+
+ def peek(self) -> int:
+ if self.stack2:
+ return self.stack2[-1]
+ else:
+ while self.stack1:
+ self.stack2.append(self.stack1.pop())
+ return self.stack2[-1]
+
+ def empty(self) -> bool:
+ if not self.stack1 and not self.stack2:
+ return True
+ else:
+ return False
+
+
+
+# Your MyQueue object will be instantiated and called as such:
+# obj = MyQueue()
+# obj.push(x)
+# param_2 = obj.pop()
+# param_3 = obj.peek()
+# param_4 = obj.empty()
\ No newline at end of file
diff --git "a/Week03/[297]\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226\344\272\214\345\217\211\346\240\221.py" "b/Week03/[297]\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226\344\272\214\345\217\211\346\240\221.py"
new file mode 100644
index 000000000..857353bdc
--- /dev/null
+++ "b/Week03/[297]\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226\344\272\214\345\217\211\346\240\221.py"
@@ -0,0 +1,47 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/25 1:42 PM
+# Definition for a binary tree node.
+class TreeNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Codec:
+ def serialize(self, root):
+ # 手写一个二叉树的层寻遍历
+ if not root: return []
+ dquene, res = [root], ''
+ while dquene:
+ cur = dquene.pop(0) # 使用了双端队列
+ if cur != None:
+ res += str(cur.val) + ','
+ dquene.append(cur.left)
+ dquene.append(cur.right)
+ else:
+ res += '#,'
+ return res
+
+ def deserialize(self, data):
+ if not data: return None
+ data = data.split(',')
+ root = TreeNode(data.pop(0))
+ dquene = [root]
+ while dquene:
+ cur = dquene.pop(0)
+ if data:
+ cur_left = data.pop(0)
+ if cur_left != '#': # 反序列化时,如果节点值为#就不处理
+ cur.left = TreeNode(cur_left)
+ dquene.append(cur.left)
+ # if data:
+ cur_right = data.pop(0)
+ if cur_right != '#':
+ cur.right = TreeNode(cur_right)
+ dquene.append(cur.right)
+ return root
+
+# Your Codec object will be instantiated and called as such:
+# codec = Codec()
+# codec.deserialize(codec.serialize(root))
\ No newline at end of file
diff --git "a/Week03/[31]\344\270\213\344\270\200\344\270\252\346\216\222\345\210\227.py" "b/Week03/[31]\344\270\213\344\270\200\344\270\252\346\216\222\345\210\227.py"
new file mode 100644
index 000000000..533007226
--- /dev/null
+++ "b/Week03/[31]\344\270\213\344\270\200\344\270\252\346\216\222\345\210\227.py"
@@ -0,0 +1,31 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 3:04 AM
+
+class Solution:
+ def nextPermutation(self, nums: List[int]) -> None:
+ """
+ Do not return anything, modify nums in-place instead.
+ """
+ # 1.从后往前,找到第一个nums[i] nums[p1]:
+ nums[i], nums[p1] = nums[p1], nums[i]
+ break
+ return self.my_reverse(nums,p1+1,size)
+
+ def my_reverse(self, nums, left, right):
+ while left <= right:
+ nums[left], nums[right] = nums[right], nums[left]
+ left, right = left + 1, right - 1
+ return nums
\ No newline at end of file
diff --git "a/Week03/[377]\347\273\204\345\220\210\346\200\273\345\222\214IV.py" "b/Week03/[377]\347\273\204\345\220\210\346\200\273\345\222\214IV.py"
new file mode 100644
index 000000000..6e5e79b5d
--- /dev/null
+++ "b/Week03/[377]\347\273\204\345\220\210\346\200\273\345\222\214IV.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 2:39 AM
+
+class Solution:
+ def combinationSum4(self, nums: List[int], target: int) -> int:
+ #dfs超时了
+ # def dfs(cur,tmp):
+ # if cur > target: return
+ # if cur == target: res.append(tmp)
+ # for i in range(len(nums)):
+ # dfs(cur+nums[i],tmp+[nums[i]])
+ # res = []
+ # dfs(0,[])
+ # return len(res)
+ dp = [0]*(target+1)
+ dp[0] = 1
+ for i in range(target+1):
+ for j in range(len(nums)):
+ if i >= nums[j]:
+ dp[i] += dp[i-nums[j]]
+ return dp[-1]
\ No newline at end of file
diff --git "a/Week03/[39]\347\273\204\345\220\210\346\200\273\345\222\214.py" "b/Week03/[39]\347\273\204\345\220\210\346\200\273\345\222\214.py"
new file mode 100644
index 000000000..820d2f43f
--- /dev/null
+++ "b/Week03/[39]\347\273\204\345\220\210\346\200\273\345\222\214.py"
@@ -0,0 +1,26 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/23 11:53 PM
+
+from typing import List
+class Solution:
+ def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
+ def dfs(candidates, target, tmp, start):
+ if target<0: return
+ if target == 0:
+ res.append(tmp)
+ # for num in candidates:
+ # dfs(candidates, target-num, tmp+[num])
+ for i in range(start, len(candidates)):
+ dfs(candidates, target-candidates[i], tmp+[candidates[i]], i)
+ res = []
+ dfs(candidates, target, [], 0)
+ return res
+ # res = [sorted(nums) for nums in res]
+ # res = [nums for nums in res if nums not in res]
+
+s = Solution()
+candidates = [2,3,6,7]
+target = 7
+res = s.combinationSum(candidates,target)
+print(res)
\ No newline at end of file
diff --git "a/Week03/[40]\347\273\204\345\220\210\346\200\273\345\222\214II.py" "b/Week03/[40]\347\273\204\345\220\210\346\200\273\345\222\214II.py"
new file mode 100644
index 000000000..9a187ffca
--- /dev/null
+++ "b/Week03/[40]\347\273\204\345\220\210\346\200\273\345\222\214II.py"
@@ -0,0 +1,28 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/24 12:42 AM
+
+from typing import List
+class Solution:
+ def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
+ def dfs(candidates, target, tmp, start):
+ if target < 0: return
+ if target == 0: res.append(tmp)
+ # visited = set()
+ for i in range(start, len(candidates)):
+ if i > 0 and candidates[i-1] == candidates[i]: continue
+ cur = candidates[i]
+ # if cur in visited: continue
+ # visited.add(cur)
+ dfs(candidates[:i]+candidates[i+1:],target-cur,tmp+[cur],i)
+ candidates.sort()
+ res = []
+ dfs(candidates,target,[],0)
+ return res
+
+s = Solution()
+# candidates = [10,1,2,7,6,1,5]
+candidates = [1,1,2,5,6,7,10]
+target = 8
+res = s.combinationSum2(candidates,target)
+print(res)
\ No newline at end of file
diff --git "a/Week03/[46]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" "b/Week03/[46]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py"
new file mode 100644
index 000000000..2fd060d22
--- /dev/null
+++ "b/Week03/[46]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py"
@@ -0,0 +1,56 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/26 10:27 PM
+
+from typing import List
+class Solution(object):
+ # def permute(self,nums):
+ # res = []
+ # self.backtracing(res,nums,[])
+ # return res
+ # def backtracing(self,res,nums,tmp):
+ # #触发结束条件
+ # if len(nums) == len(tmp):
+ # res.append(tmp[:])
+ # # return #返回上一层调用
+ # for i in range(len(nums)):
+ # #排除不合法的,处理了好多
+ # if nums[i] in tmp: continue
+ # #做选择
+ # tmp.append(nums[i])
+ # #进入下一层
+ # self.backtracing(res,nums,tmp)
+ # tmp.pop()
+ def permute(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums, tmp):
+ #触发结束条件
+ if not nums:
+ res.append(tmp[:])
+ for i in range(len(nums)):
+ #排除不合法或已存在的
+ if nums[i] in tmp: continue
+ #做选择 修改已选路径和能选择的路径
+ #进入下一次决策、回溯之前的决策
+ backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径
+ res = []
+ backtrace(nums, [])
+ return res
+
+
+
+class SolutionII:
+ def permute(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums,tmp):
+ if len(tmp) == size:
+ res.append(tmp[:])
+ for i in range(len(nums)):
+ backtrace(nums[:i]+nums[i+1:],tmp + [nums[i]])
+ res,size = [],len(nums)
+ backtrace(nums,[])
+ return res
+
+
+s = SolutionII()
+nums = [1,3,2]
+res = s.permute(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week03/[47]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" "b/Week03/[47]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py"
new file mode 100644
index 000000000..974b750f4
--- /dev/null
+++ "b/Week03/[47]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py"
@@ -0,0 +1,41 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/26 11:55 PM
+
+class Solution(object):
+ def permuteUnique(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: List[List[int]]
+ """
+ def backtrace(nums, tmp):
+ if not nums:
+ res.append(tmp[:])
+ visited = set()
+ for i in range(len(nums)):
+ if nums[i] in visited: continue#在每一层剪枝
+ visited.add(nums[i])
+ backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径
+
+ res = []
+ backtrace(nums, [])
+ return res
+
+
+from typing import List
+class SolutionII:
+ def permuteUnique(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums,tmp):
+ if len(tmp) == size:
+ res.append(tmp[:])
+ visited = set()#同层去重,每一层只能选择这一层还没有被选过的元素
+ for i in range(len(nums)):
+ if nums[i] in visited: continue
+ visited.add(nums[i])
+ backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]])
+ res, size = [], len(nums)
+ backtrace(nums,[])
+ return res
+s = SolutionII()
+res = s.permuteUnique([1,1,2])
+print(res)
\ No newline at end of file
diff --git "a/Week03/[50]\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" "b/Week03/[50]\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py"
new file mode 100644
index 000000000..c0a5fb502
--- /dev/null
+++ "b/Week03/[50]\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py"
@@ -0,0 +1,24 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/27 10:45 AM
+
+class Solution:
+ def myPow(self, x: float, n: int) -> float:
+ # if n == 0: return 1
+ # if n == 1: return x
+ # if n < 0:
+ # return 1 / self.myPow(x, -n)
+ # return self.myPow(x*x,n//2) if n%2==0 else x*self.myPow(x,n-1)
+ flag = 1
+ if n < 0: flag = 0
+ n, res = abs(n), 1
+ while n:
+ if n & 1: # 奇数时
+ res = res * x
+ x = x * x
+ n = n >> 1
+ return res if flag else 1 / res
+
+s = Solution()
+res = s.myPow(2,4)
+print(res)
diff --git "a/Week03/[77]\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\273\204\345\220\210.py" "b/Week03/[77]\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\273\204\345\220\210.py"
new file mode 100644
index 000000000..2a78841fb
--- /dev/null
+++ "b/Week03/[77]\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\273\204\345\220\210.py"
@@ -0,0 +1,23 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/26 10:02 PM
+
+class Solution(object):
+ def combine(self, n, k):
+ """
+ :type n: int
+ :type k: int
+ :rtype: List[List[int]]
+ """
+ def backtracing(first=1, tmp=[]):
+ if len(tmp) == k: #触发结束条件 如果当前元素 已经有k个,就将它加入res中
+ res.append(tmp[:])
+ for i in range(first, n + 1): # 如果当前元素个数小于k,则加入cur中
+ # 做选择
+ tmp.append(i)
+ backtracing(i + 1, tmp) # 进入下一层决策
+ tmp.pop() # 撤销刚才的选择
+
+ res = []
+ backtracing()
+ return res
diff --git "a/Week03/[77]\347\273\204\345\220\210.py" "b/Week03/[77]\347\273\204\345\220\210.py"
new file mode 100644
index 000000000..1886fc3fd
--- /dev/null
+++ "b/Week03/[77]\347\273\204\345\220\210.py"
@@ -0,0 +1,24 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/23 8:26 PM
+
+#给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
+from typing import List
+class Solution:
+ def combine(self, n: int, k: int) -> List[List[int]]:
+ def backtrace(first=1, tmp=[]):
+ if len(tmp) == k:
+ res.append(tmp[:])
+ return
+ for i in range(first,n+1):
+ tmp.append(i)
+ backtrace(i+1, tmp)
+ tmp.pop()
+ res = []
+ backtrace()
+ return res
+
+
+s = Solution()
+res = s.combine(4,3)
+print(res)
\ No newline at end of file
diff --git "a/Week03/[784]\345\255\227\346\257\215\345\244\247\345\260\217\345\206\231\345\205\250\346\216\222\345\210\227.py" "b/Week03/[784]\345\255\227\346\257\215\345\244\247\345\260\217\345\206\231\345\205\250\346\216\222\345\210\227.py"
new file mode 100644
index 000000000..474e61071
--- /dev/null
+++ "b/Week03/[784]\345\255\227\346\257\215\345\244\247\345\260\217\345\206\231\345\205\250\346\216\222\345\210\227.py"
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 2:25 AM
+
+
+class Solution:
+ def letterCasePermutation(self, strs: str) -> List[str]:
+ #如果下一个字符时字母,则将已经生成的排列拷贝一份,将下一个字母转为大小写,加到排列后
+ # 如果是数字,直接加到所有排列后
+ # 时间复杂度是2^n*N
+ res = ['']
+ for i in range(len(strs)):
+ if strs[i].isalpha():
+ res = [item+case for item in res for case in [strs[i].lower(),strs[i].upper()]]
+ elif strs[i].isdigit():
+ res = [item+str(strs[i]) for item in res]
+ return res
\ No newline at end of file
diff --git "a/Week03/[78]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" "b/Week03/[78]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py"
new file mode 100644
index 000000000..7dfc749bf
--- /dev/null
+++ "b/Week03/[78]\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py"
@@ -0,0 +1,37 @@
+from typing import List
+class Solution:
+ def subsets(self, nums: List[int]) -> List[List[int]]:
+ # res = [[]]
+ # for num in nums:
+ # res += [tmp + [num] for tmp in res]
+ # return res
+ def backtrack(first=0, tmp=[],k=0):
+ #处理结束条件
+ # if len(tmp) == k:#最后结果的长度是0-3
+ # res.append(tmp[:])
+ res.append(tmp[:])
+ for i in range(first, size):
+ tmp.append(nums[i])
+ backtrack(i + 1, tmp, k+1)
+ tmp.pop()
+
+ res = []
+ size = len(nums)
+ # for k in range(size + 1):
+ backtrack()
+ return res
+
+ # size = len(nums)
+ # res = []
+ # for i in range(2 ** size, 2 ** (size + 1)):
+ # # generate bitmask, from 0..00 to 1..11
+ # bitmask = bin(i)[3:]
+ # # append subset corresponding to that bitmask
+ # res.append([nums[j] for j in range(size) if bitmask[j] == '1'])
+ # return res
+
+
+
+s = Solution()
+res = s.subsets([1,2,3])
+print(res)
\ No newline at end of file
diff --git "a/Week03/[90]\346\257\217\346\227\245\344\270\200\351\242\2306_27\345\255\220\351\233\206II.py" "b/Week03/[90]\346\257\217\346\227\245\344\270\200\351\242\2306_27\345\255\220\351\233\206II.py"
new file mode 100644
index 000000000..ed765953b
--- /dev/null
+++ "b/Week03/[90]\346\257\217\346\227\245\344\270\200\351\242\2306_27\345\255\220\351\233\206II.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/12 8:35 PM
+from typing import List
+class Solution:
+ def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(first=0,tmp=[]):
+ res.append(tmp[:])
+ for i in range(first,size):
+ if i > first and nums[i] == nums[i-1]: continue
+ tmp.append(nums[i])
+ backtrace(i + 1, tmp)
+ tmp.pop()
+ res, size = [], len(nums)
+ nums.sort()
+ backtrace()
+ return res
+s = Solution()
+res = s.subsetsWithDup([4,4,4,1,4])
+print(res)
+print(len(res))
+
diff --git "a/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.py" "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.py"
new file mode 100644
index 000000000..accf3a79b
--- /dev/null
+++ "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.py"
@@ -0,0 +1,37 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/26 1:11 PM
+
+# Definition for a binary tree node.
+# class TreeNode:
+# def __init__(self, x):
+# self.val = x
+# self.left = None
+# self.right = None
+
+class Solution:
+ #1.递归 分析出找到最近公共祖先节点的情形,如果p,q由同一祖先节点 则p、q要么位于某棵树的左右子树
+ #要么在同一棵树上,在同一棵树上又有 p或q为根 另外存在p或q在其左右子树中
+ def lowestCommonAncestor(self, root, p, q):
+ # dfs
+ # if not root or p == root or q == root : return root
+ # left = self.lowestCommonAncestor(root.left,p,q)#表示左子树是否包含p或q
+ # right = self.lowestCommonAncestor(root.right,p,q)
+ # if left and right: return root
+ # return left if left else right
+ # hash表解法
+ hashmap = {root: None}
+
+ def dfs(root):
+ if root:
+ if root.left: hashmap[root.left] = root
+ if root.right: hashmap[root.right] = root
+ dfs(root.left)
+ dfs(root.right)
+
+ dfs(root)
+ left, right = p, q # 转化为找两个链表的相交节点
+ while left != right:
+ left = hashmap.get(left, q)
+ right = hashmap.get(right, p)
+ return left
diff --git "a/Week03/\344\273\205\344\273\205\346\230\257\347\277\273\350\275\254\345\255\227\347\254\246.py" "b/Week03/\344\273\205\344\273\205\346\230\257\347\277\273\350\275\254\345\255\227\347\254\246.py"
new file mode 100644
index 000000000..150a698d5
--- /dev/null
+++ "b/Week03/\344\273\205\344\273\205\346\230\257\347\277\273\350\275\254\345\255\227\347\254\246.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/23 8:59 PM
+
+class Solution:
+ def reverseOnlyLetters(self, strs: str) -> str:
+ tmp = list(strs)
+ left, right = 0, len(strs) - 1
+ while left <= right:
+ if not tmp[left].isalpha(): left = left + 1
+ elif not tmp[right].isalpha(): right = right - 1
+ else:
+ tmp[left], tmp[right] = tmp[right], tmp[left]
+ left, right = left + 1, right - 1
+ return ''.join(tmp)
+
+s = Solution()
+strs = "a-bC-dEf-ghIj"
+# strs = "ab-cd"
+# strs = "7_28]"
+res = s.reverseOnlyLetters(strs)
+print(res)
\ No newline at end of file
diff --git "a/Week03/\345\233\236\346\226\207\346\225\260.py" "b/Week03/\345\233\236\346\226\207\346\225\260.py"
new file mode 100644
index 000000000..0494a788d
--- /dev/null
+++ "b/Week03/\345\233\236\346\226\207\346\225\260.py"
@@ -0,0 +1,24 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/23 9:45 PM
+
+class Solution:
+ def isPalindrome(self, x: int) -> bool:
+ # if x < 0: return False
+ # tmp = str(x)
+ # left,right = 0, len(tmp)-1
+ # while left <= right:
+ # if tmp[left] != tmp[right]: return False
+ # else: left,right = left+1,right-1
+ # return True
+
+ # return str(x) == str(x)[::-1]
+ res = x
+ tmp = 0
+ while x > 0:
+ tmp = tmp*10 + x%10
+ x = x//10
+ return res == tmp
+s = Solution()
+res = s.isPalindrome(-1211)
+print(res)
diff --git "a/Week03/\345\233\236\346\272\257.md" "b/Week03/\345\233\236\346\272\257.md"
new file mode 100644
index 000000000..3d21c65a5
--- /dev/null
+++ "b/Week03/\345\233\236\346\272\257.md"
@@ -0,0 +1,115 @@
+## 回溯习题整理
+
+```python
+result = []
+def backtrack(路径, 选择列表):
+ if 满足结束条件:
+ result.add(路径)
+ return
+ for 选择 in 选择列表:
+ 做选择
+ backtrack(路径, 选择列表)
+ 撤销选择
+```
+#### 1.子集
+>给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
+说明:解集不能包含重复的子集。
+>例:nums = [1,2,3]
+输出
+[
+ [3],
+ [1],
+ [2],
+ [1,2,3],
+ [1,3],
+ [2,3],
+ [1,2],
+ []
+]
+
+首先要能想到用DFS,
+DFS的模板是
+```python
+def dfs():
+ # recursive terminator
+ # process cur_layer
+ # drill_down
+ # reverse state
+```
+其次待求是所有子集,必然涉及记录子集
+首先这一题我们能想到要用深度优先来做,但是待求是所有子集,子集中list的长度可以是0-3,
+在深度优先过程中,明显会涉及到从叶节点到父节点的回溯过程
+使用tmp记录每个子集,由于子集内容是[]->[1]->[1,2]->[1,2,3]...
+所以递归过程中需要将每个时刻的值加入到tmp传入下一层递归,对于长度到达最大后,自然需要回溯
+比如[1,2,3]->[1,3]->[2]
+```python
+class Solution:
+ def subSet(self,nums):
+ def backtrace(first=0,tmp=[]):
+ res.append(tmp[:])
+ for i in range(first,size):
+ tmp.append(nums[i])
+ backtrace(i + 1, tmp)
+ tmp.pop()
+ res, size = [], len(nums)
+ backtrace()
+ return res
+```
+
+#### 子集II
+>给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
+说明:解集不能包含重复的子集。
+例如:[1,2,2]
+输出:
+[
+ [2],
+ [1],
+ [1,2,2],
+ [2,2],
+ [1,2],
+ []
+]
+
+首先要清楚,重复解来自于哪里?明显是来自tmp.pop()之后继续for循环遍历,可以取到后边的元素,就会出现重复解
+所以,如果在for循环里面,pass掉nums[i]==numsp[i-1]的内容,
+即可同时对这个i有一定的限定,不能仅仅是i>0,而是大于当前位置
+```python
+class Solution:
+ def subSet(self,nums):
+ def backtrace(first=0,tmp=[]):
+ res.append(tmp[:])
+ for i in range(first,size):
+ if i > first and nums[i]==nums[i-1]: continue
+ tmp.append(nums[i])
+ backtrace(i + 1, tmp)
+ tmp.pop()
+ res, size = [], len(nums)
+ backtrace()
+ return res
+```
+
+#### 电话号码的字母组合
+时间复杂度是3^N*4^M M+N = len(digits)
+```python
+class Solution(object):
+ def letterCombinations(self, digits):
+ """
+ :type digits: str
+ :rtype: List[str]
+ """
+ hashmap = {'2':'abc','3':'def','4':'ghi','5':'jkl','6':'mno',
+ '7':'pqrs','8':'tuv','9':'wxyz'}
+ def backtrace(combinations,digits):
+ if digits == '':
+ res.append(combinations)
+ else:
+ for ch in hashmap[digits[0]]:
+ backtrace(combinations+ch,digits[1:])
+ res = []
+ if digits:
+ backtrace('',digits)
+ return res
+```
+
+
+
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py"
new file mode 100644
index 000000000..820a991de
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py"
@@ -0,0 +1,76 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/22 9:30 PM
+# 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
+#
+#
+#
+# 示例:
+#
+# 输入:n = 3
+# 输出:[
+# "((()))",
+# "(()())",
+# "(())()",
+# "()(())",
+# "()()()"
+# ]
+#
+# Related Topics 字符串 回溯算法
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ #1.递归的参数,递归的level
+ # def _generate_parenthesis(self,level,max_level,strs):
+ # #recursive terminator
+ # if level>=max_level:
+ # print(strs)
+ # return
+ # #current process
+ # #drill down
+ # self._generate_parenthesis(level+1,max_level,strs+'(')
+ # self._generate_parenthesis(level+1,max_level,strs+')')
+ # def generateParenthesis(self,n):
+ # """
+ # :type n: int
+ # :rtype: List[str]
+ # """
+ # self._generate_parenthesis(0, 2*n, '')
+ #击败43%
+ def generateParenthesis(self, n):
+ result = []
+ self._generate_parenthesis(0, 0, n, '', result)
+ return result
+
+ def _generate_parenthesis(self, left, right, n, res, result):
+ # recursive terminator
+ if left == n and right == n:
+ result.append(res)
+ return
+ # current process
+ if left < n: self._generate_parenthesis(left + 1, right, n, res + '(', result)
+ if left > right: self._generate_parenthesis(left, right + 1, n, res + ')', result)
+ #击败82%,不需要传递五个变量
+ def generateParenthesisII(self, n):
+
+ def _generate_parenthesis(left, right, n, res):
+ # recursive terminator
+ if left == n and right == n:#触发结束条件
+ result.append(res)
+ return
+ # current process #排除不合法的选择 做选择 进入下一层决策树
+ if left < n: _generate_parenthesis(left + 1, right, n, res + '(')
+ if left > right: _generate_parenthesis(left, right + 1, n, res + ')')
+ #取消选择
+ result = []
+ _generate_parenthesis(0, 0, n, '')
+ return result
+
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+res = s.generateParenthesis(3)
+print(res)
+
+
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_23_\344\272\214\350\277\233\345\210\266\346\261\202\345\222\214.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_23_\344\272\214\350\277\233\345\210\266\346\261\202\345\222\214.py"
new file mode 100644
index 000000000..59f436f7f
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_23_\344\272\214\350\277\233\345\210\266\346\261\202\345\222\214.py"
@@ -0,0 +1,55 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/23 9:28 PM
+
+# 给你两个二进制字符串,返回它们的和(用二进制表示)。
+#
+# 输入为 非空 字符串且只包含数字 1 和 0。
+#
+#
+#
+# 示例 1:
+#
+# 输入: a = "11", b = "1"
+# 输出: "100"
+#
+# 示例 2:
+#
+# 输入: a = "1010", b = "1011"
+# 输出: "10101"
+#
+#
+#
+# 提示:
+#
+#
+# 每个字符串仅由字符 '0' 或 '1' 组成。
+# 1 <= a.length, b.length <= 10^4
+# 字符串如果不是 "0" ,就都不含前导零。
+#
+# Related Topics 数学 字符串
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def addBinary(self, a, b):
+ """
+ :type a: str
+ :type b: str
+ :rtype: str
+ """
+ #1.利用进制转换来做
+ # return bin(int(a, 2)+int(b, 2))[2:]
+ #2.如果不能使用加减乘除运算,则使用位运算
+ x, y = int(a, 2), int(b, 2)
+ while y:
+ res = x ^ y #无进位相加结果
+ carry = (x & y) << 1#计算x+y的进位
+ x, y = res, carry
+ return bin(x)[2:]
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+a, b = "1010", "1011"
+res = s.addBinary(a, b)
+print(res)
\ No newline at end of file
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_24_\346\234\200\346\216\245\350\277\221\347\232\204\344\270\211\346\225\260\344\271\213\345\222\214.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_24_\346\234\200\346\216\245\350\277\221\347\232\204\344\270\211\346\225\260\344\271\213\345\222\214.py"
new file mode 100644
index 000000000..69e0a141a
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_24_\346\234\200\346\216\245\350\277\221\347\232\204\344\270\211\346\225\260\344\271\213\345\222\214.py"
@@ -0,0 +1,54 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/25 8:39 AM
+
+# 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和
+# 。假定每组输入只存在唯一答案。
+#
+#
+#
+# 示例:
+#
+# 输入:nums = [-1,2,1,-4], target = 1
+# 输出:2
+# 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
+#
+#
+#
+#
+# 提示:
+#
+#
+# 3 <= nums.length <= 10^3
+# -10^3 <= nums[i] <= 10^3
+# -10^4 <= target <= 10^4
+#
+# Related Topics 数组 双指针
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+from typing import List
+class Solution(object):
+ def threeSumClosest(self, nums: List[int], target: int) -> int:
+ nums.sort() # 先排序
+ # [-4,-1,1,2],1
+ min_closer = float('inf')
+ for i in range(len(nums) - 2): # 为双指针留出位置
+ if i > 0 and nums[i] == nums[i - 1]: # 保证前后两个数字不一,因为只有一组解
+ continue
+ left, right = i + 1, len(nums) - 1
+ while left < right:
+ tmp = nums[i] + nums[left] + nums[right] # 先记录当前遍历得到的三数之和
+ if abs(min_closer - target) > abs(tmp - target):
+ min_closer = tmp
+ # min_closer = min(abs(target-tmp),min_closer)
+ if tmp < target: # 如果还没有找到相等的 ,j右移
+ left = left + 1
+ # cur_diff = abs()
+ elif tmp > target: # 如果找着找着 大于target了,就需要和之前记录的min_diff比较
+ right = right - 1
+ else: # tmp==target:
+ return min_closer
+ return min_closer
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\345\215\225\350\257\215\346\213\206\345\210\206.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\345\215\225\350\257\215\346\213\206\345\210\206.py"
new file mode 100644
index 000000000..30938c697
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\345\215\225\350\257\215\346\213\206\345\210\206.py"
@@ -0,0 +1,83 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/25 8:40 AM
+
+# 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
+#
+# 说明:
+#
+#
+# 拆分时可以重复使用字典中的单词。
+# 你可以假设字典中没有重复的单词。
+#
+#
+# 示例 1:
+#
+# 输入: s = "leetcode", wordDict = ["leet", "code"]
+# 输出: true
+# 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
+#
+#
+# 示例 2:
+#
+# 输入: s = "applepenapple", wordDict = ["apple", "pen"]
+# 输出: true
+# 解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
+# 注意你可以重复使用字典中的单词。
+#
+#
+# 示例 3:
+#
+# 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
+# 输出: false
+#
+# Related Topics 动态规划
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def wordBreak(self, s, wordDict):
+ """
+ :type s: str
+ :type wordDict: List[str]
+ :rtype: bool
+ """
+ #动态规划 用大小为len(s)+1的数组保存转态结果
+ #dp[i]表示s的前i位是否能被worddict中的元素表示,最后只需要取转移数组的最后一位即可知道是否能够拆分
+ #如何转移呢?
+ #外层i从[0,len(s)),内层j[i+1,n]
+ #如何从i转移到j? 如果dp[i]=True并且s[i:j]在worddict中,即可转移
+ # dp = [False for _ in range(len(s)+1)]
+ # dp[0] = True
+ # for i in range(len(s)):
+ # for j in range(i+1,len(s)+1):
+ # if dp[i]==True and s[i:j] in wordDict:
+ # dp[j] = True
+ # return dp[-1]
+
+ #备忘录回溯
+ # import functools
+ # @functools.lru_cache
+ # def backtrace(s):
+ # if not s: return True#s已经考察结束
+ # res = False
+ # for i in range(1, len(s)+1):#
+ # if s[:i] in wordDict:
+ # res = backtrace(s[i:]) or res#记录递归过程中的res
+ # return res#最后返回的相当于是dp[-1]or(dp[-2]or(dp[-n])) 其实只用看最后一层的res即可
+ # return backtrace(s)
+
+ while s:
+ for item in wordDict:
+ s = s.replace(item, '')
+ return False
+ return s == ''
+ # leetcode submit region end(Prohibit modification and deletion)
+
+# strs = "catsandog"
+# wordDict = ["cats", "dog", "sand", "and", "cat"]
+strs = "abcd"
+wordDict = ["a","abc","b","cd"]
+s = Solution()
+res = s.wordBreak(strs,wordDict)
+print(res)
\ No newline at end of file
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\346\234\200\351\225\277\345\233\236\346\226\207\345\255\220\344\270\262.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\346\234\200\351\225\277\345\233\236\346\226\207\345\255\220\344\270\262.py"
new file mode 100644
index 000000000..1383b50f3
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\346\234\200\351\225\277\345\233\236\346\226\207\345\255\220\344\270\262.py"
@@ -0,0 +1,83 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/25 8:39 AM
+
+class Solution:
+ # def longestPalindrome(self, s: str) -> str:
+ # res,max_length = '',0
+ # for i in range(len(s)):
+ # for j in range(i+1,len(s)+1):
+ # cur_string = s[i:j]
+ # if self.isPalidrome(cur_string) and len(cur_string)>max_length:
+ # res = cur_string
+ # max_length = max(max_length,len(res))
+ # return res
+ #
+ # def isPalidrome(self,cur_string):
+ # #判断是否回文字符
+ # left,right = 0,len(cur_string)-1
+ # while left str:
+ # left, right, size = 0, 0, len(s)
+ # def extend(left, right):
+ # while left >= 0 and right < size and s[left] == s[right]:
+ # left, right = left - 1, right + 1
+ # return left + 1, right - 1
+ # for i in range(size):
+ # l1, r1 = extend(i, i)
+ # l2, r2 = extend(i, i + 1)
+ # if r1 - l1 > right - left:
+ # left, right = l1, r1
+ # if r2 - l2 > right - left:
+ # left, right = l2, r2
+ # return s[left:right + 1]
+
+ #首先 长度为0、1的字符串 它是回文串
+ #长度=2,判断左右是否相同
+ #对于strs[i,j]而言它是否是回文串 取决于它内缩2位的字符串是否是回文串同时还要判断其边界是否相同
+ #动态规划的思想就是 每一次的状态都是可以由其他时刻的状态导出的
+ #而通常我们在做题时,总会借助额外的空间,这个空间的维度与我们的状态有关,比如此时要记录i,j组合状态,就需要二维数组记录
+ def longestPalindrome(self, s: str) -> str:
+ size = len(s)
+ dp = [[False]*size for _ in range(size)]
+ res = ''
+ for l in range(size):
+ for i in range(size):
+ j = l + i
+ if j >= size: break
+ elif l == 0: dp[i][j] = True
+ elif l == 1: dp[i][j] = (s[i]==s[j])
+ else:
+ dp[i][j] = (dp[i+1][j-1] and s[i]==s[j])
+ if l >= len(res) and dp[i][j]:#如果当前串是回文且长度增加
+ res = s[i:j+1]
+ return res
+ # size = len(s)
+ # dp = [[False] * size for _ in range(size)] # 为什么是一个二维数组
+ # res = ""
+ # # 枚举子串的长度 l+1
+ # for L in range(size):
+ # # 枚举子串的起始位置 i,这样可以通过 j=i+l 得到子串的结束位置
+ # for i in range(size):
+ # j = i + L
+ # if j >= len(s):
+ # break
+ # if L == 0: # 如果当前字符长度为0
+ # dp[i][j] = True#i==j,为True
+ # elif L == 1: # 如果当前字符长度为1
+ # dp[i][j] = (s[i] == s[j])
+ # else: #
+ # dp[i][j] = (dp[i + 1][j - 1] and s[i] == s[j])
+ # if dp[i][j] and L + 1 > len(res):
+ # res = s[i:j + 1]
+ # return res
+
+
+s = Solution()
+res = s.longestPalindrome("babad")
+print(res)
\ No newline at end of file
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\247\273\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\247\273\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271.py"
new file mode 100644
index 000000000..914d37610
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\247\273\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271.py"
@@ -0,0 +1,58 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/26 5:38 PM
+
+# 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
+#
+# 示例1:
+#
+#
+# 输入:[1, 2, 3, 3, 2, 1]
+# 输出:[1, 2, 3]
+#
+#
+# 示例2:
+#
+#
+# 输入:[1, 1, 1, 1, 2]
+# 输出:[1, 2]
+#
+#
+# 提示:
+#
+#
+# 链表长度在[0, 20000]范围内。
+# 链表元素在[0, 20000]范围内。
+#
+#
+# 进阶:
+#
+# 如果不得使用临时缓冲区,该怎么解决?
+# Related Topics 链表
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for singly-linked list.
+# class ListNode(object):
+# def __init__(self, x):
+# self.val = x
+# self.next = None
+
+class Solution(object):
+ def removeDuplicateNodes(self, head):
+ """
+ :type head: ListNode
+ :rtype: ListNode
+ """
+ if not head: return head
+ once = {head.val}
+ pre = head
+ while head.next: # 如果有下一个节点
+ cur = head.next
+ if not cur.val in once:
+ once.add(cur.val)
+ head = head.next
+ else: # 如果这个元素已经出现,那就直接删除掉
+ head.next = head.next.next
+ return pre
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\344\271\230.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\344\271\230.py"
new file mode 100644
index 000000000..96fcdf989
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\344\271\230.py"
@@ -0,0 +1,51 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/28 7:21 PM
+
+# 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
+#
+# 示例 1:
+#
+# 输入: num1 = "2", num2 = "3"
+# 输出: "6"
+#
+# 示例 2:
+#
+# 输入: num1 = "123", num2 = "456"
+# 输出: "56088"
+#
+# 说明:
+#
+#
+# num1 和 num2 的长度小于110。
+# num1 和 num2 只包含数字 0-9。
+# num1 和 num2 均不以零开头,除非是数字 0 本身。
+# 不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。
+#
+# Related Topics 数学 字符串
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def multiply(self, num1, num2):
+ """
+ :type num1: str
+ :type num2: str
+ :rtype: str
+ """
+ if len(num1) < len(num2): # 确定num1是较长的
+ num1, num2 = num2, num1
+ tmp,tail = 0,0
+ for i in range(len(num1)):
+ tail = tail + int(num1[i])*10**(len(num1)-i-1)
+ for ind in range(len(num2)-1, -1, -1):#将较长的作为底数,这样int()转换的时候不会出错
+ # tmp = tmp + int(num1) * 10 ** (len(num2) - ind - 1) * int(num2[ind])
+ tmp = tmp + tail * 10 ** (len(num2) - ind - 1) * int(num2[ind])
+ return str(tmp)
+
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+num1, num2 = '123', '456'
+res = s.multiply(num1, num2)
+print(res)
\ No newline at end of file
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\345\212\240.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\345\212\240.py"
new file mode 100644
index 000000000..e93a69a65
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\345\212\240.py"
@@ -0,0 +1,44 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/28 6:45 PM
+
+# 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。
+#
+# 注意:
+#
+#
+# num1 和num2 的长度都小于 5100.
+# num1 和num2 都只包含数字 0-9.
+# num1 和num2 都不包含任何前导零。
+# 你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式。
+#
+# Related Topics 字符串
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def addStrings(self, num1, num2):
+ """
+ :type num1: str
+ :type num2: str
+ :rtype: str
+ """
+ #1.转数字计算
+ # return str(int(num1)+int(num2))
+ # 2.手动模拟加法运算
+ res = ''
+ i, j, carry = len(num1) - 1,len(num2) - 1, 0
+ while i >= 0 or j >= 0:
+ n1 = int(num1[i]) if i >= 0 else 0
+ n2 = int(num2[j]) if j >= 0 else 0
+ tmp = n1 + n2 + carry
+ carry = tmp // 10
+ res = str(tmp % 10) + res
+ i, j = i - 1, j - 1
+ return '1' + res if carry else res
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+num1, num2 = '9', '99'
+res = s.addStrings(num1,num2)
+print(res)
diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204.py"
new file mode 100644
index 000000000..107df4c1c
--- /dev/null
+++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204.py"
@@ -0,0 +1,59 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/28 8:29 PM
+# 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回
+# 0。
+#
+#
+#
+# 示例:
+#
+# 输入:s = 7, nums = [2,3,1,2,4,3]
+# 输出:2
+# 解释:子数组 [4,3] 是该条件下的长度最小的连续子数组。
+#
+#
+#
+#
+# 进阶:
+#
+#
+# 如果你已经完成了 O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
+#
+# Related Topics 数组 双指针 二分查找
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class Solution(object):
+ def minSubArrayLen(self, s, nums):
+ """
+ :type s: int
+ :type nums: List[int]
+ :rtype: int
+ """
+ # # 1. 穷举 超出时间限制
+ # for i in range(1, len(nums) + 1):
+ # # 长度为1,2,3,穷举可能的解,找到则返回
+ # for j in range(len(nums) - i + 1):
+ # if sum(nums[j:i + j]) >= s: return i
+ # return 0
+ #2.双指针
+ if not nums: return 0
+ size, res = len(nums), len(nums) + 1
+ start, end = 0, 0
+ tmp = 0 # 记录窗口和
+ while end < size:
+ tmp = tmp + nums[end]
+ while tmp >= s: # 如果当前窗口和值大于s,收缩窗口
+ res = min(res, end - start + 1)
+ tmp = tmp - nums[start]
+ start = start + 1
+ end = end + 1 # 窗口扩张
+ return 0 if end == size + 1 else res
+# leetcode submit region end(Prohibit modification and deletion)
+
+s = Solution()
+# nums = [2,3,1,2,4,3]
+nums = [1,2,3,4,5]
+res= s.minSubArrayLen(1,nums)
+print(res)
\ No newline at end of file
diff --git "a/Week03/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py" "b/Week03/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py"
new file mode 100644
index 000000000..27c5c78ee
--- /dev/null
+++ "b/Week03/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py"
@@ -0,0 +1,30 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/12 11:01 PM
+
+from typing import List
+class Solution:
+ def letterCombinations(self, digits: str) -> List[str]:
+ hashmap = {'2':'abc','3':'def','4':'ghi','5':'jkl','6':'mno',
+ '7':'pqrs','8':'tuv','9':'wxyz'}
+ # dfs
+ # def backtrace(combinations,digits):#'23'
+ # if digits == '':
+ # res.append(combinations)
+ # else:
+ # for cur_str in hashmap[digits[0]]:#'abc'
+ # backtrace(combinations + cur_str,digits[1:])#'abc'中挑一个,'3'
+ # res = []
+ # # if digits:
+ # backtrace('',digits)
+ # return res
+ # bfs
+ if digits == '': return []
+ combinations = ['']
+ for digit in digits:
+ combinations = [combination + cur for combination in combinations for cur in hashmap[digit]]
+ return combinations
+
+s = Solution()
+res = s.letterCombinations('23')
+print(res)
\ No newline at end of file
diff --git "a/Week03/\347\254\254k\344\270\252\346\216\222\345\210\227.py" "b/Week03/\347\254\254k\344\270\252\346\216\222\345\210\227.py"
new file mode 100644
index 000000000..fa5c607e6
--- /dev/null
+++ "b/Week03/\347\254\254k\344\270\252\346\216\222\345\210\227.py"
@@ -0,0 +1,5 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 3:04 AM
+
+
diff --git "a/Week03/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py" "b/Week03/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py"
new file mode 100644
index 000000000..70946c820
--- /dev/null
+++ "b/Week03/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py"
@@ -0,0 +1,41 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/22 11:08 PM
+
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Solution:
+ def invertTree(self, root: TreeNode) -> TreeNode:
+ # recursive terminator
+ #击败70%
+ # if root is None: return
+ # # current process
+ # left = self.invertTree(root.right)
+ # right = self.invertTree(root.left)
+ # root.left = left
+ # root.right = right
+ # # drill down
+ # # reverse states
+ # return root
+ #非递归写法,深度优先遍历过程中,交换左右孩子,然后继续向下做同样的操作
+ #类似层序遍历,用quene存储访问到的节点
+ #击败87%
+ if root is None: return None
+ quene = [root]
+ while quene:
+ cur = quene.pop()
+ tmp = cur.left
+ cur.left = cur.right
+ cur.right = tmp
+ if cur.left is not None: quene.append(cur.left)
+ if cur.right is not None: quene.append(cur.right)
+ return root
+
+
+
+
diff --git "a/Week03/\351\200\222\345\275\222\346\250\241\346\235\277.py" "b/Week03/\351\200\222\345\275\222\346\250\241\346\235\277.py"
new file mode 100644
index 000000000..80360055b
--- /dev/null
+++ "b/Week03/\351\200\222\345\275\222\346\250\241\346\235\277.py"
@@ -0,0 +1,16 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/22 9:16 PM
+
+def recursive(level,*args,**kwargs):
+ #recursive terminator
+ if level>max_level:
+ process_resoult
+ return
+
+ #logic process in current level
+ process(level,data)
+ #drill down
+ recursive(level+1,*args,**kwargs)
+
+ # reverse the current state if needed
diff --git "a/Week03/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" "b/Week03/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py"
new file mode 100644
index 000000000..d96d21d45
--- /dev/null
+++ "b/Week03/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py"
@@ -0,0 +1,83 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/22 11:50 PM
+
+# 给定一个二叉树,判断其是否是一个有效的二叉搜索树。
+#
+# 假设一个二叉搜索树具有如下特征:
+#
+#
+# 节点的左子树只包含小于当前节点的数。
+# 节点的右子树只包含大于当前节点的数。
+# 所有左子树和右子树自身必须也是二叉搜索树。
+#
+#
+# 示例 1:
+#
+# 输入:
+# 2
+# / \
+# 1 3
+# 输出: true
+#
+#
+# 示例 2:
+#
+# 输入:
+# 5
+# / \
+# 1 4
+# / \
+# 3 6
+# 输出: false
+# 解释: 输入为: [5,1,4,null,null,3,6]。
+# 根节点的值为 5 ,但是其右子节点值为 4 。
+#
+# Related Topics 树 深度优先搜索
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for a binary tree node.
+# class TreeNode(object):
+# def __init__(self, x):
+# self.val = x
+# self.left = None
+# self.right = None
+
+class Solution(object):
+ pre_val = float('-inf')
+ def isValidBST(self, root):
+ """
+ :type cur: TreeNode
+ :rtype: bool
+ """
+ #依据是 二叉搜索树的中序遍历是有递增的 击败11%
+ #recursive terminator
+ # if root is None: return True
+ # #current prpcess
+ # #确定左子树是否符合排序二叉树,如果不满足,就返回False
+ # if not self.isValidBST(root.left): return False
+ # if root.val <= self.pre_val: return False#不满足左子树小于根节点
+ # self.pre_val = root.val#记录上一个访问的节点的值
+ # #访问右子树
+ #
+ # # drill down
+ # return self.isValidBST(root.right)
+
+ #中序遍历 迭代 击败73%
+ stack, pre_val = [], float('-inf')
+ cur = root
+ while stack or cur is not None:
+ while cur is not None:
+ stack.append(cur)
+ cur = cur.left
+ cur = stack.pop()
+ if cur.val <= pre_val: return False
+ pre_val = cur.val
+ cur = cur.right
+ return True
+
+
+
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git a/Week04/.idea/Week04.iml b/Week04/.idea/Week04.iml
new file mode 100644
index 000000000..7c9d48f0f
--- /dev/null
+++ b/Week04/.idea/Week04.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week04/.idea/leetcode/editor.xml b/Week04/.idea/leetcode/editor.xml
new file mode 100644
index 000000000..e8f4d081f
--- /dev/null
+++ b/Week04/.idea/leetcode/editor.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week04/.idea/misc.xml b/Week04/.idea/misc.xml
new file mode 100644
index 000000000..399908725
--- /dev/null
+++ b/Week04/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week04/.idea/modules.xml b/Week04/.idea/modules.xml
new file mode 100644
index 000000000..a4d2b3c8b
--- /dev/null
+++ b/Week04/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week04/.idea/vcs.xml b/Week04/.idea/vcs.xml
new file mode 100644
index 000000000..6c0b86358
--- /dev/null
+++ b/Week04/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week04/.idea/workspace.xml b/Week04/.idea/workspace.xml
new file mode 100644
index 000000000..2f3f2f57b
--- /dev/null
+++ b/Week04/.idea/workspace.xml
@@ -0,0 +1,837 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1593440885794
+
+
+ 1593440885794
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/每日一题7_1_单词接龙.py
+ 62
+
+
+
+ file://$PROJECT_DIR$/每日一题7_1_单词接龙.py
+ 61
+
+
+
+ file://$PROJECT_DIR$/每日一题7_1_单词接龙.py
+ 63
+
+
+
+ file://$PROJECT_DIR$/每日一题7_1_单词接龙.py
+ 66
+
+
+
+ file://$PROJECT_DIR$/每日一题7_1_单词接龙.py
+ 67
+
+
+
+ file://$PROJECT_DIR$/每日一题7_1_单词接龙.py
+ 68
+
+
+
+ file://$PROJECT_DIR$/每日一题7_1_单词接龙.py
+ 69
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_买卖股票的最佳时机.py
+ 20
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_买卖股票的最佳时机.py
+ 21
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_买卖股票的最佳时机.py
+ 22
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_买卖股票的最佳时机.py
+ 29
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 4
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 5
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 7
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 8
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 9
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 11
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 10
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 14
+
+
+
+ file://$PROJECT_DIR$/每日一题7_2_零钱兑换.py
+ 32
+
+
+
+ file://$PROJECT_DIR$/每日一题7_6_不同路径II.py
+ 15
+
+
+
+ file://$PROJECT_DIR$/每日一题7_6_不同路径II.py
+ 16
+
+
+
+ file://$PROJECT_DIR$/每日一题7_6_不同路径II.py
+ 17
+
+
+
+ file://$PROJECT_DIR$/每日一题7_6_不同路径II.py
+ 18
+
+
+
+ file://$PROJECT_DIR$/每日一题7_6_不同路径II.py
+ 28
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week04/NOTE.md b/Week04/NOTE.md
index 50de30414..907cacf8c 100644
--- a/Week04/NOTE.md
+++ b/Week04/NOTE.md
@@ -1 +1,251 @@
-学习笔记
\ No newline at end of file
+学习笔记
+
+#### 二叉树的层序遍历
+1.BFS 与一般的层序遍历相比 只是要求同一层的元素放在同一个[]中 需要对之前的模板进行改造
+```python
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Solution:
+ # 由于题目限制了最后打印输出格式每一层节点放在[]中,所以需要对普通的层序遍历进行调整
+ # 在while quene循环中加入一个cur_layer记录当前层的节点以确保每次都能将该层的元素加入
+ def levelOrder(self, root: TreeNode) -> List[List[int]]:
+ if not root: return []
+ quene,res = [root],[]
+ while quene:
+ cur_layer = []
+ for _ in range(len(quene)):#确保将每一层的元素都加入cur_layer
+ cur = quene.pop(0)
+ if cur.left: quene.append(cur.left)
+ if cur.right: quene.append(cur.right)
+ cur_layer.append(cur.val)
+ res.append(cur_layer)
+ return res
+```
+2.DFS既然能够遍历整树的所有节点,如果需要按模板输出,需要在递归过程中记录当前树的深度,然后将该节点加入到res的对应部分
+```python
+class Solution:
+ def levelOrder(self, root: TreeNode) -> List[List[int]]:
+ #如果用DFS做,当然也可以得到想要的结果,只是要注意的是,遍历过程中,需要记录该节点的深度
+ # 以便将它加入到res对应下标的位置
+ res = []
+ self.dfs(root, 0, res)
+ return res
+
+ def dfs(self, root, level, res):
+ # recursion terminator
+ if not root: return
+ #process current level
+ if len(res) == level: res.append([])#在开始遍历时,生成一个[]位置,4接收参数
+ res[level].append(root.val)
+ #drill down
+ if root.left: self.dfs(root.left, level + 1, res)
+ if root.right: self.dfs(root.right, level + 1, res)
+```
+
+#### 最小基因变化
+1.BFS
+```python
+# 1.BFS 所谓BFS就是类似二叉树BFS我们使用deque的非递归实现
+import collections
+def isChangeOnce(cur,next):
+ changes = 0
+ for i in range(len(next)):
+ if next[i]==cur[i]:
+ changes = changes + 1
+ return changes == 1#但是可以不必要全部遍历完,大于1的时候就可以直接返回
+
+class Solution(object):
+ def minMutation(self, start, end, bank):
+ """
+ :type start: str
+ :type end: str
+ :type bank: List[str]
+ :rtype: int
+ """
+ quene = collections.deque()
+ quene.append((start,start,0))#cur,pre,steps
+ while quene:
+ cur,pre,steps = quene.popleft()
+ if cur == end:
+ return steps
+ for gene in bank:
+ if isChangeOnce(cur,gene) and gene != pre:
+ quene.append((gene,cur,steps+1))
+ return -1
+```
+
+2.DFS 回溯法
+从bank中挑选出于cur只有一个bit差异且之前没有访问过的元素,先将其加入visited,继续判断此时的cur是否与target相同
+```python
+rom typing import List
+class SolutionI:
+ def minMutation(self, start: str, end: str, bank: List[str]) -> int:
+ visited = set()
+ self.res = float('inf')
+ if end not in bank: return -1
+ def dfs(cur, step):
+ # recursion terminator
+ if cur == end:
+ self.res = min(self.res, step)
+ return
+ #current level process
+ for next in bank:
+ if next not in visited and isChangeOnce(cur, next):
+ visited.add(next)
+ # drill down
+ dfs(next, step+1)
+ # reverse state
+ visited.remove(next)
+ visited.add(start)
+ dfs(start, 0)
+ return self.res if self.res < float('inf') else -1
+```
+
+#### 每个树行的最大值
+```python
+class Solution(object):
+ def largestValues(self, root):
+ """
+ :type root: TreeNode
+ :rtype: List[int]
+ """
+ # 1. 思想比较简单 在二叉树的层序遍历的基础上 对每一列表求最大值后返回
+ # 2. 当然也可以在遍历过程中记录每一层的最大值
+ if not root: return []
+ quene, res = [root], []
+ while quene:
+ cur_layer = []
+ # layer_max = float('-inf')
+ for _ in range(len(quene)):
+ cur = quene.pop(0)
+ if cur.left: quene.append(cur.left)
+ if cur.right: quene.append(cur.right)
+ # layer_max = max(layer_max, cur.val)
+ cur_layer.append(cur.val)
+ res.append(cur_layer)
+ # res.append(layer_max)
+ return [max(item) for item in res]
+ # return res
+```
+其中,如果以后再遇到这样的判别
+`if not root: return []`后面接`while`循环,就直接使用如下形式
+```python
+class Solution:
+ def largestValues(self, root: TreeNode) -> List[int]:
+ # if not root: return []
+ quene, res = [root], []
+ while any(quene):
+ # cur_layer = []
+ layer_max = float('-inf')
+ for _ in range(len(quene)):
+ cur = quene.pop(0)
+ if cur.left: quene.append(cur.left)
+ if cur.right: quene.append(cur.right)
+ layer_max = max(layer_max,cur.val)
+ # cur_layer.append(cur.val)
+ # res.append(cur_layer)
+ res.append(layer_max)
+ # return [max(item) for item in res]
+ return res
+```
+最后给一段极简python代码
+```python
+class Solution:
+ def largestValues(self, root: TreeNode) -> List[int]:
+ maxes = []
+ row = [root]
+ while any(row):
+ maxes.append(max(node.val for node in row))
+ row = [kid for node in row for kid in (node.left, node.right) if kid]
+ return maxes
+```
+
+
+#### 两个栈实现队列
+主要是要考虑从队首删除元素的情形
+```python
+class CQueue(object):
+ def __init__(self):
+ self.in_stack, self.out_stack = [],[]
+
+ def appendTail(self, value):
+ self.in_stack.append(value)
+
+ def deleteHead(self):
+ """
+ 删除的时候有几点要考虑,
+ 1.如果out_stack中有元素,说明是上一次删除没有删除完的,最优先删除
+ 2.如果out_stack中元素全部删除后,in_stack中没有元素,则无法删除返回-1
+ 3.如果in_stack中有元素,将其全部转移到out_stack中,返回pop()值
+ """
+ if self.out_stack: return self.out_stack.pop()
+ if not self.in_stack: return -1
+ while self.in_stack:
+ self.out_stack.append(self.in_stack.pop())
+ return self.out_stack.pop()
+```
+
+
+#### 单词接龙
+
+#### 岛屿数量
+
+#### 岛屿最大面积
+
+#### 岛屿周长
+
+#### 买卖股票的最佳时机I
+
+#### 买卖股票的最佳时机II
+
+#### 有序矩阵中的第K小的值
+1.暴力法 时间复杂度O(N^2),空间复杂度O(N^2)
+```python
+def kthSmallestI(self, matrix: List[List[int]], k: int) -> int:
+ # 1.暴力法 时间复杂度O(N^2) 空间复杂度为O(N^2)
+ tmp = [x for item in matrix for x in item]
+ tmp.sort()
+ return tmp[-(len(tmp) - k + 1)]
+```
+2.借助小根堆 时间复杂度O(klogN),空间复杂度O(N)
+```python
+def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
+ size = len(matrix)
+ pq = [(matrix[i][0],i,0) for i in range(size)]# 维护一个最小元素队列 (i,0) means location
+ heapq.heapify(pq)
+ for i in range(k-1):#第k次pop的元素直接返回
+ num, row, col = heapq.heappop(pq)
+ if col != size - 1:
+ heapq.heappush(pq,(matrix[row][col+1],row,col+1))#如果某行没有全部删除,将当前值右边的元素如堆
+ # now time = k
+ return heapq.heappop(pq)[0]
+```
+3.双指针 时间复杂度O(Nlog(max-min)),空间复杂度O(1)
+```python
+def kthSmallestII(self, matrix: List[List[int]], k: int) -> int:
+ #双指针 时间复杂度O(Nlog(max-min))
+ # n次双指针,每次判断矩阵左侧小于num的数的个数,大于k个则右指针已动到mid
+ rows, cols = len(matrix), len(matrix[0])
+ def check(num):
+ i, j, count = rows - 1, 0, 0
+ while i >= 0 and j < cols:
+ if matrix[i][j] <= num:
+ count = count + i + 1 # 一竖行都小于
+ j = j + 1
+ else: # 如果大于num,这一层没有比num小的了
+ i = i - 1
+ return count >= k
+
+ left_up, right_down = matrix[0][0], matrix[rows - 1][cols - 1]
+ while left_up < right_down:
+ mid = (left_up + right_down) // 2
+ if check(mid):
+ right_down = mid # 左边有大于k个数,那么第k小的数肯定在左边
+ else: # 左边没有k个数
+ left_up = mid + 1
+ return left_up
+```
diff --git "a/Week04/[367]\346\257\217\346\227\245\344\270\200\351\242\2307_5_\346\234\211\346\225\210\347\232\204\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py" "b/Week04/[367]\346\257\217\346\227\245\344\270\200\351\242\2307_5_\346\234\211\346\225\210\347\232\204\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py"
new file mode 100644
index 000000000..9459cba12
--- /dev/null
+++ "b/Week04/[367]\346\257\217\346\227\245\344\270\200\351\242\2307_5_\346\234\211\346\225\210\347\232\204\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py"
@@ -0,0 +1,25 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/5 10:44 PM
+
+class Solution:
+ def isPerfectSquare(self, num: int) -> bool:
+ # 二分法
+ # left, right, res = 0, num//2+1, 0
+ # while left <= right:
+ # mid = (left+right)//2
+ # if mid*mid < num:
+ # left = mid + 1
+ # elif mid*mid >num:
+ # right = mid - 1
+ # else:
+ # res = mid
+ # break
+ # return res**2 == num
+ # 拟牛顿法
+ if num < 2: return True
+ x = num // 2
+ while x * x > num:
+ x = (x + num // x) // 2
+ return x * x == num
+
diff --git "a/Week04/[69]\346\257\217\346\227\245\344\270\200\351\242\2307_5_x\347\232\204\345\271\263\346\226\271\346\240\271.py" "b/Week04/[69]\346\257\217\346\227\245\344\270\200\351\242\2307_5_x\347\232\204\345\271\263\346\226\271\346\240\271.py"
new file mode 100644
index 000000000..208f0d783
--- /dev/null
+++ "b/Week04/[69]\346\257\217\346\227\245\344\270\200\351\242\2307_5_x\347\232\204\345\271\263\346\226\271\346\240\271.py"
@@ -0,0 +1,28 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/5 10:27 PM
+
+class Solution:
+ def mySqrt(self, x: int) -> int:
+ #1.换底公式求解
+ # if x == 0: return 0
+ # res = int(math.exp(0.5 * math.log(x)))
+ # return res + 1 if (res + 1) ** 2 <= x else res
+ #2.二分法
+ # left, right, = 0, x
+ # while left <= right:
+ # mid = (left + right) // 2
+ # if mid ** 2 <= x: # x的整数部分的平方<=x
+ # res, left = mid, mid + 1
+ # else:
+ # right = mid - 1
+ # return res
+ #3.牛顿法迭代求解
+ if x == 0: return 0
+ x0 = A = float(x)
+ while True:
+ x1 = (x0 + A/x0)//2
+ if abs(x1-x0)<1e-6:
+ break
+ x0 = x1
+ return int(x0)
\ No newline at end of file
diff --git "a/Week04/\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252.py" "b/Week04/\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252.py"
new file mode 100644
index 000000000..547b71514
--- /dev/null
+++ "b/Week04/\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252.py"
@@ -0,0 +1,66 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/30 3:08 AM
+
+from typing import List
+class Solution:
+ def searchRangeI(self, nums: List[int], target: int) -> List[int]:
+ if not nums: return [-1, -1]
+ def search(left, right, bound):
+ while left <= right:
+ mid = left + ((right - left) >> 1)
+ if nums[mid] == target:
+ if bound == 0:
+ if mid == bound or nums[mid - 1] != target:
+ return mid
+ else: right = mid - 1
+ else:
+ if mid == bound or nums[mid+1] != target:
+ return mid
+ else: left = mid + 1
+ elif nums[mid] < target:
+ left = mid + 1
+ else:
+ right = mid - 1
+ return -1
+
+ size = len(nums)
+ p1 = search(0, size - 1, 0)
+ p2 = search(0, size - 1, size - 1)
+ return [p1,p2]
+ def searchRange(self, nums: List[int], target: int) -> List[int]:
+ # 1.要考虑到如果该数字不存在的情形
+ if not nums: return [-1, -1]
+ def search_left(left,right):
+ while left <= right:
+ mid = left + ((right - left) >> 1)
+ if nums[mid] == target:
+ if mid == 0 or nums[mid-1] != target:
+ return mid
+ else: right = mid - 1
+ elif nums[mid] < target:
+ left = mid + 1
+ else:
+ right = mid - 1
+ return -1
+ def search_right(left,right):
+ while left <= right:
+ mid = left + ((right - left) >> 1)
+ if nums[mid] == target:
+ if mid == size-1 or nums[mid+1] != target:
+ return mid
+ else: left = mid + 1
+ elif nums[mid] < target:
+ left = mid + 1
+ else:
+ right = mid - 1
+ return -1
+ size = len(nums)
+ p1 = search_left(0,size-1)
+ p2 = search_right(0,size-1)
+ return [p1,p2]
+s = Solution()
+nums = [5,7,7,8,8,10]
+# nums = [1]
+res = s.searchRangeI(nums,8)
+print(res)
\ No newline at end of file
diff --git "a/Week04/\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204.py" "b/Week04/\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204.py"
new file mode 100644
index 000000000..f86509328
--- /dev/null
+++ "b/Week04/\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204.py"
@@ -0,0 +1,23 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/1 10:06 PM
+
+from typing import List
+class Solution:
+ def findLength(self, A: List[int], B: List[int]) -> int:
+ res = 0
+ for i in range(len(A)):
+ for j in range(len(B)):
+ k = 0
+ while i+k < len(a) and j+k < len(B) and A[i+k] == B[j+k]:
+ k = k + 1
+ res = max(res,k)
+ return res
+
+s = Solution()
+a = [1,2,3,2,1]
+b = [3,2,1,4,7]
+res = s.findLength(a,b)
+print(res)
+
+
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_29_\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_29_\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py"
new file mode 100644
index 000000000..b776bf03a
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_29_\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py"
@@ -0,0 +1,38 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/29 10:29 PM
+from typing import List
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+class Solution:
+ # 由于题目限制了最后打印输出格式每一层节点放在[]中,所以需要对普通的层序遍历进行调整
+ # 在while quene循环中加入一个cur_layer记录当前层的节点以确保每次都能将该层的元素加入
+ def levelOrder(self, root: TreeNode) -> List[List[int]]:
+ # if not root: return []
+ # quene,res = [root],[]
+ # while quene:
+ # cur_layer = []
+ # for _ in range(len(quene)):
+ # cur = quene.pop(0)
+ # if cur.left: quene.append(cur.left)
+ # if cur.right: quene.append(cur.right)
+ # cur_layer.append(cur.val)
+ # res.append(cur_layer)
+ # return res
+
+ #如果用DFS做,当然也可以得到想要的结果,只是要注意的是,遍历过程中,需要记录该节点的深度
+ # 以便将它加入到res对应下标的位置
+ res = []
+ self.dfs(root, 0, res)
+ return res
+
+ def dfs(self, root, level, res):
+ if not root: return
+ if len(res) == level: res.append([])#在开始遍历时,生成一个[]位置,4接收参数
+ res[level].append(root.val)
+ if root.left: self.dfs(root.left, level + 1, res)
+ if root.right: self.dfs(root.right, level + 1, res)
\ No newline at end of file
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274.py"
new file mode 100644
index 000000000..c1aeb9eb4
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274.py"
@@ -0,0 +1,55 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/30 1:06 AM
+
+# 您需要在二叉树的每一行中找到最大的值。
+#
+# 示例:
+#
+#
+# 输入:
+#
+# 1
+# / \
+# 3 2
+# / \ \
+# 5 3 9
+#
+# 输出: [1, 3, 9]
+#
+# Related Topics 树 深度优先搜索 广度优先搜索
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+# Definition for a binary tree node.
+# class TreeNode(object):
+# def __init__(self, x):
+# self.val = x
+# self.left = None
+# self.right = None
+
+class Solution(object):
+ def largestValues(self, root):
+ """
+ :type root: TreeNode
+ :rtype: List[int]
+ """
+ # 1. 思想比较简单 在二叉树的层序遍历的基础上 对每一列表求最大值后返回
+ # 2. 当然也可以在遍历过程中记录每一层的最大值
+ if not root: return []
+ quene, res = [root], []
+ while quene:
+ cur_layer = []
+ # layer_max = float('-inf')
+ for _ in range(len(quene)):
+ cur = quene.pop(0)
+ if cur.left: quene.append(cur.left)
+ if cur.right: quene.append(cur.right)
+ # layer_max = max(layer_max, cur.val)
+ cur_layer.append(cur.val)
+ res.append(cur_layer)
+ # res.append(layer_max)
+ return [max(item) for item in res]
+ # return res
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py"
new file mode 100644
index 000000000..4301aafbc
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py"
@@ -0,0 +1,130 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/30 12:19 AM
+
+# 一条基因序列由一个带有8个字符的字符串表示,其中每个字符都属于 "A", "C", "G", "T"中的任意一个。
+#
+# 假设我们要调查一个基因序列的变化。一次基因变化意味着这个基因序列中的一个字符发生了变化。
+#
+# 例如,基因序列由"AACCGGTT" 变化至 "AACCGGTA" 即发生了一次基因变化。
+#
+# 与此同时,每一次基因变化的结果,都需要是一个合法的基因串,即该结果属于一个基因库。
+#
+# 现在给定3个参数 — start, end, bank,分别代表起始基因序列,目标基因序列及基因库,请找出能够使起始基因序列变化为目标基因序列所需的最少变
+# 化次数。如果无法实现目标变化,请返回 -1。
+#
+# 注意:
+#
+#
+# 起始基因序列默认是合法的,但是它并不一定会出现在基因库中。
+# 所有的目标基因序列必须是合法的。
+# 假定起始基因序列与目标基因序列是不一样的。
+#
+#
+# 示例 1:
+#
+#
+# start: "AACCGGTT"
+# end: "AACCGGTA"
+# bank: ["AACCGGTA"]
+#
+# 返回值: 1
+#
+#
+# 示例 2:
+#
+#
+# start: "AACCGGTT"
+# end: "AAACGGTA"
+# bank: ["AACCGGTA", "AACCGCTA", "AAACGGTA"]
+#
+# 返回值: 2
+#
+#
+# 示例 3:
+#
+#
+# start: "AAAAACCC"
+# end: "AACCCCCC"
+# bank: ["AAAACCCC", "AAACCCCC", "AACCCCCC"]
+#
+# 返回值: 3
+#
+#
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+
+
+# 1.BFS 所谓BFS就是类似二叉树BFS我们使用deque的非递归实现
+import collections
+def isChangeOnce(cur,next):#时间复杂度是O(K),K是bank中字符的长度
+ changes = 0
+ for i in range(len(next)):
+ if next[i]==cur[i]:
+ changes = changes + 1
+ return changes == 1#但是可以不必要全部遍历完,大于1的时候就可以直接返回
+
+class Solution(object):
+ def minMutation(self, start, end, bank):
+ """
+ 对于每一个节点都要去找与它只相差一个的元素list,然后与这个list中所有元素进行比较,然后继续去找相差1的元素
+ 时间复杂度是O(N)*O(N)*O(K)*
+ :type start: str
+ :type end: str
+ :type bank: List[str]
+ :rtype: int
+ """
+ # quene = collections.deque()
+ # quene.append((start,start,0))#cur,pre,steps
+ # while quene:
+ # cur,pre,steps = quene.popleft()
+ # if cur == end:
+ # return steps
+ # for gene in bank:#bank长度
+ # if isChangeOnce(cur,gene) and gene != pre:
+ # quene.append((gene,cur,steps+1))
+ # return -1
+ queue = []
+ queue.append((start, 0))
+ visited = set(bank)
+ while queue:
+ cur, step = queue.pop(0)
+ if cur == end:
+ return step
+ for i in range(len(cur)):
+ for c in "AGCT": #
+ mutation = cur[:i] + c + cur[i + 1:] # 列举出所有可能的变化为1的基因串
+ if mutation in visited:
+ visited.remove(mutation)
+ queue.append((mutation, step + 1))
+ return -1
+
+
+
+# 2.DFS 回溯
+from typing import List
+class SolutionI:
+ def minMutation(self, start: str, end: str, bank: List[str]) -> int:
+ visited = set()
+ self.res = float('inf')
+ if end not in bank: return -1
+ def dfs(cur, step):
+ # recursion terminator
+ if cur == end:
+ self.res = min(self.res, step)
+ return
+ #current level process
+ for next in bank:
+ if next not in visited and isChangeOnce(cur, next):
+ visited.add(next)
+ # drill down
+ dfs(next, step+1)
+ # reverse state
+ visited.remove(next)
+ visited.add(start)
+ dfs(start, 0)
+ return self.res if self.res < float('inf') else -1
+
+
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\347\224\250\344\270\244\344\270\252\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\347\224\250\344\270\244\344\270\252\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.py"
new file mode 100644
index 000000000..b1e2a4351
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2306_30_\347\224\250\344\270\244\344\270\252\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.py"
@@ -0,0 +1,63 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/30 7:14 PM
+
+# 用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的
+# 功能。(若队列中没有元素,deleteHead 操作返回 -1 )
+#
+#
+#
+# 示例 1:
+#
+# 输入:
+# ["CQueue","appendTail","deleteHead","deleteHead"]
+# [[],[3],[],[]]
+# 输出:[null,null,3,-1]
+#
+#
+# 示例 2:
+#
+# 输入:
+# ["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
+# [[],[],[5],[2],[],[]]
+# 输出:[null,-1,null,null,5,2]
+#
+#
+# 提示:
+#
+#
+# 1 <= values <= 10000
+# 最多会对 appendTail、deleteHead 进行 10000 次调用
+#
+# Related Topics 栈 设计
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+class CQueue(object):
+
+ def __init__(self):
+ self.in_stack, self.out_stack = [],[]
+
+ def appendTail(self, value):
+ self.in_stack.append(value)
+
+ def deleteHead(self):
+ """
+ 删除的时候有几点要考虑,
+ 1.如果out_stack中有元素,说明是上一次删除没有删除完的,最优先删除
+ 2.如果out_stack中元素全部删除后,in_stack中没有元素,则无法删除返回-1
+ 3.如果in_stack中有元素,将其全部转移到out_stack中,返回pop()值
+ """
+ if self.out_stack: return self.out_stack.pop()
+ if not self.in_stack: return -1
+ while self.in_stack:
+ self.out_stack.append(self.in_stack.pop())
+ return self.out_stack.pop()
+
+
+
+# Your CQueue object will be instantiated and called as such:
+# obj = CQueue()
+# obj.appendTail(value)
+# param_2 = obj.deleteHead()
+# leetcode submit region end(Prohibit modification and deletion)
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_1_\345\215\225\350\257\215\346\216\245\351\276\231.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_1_\345\215\225\350\257\215\346\216\245\351\276\231.py"
new file mode 100644
index 000000000..49ea3a051
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_1_\345\215\225\350\257\215\346\216\245\351\276\231.py"
@@ -0,0 +1,179 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/6/30 1:18 AM
+
+# 给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
+#
+#
+#
+# 每次转换只能改变一个字母。
+# 转换过程中的中间单词必须是字典中的单词。
+#
+#
+# 说明:
+#
+#
+# 如果不存在这样的转换序列,返回 0。
+# 所有单词具有相同的长度。
+# 所有单词只由小写字母组成。
+# 字典中不存在重复的单词。
+# 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
+#
+#
+# 示例 1:
+#
+# 输入:
+# beginWord = "hit",
+# endWord = "cog",
+# wordList = ["hot","dot","dog","lot","log","cog"]
+#
+# 输出: 5
+#
+# 解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
+# 返回它的长度 5。
+#
+#
+# 示例 2:
+#
+# 输入:
+# beginWord = "hit"
+# endWord = "cog"
+# wordList = ["hot","dot","dog","lot","log"]
+#
+# 输出: 0
+#
+# 解释: endWord "cog" 不在字典中,所以无法进行转换。
+# Related Topics 广度优先搜索
+
+
+# leetcode submit region begin(Prohibit modification and deletion)
+def isChangeOnce(cur, pre):
+ changes = 0
+ for i in range(len(cur)):
+ if cur[i] != pre[i]:
+ changes += 1
+ if changes > 1: return False
+ return True
+
+from typing import List
+class Solution:
+ def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
+ # bfs,用deque实现,就不用递归
+ quene = [(beginWord, beginWord, 0, [beginWord])] # cur,pre,steps,path
+ while quene:
+ cur, pre, steps,path = quene.pop(0)
+ if cur == endWord:
+ return len(path)
+ for word in wordList:
+ if isChangeOnce(word, cur) and word != pre:
+ quene.append((word, cur, steps + 1, path+[word]))
+ return 0 # 不存在这样的转换序列
+
+# leetcode submit region end(Prohibit modification and deletion)
+
+
+from collections import defaultdict
+class SolutionI(object):
+ def ladderLength(self, beginWord, endWord, wordList):
+ if endWord not in wordList or not endWord or not beginWord or not wordList:
+ return 0
+ size = len(beginWord)
+ all_combo_dict = defaultdict(list)
+ for word in wordList:#M
+ for i in range(size):#N
+ #'*ot': ['hot', 'dot', 'lot']
+ all_combo_dict[word[:i] + "*" + word[i+1:]].append(word)
+ queue = [(beginWord, 1)]
+ visited = {beginWord: True}
+ while queue:
+ current_word, level = queue.pop(0)
+ for i in range(size):#遍历当前节点可能的one_differ类型
+ intermediate_word = current_word[:i] + "*" + current_word[i+1:]
+ #确定one_differ类型,并查探可能的下一个节点
+ for word in all_combo_dict[intermediate_word]:
+ #如果这个节点就是最后节点,返回
+ if word == endWord:
+ return level + 1
+ #如果不是最后节点,就将它作为当前节点,向后探查
+ if word not in visited:
+ visited[word] = True
+ queue.append((word, level + 1))
+ #将已经访问过的'*ot': ['hot', 'dot', 'lot']这种构型 删除掉
+ all_combo_dict[intermediate_word] = []
+ return 0
+
+# from collections import defaultdict
+class SolutionII(object):
+ def __init__(self):
+ self.size = 0
+ # Dictionary to hold combination of words that can be formed,
+ # from any given word. By changing one letter at a time.
+ self.all_combo_dict = defaultdict(list)
+
+ def visitWordNode(self, queue, visited, others_visited):
+ current_word, level = queue.pop(0)
+ for i in range(self.size):
+ intermediate_word = current_word[:i] + "*" + current_word[i+1:]
+ for word in self.all_combo_dict[intermediate_word]:
+ # If the intermediate state/word has already been visited from the
+ # other parallel traversal this means we have found the answer.
+ if word in others_visited:
+ return level + others_visited[word]
+ if word not in visited:
+ # Save the level as the value of the dictionary, to save number of hops.
+ visited[word] = level + 1
+ queue.append((word, level + 1))
+ return None
+
+ def ladderLength(self, beginWord, endWord, wordList):
+ if endWord not in wordList or not endWord or not beginWord or not wordList:
+ return 0
+ self.size = len(beginWord)
+ for word in wordList:
+ for i in range(self.size):
+ #'*ot': ['hot', 'dot', 'lot']
+ self.all_combo_dict[word[:i] + "*" + word[i+1:]].append(word)
+ # Queues for birdirectional BFS
+ queue_begin = [(beginWord, 1)] # BFS starting from beginWord
+ queue_end = [(endWord, 1)] # BFS starting from endWord
+ # Visited to make sure we don't repeat processing same word
+ visited_begin = {beginWord: 1}
+ visited_end = {endWord: 1}
+ res = None
+ # We do a birdirectional search starting one pointer from begin
+ # word and one pointer from end word. Hopping one by one.
+ while queue_begin and queue_end:
+ # One hop from begin word
+ res = self.visitWordNode(queue_begin, visited_begin, visited_end)
+ if res:
+ return res
+ # One hop from end word
+ res = self.visitWordNode(queue_end, visited_end, visited_begin)
+ if res:
+ return res
+
+ return 0
+
+
+
+
+# beginWord = "hot"
+beginWord = "hit"
+# endWord = "dog"
+endWord = "cog"
+wordList = ["hot","dot","dog","lot","log","cog"]
+# wordList = ["hot","dog","dot"]
+
+# s = Solution()
+# res = s.ladderLength(beginWord,endWord,wordList)
+# print(res)
+
+from collections import defaultdict
+ddict = defaultdict(list)
+for word in wordList:#M
+ for i in range(3):#N
+ # Key is the generic word
+ # Value is a list of words which have the same intermediate generic word.
+ ddict[word[:i] + "*" + word[i+1:]].append(word)
+
+print(ddict)
\ No newline at end of file
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_1_\345\262\233\345\261\277\346\225\260\351\207\217.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_1_\345\262\233\345\261\277\346\225\260\351\207\217.py"
new file mode 100644
index 000000000..b635c639c
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_1_\345\262\233\345\261\277\346\225\260\351\207\217.py"
@@ -0,0 +1,64 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/1 9:26 PM
+
+from typing import List
+class Solution:
+ '''
+ 将二维网格视作一个无向图,竖直或水平相邻的'1'右边
+ 遍历这个二维网格,如果某点='1',则以该点做深度优先搜索
+ 在深度优先搜索过程中,将已经访问过的节点标记为'0' 最后的岛屿数量就是待求值
+ 深度优先过程中,我们考察该点十字型结构有没有等于1的,进而深度遍历
+ 时间复杂度是O(MN),最坏情况下的空间复杂度为O(MN),此时整个二维网格全为1
+ '''
+ #深度优先搜索
+ def numIslands(self, grid: List[List[str]]) -> int:
+ rows = len(grid)
+ if rows == 0: return 0
+ cols = len(grid[0])
+ islands = 0
+ for i in range(rows):
+ for j in range(cols):
+ if grid[i][j] == '1':
+ self.dfs(grid, i, j)
+ islands += 1
+ return islands
+
+ def dfs(self, grid, i, j):
+ if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or grid[i][j] != '1':
+ return
+ grid[i][j] = '0'
+ self.dfs(grid, i + 1, j)
+ self.dfs(grid, i - 1, j)
+ self.dfs(grid, i, j + 1)
+ self.dfs(grid, i, j - 1)
+ #广度优先搜索
+ # 维护一个队列,做广度优先搜索,搜索其十字型中是否为'1',是则加入队列中
+ # 最后返回的结果就是我们广度搜索的次数
+ def numIslandsI(self, grid: List[List[str]]) -> int:
+ rows = len(grid)
+ if rows == 0: return 0
+ cols = len(grid[0])
+ count = 0
+ quene = []
+ for i in range(rows):
+ for j in range(cols):
+ if grid[i][j] == '1':
+ count = count + 1
+ quene.append((i, j))
+ while quene:
+ row, col = quene.pop()
+ if col + 1 < cols and grid[row][col + 1] == '1':
+ quene.append((row, col + 1))
+ grid[row][col + 1] = 0
+ if col - 1 >= 0 and grid[row][col - 1] == '1':
+ quene.append((row, col - 1))
+ grid[row][col - 1] = 0
+ if row - 1 >= 0 and grid[row - 1][col] == '1':
+ quene.append((row - 1, col))
+ grid[row - 1][col] = 0
+ if row + 1 < rows and grid[row + 1][col] == '1':
+ quene.append((row + 1, col))
+ grid[row + 1][col] = 0
+ return count
+
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.py"
new file mode 100644
index 000000000..96761882e
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.py"
@@ -0,0 +1,31 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/1 11:50 PM
+
+from typing import List
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ #1.暴力法 超出时间限制O(N^2)
+ res = 0
+ for i in range(len(prices)-1,0,-1):
+ for j in range(i-1,-1,-1):
+ diff = prices[i]-prices[j]#计算差值
+ if diff > 0:
+ res = max(res,diff)
+ return res
+
+ def maxProfitI(self, prices: List[int]) -> int:
+ inf = int(1e9)
+ minprice = inf
+ maxprofit = 0
+ for price in prices:
+ maxprofit = max(price - minprice, maxprofit)
+ minprice = min(price, minprice)
+ return maxprofit
+
+
+
+s = Solution()
+nums = [7,1,5,3,6,4]
+res = s.maxProfitI(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\346\234\211\345\272\217\347\237\251\351\230\265\344\270\255\347\232\204\347\254\254k\345\260\217\347\232\204\345\200\274.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\346\234\211\345\272\217\347\237\251\351\230\265\344\270\255\347\232\204\347\254\254k\345\260\217\347\232\204\345\200\274.py"
new file mode 100644
index 000000000..51d98f99e
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\346\234\211\345\272\217\347\237\251\351\230\265\344\270\255\347\232\204\347\254\254k\345\260\217\347\232\204\345\200\274.py"
@@ -0,0 +1,49 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/2 7:25 PM
+import heapq
+from typing import List
+class Solution:
+ #优秀的解释 时间复杂度是 O(KlogN)空间复杂度O(N)
+ # https://leetcode-cn.com/problems/kth-smallest-element-in-a-sorted-matrix/solution/shi-yong-dui-heapde-si-lu-xiang-jie-ling-fu-python/
+ def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
+ size = len(matrix)
+ pq = [(matrix[i][0],i,0) for i in range(size)]# 维护一个最小元素队列 (i,0) means location
+ heapq.heapify(pq)
+ for i in range(k-1):#第k次pop的元素直接返回
+ num, row, col = heapq.heappop(pq)
+ if col != size - 1:
+ heapq.heappush(pq,(matrix[row][col+1],row,col+1))#如果某行没有全部删除,将当前值右边的元素如堆
+ # now time = k
+ return heapq.heappop(pq)[0]
+
+ def kthSmallestI(self, matrix: List[List[int]], k: int) -> int:
+ # 1.暴力法 时间复杂度O(N^2) 空间复杂度为O(N^2)
+ tmp = [x for item in matrix for x in item]
+ tmp.sort()
+ return tmp[-(len(tmp) - k + 1)]
+
+ def kthSmallestII(self, matrix: List[List[int]], k: int) -> int:
+ #双指针 时间复杂度O(Nlog(max-min))
+ # n次双指针,每次判断矩阵左侧小于num的数的个数,大于k个则右指针已动到mid
+ rows, cols = len(matrix), len(matrix[0])
+ def check(num):
+ i, j, count = rows - 1, 0, 0
+ while i >= 0 and j < cols:
+ if matrix[i][j] <= num:
+ count = count + i + 1 # 一竖行都小于
+ j = j + 1
+ else: # 如果大于num,这一层没有比num小的了
+ i = i - 1
+ return count >= k
+
+ left_up, right_down = matrix[0][0], matrix[rows - 1][cols - 1]
+ while left_up < right_down:
+ mid = (left_up + right_down) // 2
+ if check(mid):
+ right_down = mid # 左边有大于k个数,那么第k小的数肯定在左边
+ else: # 左边没有k个数
+ left_up = mid + 1
+ return left_up
+
+
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\351\233\266\351\222\261\345\205\221\346\215\242.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\351\233\266\351\222\261\345\205\221\346\215\242.py"
new file mode 100644
index 000000000..cd16c55b0
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\351\233\266\351\222\261\345\205\221\346\215\242.py"
@@ -0,0 +1,34 @@
+class Solution:
+ from typing import List
+ def coinChange(self, coins: List[int], amount: int) -> int:
+ def dfs(coins, amount, i, count, res): # 如果当前coin用完了,就换面值更小的
+ if amount == 0: return min(count, res)
+ if i == -1: return res#已经遍历完所有coin
+ #current layer
+ multiple = amount//coins[i]
+ while multiple >= 0 and multiple + count < res:#这里往往是一个循环要么是for,要么是while
+ res = dfs(coins,amount-multiple*coins[i], i-1, count+multiple, res)#count用来记录上一层的组合数
+ multiple -= 1
+ return res # 回溯结束
+ if amount == 0: return 0
+ coins.sort()
+ result = dfs(coins, amount, len(coins)-1, 0, float('inf'))
+ return result if result != float('inf') else -1
+
+ #动态规划
+ def coinChangeI(self, coins: List[int], amount: int) -> int:
+ dp = [float('inf')] * (amount + 1)
+ dp[0] = 0
+ for cur in range(amount + 1):
+ for coin in coins: # 往当前位置的前[coins]个位置看,取最小的+1
+ if cur >= coin: # 如果cur bool:
+ if not bills: return True
+ five, ten = 0, 0
+ for bill in bills:
+ if bill == 5:
+ five += 1
+ elif bill == 10:
+ if five == 0: return False
+ five, ten = five - 1, ten + 1
+ else:#change 15
+ if five and ten:
+ five, ten = five - 1, ten - 1
+ elif five >= 3:
+ five = five - 3
+ else:
+ return False
+ return True
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_3_\351\245\274\345\271\262\345\210\206\345\217\221.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_3_\351\245\274\345\271\262\345\210\206\345\217\221.py"
new file mode 100644
index 000000000..4c82ebcb2
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_3_\351\245\274\345\271\262\345\210\206\345\217\221.py"
@@ -0,0 +1,18 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/3 10:08 PM
+
+class Solution:
+ #1.贪心法
+ def findContentChildren(self, A: List[int], B: List[int]) -> int:
+ A.sort()#胃口
+ B.sort()#饼干value
+ #优先满足胃口小的孩子
+ res = 0
+ i, j = 0, 0
+ while j < len(B) and i < len(A):
+ if B[j]>=A[i]:#如果当前值大于胃口值
+ res = res + 1
+ i = i + 1
+ j = j + 1
+ return res
\ No newline at end of file
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_4_\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_4_\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204.py"
new file mode 100644
index 000000000..cbee7ff2b
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_4_\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204.py"
@@ -0,0 +1,21 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/6 12:12 AM
+
+class Solution:
+ def search(self, nums: List[int], target: int) -> int:
+ if not nums: return -1
+ left, right = 0, len(nums)-1
+ while left <= right:
+ mid = (left + right)>>1
+ if target == nums[mid]:
+ return mid
+ if nums[mid] >= nums[left]:
+ if nums[left] <= target <= nums[mid]:#用两个点夹住target
+ right = mid - 1
+ else: left = mid + 1
+ else:
+ if nums[mid] <= target <= nums[right]:#用两个点夹住target
+ left = mid + 1
+ else: right = mid - 1
+ return -1
\ No newline at end of file
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204.py"
new file mode 100644
index 000000000..d1881d66d
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204.py"
@@ -0,0 +1,23 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/6 6:57 PM
+import math
+class Solution:
+ def uniquePaths(self, m: int, n: int) -> int:
+ #排列组合Cm-1,m+n-2
+ # return int(math.factorial(m + n - 2) / math.factorial(m - 1) / math.factorial(n - 1))
+ #动态规划
+ dp = [[0] * n for _ in range(m)]
+ for i in range(n):
+ dp[0][i] = 1
+ for j in range(m):
+ dp[j][0] = 1
+ for i in range(1,m):
+ for j in range(1,n):
+ dp[i][j] = dp[i-1][j] + dp[i][j-1]
+ return dp[m - 1][n - 1]
+
+m, n = 3, 7
+s = Solution()
+res = s.uniquePaths(m,n)
+print(res)
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204II.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204II.py"
new file mode 100644
index 000000000..28e273166
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204II.py"
@@ -0,0 +1,30 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/6 7:36 PM
+from typing import List
+class Solution:
+ def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
+ if not obstacleGrid or len(obstacleGrid)==0: return 0
+ m, n = len(obstacleGrid),len(obstacleGrid[0])
+ dp = [[0] * n for _ in range(m)]
+ for i in range(n):
+ if obstacleGrid[0][i]==0:
+ dp[0][i] = 1
+ for j in range(m):
+ if obstacleGrid[j][0]==0:
+ dp[j][0] = 1
+ for i in range(1,m):
+ for j in range(1,n):
+ if obstacleGrid[i][j]==0:
+ dp[i][j] = dp[i-1][j] + dp[i][j-1]
+ return dp[m - 1][n - 1]
+
+nums = [
+ [0,0,0,0,0,0],
+ [0,1,0,0,0,0],
+ [0,0,0,0,0,0]
+]
+nums1 = [[1,0]]
+s =Solution()
+res = s.uniquePathsWithObstacles(nums1)
+print(res)
\ No newline at end of file
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\272\214\345\217\211\346\240\221\350\267\257\345\276\204\346\200\273\345\222\214.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\272\214\345\217\211\346\240\221\350\267\257\345\276\204\346\200\273\345\222\214.py"
new file mode 100644
index 000000000..e47e0f71b
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\272\214\345\217\211\346\240\221\350\267\257\345\276\204\346\200\273\345\222\214.py"
@@ -0,0 +1,38 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/7 10:11 PM
+
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, x):
+ self.val = x
+ self.left = None
+ self.right = None
+
+from collections import deque
+class Solution:
+ def hasPathSum(self, root: TreeNode, num: int) -> bool:
+ #层序遍历
+ if not root: return False
+ node_quene = deque([root])
+ val_quene = deque([root.val])
+ while node_quene:
+ cur_node = node_quene.popleft()
+ cur_val = val_quene.popleft()
+ if not cur_node.left and not cur_node.right:
+ if num == cur_val:
+ return True
+ continue#如果已经是叶节点,但sum和target相同,无需执行后面的判断语句
+ if cur_node.left:
+ node_quene.append(cur_node.left)
+ val_quene.append(cur_val + cur_node.left.val)
+ if cur_node.right:
+ node_quene.append(cur_node.right)
+ val_quene.append(cur_val + cur_node.right.val)
+ return False
+ #DFS深度优先遍历 递归
+ def hasPathSumI(self, root: TreeNode, num: int) -> bool:
+ if not root: return False
+ if not root.left and not root.right:
+ return root.val == num
+ return self.hasPathSumI(root.left, num - root.val) or self.hasPathSumI(root.right, num - root.val)
diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py"
new file mode 100644
index 000000000..4f69ef606
--- /dev/null
+++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py"
@@ -0,0 +1,67 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/6 12:25 AM
+
+from typing import List
+class Solution:
+ def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
+ if not matrix: return False
+ raws = len(matrix)
+ cols = len(matrix[0])
+ if raws == 0 or cols == 0:
+ return False
+ raw, col = 0, cols - 1
+ # 方法一:从右上角开始搜索,时间复杂度为O(N+M))
+ while raw < raws and col >=0:
+ if matrix[raw][col] == target:
+ return True
+ elif matrix[raw][col] < target:
+ raw += 1
+ else:
+ col -= 1
+ return False
+ # 方法二:二分查找
+ def searchMatrixI(self, matrix: List[List[int]], target: int) -> bool:
+ if not matrix: return False
+ raws = len(matrix)
+ if len(matrix[0]) == 0: return False
+ cols = len(matrix[0])
+ if not matrix: return False
+ raws, cols = len(matrix), len(matrix[0])
+ up, bottom = 0, raws - 1
+ while up <= bottom:
+ row = (up + bottom) >> 1
+ if matrix[row][0] == target:
+ return True
+ elif matrix[row][0] < target:
+ up = row + 1
+ else:
+ bottom = row - 1
+ raw = bottom
+ left, right = 0, cols - 1
+ while left <= right:
+ mid = (left + right) >> 1
+ if matrix[raw][mid] == target:
+ return True
+ elif matrix[raw][mid] < target:
+ left = mid + 1
+ else:
+ right = mid - 1
+ return False
+ #代码简化版 二分查找
+ def searchMatrixII(self, matrix: List[List[int]], target: int) -> bool:
+ m = len(matrix)
+ if m == 0: return False
+ n = len(matrix[0])
+ left, right = 0, m * n - 1
+ while left <= right:
+ pivot_idx = (left + right) // 2
+ pivot_element = matrix[pivot_idx // n][pivot_idx % n]#刚好可以得到行列号
+ if target == pivot_element:
+ return True
+ else:
+ if target < pivot_element:
+ right = pivot_idx - 1
+ else:
+ left = pivot_idx + 1
+ return False
diff --git a/Week06/.idea/Week06.iml b/Week06/.idea/Week06.iml
new file mode 100644
index 000000000..7c9d48f0f
--- /dev/null
+++ b/Week06/.idea/Week06.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week06/.idea/misc.xml b/Week06/.idea/misc.xml
new file mode 100644
index 000000000..399908725
--- /dev/null
+++ b/Week06/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week06/.idea/modules.xml b/Week06/.idea/modules.xml
new file mode 100644
index 000000000..c96c2708b
--- /dev/null
+++ b/Week06/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week06/.idea/vcs.xml b/Week06/.idea/vcs.xml
new file mode 100644
index 000000000..6c0b86358
--- /dev/null
+++ b/Week06/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week06/.idea/workspace.xml b/Week06/.idea/workspace.xml
new file mode 100644
index 000000000..bae57ca93
--- /dev/null
+++ b/Week06/.idea/workspace.xml
@@ -0,0 +1,748 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1594649979031
+
+
+ 1594649979031
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/打家劫舍II.py
+ 14
+
+
+
+ file://$PROJECT_DIR$/打家劫舍II.py
+ 15
+
+
+
+ file://$PROJECT_DIR$/打家劫舍II.py
+ 19
+
+
+
+ file://$PROJECT_DIR$/买卖股票的最佳时机I.py
+ 38
+
+
+
+ file://$PROJECT_DIR$/买卖股票的最佳时机I.py
+ 25
+
+
+
+ file://$PROJECT_DIR$/买卖股票的最佳时机I.py
+ 26
+
+
+
+ file://$PROJECT_DIR$/买卖股票的最佳时机I.py
+ 27
+
+
+
+ file://$PROJECT_DIR$/买卖股票的最佳时机I.py
+ 28
+
+
+
+ file://$PROJECT_DIR$/买卖股票的最佳时机I.py
+ 30
+
+
+
+ file://$PROJECT_DIR$/买卖股票的最佳时机VI_手续费.py
+ 26
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week06/NOTE.md b/Week06/NOTE.md
index 50de30414..37e94b27d 100644
--- a/Week06/NOTE.md
+++ b/Week06/NOTE.md
@@ -1 +1,387 @@
-学习笔记
\ No newline at end of file
+学习笔记
+
+#### 三角形的最小路径和
+1. 分治 | 递归模板
+每次只能走它下一层的左和右,那么自然想到分治算法 F[i,j] = min(F[i+1,j],F[i+1,j+1])+a[i,j]
+写的过程中,就是递归的模板嘛 这种算法时间复杂度是O(2^N),没通过,加上缓存@lru_cache
+```python
+class Solution:
+ def minimumTotal(self, triangle: List[List[int]]) -> int:
+ # 分治 递归模板
+ from functools import lru_cache
+ @lru_cache(None)
+ def dfs(i, j):
+ #terminator
+ if i == size-1: return triangle[i][j]
+ left = dfs(i+1,j)#加左边的值
+ right = dfs(i+1,j+1)
+ min_val = min(left, right) + triangle[i][j]
+ return min_val
+ size = len(triangle)
+ return dfs(0,0)
+```
+2.DP
+DP过程:
+1) opt subproblem,这个分治算法已经帮我们解决了
+2) DP Array,合理定义DP数组的含义
+3)DP transfer equal,写出状态转移方程
+DP通常由两种,top-down和bottom-up
+还是按照分治思想,我们采用top-down的思想
+```python
+class Solution:
+ def minimumTotal(self, triangle: List[List[int]]) -> int:
+ # 2.top-down
+ dp = triangle
+ for i in range(1, len(triangle)):
+ for j in range(len(triangle[i])):
+ if j == 0:
+ dp[i][j] += triangle[i-1][j]
+ elif j == len(triangle[i])-1:
+ dp[i][j] += triangle[i-1][j-1]
+ else:
+ dp[i][j] += min(triangle[i-1][j-1], triangle[i-1][j])
+ return min(dp[-1])
+```
+可以看到上述top-down代码中有几个分支判断,这是由于能走的路径只是下三角,要考虑数组越界的情形。
+其次,上述的dp我们只是引用了,其实可以直接复用原数组
+3.bottom-up 空间复杂度只有O(N)了
+```python
+class Solution:
+ def minimumTotal(self, triangle: List[List[int]]) -> int:
+ dp = triangle[-1]
+ for i in range(len(triangle) - 2, -1, -1):
+ for j in range(len(triangle[i])):
+ dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j]
+ return dp[0]
+```
+4.复用原数组 节省空间
+```python
+class Solution:
+ def minimumTotal(self, triangle: List[List[int]]) -> int:
+ for i in range(len(triangle)-2,-1,-1):
+ for j in range(len(triangle[i])):
+ triangle[i][j] += min(triangle[i+1][j],triangle[i+1][j+1])
+ return triangle[0][0]
+```
+
+#### 最大子序和
+由于数组中有可能存在的赋负数,所以在累加的时候,如果f(i-1)+nums[i] < nums[i],就要丢弃前面f(i-1)的和了
+```python
+class Solution:
+ def maxSubArray(self, nums: List[int]) -> int:
+ dp = [0]*len(nums)
+ dp[0], max_val = nums[0], nums[0]
+ for i in range(1,len(nums)):
+ dp[i] = max(dp[i-1],0) + nums[i]
+ # max_val = max(dp[i], max_val)
+ return max(dp)
+ # return max_val
+```
+当然,这里我们也可以复用原数组
+```python
+class Solution:
+ def maxSubArray(self, nums: List[int]) -> int:
+ for i in range(1,len(nums)):
+ nums[i] = max(nums[i-1], 0) + nums[i]
+ return max(nums)
+```
+
+#### 乘积最大的子数组
+```python
+class Solution:
+ def maxProduct(self, nums: List[int]) -> int:
+ if not nums: return 0
+ if len(nums) == 1: return nums[0]
+ dp_min, dp_max = [0] * len(nums), [0] * len(nums) # dp_max记录正负交替乘法中的最大值
+ dp_min[0], dp_max[0] = nums[0], nums[0]
+ res = nums[0]
+ for i in range(1, len(nums)):
+ if nums[i] >= 0:
+ # 如果此时nums[i]大于0,如果之前是正数,那就乘上,如果是负数,那此时的最大值为此时的值
+ dp_max[i] = max(nums[i], dp_max[i - 1] * nums[i])
+ # 此时原本小于0,最小值就应该乘上nums[i];如果原本大于0,那最小的就应该是此时的值
+ dp_min[i] = min(nums[i], dp_min[i - 1] * nums[i])
+ else: # 此时nums[i]小于0
+ # 如果原本dp_min小于0,它乘上num可能是最大值;如果原来是正值,(+值*负值和负值) 中要求大值
+ dp_max[i] = max(dp_min[i - 1] * nums[i], nums[i])
+ dp_min[i] = min(dp_max[i - 1] * nums[i], nums[i])
+ res = max(res, dp_max[i])
+ return res
+```
+上面的代码看上去有些冗余,考虑是否能优化
+可以看到记录大值和小值时是用max和min,考虑以此考虑合并
+[说实话 我被这题搞吐了,气死我了😤]
+```python
+class Solution:
+ def maxProduct(self, nums: List[int]) -> int:
+ if not nums: return 0
+ if len(nums) == 1: return nums[0]
+ dp_min, dp_max = [0] * len(nums), [0] * len(nums) # dp_max记录正负交替乘法中的最大值
+ dp_min[0], dp_max[0] = nums[0], nums[0]
+ res = nums[0]
+ for i in range(1, len(nums)):
+ dp_max[i] = max(nums[i],nums[i]*dp_max[i-1],dp_min[i-1]*nums[i])
+ dp_min[i] = min(nums[i],nums[i]*dp_max[i-1],dp_min[i-1]*nums[i])
+ # dp_max[i] = max(max(nums[i],nums[i]*dp_max[i-1]),dp_min[i-1]*nums[i])
+ # dp_min[i] = min(min(nums[i],nums[i]*dp_max[i-1]),dp_min[i-1]*nums[i])
+
+ # if nums[i] >= 0:
+ # dp_max[i] = max(nums[i], dp_max[i - 1] * nums[i])
+ # dp_min[i] = min(nums[i], dp_min[i - 1] * nums[i])
+ # else: # 此时nums[i]小于0
+ # dp_max[i] = max(dp_min[i - 1] * nums[i], nums[i])
+ # dp_min[i] = min(dp_max[i - 1] * nums[i], nums[i])
+ res = max(res, dp_max[i])
+ return res
+```
+观察上面的执行过程,其实我们使用到的dp_max和dp_min我们在计算过程中,都只使用到了最后一个,考虑进行空间优化
+```python
+class Solution:
+ def maxProduct(self, nums: List[int]) -> int:
+ if not nums: return
+ res,pre_max,pre_min = nums[0],nums[0],nums[0]
+ for num in nums[1:]:
+ cur_max = max(pre_max * num, pre_min * num, num)
+ cur_min = min(pre_max * num, pre_min * num, num)
+ res = max(res, cur_max)
+ pre_max = cur_max
+ pre_min = cur_min
+ return res
+```
+
+#### 打家劫舍
+1.定义`dp[i][0,1]`为到第i个房子能取得的max_val,0代表不取,1代表取
+所以有 `dp[i][0]=max(dp[i-1][0],dp[i-1][1])`i不偷,那么i-1可偷可不偷
+`dp[i][1]=dp[i-1][0]+nums[i]`确定i偷,那么i-1不偷
+```python
+class Solution:
+ def rob(self, nums: List[int]) -> int:
+ if not nums: return 0
+ dp = [[0]*2 for _ in range(len(nums))]
+ dp[0][0],dp[0][1] = 0, nums[0]
+ for i in range(1,len(nums)):
+ dp[i][0] = max(dp[i-1][0],dp[i-1][1])#i不偷,那么i-1可偷可不偷
+ dp[i][1] = dp[i-1][0] + nums[i]#确定i偷,那么i-1不偷
+ return max(dp[-1][0],dp[-1][1])
+```
+2.定义为dp[i]为i偷的时候的最大值,那么有:`dp[i]=max(dp[i-1],dp[i-2]+nums[i])`
+```python
+class Solution:
+ def rob(self, nums: List[int]) -> int:
+ if not nums: return 0
+ dp = [0]*(len(nums)+1)
+ dp[1] = nums[0]
+ for i in range(2,len(nums)+1):
+ dp[i] = max(dp[i-1],dp[i-2]+nums[i-1])
+ return dp[-1]
+```
+同样的在更新dp的时候也只是使用到了前面两个值,这里考虑空间优化
+```python
+class Solution:
+ def rob(self, nums: List[int]) -> int:
+ pre_max, cur_max = 0,0
+ for i in range(len(nums)):
+ # tmp = cur_max
+ # cur_max = max(cur_max,nums+pre_max)
+ # pre_max = tmp
+ pre_max, cur_max = cur_max, max(cur_max,pre_max+nums[i])
+ return cur_max
+```
+
+#### 买卖股票的最佳时机I
+1.暴力解法 枚举每第i天买第j天抛除的所有可能,记录并返回最大值 (感觉是动态规划的一种)
+```python
+from typing import List
+class Solution:
+ # 只能买卖一次
+ def maxProfit(self, prices: List[int]) -> int:
+ # 暴力法 O(N^2)枚举第i天买入第j天卖出,记录最大值
+ res = 0
+ for i in range(len(prices)-1):
+ for j in range(i+1,len(prices)):
+ res = max(res,prices[j]-prices[i])
+ return res
+```
+2.动态规划 累计到第i天的最大收益为 第i-1天的最大收益值 和 第i天股票价格与当前历史最低股价差值 之间的最大值
+```python
+from typing import List
+class Solution:
+ # 只能买卖一次
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ dp = [0] * len(prices)
+ lowest = prices[0]
+ for i in range(1, len(prices)):
+ if prices[i] < lowest:
+ lowest = prices[i]
+ dp[i] = max(dp[i - 1], prices[i] - lowest)#状态转移只与前一个状态有关
+ return dp[-1]
+```
+3. 看到labuladong的题解,里面对空间降维有这样一句描述 由于状态转化过程仅与前一个状态相关,所以可以用变量来存储
+对程序稍作修改,第一次难免会犯错
+```python
+from typing import List
+class Solution:
+ # 只能买卖一次
+ def maxProfit(self, prices: List[int]) -> int:
+ pre, cur, lowest = 0,0,prices[0]
+ for i in range(len(prices)):
+ if prices[i] < lowest:
+ lowest = prices[i]
+ cur = max(cur,prices[i]-lowest)
+ # pre, cur = cur, max(cur, prices[i]-lowest)
+ print(pre,cur)
+ # return max(cur,pre)
+ return cur
+```
+刚开始就想着那就拿两个数来存咯,然后在返回结果的时候就发现cur并不是最大的 打印pre,cur才知道转移过程写错了
+思考后,发现两个状态转移,一个变量就搞定了 所以有了上面的最终代码
+
+#### 买卖股票的最佳时机II 可以买卖股票多次
+由于没有对买卖次数进行限制,我们可以找到股票图里所有上升段进行求和
+```python
+from typing import List
+class Solution:
+ #可以买卖K次
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ res = 0
+ for i in range(1,len(prices)):
+ if prices[i] > prices[i-1]:
+ res += prices[i] - prices[i-1]
+ return res
+```
+#### 买卖股票的最佳时机III 只能买卖两次
+考虑用二维数组做,dp[i][0,1,2,3]表示到i天买卖0-3次时 最大收益,这样定义状态的原因是因为限定了k=2,所以只有五种状态(原始状态+1)
+```python
+from typing import List
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次
+ # dp = [[0]*len(prices) for _ in range(2*2+1)]
+ dp = [[0]*5 for _ in range(len(prices))]
+ dp[0][0] = dp[0][2] = dp[0][4] = 0
+ dp[0][1] = dp[0][3] = -prices[0]
+ for i in range(1,len(prices)):
+ dp[i][0] = 0 #如果第i天没有买入,那么只可能i-1天没有买入
+ #第i天买入一次,可能是i-1天未买i天买 或 第i-1天买i未买
+ dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
+ #第i天买入一次卖出一次,可能是i-1天买入i天卖出或者i-1天已经买入卖出了
+ dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])
+ #第i天买入2次卖出1次,可能是i-1买卖(1,1)次,i天买入;也可能是是i-1天已经买卖(2,1)次
+ dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])
+ # 第i天买卖(2,2)可能是i-1天买卖(2,2)也可能是i-1天买卖(2,1),i卖出
+ dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i])
+ #最后手头没有股票剩余,实际收益最高
+ return dp[-1][4]
+```
+很自然的看出,每一种状态的转移有着高度的相似性,我们考虑降维
+很显然这个状态转移,只与前一天相同状态dp[i-1][k]和前一天不同状态dp[i-1][k-1]有关,那么我们就能简化上述过程。
+【刚开始我也是去找别人的代码,发现状态转移稀奇古怪,】
+【要么是 对状态转移方程中对dp[i][1]和dp[i][3]做min操作,要么是做一些不直观的额外处理】
+【我想,既然是简化,那么状态转移过程应该与上述代码高度一致】
+【而不应该是在简化的状态转移方程中对dp[i][1]和dp[i][3]做min操作,也不应该做过多的边界处理】
+【按自己的思路对照上述方程,得如下】
+```
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ in_1,in_2 = float('-inf'),float('-inf')
+ out_1,out_2 = 0,0
+ for p in prices:
+ in_1 = max(in_1,-p)
+ out_1 = max(out_1, in_1 + p)
+ in_2 = max(in_2,out_1 - p)
+ out_2 = max(out_2, in_2 + p)
+ return out_2
+```
+【我做题的时候就最烦我的思路和别人不一样,要改弦更张,记忆的细节就更多了】
+【你看,现在是不是与前面的逻辑一毛一样,方便记忆】
+但是对于后面k很大,比如就是三的时候,刚开始的思路是正确,但是就要写很多,这道题我还没做,做的时候再考虑该怎么处理~
+
+#### 买卖股票的最佳时机IV
+```python
+from typing import List
+class Solution:
+ def maxProfit(self, k: int, prices: List[int]) -> int:
+ def no_limit(prices):
+ res = 0
+ for i in range(1, len(prices)):
+ if prices[i] > prices[i - 1]:
+ res += prices[i] - prices[i - 1]
+ return res
+ size = len(prices)
+ if k > size / 2:
+ return no_limit(prices)
+ dp = [[[0] * 2 for _ in range(k + 1)] for _ in range(size)]
+ for i in range(size):
+ for j in range(1, k + 1):
+ if i == 0:
+ dp[i][j][0] = 0
+ dp[i][j][1] = -prices[i]
+ else:
+ dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1] + prices[i])#前一天持有并卖掉
+ dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0] - prices[i])#前一天不持有,并买入
+ return dp[size - 1][k][0]
+```
+
+#### 买卖股票的最佳时机V 冷冻期
+实际上与前三题没什么不同,只是比第四题操作少一些,我们还是定义可能存在的状态
+```python
+from typing import List
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ # dp[i][0,1,2,3] 初始状态、买入、卖出、冷冻期
+ # dp[i][0] = 0
+ # dp[i][1] = max(dp[i-1][1],dp[i-1][0] -p)
+ # dp[i][2] = max(dp[i-1][2],dp[i-1][1] + p)
+ # dp[i][3] = max(dp[i-1][3],dp[i-1][2])#要么是之前已经闲置,要么是正在闲置-->可以和初始状态合并
+ if not prices: return 0
+ dp = [[0]*3 for _ in range(len(prices))]
+ dp[0][0], dp[0][1], dp[0][2] = 0, -prices[0], 0
+ for i in range(1,len(prices)):
+ dp[i][0] = max(dp[i-1][0],dp[i-1][2])
+ dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i])
+ dp[i][2] = max(dp[i-1][2],dp[i-1][1] + prices[i])
+ return dp[-1][2]
+```
+老样子,降维 但是直接降维会出错,要加中间状态
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ keep, in1, out1 = 0, -prices[0], 0
+ for price in prices:
+ new_keep = max(keep,out1)
+ new_in1 = max(in1,keep-price)
+ new_out1 = max(out1,in1+price)
+ keep,in1,out1 = new_keep,new_in1,new_out1
+ return out1
+```
+
+#### 买卖股票的最佳时机VI 手续费
+```python
+class Solution:
+ def maxProfit(self, prices: List[int], fee: int) -> int:
+ # dp[i][0],dp[i][1] 买入的最大值,卖出的最大值
+ dp = [[0,0] for _ in range(len(prices))]
+ dp[0][0],dp[0][1] = -prices[0] - fee,0
+ # 每笔交易你只需要为支付一次手续费, 可以在买入的时候付,也可以在卖出的时候付,这里在买入的时候付
+ for i in range(1,len(prices)):
+ dp[i][0] = max(dp[i-1][0] , dp[i-1][1] - prices[i] - fee)#持股
+ dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])#不持股
+ return dp[-1][1]
+```
+降维
+```python
+class Solution:
+ def maxProfit(self, prices: List[int], fee: int) -> int:
+ in1, out1 = -prices[0] - fee, 0#在买入的时候付费
+ for price in prices:
+ in1 = max(in1, out1-price-fee)
+ out1 = max(out1, in1 + price)
+ return out1
+```
+
+
+
diff --git "a/Week06/[1143]\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" "b/Week06/[1143]\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py"
new file mode 100644
index 000000000..c78aadb81
--- /dev/null
+++ "b/Week06/[1143]\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/13 11:08 PM
+
+class Solution:
+ def longestCommonSubsequence(self, text1: str, text2: str) -> int:
+ if text1 == '' or text2 == '': return 0
+ m, n = len(text1), len(text2)
+ dp = [[0]*(n + 1) for _ in range(m + 1)]
+ for i in range(1, m + 1):
+ for j in range(1, n + 1):
+ if text1[i-1] == text2[j-1]:
+ dp[i][j] = dp[i-1][j-1] + 1
+ else:
+ dp[i][j] = max(dp[i-1][j],dp[i][j-1])
+ return dp[-1][-1]
+
+s = Solution()
+text1 = "abcde"
+text2 = "ace"
+res = s.longestCommonSubsequence(text1,text2)
+print(res)
\ No newline at end of file
diff --git "a/Week06/[120]\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" "b/Week06/[120]\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py"
new file mode 100644
index 000000000..de45b1992
--- /dev/null
+++ "b/Week06/[120]\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py"
@@ -0,0 +1,44 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/14 12:43 AM
+
+from typing import List
+class Solution:
+ def minimumTotal(self, triangle: List[List[int]]) -> int:
+ # 1.分治 F[i,j] = min(F[i+1,j],f[i,j+1]) + a[i,j]
+ # from functools import lru_cache
+ # @lru_cache(None)
+ # def dfs(row,col):
+ # if row == size - 1:return triangle[row][col]
+ # left = dfs(row+1,col)
+ # right = dfs(row+1,col+1)
+ # return min(left,right) + triangle[row][col]
+ # size = len(triangle)
+ # return dfs(0,0)
+
+ # res = triangle[-1]
+ # for i in xrange(len(triangle)-2, -1, -1):
+ # for j in xrange(len(triangle[i])):
+ # res[j] = min(res[j], res[j+1]) + triangle[i][j]
+ # return res[0]
+ # dp = triangle
+ # for i in range(len(dp)-2,-1,-1):
+ # for j in range(len(dp[i])):
+ # dp[i][j] = min(dp[i+1][j],dp[i+1][j+1]) + dp[i][j]
+ # return dp[0][0]
+ dp = triangle[-1]
+ for i in range(len(triangle) - 2, -1, -1):
+ for j in range(len(triangle[i])):
+ dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j]
+ return dp[0]
+
+
+nums = [
+ [2],
+ [3,4],
+ [6,5,7],
+ [4,1,8,3]
+]
+s = Solution()
+res = s.minimumTotal(nums)
+print(res)
diff --git "a/Week06/[121]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272I.py" "b/Week06/[121]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272I.py"
new file mode 100644
index 000000000..1fc8cf553
--- /dev/null
+++ "b/Week06/[121]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272I.py"
@@ -0,0 +1,40 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/16 9:06 PM
+
+from typing import List
+class Solution:
+ # 只能买卖一次
+ def maxProfit(self, prices: List[int]) -> int:
+ # 暴力法 O(N^2)枚举第i天买入第j天卖出,记录最大值
+ # res = 0
+ # for i in range(len(prices)-1):
+ # for j in range(i+1,len(prices)):
+ # res = max(res,prices[j]-prices[i])
+ # return res
+ # 动态规划 到第i天获得的最大收益等于到第i-1天的最大收益 和 当前股价与当前最低股价差值之间的最大值
+
+ # if not prices: return 0
+ # dp = [0] * len(prices)
+ # lowest = prices[0]
+ # for i in range(1, len(prices)):
+ # if prices[i] < lowest:
+ # lowest = prices[i]
+ # dp[i] = max(dp[i - 1], prices[i] - lowest)#状态转移只与前一个状态有关
+ # return dp[-1]
+ if not prices: return 0
+ pre, cur, lowest = 0,0,prices[0]
+ for i in range(len(prices)):
+ if prices[i] < lowest:
+ lowest = prices[i]
+ # cur = max(cur,prices[i]-lowest)
+ pre, cur = cur, max(cur, prices[i]-lowest)
+ print(pre,cur)
+ # return max(cur,pre)
+ return cur
+
+
+
+s = Solution()
+res = s.maxProfit([7,1,5,3,6,4,2,18,4])
+print(res)
\ No newline at end of file
diff --git "a/Week06/[122]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II.py" "b/Week06/[122]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II.py"
new file mode 100644
index 000000000..19c7254f6
--- /dev/null
+++ "b/Week06/[122]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/16 10:01 PM
+
+from typing import List
+class Solution:
+ #可以买卖K次
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ res = 0
+ for i in range(1,len(prices)):
+ if prices[i] > prices[i-1]:
+ res += prices[i] - prices[i-1]
+ return res
+ # dp
+ # if not prices: return 0
+ # dp = [[0] * 2 for _ in range(len(prices))]
+ # dp[0][0], dp[0][1] = 0, -prices[0]
+ # for i in range(1, len(prices)):
+ # dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]) # hold,sell
+ # dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]) # hold,buy
+ # return dp[-1][0]
\ No newline at end of file
diff --git "a/Week06/[123]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" "b/Week06/[123]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py"
new file mode 100644
index 000000000..387cc97b5
--- /dev/null
+++ "b/Week06/[123]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py"
@@ -0,0 +1,51 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/17 1:36 AM
+
+from typing import List
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ # dp[i][k][0,1] 0 未持有 1 持有
+ dp = [[[0, 0] for i in range(3)] for i in range(len(prices))]
+ dp[0][1][0] = dp[0][2][0] = 0
+ dp[0][1][1] = dp[0][2][1] = -prices[0]
+ for i in range(1, len(prices)):
+ for k in range(1, 3):
+ dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]) # hold,sell
+ # 买入的时候计算次数
+ dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - prices[i]) # hold,buy
+ return dp[-1][-1][0]
+ # if not prices: return 0
+ # #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次
+ # # dp = [[0]*len(prices) for _ in range(2*2+1)]
+ # dp = [[0]*5 for _ in range(len(prices))]
+ # dp[0][0] = dp[0][2] = dp[0][4] = 0
+ # dp[0][1] = dp[0][3] = -prices[0]
+ # for i in range(1,len(prices)):
+ # dp[i][0] = 0 #如果第i天没有买入,那么只可能i-1天没有买入
+ # #第i天买入一次,可能是i-1天未买i天买 或 第i-1天买i未买
+ # dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
+ # #第i天买入一次卖出一次,可能是i-1天买入i天卖出或者i-1天已经买入卖出了
+ # dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])
+ # #第i天买入2次卖出1次,可能是i-1买卖(1,1)次,i天买入;也可能是是i-1天已经买卖(2,1)次
+ # dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])
+ # # 第i天买卖(2,2)可能是i-1天买卖(2,2)也可能是i-1天买卖(2,1),i卖出
+ # dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i])
+ # #最后手头没有股票剩余,实际收益最高
+ # return dp[-1][4]
+
+ # in_1, in_2 = float('-inf'), float('-inf')
+ # out_1, out_2 = 0, 0
+ # for p in prices:
+ # in_1 = max(in_1, -p)
+ # out_1 = max(out_1, in_1 + p)
+ # in_2 = max(in_2, out_1 - p)
+ # out_2 = max(out_2, in_2 + p)
+ # return out_2
+
+
+s = Solution()
+nums = [3,3,5,0,0,3,1,4]
+res = s.maxProfit(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week06/[14]\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py" "b/Week06/[14]\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py"
new file mode 100644
index 000000000..f14b68ed6
--- /dev/null
+++ "b/Week06/[14]\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py"
@@ -0,0 +1,3 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 9:06 AMƒ
\ No newline at end of file
diff --git "a/Week06/[152]\344\271\230\347\247\257\346\234\200\345\244\247\347\232\204\345\255\220\346\225\260\347\273\204.py" "b/Week06/[152]\344\271\230\347\247\257\346\234\200\345\244\247\347\232\204\345\255\220\346\225\260\347\273\204.py"
new file mode 100644
index 000000000..b86d1a2f3
--- /dev/null
+++ "b/Week06/[152]\344\271\230\347\247\257\346\234\200\345\244\247\347\232\204\345\255\220\346\225\260\347\273\204.py"
@@ -0,0 +1,41 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/14 9:15 PM
+
+from typing import List
+class Solution:
+ def maxProduct(self, nums: List[int]) -> int:
+ if not nums: return 0
+ if len(nums) == 1: return nums[0]
+ dp_min, dp_max = [0] * len(nums), [0] * len(nums) # dp_max记录正负交替乘法中的最大值
+ dp_min[0], dp_max[0] = nums[0], nums[0]
+ res = nums[0]
+ for i in range(1, len(nums)):
+ if nums[i] >= 0:
+ # 如果此时nums[i]大于0,如果之前是正数,那就乘上,如果是负数,那此时的最大值为此时的值
+ dp_max[i] = max(nums[i], dp_max[i - 1] * nums[i])
+ # 此时原本小于0,最小值就应该乘上nums[i];如果原本大于0,那最小的就应该是此时的值
+ dp_min[i] = min(nums[i], dp_min[i - 1] * nums[i])
+ else: # 此时nums[i]小于0
+ # 如果原本dp_min小于0,它乘上num可能是最大值;如果原来是正值,(+值*负值和负值) 中要求大值
+ dp_max[i] = max(dp_min[i - 1] * nums[i], nums[i])
+ dp_min[i] = min(dp_max[i - 1] * nums[i], nums[i])
+ res = max(res, dp_max[i])
+ return res
+ # dp_max = [1] * (len(nums)+1)
+ # dp_min = [1] * (len(nums)+1)
+ # for i in range(1, len(nums)+1):
+ # dp_max[i] = max(dp_max[i - 1] * nums[i-1], dp_min[i - 1] * nums[i-1], nums[i-1])
+ # dp_min[i] = min(dp_max[i - 1] * nums[i-1], dp_min[i - 1] * nums[i-1], nums[i-1])
+ # return max(dp_max)
+
+
+
+s = Solution()
+# nums = [2,3,-2,-4]
+# nums = [3,-1,4]
+# nums = [0, 2]
+# nums = [2,3,-2,4]
+nums = [2,-5,-2,-4,3]
+res = s.maxProduct(nums)
+print(res)
diff --git "a/Week06/[188]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272IV.py" "b/Week06/[188]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272IV.py"
new file mode 100644
index 000000000..e23d5786c
--- /dev/null
+++ "b/Week06/[188]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272IV.py"
@@ -0,0 +1,37 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/17 9:09 PM
+from typing import List
+class Solution:
+ def maxProfit(self, k: int, prices: List[int]) -> int:
+ def no_limit(prices):
+ res = 0
+ for i in range(1, len(prices)):
+ if prices[i] > prices[i - 1]:
+ res += prices[i] - prices[i - 1]
+ return res
+ size = len(prices)
+ if k > size / 2:
+ return no_limit(prices)
+ dp = [[[0] * 2 for _ in range(k + 1)] for _ in range(size)]
+ for i in range(size):
+ for j in range(1, k + 1):
+ if i == 0:
+ dp[i][j][0] = 0
+ dp[i][j][1] = -prices[i]
+ else:
+ dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1] + prices[i])#前一天持有并卖掉
+ dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0] - prices[i])#前一天不持有,并买入
+ return dp[size - 1][k][0]
+
+ # in_1_k = [float('-inf')] * k
+ # in_2_k = [float('-inf')] * k
+ # out_1_k = [0] * k
+ # out_2_k = [0] * k
+ # for j in range(0,k):
+ # for p in prices:
+ # in_1_k[j] = max(in_1_k[j], -p)
+ # out_1_k[j] = max(out_1_k[j], in_1_k[j] + p)
+ # in_2_k[j] = max(in_2_k[j], out_1_k[j] - p)
+ # out_2_k[j] = max(out_2_k[j], in_2_k[j] + p)
+ # return out_2_k[k]
\ No newline at end of file
diff --git "a/Week06/[198]\346\211\223\345\256\266\345\212\253\350\210\215I.py" "b/Week06/[198]\346\211\223\345\256\266\345\212\253\350\210\215I.py"
new file mode 100644
index 000000000..3016e4468
--- /dev/null
+++ "b/Week06/[198]\346\211\223\345\256\266\345\212\253\350\210\215I.py"
@@ -0,0 +1,50 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/15 11:13 PM
+
+from typing import List
+
+
+class Solution:
+ def rob(self, nums: List[int]) -> int:
+ # def dfs(nums, i):
+ # if i >= len(nums): return 0
+ # if nums[i] != -1: return nums[i]
+ # res = max(dfs(nums, i + 1), dfs(nums, i + 2) + nums[i])
+ # cache[i] = res # 备忘录 防止超时
+ # return res
+ # cache = [-1] * len(nums)
+ # return dfs(nums, 0)
+
+ # dp[i][0,1]偷到第i户人家 能得到的最大金额0偷,1不偷
+ # dp[i][0,1] = max(dp[i-1][1]+nums[i],dp[i-1][0])
+ # dp[i] 表示第i天偷能获得的最大金额
+ # dp[i] = max(dp[i-2]+nums[i],dp[i-1])
+
+ if not nums: return 0
+ dp = [[0]*2 for _ in range(len(nums))]
+ dp[0][0],dp[0][1] = 0, nums[0]
+ for i in range(1,len(nums)):
+ # dp[i][0,1] 0不偷,1偷 如果i天偷,那么i-1不偷,而i天不偷,则可能是i-1不偷,也可能是i-1偷了
+ dp[i][0] = max(dp[i-1][0],dp[i-1][1])#i不偷,那么i-1可偷可不偷
+ dp[i][1] = dp[i-1][0] + nums[i]#确定i偷,那么i-1不偷
+ return max(dp[-1][0],dp[-1][1])
+
+ # i偷的max_val = max(f(i-1),f(i-2)+nums[i])
+ # if not nums: return 0
+ # dp = [0]*(len(nums)+1)
+ # dp[1] = nums[0]
+ # for i in range(2,len(nums)+1):
+ # dp[i] = max(dp[i-1],dp[i-2]+nums[i-1])
+ # return dp[-1]
+
+ # pre_max, cur_max = 0,0
+ # for i in range(len(nums)):
+ # pre_max, cur_max = cur_max, max(cur_max,pre_max+nums[i])
+ # return cur_max
+
+
+s = Solution()
+res = s.rob([2,3,1])
+print(res)
+
diff --git "a/Week06/[213]\346\211\223\345\256\266\345\212\253\350\210\215II.py" "b/Week06/[213]\346\211\223\345\256\266\345\212\253\350\210\215II.py"
new file mode 100644
index 000000000..6801b2e82
--- /dev/null
+++ "b/Week06/[213]\346\211\223\345\256\266\345\212\253\350\210\215II.py"
@@ -0,0 +1,21 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/16 12:15 AM
+
+from typing import List
+
+
+class Solution:
+ def rob(self, nums: List[int]) -> int:
+ #在上一题优化空间解法的基础上很容易理解
+ def subRob(nums):
+ pre_max, cur_max = 0, 0
+ for i in range(len(nums)):
+ pre_max, cur_max = cur_max, max(cur_max,pre_max+nums[i])
+ return cur_max
+ if not nums: return 0
+ #取两种偷法里的最大值 不偷最后一个房子和不偷第一个房子
+ return max(subRob(nums[:-1]), subRob(nums[1:])) if len(nums) != 1 else nums[0]
+s = Solution()
+res = s.rob([1])
+print(res)
\ No newline at end of file
diff --git "a/Week06/[309]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272V_\345\206\267\345\206\273\346\234\237.py" "b/Week06/[309]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272V_\345\206\267\345\206\273\346\234\237.py"
new file mode 100644
index 000000000..58c6ccf66
--- /dev/null
+++ "b/Week06/[309]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272V_\345\206\267\345\206\273\346\234\237.py"
@@ -0,0 +1,39 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/17 10:38 PM
+
+from typing import List
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ size = len(prices)
+ dp = [[0] * 2 for _ in range(size)]
+ # 0不持有 1 持有
+ dp[0][0], dp[0][1] = 0, -prices[0]
+ for i in range(1, size):
+ dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]) # hold,sell
+ dp[i][1] = max(dp[i - 1][1], dp[i - 2][0] - prices[i]) # hold,buy,如果i天买入,那么i-2天就不持有
+ return dp[-1][0]
+ # dp[i][0,1,2,3] 初始状态、买入、卖出、冷冻期
+ # dp[i][0] = 0
+ # dp[i][1] = max(dp[i-1][1],dp[i-1][0] -p)
+ # dp[i][2] = max(dp[i-1][2],dp[i-1][1] + p)
+ # dp[i][3] = max(dp[i-1][3],dp[i-1][2])#要么是之前已经闲置,要么是正在闲置-->可以和初始状态合并
+ # if not prices: return 0
+ # dp = [[0]*3 for _ in range(len(prices))]
+ # dp[0][0], dp[0][1], dp[0][2] = 0, -prices[0], 0
+ # for i in range(1,len(prices)):
+ # dp[i][0] = max(dp[i-1][0],dp[i-1][2])
+ # dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i])
+ # dp[i][2] = max(dp[i-1][2],dp[i-1][1] + prices[i])
+ # return dp[-1][2]
+
+ # if not prices: return 0
+ # keep, in1, out1 = 0, -prices[0], 0
+ # for price in prices:
+ # new_keep = max(keep, out1)
+ # new_in1 = max(in1, keep - price)
+ # new_out1 = max(out1, in1 + price)
+ # keep, in1, out1 = new_keep, new_in1, new_out1
+ # return out1
+
diff --git "a/Week06/[322]\351\233\266\351\222\261\345\205\221\346\215\242.py" "b/Week06/[322]\351\233\266\351\222\261\345\205\221\346\215\242.py"
new file mode 100644
index 000000000..0814edb59
--- /dev/null
+++ "b/Week06/[322]\351\233\266\351\222\261\345\205\221\346\215\242.py"
@@ -0,0 +1,36 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/15 12:38 AM
+
+from typing import List
+class Solution:
+ def coinChange(self, coins: List[int], amount: int) -> int:
+ # @functools.lru_cache(amount)
+ # def dfs(coins,amount,i,count,res):
+ # if amount == 0: return min(count,res)
+ # if i == -1: return res#coins下标为0还没有使得amount=0,那么找不到了
+ # m = amount//coins[i]
+ # while m >= 0 and m+count < res:
+ # res = dfs(coins,amount-m*coins[i],i-1,m+count,res)
+ # m = m - 1
+ # return res
+ # coins.sort()
+ # res = dfs(coins,amount,len(coins)-1,0,float('inf'))
+ # return res if res!=float('inf') else -1
+ dp = [float('inf')]*(amount+1)
+ dp[0] = 0
+ #dp[i]代表拼凑出i元的最少纸币数
+ for i in range(amount+1):
+ for coin in coins:
+ if i >= coin:
+ dp[i] = min(dp[i-coin] + 1,dp[i])
+ return dp[-1] if dp[-1]!=float('inf') else -1
+ # dp = [float('inf')] * (amount + 1)
+ # dp[0] = 0
+ # for i in range(amount + 1):
+ # for coin in coins:
+ # if i >= coin: # 实际上是min(dp[i-coin1]+1,dp[i-coin2]+1,dp[i-coin3]+1)
+ # dp[i] = min(dp[i - coin] + 1, dp[i])
+ # return dp[-1] if dp[-1] != float('inf') else -1
+
+
diff --git "a/Week06/[32]\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267.py" "b/Week06/[32]\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267.py"
new file mode 100644
index 000000000..4a6a52fdd
--- /dev/null
+++ "b/Week06/[32]\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267.py"
@@ -0,0 +1,63 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/30 2:09 AM
+
+class Solution:
+ def longestValidParentheses(self, strs: str) -> int:
+ #先和面试官讨论清楚,最长有效括号是否是连续的
+ pass
+ #中心扩散???-->NO
+ # 1.遍历可能的最大长度,再判断子串是否为有效子串 用栈实现O(N3)
+ # 2.动态规划
+ # dp = [0]*len(strs)#表示下标为i的有效括号长度
+ # for i in range(len(strs)):
+ # if strs[i] == ')' and strs[i-dp[i-1]-1] =='(' and i-dp[i-1]-1>=0:#自身是否为有效括号
+ # dp[i] = 2 + dp[i-1] + dp[i-dp[i-1]-2]#自身+内有效括号+外有效括号
+ # return max(dp)
+ # 3.使用栈
+ # stack = [-1]
+ # length, max_length = 0, 0
+ # # ")())())"
+ # for i in range(len(strs)):# 小心这种情形 strs = "()(()"
+ # if strs[i] == '(':
+ # stack.append(i)
+ # else:
+ # stack.pop()
+ # if stack == []:
+ # stack.append(i)
+ # else:
+ # length = i - stack[-1]
+ # max_length = max(length, max_length)
+ # return max_length
+ #正反向遍历
+ size,left,right,max_length = len(strs),0,0,0
+ for i in range(size):
+ if strs[i] == '(':
+ left += 1
+ else:
+ right += 1
+ if left == right:
+ max_length = max(max_length, left*2)
+ elif right > left:
+ left, right = 0, 0
+ left, right = 0, 0 #反序的时候清0
+ for i in range(size-1, -1, -1):
+ if strs[i] == '(':
+ left += 1
+ else:
+ right += 1
+ if left == right:
+ max_length = max(max_length, left*2)
+ elif left > right:
+ left, right = 0, 0
+ return max_length
+
+
+
+s = Solution()
+strs = "(()"
+# strs = ")()())"
+# strs = "()(())"
+# strs = "()(()"
+res = s.longestValidParentheses(strs)
+print(res)
\ No newline at end of file
diff --git "a/Week06/[337]\346\211\223\345\256\266\345\212\253\350\210\215III.py" "b/Week06/[337]\346\211\223\345\256\266\345\212\253\350\210\215III.py"
new file mode 100644
index 000000000..43f75c41e
--- /dev/null
+++ "b/Week06/[337]\346\211\223\345\256\266\345\212\253\350\210\215III.py"
@@ -0,0 +1,27 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 1:16 AM
+
+# Definition for a binary tree node.
+# class TreeNode:
+# def __init__(self, x):
+# self.val = x
+# self.left = None
+# self.right = None
+
+# https://leetcode-cn.com/problems/house-robber-iii/solution/dfs-ni-neng-kan-dong-de-jie-shi-by-mqray/
+class Solution:
+ def rob(self, root: TreeNode) -> int:
+ #要么就是偷左右孩子,要么就是偷根节点和直系孙子
+ #dfs是求以该节点为根,在该点能拿到的最大值 对于这个节点,有拿和不拿两种
+ def dfs(root):
+ if not root: return 0, 0 # 偷,不偷
+ left = dfs(root.left)
+ right = dfs(root.right)
+ # 偷当前节点, 则左右子树都不能偷
+ v1 = root.val + left[1] + right[1]
+ # 不偷当前节点, 则取左右子树中最大的值
+ # v2 = left[0] + right[0]
+ v2 = max(left) + max(right)
+ return v1, v2
+ return max(dfs(root))
\ No newline at end of file
diff --git "a/Week06/[349]\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206.py" "b/Week06/[349]\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206.py"
new file mode 100644
index 000000000..73a76e57d
--- /dev/null
+++ "b/Week06/[349]\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206.py"
@@ -0,0 +1,23 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/13 11:59 PM
+
+from typing import List
+class Solution:
+ def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ # 1.暴力解法 时间复杂度O(M*N),空间复杂度O(1)
+ # res = [num for num in nums1 if num in nums2]
+ # return set(res)
+ # 2.hashmap 时间复杂度O(M+N),空间复杂度O(min(M,N))
+ # hashmap, res = {}, []
+ # for num in nums1:
+ # hashmap[num] = hashmap.get(num, 0) + 1
+ # for num in nums2:
+ # if hashmap.get(num): # 能get到内容时,才加入res
+ # res.append(num)
+ # hashmap[num] -= 1
+ # return set(res)
+ # 3.奇技淫巧 时间复杂度应该是O(M+N),空间复杂度O(M+N)
+ set1 = set(nums1)
+ set2 = set(nums2)
+ return list(set1 ^ set2)
diff --git "a/Week06/[350]\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II.py" "b/Week06/[350]\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II.py"
new file mode 100644
index 000000000..7819af580
--- /dev/null
+++ "b/Week06/[350]\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II.py"
@@ -0,0 +1,40 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/13 11:40 PM
+
+from typing import List
+class Solution:
+ def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ #1.hashmap 时间复杂度O(M+N),空间复杂度O(max(M,N)),可以优化为min
+ # hashmap,res = {}, []
+ # for num in nums1:
+ # hashmap[num] = hashmap.get(num,0) + 1
+ # for num in nums2:
+ # if hashmap.get(num):#能get到内容时,才加入res
+ # res.append(num)
+ # hashmap[num] -= 1
+ # return res
+ # 假如两个数组排好序,如何优化你的算法
+ # 时间复杂度O(NlogN+MlogM),空间复杂度O(min(M,N))
+ # 如果一个长度很短一个长度很小,采用法2好,查询开销小
+ # 若内存有限,法1好,只涉及到查询,而不用在内存中排序
+ nums1.sort()
+ nums2.sort()
+ res, p1, p2 = [], 0, 0
+ size1, size2 = len(nums1), len(nums2)
+ while p1 < size1 and p2 < size2:
+ if nums1[p1] == nums2[p2]:
+ res.append(nums1[p1])
+ p1, p2 = p1 + 1, p2 + 1
+ elif nums1[p1] > nums2[p2]:
+ p2 = p2 + 1
+ else:
+ p1 = p1 + 1
+ return res
+# nums1 = [1,2,2,1]
+# nums2 = [2,2]
+nums1 = [1,2,2,1]
+nums2 = [2,2,2]
+s = Solution()
+res = s.intersect(nums1,nums2)
+print(res)
\ No newline at end of file
diff --git "a/Week06/[35]\346\257\217\346\227\245\344\270\200\351\242\2307_17_\346\220\234\347\264\242\346\217\222\345\205\245\344\275\215\347\275\256.py" "b/Week06/[35]\346\257\217\346\227\245\344\270\200\351\242\2307_17_\346\220\234\347\264\242\346\217\222\345\205\245\344\275\215\347\275\256.py"
new file mode 100644
index 000000000..4a9168055
--- /dev/null
+++ "b/Week06/[35]\346\257\217\346\227\245\344\270\200\351\242\2307_17_\346\220\234\347\264\242\346\217\222\345\205\245\344\275\215\347\275\256.py"
@@ -0,0 +1,15 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/17 11:58 PM
+
+from typing import List
+class Solution:
+ def searchInsert(self, nums: List[int], target: int) -> int:
+ if not nums : return 0
+ left,right = 0,len(nums)-1
+ while left <= right:
+ mid = left + (right-left)//2#防溢出
+ if nums[mid] == target: return mid
+ elif nums[mid] > target:right = mid - 1
+ else: left = mid + 1
+ return left
diff --git "a/Week06/[53]\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py" "b/Week06/[53]\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py"
new file mode 100644
index 000000000..95fc95d23
--- /dev/null
+++ "b/Week06/[53]\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py"
@@ -0,0 +1,19 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/14 8:28 PM
+
+from typing import List
+class Solution:
+ def maxSubArray(self, nums: List[int]) -> int:
+ dp = [0] * len(nums)
+ dp[0], max_val = nums[0], nums[0]
+ for i in range(1, len(nums)):
+ dp[i] = max(dp[i - 1] + nums[i], nums[i])
+ max_val = max(dp[i], max_val)
+ # return max(dp)
+ return max_val
+
+
+s = Solution()
+res = s.maxSubArray([-2,1,-3,4,-1,2,1,-5,4])
+print(res)
diff --git "a/Week06/[62]\344\270\215\345\220\214\350\267\257\345\276\204.py" "b/Week06/[62]\344\270\215\345\220\214\350\267\257\345\276\204.py"
new file mode 100644
index 000000000..f8937ddec
--- /dev/null
+++ "b/Week06/[62]\344\270\215\345\220\214\350\267\257\345\276\204.py"
@@ -0,0 +1,3 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/13 10:19 PM
\ No newline at end of file
diff --git "a/Week06/[63]\344\270\215\345\220\214\350\267\257\345\276\204II.py" "b/Week06/[63]\344\270\215\345\220\214\350\267\257\345\276\204II.py"
new file mode 100644
index 000000000..9b9ba30e0
--- /dev/null
+++ "b/Week06/[63]\344\270\215\345\220\214\350\267\257\345\276\204II.py"
@@ -0,0 +1,28 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/13 10:20 PM
+from typing import List
+class Solution:
+ def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
+ m, n = len(obstacleGrid), len(obstacleGrid[0])
+ if obstacleGrid[0][0] == 1:return 0
+ dp = [[0 for _ in range(n)] for _ in range(m)]
+ dp[0][0] = 1
+ for i in range(1, m):
+ if obstacleGrid[i][0] == 0:
+ dp[i][0] = dp[i-1][0]#在dp数组中进行转移
+ for j in range(1, n):
+ if obstacleGrid[0][j] == 0:
+ dp[0][j] = dp[0][j-1]
+ print(dp)
+ for i in range(1, m):
+ for j in range(1, n):
+ if obstacleGrid[i][j] == 1:
+ dp[i][j] = 0
+ else:
+ dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
+ return dp[m - 1][n - 1]
+
+s = Solution()
+res = s.uniquePathsWithObstacles([[0,0],[1,1],[0,0]])
+print(res)
\ No newline at end of file
diff --git "a/Week06/[714]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272VI_\346\211\213\347\273\255\350\264\271.py" "b/Week06/[714]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272VI_\346\211\213\347\273\255\350\264\271.py"
new file mode 100644
index 000000000..4808423b3
--- /dev/null
+++ "b/Week06/[714]\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272VI_\346\211\213\347\273\255\350\264\271.py"
@@ -0,0 +1,28 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/17 11:33 PM
+
+from typing import List
+class Solution:
+ def maxProfit(self, prices: List[int], fee: int) -> int:
+ # dp[i][0],dp[i][1] 买入的最大值,卖出的最大值
+ # dp = [[0, 0] for _ in range(len(prices))]
+ # dp[0][0], dp[0][1] = -prices[0] - fee, 0
+ # # 每笔交易你只需要为支付一次手续费, 可以在买入的时候付,也可以在卖出的时候付,这里在买入的时候付
+ # for i in range(1, len(prices)):
+ # dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i] - fee) # 持股
+ # dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]) # 不持股
+ # return dp[-1][1]
+ #降维
+ in1, out1 = -prices[0] - fee, 0
+ for price in prices:
+ in1 = max(in1, out1-price-fee)
+ out1 = max(out1, in1 + price)
+ return out1
+
+
+
+
+s = Solution()
+res = s.maxProfit(prices = [1, 3, 2, 8, 4, 9],fee=2)
+print(res)
\ No newline at end of file
diff --git "a/Week06/[91]\350\247\243\347\240\201\346\226\271\346\263\225I.py" "b/Week06/[91]\350\247\243\347\240\201\346\226\271\346\263\225I.py"
new file mode 100644
index 000000000..3a3e6090e
--- /dev/null
+++ "b/Week06/[91]\350\247\243\347\240\201\346\226\271\346\263\225I.py"
@@ -0,0 +1,29 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/19 9:19 AM
+
+
+class Solution:
+ def numDecodings(self, s: str) -> int:
+ size=len(s)
+ if not s or s[0]=="0":
+ return 0
+ dp=[0]*(size+1)
+ dp[0], dp[1] = 1, 1
+ for i in range(1,size):
+ if s[i]=="0":#如果当前位为0
+ if s[i-1] == "1" or s[i-1] == "2":#它最多能与前一位合并,那时的解码方法等于dp[i-1]
+ dp[i+1] = dp[i-1]
+ else:
+ return 0
+ else:
+ if '10'<=s[i-1:i+1]<='26':
+ # if(s[i-1]=="1" or (s[i-1]=="2" and "1"<=s[i]<="6")):
+ dp[i+1] = dp[i]+dp[i-1] # 等于上一个位置和上上个位置的解码方法和
+ else:
+ dp[i+1] = dp[i]
+ return dp[-1]
+
+s = Solution()
+res = s.numDecodings('1236')
+print(res)
\ No newline at end of file
diff --git "a/Week06/[95]\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221II.py" "b/Week06/[95]\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221II.py"
new file mode 100644
index 000000000..f3afce614
--- /dev/null
+++ "b/Week06/[95]\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221II.py"
@@ -0,0 +1,26 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 1:25 AM
+
+# Definition for a binary tree node.
+class TreeNode:
+ def __init__(self, val=0, left=None, right=None):
+ self.val = val
+ self.left = left
+ self.right = right
+class Solution:
+ def generateTrees(self, n):
+ def generate_trees(start,end):
+ if start > end: return [None]
+ trees = []
+ for i in range(start, end+1):
+ ltree = generate_trees(start,i-1)
+ rtree = generate_trees(i+1,end)
+ for lnode in ltree:
+ for rnode in rtree:
+ cur = TreeNode(i)
+ cur.left = lnode
+ cur.right = rnode
+ trees.append(cur)
+ return trees
+ return generate_trees(1,n) if n else []
\ No newline at end of file
diff --git "a/Week06/[96]\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" "b/Week06/[96]\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py"
new file mode 100644
index 000000000..8ce465d17
--- /dev/null
+++ "b/Week06/[96]\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py"
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/15 12:41 AM
+
+
+class Solution:
+ def numTrees(self, n: int) -> int:
+ dp = [0]*(n+1)
+ dp[0], dp[1] = 1, 1
+ for i in range(2,n+1):
+ for j in range(1,i):
+ dp[i] += dp[j-1]*dp[i-j]
+ return dp[-1]
+ # c = 1
+ # for i in range(n):
+ # c = c*2*(2*i+1)/(i+2)
+ # return int(c)
\ No newline at end of file
diff --git "a/Week06/\345\207\272\347\216\260\346\254\241\346\225\260\346\234\200\345\244\232\347\232\204\345\205\203\347\264\240.py" "b/Week06/\345\207\272\347\216\260\346\254\241\346\225\260\346\234\200\345\244\232\347\232\204\345\205\203\347\264\240.py"
new file mode 100644
index 000000000..4e4a5aede
--- /dev/null
+++ "b/Week06/\345\207\272\347\216\260\346\254\241\346\225\260\346\234\200\345\244\232\347\232\204\345\205\203\347\264\240.py"
@@ -0,0 +1,20 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/14 6:41 PM
+
+nums = [2,5,5,2,4,4]
+size = len(nums)
+delta = 1000
+for i in range(size):
+ times = nums[i] %delta
+ nums[times] += delta
+ nums[i] -= times
+ print(nums)
+MAX=0
+res=0
+for i in range(size):
+ print("数字",i,"在数组中出现的次数:",nums[i]//delta)
+ if MAX <= nums[i]//delta:
+ MAX = nums[i]//delta
+ res = i
+print("出现次数最多的数字",res)
\ No newline at end of file
diff --git "a/Week06/\350\202\241\347\245\250\351\227\256\351\242\230\351\200\232\347\224\250\350\247\243.md" "b/Week06/\350\202\241\347\245\250\351\227\256\351\242\230\351\200\232\347\224\250\350\247\243.md"
new file mode 100644
index 000000000..182ef5597
--- /dev/null
+++ "b/Week06/\350\202\241\347\245\250\351\227\256\351\242\230\351\200\232\347\224\250\350\247\243.md"
@@ -0,0 +1,166 @@
+--------
+#### 买卖股票的最佳时机I 买卖一次
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ # 只能交易一次 找到nums[i]-nums[i+1]的最大差值即可 这种思路是错的
+ # 正确的思路应该是 当前股价减去历史最低股价
+ # if not prices: return 0
+ # low = prices[0]
+ # res = 0
+ # for i in range(len(prices)):
+ # if prices[i] < low:
+ # low = prices[i]
+ # else:
+ # res = max(res,prices[i]-low)
+ # return res
+ # 0代表不持股 1代表持股
+ # if not prices: return 0
+ # size = len(prices)
+ # dp = [[0]*2 for _ in range(size)]
+ # dp[0][0], dp[0][1] = 0,-prices[0]
+ # for i in range(1,size):
+ # dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i])#i-1天已经卖出,或者第i天卖出
+ # #要么就是i-1天已经买入,要么就是第i天买入而不能从dp[i-1][0]-买入->dp[i][1]因为只能买入一次
+ # dp[i][1] = max(dp[i-1][1],-prices[i])
+ # return dp[-1][0]
+ if not prices: return 0
+ dp0, dp1 = 0, -prices[0]
+ for price in prices:
+ tmp1 = max(dp0, dp1 + price)
+ tmp2 = max(dp1, - price)
+ dp0, dp1 = tmp1, tmp2
+ return dp0
+
+```
+#### 买卖股票的最佳时机II 买卖无限次
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ # 可以买卖多次 那我们找到所有正序序列即可
+ # res = 0
+ # for i in range(len(prices)-1):
+ # if prices[i+1] - prices[i]>0:
+ # res += prices[i+1]-prices[i]
+ # return res
+ # 动态规划如何做?
+ # dp[i][0,1]第i天的最大利润 0 不持有,1持有股票
+ # if not prices: return 0
+ # dp = [[0]*2 for _ in range(len(prices))]
+ # dp[0][0], dp[0][1] = 0, -prices[0]
+ # for i in range(1,len(prices)):
+ # dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])#hold,sell
+ # dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i])#hold,buy
+ # return dp[-1][0]
+ if not prices: return 0
+ dp0, dp1 = 0, -prices[0]
+ for price in prices:
+ tmp1 = max(dp0, dp1 + price)
+ tmp2 = max(dp1, dp0 - price)
+ dp0, dp1 = tmp1, tmp2
+ return dp0
+```
+**特别注意**
+**k=n状态转移dp[i-1][k-1][0] - prices[i]**
+**冷冻期dp[i-2][0] - prices[i]**
+
+#### 买卖股票的最佳时机 III 买卖2次
+```python
+from typing import List
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ if not prices: return 0
+ # dp[i][k][0,1] 0 未持有 1 持有
+ dp = [[[0, 0] for i in range(3)] for i in range(len(prices))]
+ dp[0][1][0] = dp[0][2][0] = 0
+ dp[0][1][1] = dp[0][2][1] = -prices[0]
+ for i in range(1, len(prices)):
+ for k in range(1, 3):
+ dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]) # hold,sell
+ # 买入的时候计算次数
+ dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - prices[i]) # hold,buy
+ return dp[-1][-1][0]
+```
+
+#### 买卖股票的最佳时机 IV k指定
+```python
+class Solution:
+ def maxProfit(self, k: int, prices: List[int]) -> int:
+ def no_limit(prices):
+ res = 0
+ for i in range(1,len(prices)):
+ if prices[i] > prices[i-1]:
+ res += prices[i]-prices[i-1]
+ return res
+ #如果k值大于等于size/2,就等价于无限次,累加上升线条即可
+ size = len(prices)
+ if k > size/ 2:
+ return no_limit(prices)
+ #0 不持有 1持有
+ dp = [[[0] * 2 for _ in range(k+1)] for _ in range(size)]
+ for i in range(size):
+ for j in range(1, k+1):
+ if i == 0:
+ dp[i][j][0] = 0
+ dp[i][j][1] = -prices[i]
+ else:
+ #前一天持有并卖掉
+ dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1] + prices[i])#hold,sell
+ #前一天不持有,并买入,计入次数
+ dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0] - prices[i])#hold,buy
+ return dp[size-1][k][0]
+```
+
+#### 买卖股票的最佳时机V 冷冻期
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ # if not prices: return 0
+ # size = len(prices)
+ # dp = [[0]*2 for _ in range(size)]
+ # # 0不持有 1 持有
+ # dp[0][0],dp[0][1] = 0,-prices[0]
+ # for i in range(1,size):
+ # dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i])#hold,sell
+ # dp[i][1] = max(dp[i-1][1],dp[i-2][0] - prices[i])#hold,buy,如果i天买入,那么i-2天就不持有
+ # return dp[-1][0]
+ if not prices: return 0
+ size = len(prices)
+ dp0, dp1, dp2 = 0, -prices[0], 0
+ for price in prices:
+ tmp1 = max(dp0, dp1 + price)
+ tmp2 = max(dp1, dp2 - price )
+ tmp3 = dp0
+ dp0, dp1, dp2 = tmp1, tmp2, tmp3
+ return dp0
+```
+
+#### 买卖股票的最佳时机VI 含手续费
+```python
+class Solution:
+ def maxProfit(self, prices: List[int], fee: int) -> int:
+ # if not prices: return 0
+ # size = len(prices)
+ # dp = [[0]*2 for _ in range(size)]
+ # dp[0][0], dp[0][1] = 0, -prices[0]#0不持有 1持有
+ # for i in range(1,size):
+ # dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i] - fee)# hold, sell -fee
+ # dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i])#hold, buy
+ # return dp[-1][0]
+ #降维
+ size = len(prices)
+ dp0, dp1 = 0, -prices[0]
+ for price in prices:
+ tmp1 = max(dp0, dp1 + price - fee)
+ tmp2 = max(dp1, dp0 - price)
+ dp0, dp1 = tmp1, tmp2
+ return dp0
+```
+
+
+
+
+
+
+
+
diff --git a/Week07/.idea/Week07.iml b/Week07/.idea/Week07.iml
new file mode 100644
index 000000000..7c9d48f0f
--- /dev/null
+++ b/Week07/.idea/Week07.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week07/.idea/leetcode/editor.xml b/Week07/.idea/leetcode/editor.xml
new file mode 100644
index 000000000..0118ed9fc
--- /dev/null
+++ b/Week07/.idea/leetcode/editor.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week07/.idea/misc.xml b/Week07/.idea/misc.xml
new file mode 100644
index 000000000..399908725
--- /dev/null
+++ b/Week07/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week07/.idea/modules.xml b/Week07/.idea/modules.xml
new file mode 100644
index 000000000..bfa0e81e0
--- /dev/null
+++ b/Week07/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week07/.idea/vcs.xml b/Week07/.idea/vcs.xml
new file mode 100644
index 000000000..6c0b86358
--- /dev/null
+++ b/Week07/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week07/.idea/workspace.xml b/Week07/.idea/workspace.xml
new file mode 100644
index 000000000..cf13d5f45
--- /dev/null
+++ b/Week07/.idea/workspace.xml
@@ -0,0 +1,476 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1595247635043
+
+
+ 1595247635043
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week07/NOTE.md b/Week07/NOTE.md
index 50de30414..6be75b82b 100644
--- a/Week07/NOTE.md
+++ b/Week07/NOTE.md
@@ -1 +1,135 @@
-学习笔记
\ No newline at end of file
+学习笔记
+
+#### Trie树
+Trie树每个节点只存单一字符,每条路径存相对应的单词
+要实现三个方法insert、search、startwith
+```python
+from collections import defaultdict
+class TrieNode:
+ def __init__(self):
+ self.children = defaultdict(TrieNode)
+ self.is_word = False
+
+class Trie:
+ def __init__(self):
+ self.root = TrieNode()
+
+ def insert(self, word):
+ node = self.root
+ for ch in word:
+ node = node.children[ch]
+ node.is_word = True
+
+ def search(self, word):
+ node = self.root
+ for ch in word:
+ if ch in node.children:
+ node = node.children[ch]
+ else:
+ return False
+ return node.is_word
+
+ def startsWith(self, prefix):
+ node = self.root
+ for ch in prefix:
+ if ch in node.children:
+ node = node.children[ch]
+ else:
+ return False
+ return True
+```
+
+#### 单词搜索I
+判断单词是否在矩阵中
+从矩阵的任意位置出发,开始寻找
+DFS+回溯 时间复杂度为O(4MNMN)
+```python
+from typing import List
+class Solution:
+ def exist(self, board: List[List[str]], word: str) -> bool:
+ if not board: return False
+ m, n = len(board), len(board[0])
+ for i in range(m):
+ for j in range(n):
+ if self.dfs(i, j, board, word):
+ return True
+ return False
+
+ def dfs(self, i, j, board, word):
+ if len(word) == 0: return True
+ if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] != word[0]:
+ return # 回溯
+ tmp = board[i][j]
+ board[i][j] = '#' # 标志着已经选用过,到下一层哪怕选了 也是!=word[0],会回溯
+ res = self.dfs(i + 1, j, board, word[1:]) or self.dfs(i - 1, j, board, word[1:]) \
+ or self.dfs(i, j + 1, board,word[1:]) or self.dfs(i,j - 1,board,word[1:])
+ board[i][j] = tmp
+ return res
+```
+
+#### 单词搜索II
+和上一题意思差不多,只不过这次是判断字典中的字符串是否在矩阵中,输出在矩阵中的字符串
+可以还是照上面的思路 但是又要加一层循环,所以是O(K4MNMN),k是字典中字符串的个数
+在回溯的过程中,我们是对一个节点的四个兄弟节点判断完都不符合之后才能回溯,然后继续这样向上回溯
+但是在某个时刻 如果当前路径不是待求字符串的前缀,我们可以不用向下走了
+此时的时间复杂度是O(MN4*3^(L-1))
+从一个单元格开始,最初我们最多可以探索4个方向。
+假设每个方向都是有效的(即最坏情况),在接下来的探索中,我们最多有 3 个相邻的单元
+```python
+from typing import List
+class Solution:
+ def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
+ if not board or not board[0] or not words: return []
+ root = {}
+ for word in words:
+ node = root
+ for ch in word:
+ node = node.setdefault(ch,{})
+ node['end'] = 0 #将所有word构建为tree树
+ rows, cols = len(board), len(board[0])
+ res = set()
+ def dfs(i,j,root,s):
+ cur = board[i][j]
+ if cur not in root: return#剪枝
+ root = root[cur]#下探
+ if 'end' in root and root['end'] == 0:
+ res.add(s+cur)#到达叶节点,加入到结果集
+ board[i][j] = '@'#
+ for x,y in [[-1,0],[1,0],[0,1],[0,-1]]:
+ tmp_i,tmp_j = x + i, y + j
+ if 0 <= tmp_i < rows and 0 <= tmp_j < cols and board[tmp_i][tmp_j]!='@':
+ dfs(tmp_i,tmp_j,root,s + cur)
+ board[i][j] = cur#reverse state
+ for i in range(rows):
+ for j in range(cols):
+ dfs(i,j,root,'')
+ return list(res)
+```
+
+#### 并查集
+并查集是用来判断图中是否有环的算法
+需要实现两个函数 find 和 union
+```python
+SIZE = 7
+parent =[-1] * SIZE#-1代表指向自己,自己成环
+rank = [0] * SIZE#记录当前的深度
+def find(x, parent):#找到老大
+ node = x
+ while parent[node] != -1:
+ node = parent[node]
+ return node
+
+def union(x, y):#合并两个节点
+ x_root = find(x, parent)
+ y_root = find(y, parent)
+ if x_root == y_root:#如果老大是同一人
+ return
+ # parent[y_root] = x_root
+ if rank[x_root] > rank[y_root]:
+ parent[y_root] = x_root
+ elif rank[y_root] > rank[x_root]:
+ parent[x_root] = y_root
+ else:
+ parent[x_root] = y_root
+ rank[y_root] += 1
+```
\ No newline at end of file
diff --git "a/Week07/N\347\232\207\345\220\216.py" "b/Week07/N\347\232\207\345\220\216.py"
new file mode 100644
index 000000000..29ed99186
--- /dev/null
+++ "b/Week07/N\347\232\207\345\220\216.py"
@@ -0,0 +1,26 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/21 9:15 PM
+
+class Solution:
+ def solveNQueens(self, n: int) -> List[List[str]]:
+ # 皇后放置问题,八个数的全排列N! 所以时间复杂度就是N!,空间复杂度O(N)
+ # record记录皇后的放置情况
+ def dfs(row,record):
+ if row == n:
+ res.append(record)
+ return
+ for col in range(n):
+ if isvalid(row,col,record):
+ dfs(row+1,record+[col])
+ def isvalid(row,col,record):
+ if col in record:#这一行肯定不能被其他皇后占据
+ return False
+ for i in range(row):#判断是否在可攻击范围
+ # if row + col == i + record[i] or row - col == i - record[i]:
+ if i + record[i] == row + col or i - record[i] == row - col:
+ return False
+ return True
+ res = []
+ dfs(0,[])
+ return [['.' * i + 'Q' +'.'*(n-i-1) for i in row]for row in res]
\ No newline at end of file
diff --git "a/Week07/Trie\346\240\221.py" "b/Week07/Trie\346\240\221.py"
new file mode 100644
index 000000000..ede9976c8
--- /dev/null
+++ "b/Week07/Trie\346\240\221.py"
@@ -0,0 +1,50 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/20 8:20 PM
+
+
+# 节点不存完整单词
+# 从根节点到某一节点,路径上的字符连接起来为该节点的字符串
+# 每个节点的所有子节点路径代表不同的字符串
+# 需要实现三个方法1.insert、search、startwith
+from collections import defaultdict
+class TrieNode:
+ def __init__(self):
+ self.children = defaultdict(TrieNode)
+ self.is_word = False
+
+class Trie:
+ def __init__(self):
+ self.root = TrieNode()
+
+ def insert(self, word):
+ node = self.root
+ for ch in word:
+ node = node.children[ch]
+ node.is_word = True
+
+ def search(self, word):
+ node = self.root
+ for ch in word:
+ if ch in node.children:
+ node = node.children[ch]
+ else:
+ return False
+ return node.is_word
+
+ def startsWith(self, prefix):
+ node = self.root
+ for ch in prefix:
+ if ch in node.children:
+ node = node.children[ch]
+ else:
+ return False
+ return True
+
+
+
+# Your Trie object will be instantiated and called as such:
+# obj = Trie()
+# obj.insert(word)
+# param_2 = obj.search(word)
+# param_3 = obj.startsWith(prefix)
\ No newline at end of file
diff --git "a/Week07/\345\215\225\350\257\215\346\220\234\347\264\242I.py" "b/Week07/\345\215\225\350\257\215\346\220\234\347\264\242I.py"
new file mode 100644
index 000000000..2767cf5ce
--- /dev/null
+++ "b/Week07/\345\215\225\350\257\215\346\220\234\347\264\242I.py"
@@ -0,0 +1,58 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/24 10:17 PM
+
+
+# 给定一个二维网格和一个单词,找出该单词是否存在于网格中。
+#
+# 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
+#
+#
+#
+# 示例:
+#
+# board =
+# [
+# ['A','B','C','E'],
+# ['S','F','C','S'],
+# ['A','D','E','E']
+# ]
+#
+# 给定 word = "ABCCED", 返回 true
+# 给定 word = "SEE", 返回 true
+# 给定 word = "ABCB", 返回 false
+#
+#
+#
+# 提示:
+#
+#
+# board 和 word 中只包含大写和小写英文字母。
+# 1 <= board.length <= 200
+# 1 <= board[i].length <= 200
+# 1 <= word.length <= 10^3
+#
+# Related Topics 数组 回溯算法
+
+from typing import List
+class Solution:
+ def exist(self, board: List[List[str]], word: str) -> bool:
+ if not board: return False
+ m, n = len(board), len(board[0])
+ for i in range(m):
+ for j in range(n):
+ if self.dfs(i, j, board, word):
+ return True
+ return False
+
+ def dfs(self, i, j, board, word):
+ if len(word) == 0: return True
+ if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] != word[0]:
+ return # 回溯
+ tmp = board[i][j]
+ board[i][j] = '#' # 标志着已经选用过,到下一层哪怕选了 也是!=word[0],会回溯
+ res = self.dfs(i + 1, j, board, word[1:]) or self.dfs(i - 1, j, board, word[1:]) \
+ or self.dfs(i, j + 1, board,word[1:]) or self.dfs(i,j - 1,board,word[1:])
+ board[i][j] = tmp
+ return res
+
diff --git "a/Week07/\345\215\225\350\257\215\346\220\234\347\264\242II.py" "b/Week07/\345\215\225\350\257\215\346\220\234\347\264\242II.py"
new file mode 100644
index 000000000..215e708fe
--- /dev/null
+++ "b/Week07/\345\215\225\350\257\215\346\220\234\347\264\242II.py"
@@ -0,0 +1,62 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/20 9:40 PM
+
+# 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
+#
+# 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
+#
+#
+# 示例:
+#
+# 输入:
+# words = ["oath","pea","eat","rain"] and board =
+# [
+# ['o','a','a','n'],
+# ['e','t','a','e'],
+# ['i','h','k','r'],
+# ['i','f','l','v']
+# ]
+#
+# 输出: ["eat","oath"]
+#
+# 说明:
+# 你可以假设所有输入都由小写字母 a-z 组成。
+#
+# 提示:
+#
+#
+# 你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
+# 如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何
+# 实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。
+#
+# Related Topics 字典树 回溯算法
+from typing import List
+class Solution:
+ def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
+ if not board or not board[0] or not words: return []
+ root = {}
+ for word in words:
+ node = root
+ for ch in word:
+ node = node.setdefault(ch,{})
+ node['end'] = 0 #将所有word构建为tree树
+ rows, cols = len(board), len(board[0])
+ res = set()
+ def dfs(i,j,root,s):
+ cur = board[i][j]
+ if cur not in root: return#剪枝
+ root = root[cur]#下探
+ if 'end' in root and root['end'] == 0:
+ res.add(s+cur)#到达叶节点,加入到结果集
+ board[i][j] = '@'#
+ for x,y in [[-1,0],[1,0],[0,1],[0,-1]]:
+ tmp_i,tmp_j = x + i, y + j
+ if 0 <= tmp_i < rows and 0 <= tmp_j < cols and board[tmp_i][tmp_j]!='@':
+ dfs(tmp_i,tmp_j,root,s + cur)
+ board[i][j] = cur#reverse state
+ for i in range(rows):
+ for j in range(cols):
+ dfs(i,j,root,'')
+ return list(res)
+
diff --git "a/Week07/\345\271\266\346\237\245\351\233\206\346\250\241\346\235\277.py" "b/Week07/\345\271\266\346\237\245\351\233\206\346\250\241\346\235\277.py"
new file mode 100644
index 000000000..55d1cfd97
--- /dev/null
+++ "b/Week07/\345\271\266\346\237\245\351\233\206\346\250\241\346\235\277.py"
@@ -0,0 +1,29 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/20 11:12 PM
+
+
+
+SIZE = 7
+parent =[-1] * SIZE
+rank = [0] * SIZE
+# 并查集就是实现了两个方法 一个find一个union
+def find(x, parent):
+ node = x
+ while parent[node] != -1:
+ node = parent[node]
+ return node
+
+def union(x, y):
+ x_root = find(x, parent)
+ y_root = find(y, parent)
+ if x_root == y_root:
+ return
+ # parent[y_root] = x_root
+ if rank[x_root] > rank[y_root]:
+ parent[y_root] = x_root
+ elif rank[y_root] > rank[x_root]:
+ parent[x_root] = y_root
+ else:
+ parent[x_root] = y_root
+ rank[y_root] += 1
\ No newline at end of file
diff --git "a/Week07/\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" "b/Week07/\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py"
new file mode 100644
index 000000000..4a500f369
--- /dev/null
+++ "b/Week07/\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py"
@@ -0,0 +1,40 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/21 9:15 PM
+
+from typing import List
+class Solution:
+ def isValidSudoku(self, board: List[List[str]]) -> bool:
+ rows = [{} for i in range(9)]
+ cols = [{} for i in range(9)]
+ boxs = [{} for i in range(9)]
+
+ for i in range(9):
+ for j in range(9):
+ num = board[i][j]
+ if num != '.':
+ # num = int(num)
+ box = (i // 3) * 3 + j // 3
+
+ rows[i][num] = rows[i].get(num, 0) + 1
+ cols[j][num] = cols[j].get(num, 0) + 1
+ boxs[box][num] = boxs[box].get(num, 0) + 1
+
+ if rows[i][num] > 1 or cols[j][num] > 1 or boxs[box][num] > 1:
+ return False
+ return True
+
+ # rows = [set() for _ in range(9)]
+ # cols = [set() for _ in range(9)]
+ # boxs = [set() for _ in range(9)]
+ # for i in range(9):
+ # for j in range(9):
+ # box_index, num = i // 3 * 3 + j // 3, board[i][j]
+ # if num != '.':
+ # if num in rows[i] or num in cols[j] or num in boxs[box_index]:
+ # return False
+ # else:
+ # rows[i].add(num)
+ # cols[j].add(num)
+ # boxs[box_index].add(num)
+ # return True
\ No newline at end of file
diff --git "a/Week07/\346\234\213\345\217\213\345\234\210.py" "b/Week07/\346\234\213\345\217\213\345\234\210.py"
new file mode 100644
index 000000000..4faec387b
--- /dev/null
+++ "b/Week07/\346\234\213\345\217\213\345\234\210.py"
@@ -0,0 +1,45 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/20 10:58 PM
+
+from typing import List
+
+
+class Solution:
+ def findCircleNum(self, nums: List[List[int]]) -> int:
+ if not nums: return 0
+ def find(x):
+ node = x
+ while parent[node] != -1:
+ node = parent[node]
+ return node
+ def union(x, y):
+ x_root = find(x)
+ y_root = find(y)
+ if x_root == y_root:#如果根节点一致,结束此次
+ return
+ # parent[y_root] = x_root
+ if rank[x_root] > rank[y_root]: parent[y_root] = x_root
+ elif rank[y_root] > rank[x_root]: parent[x_root] = y_root
+ else:
+ parent[x_root] = y_root
+ rank[y_root] += 1
+ size = len(nums)
+ parent = [-1] * size
+ rank = [0] * size
+ for i in range(size):
+ for j in range(size):
+ if i != j and nums[i][j] == 1:
+ union(i, j)
+ count = 0
+ for i in parent:
+ if i < 0:
+ count += 1
+ return count
+
+nums = [[1,1,0],
+ [1,1,0],
+ [0,0,1]]
+s = Solution()
+res = s.findCircleNum(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week07/\347\273\204\345\220\210\346\200\273\345\222\214IV.py" "b/Week07/\347\273\204\345\220\210\346\200\273\345\222\214IV.py"
new file mode 100644
index 000000000..92a70a98d
--- /dev/null
+++ "b/Week07/\347\273\204\345\220\210\346\200\273\345\222\214IV.py"
@@ -0,0 +1,26 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/25 2:22 AM
+
+from typing import List
+class Solution:
+ def combinationSum4(self, nums: List[int], target: int) -> int:
+ # def dfs(cur,tmp):
+ # if cur > target: return
+ # if cur == target: res.append(tmp)
+ # for i in range(len(nums)):
+ # dfs(cur+nums[i],tmp+[nums[i]])
+ # res = []
+ # dfs(0,[])
+ # return len(res)
+ dp = [0]*(target+1)
+ dp[0] = 1
+ for i in range(target+1):
+ for j in range(len(nums)):
+ if i >= nums[j]:
+ dp[i] += dp[i-nums[j]]#这句话是有可能访问越界的
+ return dp[-1]
+
+s = Solution()
+res = s.combinationSum4([1,2,4],7)
+print(res)
\ No newline at end of file
diff --git "a/Week07/\350\247\243\346\225\260\347\213\254.py" "b/Week07/\350\247\243\346\225\260\347\213\254.py"
new file mode 100644
index 000000000..63da90af5
--- /dev/null
+++ "b/Week07/\350\247\243\346\225\260\347\213\254.py"
@@ -0,0 +1,51 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/21 9:15 PM
+
+from typing import List
+class Solution:
+ def solveSudoku(self, board: List[List[str]]) -> None:
+ cols = [set() for _ in range(9)]
+ rows = [set() for _ in range(9)]
+ boxs = [set() for _ in range(9)]
+ #预先扫描一次
+ for i in range(9):
+ for j in range(9):
+ if board[i][j] != '.':
+ cols[i].add(board[i][j])
+ rows[i].add(board[i][j])
+ boxs[i//3*3+j//3].add(board[i][j])
+
+ def dfs(i, j):
+ if board[i][j] != '.':
+ if i == 8 and j == 8:
+ self.flag = True
+ return
+ if j < 8:
+ dfs(i, j + 1)
+ else:
+ dfs(i + 1, 0)
+ return
+ for ch in range(1, 10):#对于每一个位置,用1-9试探
+ ch = str(ch)
+ if ch not in cols[j] and ch not in rows[i] and ch not in boxs[i // 3 * 3 + j // 3]:
+ #如果可以放置,更新三个set(),并将此刻的位置修改
+ cols[j].add(ch)
+ rows[i].add(ch)
+ boxs[i // 3][j // 3].add(ch)
+ board[i][j] = ch
+ if i == 8 and j == 8:
+ self.flag = True
+ return
+ if j < 8:
+ dfs(i, j + 1)
+ else:
+ dfs(i + 1, 0)
+ if self.flag: return
+ board[i][j] = '.'
+ cols[j].remove(ch)
+ rows[i].remove(ch)
+ boxs[i // 3][j // 3].remove(ch)
+
+ self.flag = False
+ dfs(0, 0)
diff --git "a/Week08/2\347\232\204\345\271\202.py" "b/Week08/2\347\232\204\345\271\202.py"
new file mode 100644
index 000000000..66eee7df2
--- /dev/null
+++ "b/Week08/2\347\232\204\345\271\202.py"
@@ -0,0 +1,16 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/27 9:00 PM
+
+class Solution:
+ def isPowerOfTwo(self, n: int) -> bool:
+ # if n==0: return False#与面试官沟通边界
+ # if n==1: return True
+ # while n!=1:
+ # if n%2!=0: return False
+ # else: n = n//2
+ # return True
+ # 该数的二进制位有且仅有一个1
+ if n==0: return False
+ while n!=0:
+ return (n&(n-1))==0 #打掉最后一个1看是否为0 以此检查是否只有一个1
\ No newline at end of file
diff --git a/Week08/LRUcache.py b/Week08/LRUcache.py
new file mode 100644
index 000000000..1fb601d00
--- /dev/null
+++ b/Week08/LRUcache.py
@@ -0,0 +1,121 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/27 11:21 PM
+
+# hashmap+double-linklist
+
+class ListNode:
+ def __init__(self,key,val):
+ self.key = key
+ self.val = val
+ self.next = None
+ self.prev = None
+
+class LRUCache:
+ def __init__(self, capacity: int):
+ self.dic = {}
+ self.head = ListNode(None,None)
+ self.tail = ListNode(None,None)
+ self.head.next = self.tail
+ self.tail.prev = self.head
+ self.capacity = capacity
+
+ def get(self, key: int) -> int:
+ if not key in self.dic:
+ return -1
+ node = self.dic[key]
+ self.delete(node)#访问过后要将它放到链表头部
+ self.insert(node)
+ return node.val
+
+ def insert(self,node):
+ node.next, node.prev = self.head.next, self.head
+ temp = self.head.next
+ self.head.next = node
+ temp.prev = node
+
+ def delete(self,node):
+ node.prev.next, node.next.prev = node.next, node.prev
+
+ def put(self, key: int, value: int) -> None:
+ if key in self.dic:#如果相同key值出现过,更新dic和链表
+ node = self.dic[key]
+ node.val = value
+ self.delete(node)
+ self.insert(node)
+ return
+ if len(self.dic) == self.capacity:
+ node=self.tail.prev#删除第一个元素
+ self.delete(node)
+ del self.dic[node.key]
+ self.capacity -= 1
+ node = ListNode(key,value)#将此元素加入到第一个元素
+ self.dic[key] = node
+ self.insert(node)
+ self.capacity += 1
+
+
+
+# Your LRUCache object will be instantiated and called as such:
+# obj = LRUCache(capacity)
+# param_1 = obj.get(key)
+# obj.put(key,value)
+
+class ListNode:
+ def __init__(self, key, val):
+ self.key = key
+ self.val = val
+ self.next = None
+ self.pre = None
+
+
+class LRUCache:
+ def __init__(self, capacity):
+ self.dic = {}
+ self.capacity = capacity
+ self.head = ListNode(None, None)
+ self.tail = ListNode(None, None)
+ self.head.next = self.tail
+ self.tail.pre = self.head
+
+ def put(self, key, value):
+ # 先判断要放进去的元素是否在hashmap里面
+ if key not in self.dic: # 如果不在里面
+ if self.capacity != 0: # 如果不在里面且还有额外的空间,就往里加
+ self.insert(key, value)
+ else: # 没有额外的空间了,就应当删除双向链表中的最后一个元素
+ last = self.tail.pre
+ self.delete(last)
+ self.insert(key, value)
+ else: # 如果在里面
+ # 应当先删除这个元素/更新
+ cur = self.dic[key]
+ self.delete(cur) # 删除这一个
+ self.insert(key, value)
+
+ def get(self, key):
+ if key not in self.dic:
+ return -1
+ else:
+ # 将该元素放到head之后
+ cur = self.dic[key]
+ value = cur.val
+ self.delete(cur)
+ self.insert(key, value)
+ return value
+
+ def delete(self, node):
+ node.pre.next = node.next
+ node.next.pre = node.pre
+ del self.dic[node.key]
+ self.capacity += 1
+
+ def insert(self, key, value):
+ cur = ListNode(key, value)
+ cur.next = self.head.next
+ cur.pre = self.head
+ tmp = self.head.next
+ tmp.pre = cur
+ self.head.next = cur
+ self.capacity -= 1
+ self.dic[key] = cur
\ No newline at end of file
diff --git a/Week08/NOTE.md b/Week08/NOTE.md
index 50de30414..b391dd469 100644
--- a/Week08/NOTE.md
+++ b/Week08/NOTE.md
@@ -1 +1,339 @@
-学习笔记
\ No newline at end of file
+学习笔记
+判断奇偶
+x&1 == 1 if odd else even
+x = x & (x-1) 清除最右的1
+x = x & (-x) 得到最右的1
+
+#### 位为1的个数
+给一个无符号整数,返回其二进制表示中1的个数
+1. 先转二进制,匹配二进制字符串中1的个数,最后返回
+```python
+class Solution:
+ def hammingWeight(self, n: int) -> int:
+ tmp = bin(n)[2:]
+ count = 0
+ for i in range(len(tmp)):
+ if tmp[i] == '1':
+ count += 1
+ return count
+```
+2.判断最低位是否为1,然后右移一位,继续判断
+```python
+class Solution:
+ def hammingWeight(self, n: int) -> int:
+ count = 0
+ while n!=0:
+ if n & 1 == 1:#判断最低位是否为1
+ count += 1
+ n = n >>1
+ return count
+```
+3.直接找到最低位的1,看能找几次
+```python
+class Solution:
+ def hammingWeight(self, n: int) -> int:
+ count = 0
+ while n!=0:
+ n = n & (n-1)#清除最低位的1
+ count += 1
+ return count
+```
+
+#### 二的幂
+判断是否是2的幂次
+1.辗转相除法,直到结果为1为止
+```python
+class Solution:
+ def isPowerOfTwo(self, n: int) -> bool:
+ if n==0: return False#与面试官沟通边界
+ if n==1: return True
+ while n!=1:
+ if n%2!=0: return False
+ else: n = n//2
+ return True
+```
+2.如果是2的幂次,那么其二进制位应该有且仅有一个1.
+```python
+class Solution:
+ def isPowerOfTwo(self, n: int) -> bool:
+ if n==0: return False
+ while n!=0:
+ return (n&(n-1))==0 #打掉最后一个1看是否为0 以此检查是否只有一个1
+```
+
+#### 颠倒二进制位
+想法是将二进制位里面的第i为调换到31-i位上,然后用加法累计所有位的调换
+从右向左遍历,然后将数左移以调换
+
+```python
+class Solution:
+ def reverseBits(self, n: int) -> int:
+ res,power= 0,31
+ while n:
+ res += (n&1)<>1#以取得新的最后一位
+ power -= 1
+ return res
+```
+
+#### 布隆过滤器
+布隆过滤器常用作 防止缓存击穿情况的出现 预先判断数据是否存在数据库中,可以缓解对数据库的压力
+布隆过滤器的思想是,利用一个二进制数组,对于任何一个value,我们都给他它分配一个定长的k位二进制数,可以不连续
+每次有元素进来,就使用特定的hash函数生成k个01,代表它的二进制描述,
+在查找的时候,如果待查元素不在布隆过滤器中,说明一定不存在,反之说明可能存在
+```python
+from bitarray import bitarray
+import mmh3
+class BooleanFilter:
+ def __init__(self,size,hash_num):
+ self.size = size
+ self.hash_num = hash_num
+ self.bit_array = bitarray
+ self.bit_array.setall(0)
+ def get(self,x):
+ for seed in range(self.hash_num):
+ result = mmh3.hash(x,seed)%self.size#用k位二进制表示是否存在
+ self.bit_array[result] = 1
+ def lookup(self,x):
+ for seed in range(self.hash_num):#检查x的每一位的0,1,只要不是1,就不在
+ result = mmh3.hash(x,seed)%self.size
+ if self.bit_array[result] != 1:
+ return 'not in'
+ return 'probably in'
+```
+
+#### LRUcache
+最近最久未使用算法,例如手机后台切换的时候看到的算法
+实现起来是利用hash表+双向链表
+注意到这个双向链表维护了两个节点并不存值,是head和tail
+每次有新的元素进来,如果capicity还有容量,就加入到双向链表**首部**
+如果没有容量了,就从双向链表末尾删除一个元素
+如果新进来的元素在双向链表中[这就是为什么要使用hash表的原因,查在不在hash表中O(1)]
+就先拿出来,修改值,再插入到双向链表**首部**
+>实现的时候就是要实现两个函数insert和delete
+
+```python
+class ListNode:
+ def __init__(self,key,val):
+ self.key = key
+ self.val = val
+ self.next = None
+ self.prev = None
+
+class LRUCache:
+ def __init__(self, capacity: int):
+ self.dic = {}
+ self.head = ListNode(None,None)
+ self.tail = ListNode(None,None)
+ self.head.next = self.tail
+ self.tail.prev = self.head
+ self.capacity = capacity
+
+ def get(self, key: int) -> int:
+ if not key in self.dic:
+ return -1
+ node = self.dic[key]
+ self.delete(node)#访问过后要将它放到链表头部
+ self.insert(node)
+ return node.val
+
+ def insert(self,node):
+ node.next, node.prev = self.head.next, self.head
+ temp = self.head.next
+ self.head.next = node
+ temp.prev = node
+
+ def delete(self,node):
+ node.prev.next, node.next.prev = node.next, node.prev
+
+ def put(self, key: int, value: int) -> None:
+ if key in self.dic:#如果相同key值出现过,更新dic和链表
+ node = self.dic[key]
+ node.val = value
+ self.delete(node)
+ self.insert(node)
+ return
+ if len(self.dic) == self.capacity:
+ node=self.tail.prev#删除第一个元素
+ self.delete(node)
+ del self.dic[node.key]
+ node = ListNode(key,value)#将此元素加入到第一个元素
+ self.dic[key] = node
+ self.insert(node)
+```
+
+#### 归并排序
+归并排序的思想就是分治到单个元素,然后回头 治理 回头的时候就有左右两个子数组已经有序了
+主要就是实现的时候需要用额外的空间
+```python
+class Solution:
+ def merge_sort(self, nums):
+ if len(nums)<2:
+ return nums
+ mid = len(nums)//2
+ nums1 = nums[:mid]
+ nums2 = nums[mid:]
+ return self.merge(self.merge_sort(nums1), self.merge_sort(nums2))
+
+ def merge(self, nums1, nums2):
+ res = []
+ while nums1 and nums2:
+ if nums1[0] <= nums2[0]:
+ res.append(nums1.pop(0))
+ else:
+ res.append(nums2.pop(0))
+ while nums1:
+ res.append(nums1.pop(0))
+ while nums2:
+ res.append(nums2.pop(0))
+ return res
+```
+#### 快速排序
+快速排序的思想是界定一个pivot,找到左边比pivot大的找到右边比pivot小的,交换
+使得每一轮排序后,左右数组符合左数组= right:
+ return
+ ind = left + ((right-left) >> 1)
+ pivot = self.partition(nums, left, right, nums[ind])
+ self.quick_sort(nums, left, pivot-1) #左
+ self.quick_sort(nums, pivot, right) #右
+
+ def partition(self, nums, left, right, pivot):
+ while left <= right:
+ while nums[left] < pivot:
+ left += 1
+ while nums[right] > pivot:
+ right -= 1
+ if left <= right:
+ nums[left], nums[right] = nums[right], nums[left]
+ left, right = left + 1, right - 1
+ return left
+```
+
+#### 堆排序
+首先从右往左遍历,使得每个小三角的顶最大,这是建堆
+前边建堆nums[0]最大,我们把最大的元素与末尾交换,然后调整堆[只用调整除末尾元素外的]
+```python
+class Solution:
+ def heap_sort(self, nums):
+ self.build_heap(nums)
+ for i in range(len(nums)-1,-1,-1):#调整堆的时候将最大的元素nums[0]放到最后面,
+ nums[i],nums[0] = nums[0],nums[i]
+ self.heapify(nums,i,0)
+
+ def build_heap(self, nums):#使得每个小三角形都是顶最大
+ for i in range(len(nums)-1//2,-1,-1):
+ self.heapify(nums,len(nums), i)
+
+ def heapify(self, nums, n, i):
+ if i >= n: return
+ c1, c2 = i*2+1, i*2+2
+ ind = i
+ if c1 < n and nums[c1] > nums[ind]:
+ ind = c1
+ if c2 < n and nums[c2] > nums[ind]:
+ ind = c2
+ if ind != i:
+ nums[i], nums[ind] = nums[ind], nums[i]
+ self.heapify(nums,n,ind) #调整堆之后要继续保持堆的特性
+```
+
+
+#### 数组的相对排序
+就是把arr1的元素按这样的规律排序:如果arr1[i]在arr2中,就将其在arr2中的相对位置排序
+如果不在,则按大小排序
+思路就是,将arr1元素记录在hashmap中,遍历arr2,修改arr1,这样必然可以满足在arr2中的元素,按其在arr2中的顺序排序
+对于不在的,拿出来排序再赋值到arr1中
+```python
+class Solution:
+ def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
+ hashmap = {}
+ for i, num in enumerate(arr1):
+ hashmap[num] = hashmap.get(num,0) + 1
+ ind = 0
+ for i in range(len(arr2)):
+ cur = arr2[i]
+ while hashmap.get(cur) > 0:
+ arr1[ind] = cur
+ hashmap[cur] -= 1
+ ind += 1
+ # 将不在arr2中的元素升序排列,但由于不是有序字典
+ tmp = []
+ for key, val in hashmap.items():
+ while val > 0:
+ tmp.append(key)
+ hashmap[key] -= 1
+ val -= 1
+ tmp.sort()
+ arr1[ind:] = tmp
+ # return arr1[:ind] + tmp
+ return arr1
+```
+
+#### 区间合并
+给定一个区间集合,合并所有重叠的区间
+这一题如果没做过,真不简单
+秒解是 **先按照左区间排好序** 这样有两个好处
+1所有可以合并的区间必然相连 2合并时只用看前边的区间右值与当前区间的左值的大小
+```python
+class Solution:
+ def merge(self, intervals: List[List[int]]) -> List[List[int]]:
+ #按区间左端点值进行排序,那么能合并的区间必然相连
+ intervals.sort(key=lambda x:x[0])
+ res = []
+ for interval in intervals:
+ if not res or res[-1][1] < interval[0]:#res[-1]区间右值小于起始值
+ res.append(interval)
+ else:#否则更新右值
+ res[-1][1] = max(res[-1][1],interval[1])
+ return res
+```
+
+#### 493 翻转对
+
+#### 315 计算右侧小于当前元素的个数
+
+#### 剑指offer51 数组中的逆序数对
+```python
+class Solution:
+ def reversePairs(self, nums: List[int]) -> int:
+ size = len(nums)
+ if size < 2:
+ return 0
+ temp = [0 for _ in range(size)]
+ return self.reverse_pairs(nums, 0, size - 1, temp)
+
+ def reverse_pairs(self, nums, left, right, temp):#在数组 nums 的区间 [l,r] 统计逆序对
+ if left == right:
+ return 0
+ mid = left + ((right-left) >> 1)
+ lpairs = self.reverse_pairs(nums, left, mid, temp)
+ rpairs = self.reverse_pairs(nums, mid + 1, right, temp)
+ cross_pairs = self.merge_and_count(nums, left, mid, right, temp)
+ return lpairs + rpairs + cross_pairs
+
+ def merge_and_count(self, nums, left, mid, right, temp):
+ for i in range(left, right + 1):
+ temp[i] = nums[i]
+ i,j,count = left, mid+1,0
+ for k in range(left, right + 1):
+ if i == mid + 1:#左侧处理完之后
+ nums[k] = temp[j]
+ j += 1
+ elif j == right + 1:#右侧处理完之后
+ nums[k] = temp[i]
+ i += 1
+ elif temp[i] <= temp[j]:#前边的小,不用计数,将前边的值归并到temp中
+ nums[k] = temp[i]
+ i += 1
+ else:
+ nums[k] = temp[j]#后边的小,将后边的值归并到tmp中,累计计数值
+ j += 1
+ count += (mid - i + 1)#
+ return count
+
+```
+
diff --git a/Week08/selftest.py b/Week08/selftest.py
new file mode 100644
index 000000000..793f6795a
--- /dev/null
+++ b/Week08/selftest.py
@@ -0,0 +1,135 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/31 7:03 PM
+
+class SolutionI:
+
+ def merge_sort(self,nums):
+ # 递归终止条件 左右子数组长度为1的时候返回该数组
+ if len(nums) <2: return nums
+ #归并排序 左右都已经排好序合并两个
+ mid = len(nums)//2
+ # nums1 = nums[:mid]
+ # nums2 = nums[mid:]
+ return self.merge(self.merge_sort(nums[:mid]),self.merge_sort(nums[mid:]))
+
+
+ def merge(self,nums1,nums2):
+ res = []
+ while nums1 and nums2:
+ if nums1[0] > nums2[0]:
+ res.append(nums2.pop(0))
+ else:
+ res.append(nums1.pop(0))
+
+ while nums1:
+ res.append(nums1.pop(0))
+ while nums2:
+ res.append(nums2.pop(0))
+ return res
+
+
+class SolutionII:
+
+ def quicksort(self,nums,left,right):
+ #快速排序,partition返回下标
+ # left,right = 0, len(nums)
+ if left >= right: return
+ # pivot = nums[mid]
+ mid = left + ((right-left)>>1)
+ pivot = self.partition(nums,left,right,nums[mid])
+ self.quicksort(nums,left,pivot-1)#左
+ self.quicksort(nums,pivot,right)#右
+ return nums
+
+ def partition(self,nums,left,right,pivot):
+ while left <= right:
+ while nums[left] < pivot:
+ left += 1
+ while nums[right] > pivot:
+ right -= 1
+ if left <= right:
+ nums[left],nums[right] = nums[right],nums[left]
+ left,right = left+1,right-1
+ return left
+
+
+class SolutionIII:
+ def heapsort(self,nums):
+ self.build_heap(nums)
+ for i in range(len(nums)-1,-1,-1):#从后往前遍历,把最大的放到最后
+ #这里要交换!
+ nums[i],nums[0] = nums[0],nums[i]
+ self.heapify(nums,i,0)
+
+ def build_heap(self,nums):
+ for i in range(len(nums)//2):#建堆错了没??,应该是从后往前建堆,因为后面的堆调整后要继续向前
+ self.heapify(nums,len(nums),i)
+
+ def heapify(self,nums,n,i):
+ #少了递归终止条件
+ if i >= n: return
+ c1,c2 = i*2+1,i*2+2
+ max_ind = i
+ #堆排序内部,是没有for循环的只有递归
+ if c1 < n and nums[c1] > nums[max_ind]:
+ max_ind = c1
+ if c2 < n and nums[c2] > nums[max_ind]:
+ max_ind = c2
+ if i != max_ind:#这里的条件记清楚了!
+ nums[max_ind], nums[i] = nums[i], nums[max_ind]
+ self.heapify(nums, n, max_ind)#调整后继续维持堆
+
+
+s = SolutionI()
+nums = [2, 3, 1, 4, 2, 5, 6, 8, 6, 5, 7]
+res = s.merge_sort(nums)
+print(res)
+
+
+# 1.想办法合并这几个数组,合并的规则是
+# merge =[0,...,max_n]
+# [a1...a2] [b1...b2]
+def maxK(nums,n):
+ #但是这种方法不能解决 15 23 15 24 的情形,所以要动态的创建set,依次判断是否在set中
+ # 即使是 15 23 15 24
+ # 求出所有课程中耗时最长的,构建一个数组存放,记录课程起止时间出现的次数,返回数组中的最大计数
+ size = max(max(nums))
+ tmp = [0]*(size+1)
+ for num in nums:
+ for cur in num:
+ tmp[cur] += 1
+ return max(tmp)
+
+
+# 2.最终奖励值 等于自己选的 加上 从剩余的中选的最大值 |或者干脆就不选,如果不选,其他人的奖励值就只由取到的奖券面额决定
+# f[n] = f[n-1]+nums[n] f[n]代表第n-1个同学能拿到的最大面值
+# 动态规划方程出来了
+
+
+size = 40
+a = 30
+b = 10
+
+def tickets(size,a,b):#a,b分指50 和 100
+ count = 0
+ start = 1
+
+ return count
+
+
+def dfs(size, a, b, cur, count, start):
+ if cur < 0: return
+ if start == size: return count
+ cur += 50
+ while start < size:
+ dfs(size,a - 1,b,cur,count)
+
+
+
+
+
+
+
+
+
diff --git "a/Week08/\344\271\260\347\245\250\346\246\202\347\216\207\351\227\256\351\242\230.py" "b/Week08/\344\271\260\347\245\250\346\246\202\347\216\207\351\227\256\351\242\230.py"
new file mode 100644
index 000000000..31c4ce3ca
--- /dev/null
+++ "b/Week08/\344\271\260\347\245\250\346\246\202\347\216\207\351\227\256\351\242\230.py"
@@ -0,0 +1,36 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/1 9:39 PM
+
+from functools import lru_cache
+class Solution:
+ # @lru_cache
+ def buy_tickets(self, m, n):# m,n 分别代表50,100
+ # 假设第m+n个人手持100,则他前面有m个手持50,n-1个手持100 则f(m,n) = f(m,n-1)
+ # m+n手持50.他前面m-1个手持50,n个手持100 f(m,n) = f(m-1,n)
+ # m 0; n=0 -> 1
+ res = 0
+ if n == 0:
+ return 1
+ elif m < n:
+ return 0
+ else:
+ res = self.buy_tickets(m,n-1) + self.buy_tickets(m-1,n)
+ return res
+ def buy_ticketsI(self,m,n):
+ dp = [[0]*(n+1) for _ in range(m+1)]
+ for col in range(n+1):
+ dp[0][col] = 0
+ for row in range(m+1):
+ dp[row][0] = 1
+ for i in range(1,m+1):
+ for j in range(1,n+1):
+ if i < j: dp[i][j] = 0
+ else:
+ dp[i][j] = dp[i-1][j] + dp[i][j-1]
+ return dp[-1][-1]
+
+
+s = Solution()
+res = s.buy_ticketsI(20,10)
+print(res)
diff --git "a/Week08/\344\275\2151\347\232\204\344\270\252\346\225\260.py" "b/Week08/\344\275\2151\347\232\204\344\270\252\346\225\260.py"
new file mode 100644
index 000000000..5e689827f
--- /dev/null
+++ "b/Week08/\344\275\2151\347\232\204\344\270\252\346\225\260.py"
@@ -0,0 +1,23 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/27 8:59 PM
+class Solution:
+ def hammingWeight(self, n: int) -> int:
+ # 笨方法
+ # tmp = bin(n)[2:]
+ # count = 0
+ # for i in range(len(tmp)):
+ # if tmp[i] == '1':
+ # count += 1
+ # return count
+ # count = 0
+ # while n!=0:
+ # if n & 1 == 1:#判断最低位是否为1
+ # count += 1
+ # n = n >>1
+ # return count
+ count = 0
+ while n!=0:
+ n = n & (n-1)#清除最低位的1
+ count += 1
+ return count
\ No newline at end of file
diff --git "a/Week08/\345\206\222\346\263\241\346\216\222\345\272\217.py" "b/Week08/\345\206\222\346\263\241\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..df9e51763
--- /dev/null
+++ "b/Week08/\345\206\222\346\263\241\346\216\222\345\272\217.py"
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/28 8:08 PM
+
+# 冒泡排序是稳定的
+class Solution:
+ def bubblesort(self,nums):
+ for i in range(len(nums)):
+ for j in range(i,len(nums)):
+ if nums[i]>nums[j]:
+ nums[i],nums[j] = nums[j],nums[i]
+
+
+s = Solution()
+nums = [2,3,1,4,2,5,6,8,6,5,7]
+s.bubblesort(nums)
+print(nums)
\ No newline at end of file
diff --git "a/Week08/\345\220\210\345\271\266\345\214\272\351\227\264.py" "b/Week08/\345\220\210\345\271\266\345\214\272\351\227\264.py"
new file mode 100644
index 000000000..2e8d854d8
--- /dev/null
+++ "b/Week08/\345\220\210\345\271\266\345\214\272\351\227\264.py"
@@ -0,0 +1,24 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/2 11:55 AM
+
+from typing import List
+class Solution:
+ def merge(self, intervals: List[List[int]]) -> List[List[int]]:
+ #按区间左端点值进行排序,那么能合并的区间必然相连
+ intervals.sort(key=lambda x:x[0])
+ print(intervals)
+ res = []
+ for interval in intervals:
+ if not res or res[-1][1] < interval[0]:#区间右值小于起始值
+ res.append(interval)
+ else:#否则更新右值
+ res[-1][1] = max(res[-1][1],interval[1])
+ print(res)
+ return res
+
+
+s = Solution()
+nums = [[1,3],[2,6],[8,10],[15,18]]
+res = s.merge(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week08/\345\240\206\346\216\222\345\272\217.py" "b/Week08/\345\240\206\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..4336c79fe
--- /dev/null
+++ "b/Week08/\345\240\206\346\216\222\345\272\217.py"
@@ -0,0 +1,33 @@
+# # -*- coding:utf-8 -*-
+# # Author : Ray
+# # Data : 2020/7/28 9:04 PM
+#
+# 不稳定
+class Solution:
+ def heap_sort(self, nums):
+ self.build_heap(nums)
+ for i in range(len(nums)-1,-1,-1):#调整堆的时候将最大的元素nums[0]放到最后面,
+ nums[i],nums[0] = nums[0],nums[i]
+ self.heapify(nums,i,0)
+
+ def build_heap(self, nums):#使得每个小三角形都是顶最大
+ for i in range(len(nums)-1//2,-1,-1):
+ self.heapify(nums,len(nums), i)
+
+ def heapify(self, nums, n, i):
+ if i >= n: return
+ c1, c2 = i*2+1, i*2+2
+ ind = i
+ if c1 < n and nums[c1] > nums[ind]:
+ ind = c1
+ if c2 < n and nums[c2] > nums[ind]:
+ ind = c2
+ if ind != i:
+ nums[i], nums[ind] = nums[ind], nums[i]
+ self.heapify(nums,n,ind) #调整堆之后要继续保持堆的特性
+
+
+s = Solution()
+nums = [2,3,1,4,2,5,6,8,6,5,7]
+s.heap_sort(nums)
+print(nums)
diff --git "a/Week08/\345\270\203\351\232\206\350\277\207\346\273\244\345\231\250.py" "b/Week08/\345\270\203\351\232\206\350\277\207\346\273\244\345\231\250.py"
new file mode 100644
index 000000000..69de1aa6b
--- /dev/null
+++ "b/Week08/\345\270\203\351\232\206\350\277\207\346\273\244\345\231\250.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/27 11:11 PM
+
+from bitarray import bitarray
+import mmh3
+class BooleanFilter:
+ def __init__(self,size,hash_num):
+ self.size = size
+ self.hash_num = hash_num
+ self.bit_array = bitarray
+ self.bit_array.setall(0)
+ def get(self,x):
+ for seed in range(self.hash_num):
+ result = mmh3.hash(x,seed)%self.size#用k位二进制表示是否存在
+ self.bit_array[result] = 1
+ def lookup(self,x):
+ for seed in range(self.hash_num):
+ result = mmh3.hash(x,seed)%self.size
+ if self.bit_array[result] != 1:
+ return 'not in'
+ return 'probably in'
\ No newline at end of file
diff --git "a/Week08/\345\275\222\345\271\266\346\216\222\345\272\217.py" "b/Week08/\345\275\222\345\271\266\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..74075efd2
--- /dev/null
+++ "b/Week08/\345\275\222\345\271\266\346\216\222\345\272\217.py"
@@ -0,0 +1,35 @@
+# # -*- coding:utf-8 -*-
+# # Author : Ray
+# # Data : 2020/7/28 8:44 PM
+#
+# 归并排序的思想是将数组分作AB两区,AB两区都区内有序之后,合并这两个区
+# 如果归并的时候 有相同的值,将左侧的放到tmp中就是稳定的
+class Solution:
+ def merge_sort(self, nums):
+ if len(nums)<2:
+ return nums
+ mid = len(nums)//2
+ nums1 = nums[:mid]
+ nums2 = nums[mid:]
+ return self.merge(self.merge_sort(nums1), self.merge_sort(nums2))
+
+ def merge(self, nums1, nums2):
+ res = []
+ while nums1 and nums2:
+ if nums1[0] <= nums2[0]:
+ res.append(nums1.pop(0))
+ else:
+ res.append(nums2.pop(0))
+ while nums1:
+ res.append(nums1.pop(0))
+ while nums2:
+ res.append(nums2.pop(0))
+ return res
+
+
+s = Solution()
+nums = [2,3,1,4,2,5,6,8,6,5,7]
+res = s.merge_sort(nums)
+print(res)
+
+
diff --git "a/Week08/\345\277\253\351\200\237\346\216\222\345\272\217.py" "b/Week08/\345\277\253\351\200\237\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..993fbbe03
--- /dev/null
+++ "b/Week08/\345\277\253\351\200\237\346\216\222\345\272\217.py"
@@ -0,0 +1,33 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/28 8:31 PM
+
+
+# 快速排序的思想是在数组中找一个pivot使得左边比pivot小,右边比pivot大,然后对左右两侧元素同逻辑处理
+# 也是不稳定的
+class Solution:
+ def quick_sort(self, nums, left, right):
+ if left >= right:
+ return
+ ind = left + ((right-left) >> 1)
+ pivot = self.partition(nums, left, right, nums[ind])
+ self.quick_sort(nums, left, pivot-1) #左
+ self.quick_sort(nums, pivot, right) #右
+
+ def partition(self, nums, left, right, pivot):
+ while left <= right:
+ while nums[left] < pivot:
+ left += 1
+ while nums[right] > pivot:
+ right -= 1
+ if left <= right:
+ nums[left], nums[right] = nums[right], nums[left]
+ left, right = left + 1, right - 1
+ return left
+
+
+
+s = Solution()
+nums = [2,3,1,4,2,5,6,8,6,5,7]
+s.quick_sort(nums,0,len(nums)-1)
+print(nums)
\ No newline at end of file
diff --git "a/Week08/\346\217\222\345\205\245\346\216\222\345\272\217.py" "b/Week08/\346\217\222\345\205\245\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..f2a84d983
--- /dev/null
+++ "b/Week08/\346\217\222\345\205\245\346\216\222\345\272\217.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/28 8:15 PM
+
+
+# 插入排序的思想是,假设数组分作两区,A区一直有序,每次从B区中取出元素,插入A区的合适位置
+# 所以是不稳定的
+class Solution:
+ def insertsort(self, nums):
+ for i in range(1,len(nums)):
+ tmp, j = nums[i], i - 1#j要在A区中找到合适位置【往前找】,同时还要挪动其他元素
+ while j >= 0 and nums[j] > tmp:
+ nums[j+1] = nums[j]
+ j -= 1
+ nums[j+1] = tmp
+
+
+
+s = Solution()
+nums = [2, 3, 1, 4, 2, 5, 6, 8, 6, 5, 7]
+s.insertsort(nums)
+print(nums)
diff --git "a/Week08/\346\225\260\347\273\204\344\270\255\347\232\204\351\200\206\345\272\217\345\257\271.py" "b/Week08/\346\225\260\347\273\204\344\270\255\347\232\204\351\200\206\345\272\217\345\257\271.py"
new file mode 100644
index 000000000..918496501
--- /dev/null
+++ "b/Week08/\346\225\260\347\273\204\344\270\255\347\232\204\351\200\206\345\272\217\345\257\271.py"
@@ -0,0 +1,51 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/2 8:07 PM
+
+from typing import List
+# 前有序数组中元素出列的时候,计算逆序个数
+
+from typing import List
+
+
+class Solution:
+ def reversePairs(self, nums: List[int]) -> int:
+ size = len(nums)
+ if size < 2:
+ return 0
+ temp = [0 for _ in range(size)]
+ return self.reverse_pairs(nums, 0, size - 1, temp)
+
+ def reverse_pairs(self, nums, left, right, temp):#在数组 nums 的区间 [l,r] 统计逆序对
+ if left == right:
+ return 0
+ mid = left + ((right-left) >> 1)
+ lpairs = self.reverse_pairs(nums, left, mid, temp)
+ rpairs = self.reverse_pairs(nums, mid + 1, right, temp)
+ cross_pairs = self.merge_and_count(nums, left, mid, right, temp)
+ return lpairs + rpairs + cross_pairs
+
+ def merge_and_count(self, nums, left, mid, right, temp):
+ for i in range(left, right + 1):
+ temp[i] = nums[i]
+ i,j,count = left, mid+1,0
+ for k in range(left, right + 1):
+ if i == mid + 1:#左侧处理完之后
+ nums[k] = temp[j]
+ j += 1
+ elif j == right + 1:#右侧处理完之后
+ nums[k] = temp[i]
+ i += 1
+ elif temp[i] <= temp[j]:#前边的小,不用计数,将前边的值归并到temp中
+ nums[k] = temp[i]
+ i += 1
+ else:
+ nums[k] = temp[j]#后边的小,将后边的值归并到tmp中,累计计数值
+ j += 1
+ count += (mid - i + 1)#
+ return count
+
+
+s = Solution()
+res = s.reversePairs(nums=[5,2,6,1])
+print(res)
\ No newline at end of file
diff --git "a/Week08/\346\225\260\347\273\204\347\232\204\347\233\270\345\257\271\346\216\222\345\272\217.py" "b/Week08/\346\225\260\347\273\204\347\232\204\347\233\270\345\257\271\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..3ee814bba
--- /dev/null
+++ "b/Week08/\346\225\260\347\273\204\347\232\204\347\233\270\345\257\271\346\216\222\345\272\217.py"
@@ -0,0 +1,39 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/2 11:00 AM
+
+from typing import List
+class Solution:
+ def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
+ # 双指针,左指针向后找不在arr2中的元素,右指针向前找到在arr2中的元素,交换left++right
+ hashmap = {}
+ for i, num in enumerate(arr1):
+ hashmap[num] = hashmap.get(num,0) + 1
+ ind = 0
+ for i in range(len(arr2)):
+ cur = arr2[i]
+ while hashmap.get(cur) > 0:
+ arr1[ind] = cur
+ hashmap[cur] -= 1
+ ind += 1
+ # 将不在arr2中的元素升序排列,如何保证升序???
+ print(hashmap)
+ tmp = []
+ for key, val in hashmap.items():
+ # if val > 0:
+ while val > 0 :
+ tmp.append(key)
+ hashmap[key] -= 1
+ val -= 1
+ tmp.sort()
+ print('tmp',tmp)
+ return arr1[:ind] + tmp
+ #
+s = Solution()
+# nums1 = [2,3,1,3,2,4,6,7,9,2,19]
+# nums2 = [2,1,4,3,9,6]
+# [2,42,38,0,43,21,5,7,12,12,13,23,24,24,27,29,30,31,33,48]
+nums1 = [2,21,43,38,0,42,33,7,24,13,12,27,12,24,5,23,29,48,30,31]
+nums2 = [2,42,38,0,43,21]
+res = s.relativeSortArray(nums1,nums2)
+print(res)
\ No newline at end of file
diff --git "a/Week08/\346\225\264\346\225\260\346\213\206\345\210\206.py" "b/Week08/\346\225\264\346\225\260\346\213\206\345\210\206.py"
new file mode 100644
index 000000000..8b4e9624a
--- /dev/null
+++ "b/Week08/\346\225\264\346\225\260\346\213\206\345\210\206.py"
@@ -0,0 +1,25 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/30 7:58 PM
+
+from functools import lru_cache
+class Solution:
+ @lru_cache
+ def integerBreak(self, n: int) -> int:
+ # 怎么感觉又是零钱兑换、背包问题
+ res = 0
+ for i in range(1, n-1):
+ res = max(res, (n-i)*i, i * self.integerBreak(n-i))
+ return res
+ # f(n) = f(n-1,1) f(n-2,2) f(n-3,3)
+ # dp = [1] * (n + 1)
+ # for i in range(3, n + 1):
+ # for j in range(1, i):
+ # dp[i] = max(dp[i], max(dp[j], j) * (i - j))
+ # return dp[-1]
+
+
+
+s = Solution()
+res = s.integerBreak(10)
+print(res)
\ No newline at end of file
diff --git "a/Week08/\346\235\250\350\276\211\344\270\211\350\247\222.py" "b/Week08/\346\235\250\350\276\211\344\270\211\350\247\222.py"
new file mode 100644
index 000000000..bb2eadc3f
--- /dev/null
+++ "b/Week08/\346\235\250\350\276\211\344\270\211\350\247\222.py"
@@ -0,0 +1,28 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/1 11:30 PM
+
+from typing import List
+
+
+class Solution:
+
+ def generate(self, rows: int) -> List[List[int]]:
+ dp = [[0]* rows for _ in range(rows)]
+ for row in range(rows):
+ dp[row][0] = 1
+ for i in range(1,rows):
+ for j in range(rows):
+ if i-1 >= 0:
+ dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
+
+ for i in range(rows):
+ #第0行pop四个,第1行pop3个、2 2 、3 1 4,0
+ tmp = rows-i-1
+ for i in range(tmp):
+ dp[i].pop()
+ return dp
+
+s = Solution()
+res = s.generate(5)
+print(res,'\n')
\ No newline at end of file
diff --git "a/Week08/\346\235\250\350\276\211\344\270\211\350\247\222II.py" "b/Week08/\346\235\250\350\276\211\344\270\211\350\247\222II.py"
new file mode 100644
index 000000000..be4352ff4
--- /dev/null
+++ "b/Week08/\346\235\250\350\276\211\344\270\211\350\247\222II.py"
@@ -0,0 +1,55 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/1 11:47 PM
+
+from typing import List
+
+
+class Solution:
+
+ def generate(self, rows: int) -> List[List[int]]:
+ # dp = [[0]* rows for _ in range(rows)]
+ # for row in range(rows):
+ # dp[row][0] = 1
+ # for i in range(1,rows):
+ # for j in range(rows):
+ # if i-1 >= 0:
+ # dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
+ #
+ # for i in range(rows):
+ # #第0行pop四个,第1行pop3个、2 2 、3 1 4,0
+ # tmp = rows-i-1
+ # for i in range(tmp):
+ # dp[i].pop()
+ # return dp
+ #这里只用返回第k行 想办法优化到O(K),每次在dp上覆盖修改
+ # [1]
+ # [1, 1]
+ # [1, 2, 1]
+ # [1, 3, 3, 1]
+ # [1, 5, 10, 10, 5, 1]
+ # dp = [0] * (rows+1)
+ # dp[0] = 1
+ # print(dp)
+ # for i in range(1, rows+1):
+ # for j in range(1, i):#2
+ # dp[j] = dp[j]+dp[j-1]#
+ # print(dp)
+ # dp[i] = 1
+ # return dp
+ dp = [1] * (rows + 1)
+ for i in range(2, rows + 1):
+ for j in range(i - 1, 0, -1):#首尾的1,不用更新
+ dp[j] += dp[j - 1]
+ return dp
+ # dp =[1]
+ # for i in range(1, rows + 1):
+ # dp.append(0)
+ # for j in range(1, i + 1):
+ # dp[-j] = dp[-j] + dp[-j - 1]
+ # print(dp)
+ # return dp
+
+s = Solution()
+res = s.generate(3)
+# print(res)
\ No newline at end of file
diff --git "a/Week08/\346\257\224\347\211\271\344\275\215\350\256\241\346\225\260.py" "b/Week08/\346\257\224\347\211\271\344\275\215\350\256\241\346\225\260.py"
new file mode 100644
index 000000000..34ab42395
--- /dev/null
+++ "b/Week08/\346\257\224\347\211\271\344\275\215\350\256\241\346\225\260.py"
@@ -0,0 +1,19 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/27 9:46 PM
+
+class Solution:
+ def countBits(self, num: int) -> List[int]:
+ # res = []
+ # for i in range(num+1):
+ # count = 0
+ # while i!=0:
+ # i = i &(i-1)#消除末尾1
+ # count += 1
+ # res.append(count)
+ # return res
+ #动态规划 dp[n] = dp[n//2] + 1 if odd else + 0
+ dp = [0] * (num + 1)
+ for i in range(1, num + 1): # 0不用处理
+ dp[i] = dp[i >> 1] + (i & 1)
+ return dp
\ No newline at end of file
diff --git "a/Week08/\347\277\273\350\275\254\345\257\271.py" "b/Week08/\347\277\273\350\275\254\345\257\271.py"
new file mode 100644
index 000000000..74788bddd
--- /dev/null
+++ "b/Week08/\347\277\273\350\275\254\345\257\271.py"
@@ -0,0 +1,34 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/2 12:32 PM
+
+
+# from typing import List
+#
+#
+# class Solution:
+#
+# def reversePairs(self, nums: List[int]) -> int:
+# return self.mergeSort(nums, 0, len(nums) - 1)
+#
+# def mergeSort(self, nums, l, r):
+# if l >= r:
+# return 0
+# mid = l + ((r - l) >> 1)
+# left = self.mergeSort(nums, l, mid)
+# right = self.mergeSort(nums, mid + 1, r)
+# return self.merge(nums, l, mid, r) + left + right
+#
+# def merge(self, nums, l, mid, r):
+# # 找翻转对的代码
+# ans = 0
+# i, j = l, mid + 1
+# while i <= mid and j <= r:
+# if (nums[i] + 1) >> 1 > nums[j]:
+# ans += (mid - i + 1)
+# j += 1
+# else:
+# i += 1
+# nums[l:r + 1] = sorted(nums[l:r + 1])
+# return ans
+
diff --git "a/Week08/\350\256\241\347\256\227\345\217\263\344\276\247\345\260\217\344\272\216\345\275\223\345\211\215\345\205\203\347\264\240\347\232\204\344\270\252\346\225\260.py" "b/Week08/\350\256\241\347\256\227\345\217\263\344\276\247\345\260\217\344\272\216\345\275\223\345\211\215\345\205\203\347\264\240\347\232\204\344\270\252\346\225\260.py"
new file mode 100644
index 000000000..89ccc5e09
--- /dev/null
+++ "b/Week08/\350\256\241\347\256\227\345\217\263\344\276\247\345\260\217\344\272\216\345\275\223\345\211\215\345\205\203\347\264\240\347\232\204\344\270\252\346\225\260.py"
@@ -0,0 +1,75 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/2 10:13 PM
+
+
+from typing import List
+from typing import List
+
+
+class Solution:
+
+ def countSmaller(self, nums: List[int]) -> List[int]:
+ size = len(nums)
+ if size == 0: return []
+ if size == 1: return [0]
+
+ tmp = [None for _ in range(size)]
+ res = [0 for _ in range(size)]
+ # 索引数组,作用:归并回去的时候,方便知道是哪个下标的元素
+ indexes = [i for i in range(size)]
+
+ self.__merge_and_count_smaller(nums, 0, size - 1, tmp, indexes, res)
+ return res
+
+ def __merge_and_count_smaller(self, nums, left, right, temp, indexes, res):
+ if left == right:
+ return
+ mid = left + (right - left) // 2
+ self.__merge_and_count_smaller(nums, left, mid, temp, indexes, res)
+ self.__merge_and_count_smaller(nums, mid + 1, right, temp, indexes, res)
+
+ if nums[indexes[mid]] <= nums[indexes[mid + 1]]:
+ return
+ self.__sort_and_count_smaller(nums, left, mid, right, temp, indexes, res)
+
+ def __sort_and_count_smaller(self, nums, left, mid, right, temp, indexes, res):
+ # [left,mid] 前有序数组
+ # [mid+1,right] 后有序数组
+
+ # 先拷贝,再合并
+ for i in range(left, right + 1):
+ temp[i] = indexes[i]
+
+ i = left
+ j = mid + 1
+ for k in range(left, right + 1):
+ if i > mid:
+ indexes[k] = temp[j]
+ j += 1
+ elif j > right:
+ indexes[k] = temp[i]
+ i += 1
+ res[indexes[k]] += (right - mid)
+ elif nums[temp[i]] <= nums[temp[j]]:
+ indexes[k] = temp[i]
+ i += 1
+ res[indexes[k]] += (j - mid - 1)
+ else:
+ indexes[k] = temp[j]
+ j += 1
+
+
+if __name__ == '__main__':
+ nums = [5, 2, 6, 1]
+ solution = Solution()
+ result = solution.countSmaller(nums)
+ print(result)
+
+s = Solution()
+res = s.reversePairs(nums=[5,2,6,1])
+print(res)
+
+
+
+
diff --git "a/Week08/\351\200\211\346\213\251\346\216\222\345\272\217.py" "b/Week08/\351\200\211\346\213\251\346\216\222\345\272\217.py"
new file mode 100644
index 000000000..1f0e8cc09
--- /dev/null
+++ "b/Week08/\351\200\211\346\213\251\346\216\222\345\272\217.py"
@@ -0,0 +1,19 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/28 8:17 PM
+
+
+# 选择排序的思想是分作AB两区,A一直有序,每次从B中取出最小的元素,放在A区
+class Solution:
+ def insertsort(self,nums):
+ for i in range(len(nums)-1):
+ min_loc = i
+ for j in range(i+1,len(nums)):#找到B区最小的元素
+ if nums[min_loc] > nums[j]:
+ min_loc = j
+ nums[i],nums[min_loc] = nums[min_loc],nums[i]
+
+s = Solution()
+nums = [2,3,1,4,2,5,6,8,6,5,7]
+s.insertsort(nums)
+print(nums)
\ No newline at end of file
diff --git "a/Week08/\351\242\240\345\200\222\344\272\214\350\277\233\345\210\266\344\275\215.py" "b/Week08/\351\242\240\345\200\222\344\272\214\350\277\233\345\210\266\344\275\215.py"
new file mode 100644
index 000000000..1a1a32529
--- /dev/null
+++ "b/Week08/\351\242\240\345\200\222\344\272\214\350\277\233\345\210\266\344\275\215.py"
@@ -0,0 +1,16 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/27 9:13 PM
+
+class Solution:
+ def reverseBits(self, n: int) -> int:
+ # 脱裤子放屁
+ # tmp = bin(n)[2:].zfill(32)
+ # return int(tmp[::-1],2)
+ # 逐位颠倒
+ res, bits = 0, 31
+ while n!=0:
+ res += (n&1)<>1
+ bits -= 1
+ return res
diff --git "a/Week09/[100]\347\233\270\345\220\214\347\232\204\346\240\221.py" "b/Week09/[100]\347\233\270\345\220\214\347\232\204\346\240\221.py"
new file mode 100644
index 000000000..d5be784b5
--- /dev/null
+++ "b/Week09/[100]\347\233\270\345\220\214\347\232\204\346\240\221.py"
@@ -0,0 +1,18 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/7 10:47 PM
+
+
+# Definition for a binary tree node.
+# class TreeNode:
+# def __init__(self, val=0, left=None, right=None):
+# self.val = val
+# self.left = left
+# self.right = right
+class Solution:
+ def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
+ if not p and not q: return True
+ if not p or not q: return False
+ if p.val!=q.val: return False
+ else:
+ return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
\ No newline at end of file
diff --git "a/Week09/[1114]\345\244\232\347\272\277\347\250\213\344\271\213\346\214\211\345\272\217\346\211\223\345\215\260.py" "b/Week09/[1114]\345\244\232\347\272\277\347\250\213\344\271\213\346\214\211\345\272\217\346\211\223\345\215\260.py"
new file mode 100644
index 000000000..391cde6cf
--- /dev/null
+++ "b/Week09/[1114]\345\244\232\347\272\277\347\250\213\344\271\213\346\214\211\345\272\217\346\211\223\345\215\260.py"
@@ -0,0 +1,27 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/18 11:08 PM
+
+from threading import Lock
+class Foo:
+ def __init__(self):
+ self.firstJob = Lock()
+ self.secondJob = Lock()
+ self.firstJob.acquire()
+ self.secondJob.acquire()
+
+ def first(self, printFirst: 'Callable[[], None]') -> None:
+ # printFirst() outputs "first". Do not change or remove this line.
+ printFirst()
+ self.firstJob.release()
+
+ def second(self, printSecond: 'Callable[[], None]') -> None:
+ with self.firstJob:#请求锁
+ # printSecond() outputs "second". Do not change or remove this line.
+ printSecond()
+ self.secondJob.release()
+
+ def third(self, printThird: 'Callable[[], None]') -> None:
+ with self.secondJob:
+ # printThird() outputs "third". Do not change or remove this line.
+ printThird()
\ No newline at end of file
diff --git "a/Week09/[1116]\345\244\232\347\272\277\347\250\213\344\271\213\344\272\244\345\217\211\346\211\223\345\215\260\345\245\207\345\201\266\345\200\274.py" "b/Week09/[1116]\345\244\232\347\272\277\347\250\213\344\271\213\344\272\244\345\217\211\346\211\223\345\215\260\345\245\207\345\201\266\345\200\274.py"
new file mode 100644
index 000000000..150b80024
--- /dev/null
+++ "b/Week09/[1116]\345\244\232\347\272\277\347\250\213\344\271\213\344\272\244\345\217\211\346\211\223\345\215\260\345\245\207\345\201\266\345\200\274.py"
@@ -0,0 +1,40 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/18 11:24 PM
+
+
+from threading import Lock
+
+
+class ZeroEvenOdd:
+ def __init__(self, n):
+ self.n = n
+ self.zero_lock = Lock()
+ self.even_lock = Lock()
+ self.odd_lock = Lock()
+ self.even_lock.acquire()
+ self.odd_lock.acquire()
+
+ # printNumber(x) outputs "x", where x is an integer.
+ def zero(self, printNumber: 'Callable[[int], None]') -> None:
+ for i in range(1, self.n + 1):
+ self.zero_lock.acquire()
+ printNumber(0)
+ if i & 1:
+ self.odd_lock.release()
+ else:
+ self.even_lock.release()
+
+ def even(self, printNumber: 'Callable[[int], None]') -> None:
+ for i in range(1, self.n + 1):
+ if i & 1 == 0:
+ self.even_lock.acquire()
+ printNumber(i)
+ self.zero_lock.release()
+
+ def odd(self, printNumber: 'Callable[[int], None]') -> None:
+ for i in range(1, self.n + 1):
+ if i & 1:
+ self.odd_lock.acquire()
+ printNumber(i)
+ self.zero_lock.release()
\ No newline at end of file
diff --git "a/Week09/[1143]\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" "b/Week09/[1143]\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py"
new file mode 100644
index 000000000..64ec31564
--- /dev/null
+++ "b/Week09/[1143]\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py"
@@ -0,0 +1,19 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 5:16 PM
+
+class Solution:
+ def longestCommonSubsequence(self, text1: str, text2: str) -> int:
+ # 看题目和之前那道最长公共回文串,很类似,这里用动态规划做,
+ # 但是要注意 这里是最长公共子序列,是可以间断的
+ if not text1 and not text2: return 0
+ m, n = len(text1), len(text2)
+ dp = [[0]*(n+1) for _ in range(m+1)]
+ for i in range(1,m+1):
+ for j in range(1,n+1):
+ if text1[i-1] == text2[j-1]:
+ dp[i][j] = dp[i-1][j-1] + 1
+ else:
+ dp[i][j] = max(dp[i-1][j],dp[i][j-1])
+ return dp[-1][-1]
+
diff --git "a/Week09/[120]\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" "b/Week09/[120]\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py"
new file mode 100644
index 000000000..4f03a9f9f
--- /dev/null
+++ "b/Week09/[120]\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py"
@@ -0,0 +1,36 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/3 1:57 AM
+
+from typing import List
+class Solution:
+ def minimumTotal(self, triangle: List[List[int]]) -> int:
+ # 分治 递归模板
+ # from functools import lru_cache
+ # @lru_cache(None)
+ # def dfs(i, j):
+ # #terminator
+ # if i == size-1: return triangle[i][j]
+ # left = dfs(i+1,j)#加左边的值
+ # right = dfs(i+1,j+1)
+ # min_val = min(left, right) + triangle[i][j]
+ # return min_val
+ # size = len(triangle)
+ # return dfs(0,0)
+ # 2.top-down
+ # if not triangle: return
+ # dp = triangle
+ # for i in range(1, len(triangle)):
+ # for j in range(len(triangle[i])):
+ # if j == 0:
+ # dp[i][j] += triangle[i-1][j]
+ # elif j == len(triangle[i])-1:
+ # dp[i][j] += triangle[i-1][j-1]
+ # else:
+ # dp[i][j] += min(triangle[i-1][j-1], triangle[i-1][j])
+ # return min(dp[-1])
+ # 3.bottom-up
+ for i in range(len(triangle) - 2, -1, -1):
+ for j in range(len(triangle[i])):
+ triangle[i][j] += min(triangle[i + 1][j], triangle[i + 1][j + 1])
+ return triangle[0][0]
diff --git "a/Week09/[125]\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262.py" "b/Week09/[125]\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262.py"
new file mode 100644
index 000000000..eb6b16f9c
--- /dev/null
+++ "b/Week09/[125]\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262.py"
@@ -0,0 +1,20 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 1:31 PM
+
+class Solution:
+ def isPalindrome(self, s: str) -> bool:
+ # tmp = ''.join(ch.lower() for ch in s if ch.isalnum())
+ # return tmp == tmp[::-1]
+ tmp = ''.join(ch.lower() for ch in s if ch.isalnum())
+ # print(tmp)
+ left, right = 0, len(tmp)-1
+ while left <= right:
+ if tmp[left] != tmp[right]:
+ return False
+ left, right = left + 1, right - 1
+ return True
+s = Solution()
+strs = "A man, a plan, a canal: Panama"
+res = s.isPalindrome(strs)
+print(res)
\ No newline at end of file
diff --git "a/Week09/[151]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215.py" "b/Week09/[151]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215.py"
new file mode 100644
index 000000000..79efa2e56
--- /dev/null
+++ "b/Week09/[151]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215.py"
@@ -0,0 +1,16 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 10:27 AM
+
+
+class Solution:
+ def reverseWords(self, s: str) -> str:
+ # #要注意到原字符串两边的空格以及 单词之间多余1的空格
+ # tmp = s.split(' ')
+ # #删除多余的空格
+ # tmp = [] + [item for item in tmp if item!='']
+ # # tmp = s.strip().split(' ')
+ # tmp = list(reversed(tmp))
+ # res = ' '.join(tmp )
+ # return res
+ return " ".join(reversed(s.split()))#split()不加参数会把结果中的' '删除
\ No newline at end of file
diff --git "a/Week09/[242]\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" "b/Week09/[242]\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py"
new file mode 100644
index 000000000..6de4822bb
--- /dev/null
+++ "b/Week09/[242]\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py"
@@ -0,0 +1,14 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 11:10 AM
+
+class Solution:
+ def isAnagram(self, s: str, t: str) -> bool:
+ hashmap = {}
+ for ch in s:
+ hashmap[ch] = hashmap.get(ch,0) + 1
+ for ch in t:
+ hashmap[ch] = hashmap.get(ch,0) - 1
+ for key,val in hashmap.items():
+ if val != 0: return False
+ return True
\ No newline at end of file
diff --git "a/Week09/[300]\346\234\200\351\225\277\344\270\212\345\215\207\345\255\220\345\272\217\345\210\227.py" "b/Week09/[300]\346\234\200\351\225\277\344\270\212\345\215\207\345\255\220\345\272\217\345\210\227.py"
new file mode 100644
index 000000000..6a20204ab
--- /dev/null
+++ "b/Week09/[300]\346\234\200\351\225\277\344\270\212\345\215\207\345\255\220\345\272\217\345\210\227.py"
@@ -0,0 +1,54 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/4 1:39 AM
+
+from typing import List
+
+
+class Solution:
+ def lengthOfLIS(self, nums: List[int]) -> int:
+ # dp
+ # if not nums: return 0
+ # dp = [1]*len(nums)
+ # 其实说白了就是暴力法的另外一种写法
+ # 枚举起始点,看以它为终点的位置 上升子序列长度是多少,只不过比平常的暴力解法还是稍微简单一些
+ # 以nums[i]为尾元素的最大子序列长度
+ # for i in range(len(nums)):
+ # for j in range(i):
+ # if nums[i] > nums[j]:
+ # dp[i] = max(dp[i],dp[j]+1)
+ # return max(dp)
+ size = len(nums)
+ if size < 2: return size
+ tmp = [nums[0]] # 维护一个单调栈
+ # 遍历数组,如果比末尾元素大,加入,如果小于等于 找到第一个比他大的数,替换掉
+ for num in nums[1:]:
+ if num > tmp[-1]:
+ tmp.append(num)
+ # [2,2,4] 3
+ else: # 在有序数组中找到第一个比num大的位置
+ left, right = 0,len(tmp)-1
+ while left <= right:
+ mid = left + ((right-left)//2)
+ if tmp[mid] >= num:
+ if mid == 0 or tmp[mid-1] < num:
+ tmp[mid] = num
+ break
+ else: right = mid - 1
+ else:
+ left = mid + 1
+
+ # for i in range(len(tmp)):
+ # if tmp[i] == num:
+ # break
+ # elif tmp[i] > num:
+ # tmp[i] = num
+ # break
+ print(tmp)
+ return len(tmp)
+
+s = Solution()
+# nums = [10,9,2,5,3,7,101,18]
+nums = [4,10,4,3,8,9]
+res = s.lengthOfLIS(nums)
+print(res)
\ No newline at end of file
diff --git "a/Week09/[344]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262.py" "b/Week09/[344]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262.py"
new file mode 100644
index 000000000..2e3e92836
--- /dev/null
+++ "b/Week09/[344]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262.py"
@@ -0,0 +1,15 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/7 10:44 PM
+
+class Solution:
+ def reverseString(self, strs: List[str]) -> None:
+ """
+ Do not return anything, modify s in-place instead.
+ """
+ size = len(strs)
+ left, right = 0, size-1
+ while left < right:
+ strs[left],strs[right] = strs[right],strs[left]
+ left, right = left + 1, right - 1
+ return strs
\ No newline at end of file
diff --git "a/Week09/[387]\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\224\257\344\270\200\345\255\227\347\254\246.py" "b/Week09/[387]\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\224\257\344\270\200\345\255\227\347\254\246.py"
new file mode 100644
index 000000000..df5d2c9d2
--- /dev/null
+++ "b/Week09/[387]\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\224\257\344\270\200\345\255\227\347\254\246.py"
@@ -0,0 +1,26 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/5 12:31 AM
+
+class Solution:
+ def firstUniqChar(self, s: str) -> int:
+ hashmap = {}
+ for ch in s:
+ hashmap[ch] = hashmap.get(ch, 0) + 1
+ for i in range(len(s)):
+ if hashmap.get(s[i]) == 1:
+ return i
+ return -1
+ # 这里我是用hashmap中times=1的ch反向查找字符串 这里的时间复杂度就是O(MN)了
+ # tmp = ''
+ # for ch, times in hashmap.items():
+ # if times == 1:
+ # tmp = ch
+ # break
+ # if not tmp:
+ # return -1
+ # else:
+ # return s.index(ch)
+ # 更好的做法应该是再遍历字符串,检查其times是否为1即可
+
+
diff --git "a/Week09/[41]\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260.py" "b/Week09/[41]\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260.py"
new file mode 100644
index 000000000..8341d12bc
--- /dev/null
+++ "b/Week09/[41]\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260.py"
@@ -0,0 +1,40 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 7:44 PM
+
+from typing import List
+class Solution:
+ def firstMissingPositive(self, nums: List[int]) -> int:
+ # if not nums: return 1
+ # hashmap = {}
+ # max_val = float('-inf')
+ # for num in nums:
+ # if num > 0:
+ # hashmap[num] = hashmap.get(num,0)+1
+ # if num > max_val:
+ # max_val = num
+ # if not hashmap: return 1
+ # for num in range(1,max_val):
+ # if not hashmap.get(num):
+ # return num
+ # return max_val + 1
+
+ size = len(nums)
+ for i in range(size):#将所有负值赋值为N+1
+ if nums[i] <= 0:
+ nums[i] = size + 1#后面不需要管这些显然大于数组长度的数值
+ for i in range(size):
+ ind = abs(nums[i])
+ if ind <= size:
+ nums[ind - 1] = -abs(nums[ind - 1])
+ for i in range(size):
+ if nums[i] > 0:
+ return i + 1
+
+ return size + 1
+
+ # print(nums)
+s = Solution()
+nums = [-1,2,1,4,6,7]
+print(nums)
+s.firstMissingPositive(nums)
diff --git "a/Week09/[438]\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" "b/Week09/[438]\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py"
new file mode 100644
index 000000000..0413be58f
--- /dev/null
+++ "b/Week09/[438]\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py"
@@ -0,0 +1,63 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 11:37 AM
+
+from typing import List
+class Solution:
+ def findAnagrams(self, s: str, p: str) -> List[int]:
+ #n个a,a 超时,这个过程不断的取一截,就很费操作
+ # 用滑动窗口试一下
+ m, n = len(s), len(p)
+ res = []
+ for i in range(m-n+1):
+ cur = s[i:i+n]
+ #判断此时的cur和p是否是异位词
+ if self.isAngrams(cur,p): res.append(i)
+ return res
+ def isAngrams(self,s,p):
+ hashmap = {}
+ for ch in s:
+ hashmap[ch] = hashmap.get(ch,0) + 1
+ for ch in p:
+ hashmap[ch] = hashmap.get(ch,0) - 1
+ for key,value in hashmap.items():
+ if value !=0 : return False
+ return True
+
+ def findAnagramsI(self, s: str, p: str) -> List[int]:
+ from collections import deque
+ m, n = len(s), len(p)
+ hashmap = {}
+ for ch in p:
+ hashmap[ch] = hashmap.get(ch,0) + 1
+ quene = deque()# 滑动窗口
+ hashmap1 = {}
+ res = []
+ # s: "cbaebabacd"
+ # p: "abc"
+ for i in range(m+1):
+ if len(quene) == n:
+ if hashmap == hashmap1:
+ res.append(i-n)
+ left = quene[0]
+ if hashmap1[left] > 1:
+ hashmap1[left] -= 1
+ else:
+ del hashmap1[left]
+ quene.popleft()
+ if i < m:
+ ch = s[i]
+ quene.append(ch)
+ hashmap1[ch] = hashmap1.get(ch, 0) + 1
+ return res
+s = Solution()
+# s1 = "cbaebabacdc"
+# s2 = "abc"
+s1 = "abab"
+s2 = "ab"
+res = s.findAnagramsI(s1,s2)
+print(res)
+
+
+
+
diff --git "a/Week09/[49]\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py" "b/Week09/[49]\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py"
new file mode 100644
index 000000000..06aecf8e1
--- /dev/null
+++ "b/Week09/[49]\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py"
@@ -0,0 +1,12 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 11:21 AM
+
+class Solution(object):
+ def groupAnagrams(self, strs):
+ hashmap = {}
+ for ch in strs:
+ cur = ''.join(sorted(ch))
+ hashmap[cur] = hashmap.get(cur,[]) + [ch]
+ # print(hashmap)
+ return [hashmap[item] for item in hashmap]
\ No newline at end of file
diff --git "a/Week09/[518]\351\233\266\351\222\261\345\205\221\346\215\242II.py" "b/Week09/[518]\351\233\266\351\222\261\345\205\221\346\215\242II.py"
new file mode 100644
index 000000000..4dc54a142
--- /dev/null
+++ "b/Week09/[518]\351\233\266\351\222\261\345\205\221\346\215\242II.py"
@@ -0,0 +1,30 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/5 9:11 PM
+
+
+from typing import List
+class Solution:
+ def change(self, amount: int, coins: List[int]) -> int:
+ dp = [[0] * (amount + 1) for i in range(len(coins) + 1)]
+ #进行初始化
+ for i in range(len(coins) + 1):
+ dp[i][0] = 1
+ for i in range(1,len(coins) + 1):
+ for j in range(1, amount + 1):
+ if j >= coins[i-1]:
+ dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i-1]]
+ else:
+ dp[i][j] = dp[i - 1][j]
+ return dp[-1][-1]
+ # dp = [0] * (amount+1)
+ # dp[0] = 1
+ # for coin in coins:#[1,2,5]
+ # for i in range(coin,amount+1):
+ # dp[i] += dp[i-coin]
+ # return dp[-1]
+
+s = Solution()
+coins = [1,101,102,103]
+res = s.change(100,coins)
+print(res)
diff --git "a/Week09/[541]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262II.py" "b/Week09/[541]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262II.py"
new file mode 100644
index 000000000..97171234d
--- /dev/null
+++ "b/Week09/[541]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262II.py"
@@ -0,0 +1,12 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 10:27 AM
+
+
+class Solution:
+ def reverseStr(self, s: str, k: int) -> str:
+ #每隔2k个元素就将前k个元素逆序存到res中
+ a = list(s)
+ for i in range(0, len(a), 2*k):#将步长设置为2k即可
+ a[i:i+k] = reversed(a[i:i+k])
+ return "".join(a)
\ No newline at end of file
diff --git "a/Week09/[557]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\215\225\350\257\215III.py" "b/Week09/[557]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\215\225\350\257\215III.py"
new file mode 100644
index 000000000..15c6926a7
--- /dev/null
+++ "b/Week09/[557]\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\215\225\350\257\215III.py"
@@ -0,0 +1,11 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 10:52 AM
+
+# 组内翻转单词
+
+class Solution:
+ def reverseWords(self, s: str) -> str:
+ s = s.split()
+ res= [''.join(reversed(item)) for item in s]
+ return ' '.join(res)
\ No newline at end of file
diff --git "a/Week09/[58]\346\234\200\345\220\216\344\270\200\344\270\252\345\215\225\350\257\215\347\232\204\351\225\277\345\272\246.py" "b/Week09/[58]\346\234\200\345\220\216\344\270\200\344\270\252\345\215\225\350\257\215\347\232\204\351\225\277\345\272\246.py"
new file mode 100644
index 000000000..c7c4e1b40
--- /dev/null
+++ "b/Week09/[58]\346\234\200\345\220\216\344\270\200\344\270\252\345\215\225\350\257\215\347\232\204\351\225\277\345\272\246.py"
@@ -0,0 +1,22 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/4 11:52 PM
+
+class Solution:
+ def lengthOfLastWord(self, s: str) -> int:
+ # s = s.split()
+ # if not s: return 0 #去除全部是空格
+ # return len(s[-1])
+ p1 = len(s)-1
+ while p1 >= 0 and s[p1] == ' ':#先略过末尾的空格
+ p1 -= 1
+ if p1 == -1: return 0#全部为空格
+ p2 = p1
+ while p2 >= 0 and s[p2] != ' ':#从后向前找到第一个不为空格的字符
+ p2 -= 1
+ return p1 - p2
+
+s = Solution()
+strs = "Hello World "
+res = s.lengthOfLastWord(strs)
+print(res)
\ No newline at end of file
diff --git "a/Week09/[647]\345\233\236\346\226\207\345\255\220\344\270\262.py" "b/Week09/[647]\345\233\236\346\226\207\345\255\220\344\270\262.py"
new file mode 100644
index 000000000..93068c6ae
--- /dev/null
+++ "b/Week09/[647]\345\233\236\346\226\207\345\255\220\344\270\262.py"
@@ -0,0 +1,21 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/19 12:52 AM
+
+class Solution:
+ def countSubstrings(self, s: str) -> int:
+ if not s: return 0
+ size = len(s)
+ dp = [[True]*size for i in range(size)]
+ count = 0
+ for l in range(size):
+ for i in range(size):
+ j = i + l
+ if j >= size: break
+ if l == 0: dp[i][j] = True
+ elif l == 1: dp[i][j] = (s[i]==s[j])
+ else:
+ dp[i][j] = (dp[i+1][j-1] and s[i] == s[j])
+ if dp[i][j]:
+ count += 1
+ return count
\ No newline at end of file
diff --git "a/Week09/[680]\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262II.py" "b/Week09/[680]\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262II.py"
new file mode 100644
index 000000000..7843133c3
--- /dev/null
+++ "b/Week09/[680]\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262II.py"
@@ -0,0 +1,24 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 1:37 PM
+
+class Solution:
+ def validPalindrome(self, s: str) -> bool:
+ # pass
+ # 左右指针对撞, 如果 相同就向中心靠拢
+ # 如果不等,就left++ 或者right--,判断是否是回文
+ def check(left, right):
+ while left <= right:
+ if s[left] != s[right]:
+ return False
+ left, right = left + 1, right - 1
+ return True
+
+ left, right = 0, len(s) - 1
+ while left <= right:
+ if s[left] == s[right]:
+ left, right = left + 1, right - 1
+ else:
+ return check(left + 1, right) or check(left, right - 1)
+ return True
+
diff --git "a/Week09/[696]\350\256\241\346\225\260\344\272\214\350\277\233\345\210\266\345\255\220\344\270\262.py" "b/Week09/[696]\350\256\241\346\225\260\344\272\214\350\277\233\345\210\266\345\255\220\344\270\262.py"
new file mode 100644
index 000000000..fdae3aadd
--- /dev/null
+++ "b/Week09/[696]\350\256\241\346\225\260\344\272\214\350\277\233\345\210\266\345\255\220\344\270\262.py"
@@ -0,0 +1,24 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/10 11:01 PM
+
+class Solution:
+ def countBinarySubstrings(self, s: str) -> int:
+ count = [1]
+ j = 0
+ for i in range(1, len(s)): # 统计连续的频数
+ if s[i] == s[i - 1]:
+ count[j] += 1
+ else:
+ count.append(1)
+ j += 1
+ res = 0
+ for k in range(1, len(count)):
+ res += min(count[k], count[k - 1]) # 取相邻频数的最小值
+ return res
+
+s = Solution()
+strs = "001110011"
+res = s.countBinarySubstrings(strs)
+print(res)
+
diff --git "a/Week09/[709]\350\275\254\346\215\242\346\210\220\345\260\217\345\206\231\345\255\227\346\257\215.py" "b/Week09/[709]\350\275\254\346\215\242\346\210\220\345\260\217\345\206\231\345\255\227\346\257\215.py"
new file mode 100644
index 000000000..e4d0b2463
--- /dev/null
+++ "b/Week09/[709]\350\275\254\346\215\242\346\210\220\345\260\217\345\206\231\345\255\227\346\257\215.py"
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/4 11:26 PM
+
+class Solution:
+ def toLowerCase(self, str: str) -> str:
+ # return str.lower()
+ # A 65 a 97 差32 '0'的ascii 为48
+ # ord('x')-->ascii值
+ # chr(ascii值)-->str
+ res = ''
+ for i in range(len(str)):
+ if 65<= ord(str[i]) < 97:
+ res += chr(ord(str[i])+32)
+ else:
+ res += str[i]
+ return res
\ No newline at end of file
diff --git "a/Week09/[718]\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204.py" "b/Week09/[718]\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204.py"
new file mode 100644
index 000000000..4f725a0a0
--- /dev/null
+++ "b/Week09/[718]\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204.py"
@@ -0,0 +1,27 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 6:42 PM
+
+
+from typing import List
+class Solution:
+ def findLength(self, A: List[int], B: List[int]) -> int:
+ def maxLength(addA: int, addB: int, length: int) -> int:
+ ret = k = 0
+ for i in range(length):
+ if A[addA + i] == B[addB + i]:
+ k += 1
+ ret = max(ret, k)
+ else:
+ k = 0
+ return ret
+
+ n, m = len(A), len(B)
+ ret = 0
+ for i in range(n):
+ length = min(m, n - i)
+ ret = max(ret, maxLength(i, 0, length))
+ for i in range(m):
+ length = min(n, m - i)
+ ret = max(ret, maxLength(0, i, length))
+ return ret
diff --git "a/Week09/[72]\347\274\226\350\276\221\350\267\235\347\246\273.py" "b/Week09/[72]\347\274\226\350\276\221\350\267\235\347\246\273.py"
new file mode 100644
index 000000000..103787dca
--- /dev/null
+++ "b/Week09/[72]\347\274\226\350\276\221\350\267\235\347\246\273.py"
@@ -0,0 +1,21 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/3 1:20 AM
+
+
+class Solution:
+ def minDistance(self, word1: str, word2: str) -> int:
+ m, n = len(word1), len(word2)
+ dp = [[0]*(n+1) for _ in range(m+1)]
+ #dp[i][j]表示word1[:i]到word2[:j]的编辑距离
+ for i in range(1,m+1):
+ dp[i][0] = i
+ for j in range(1,n+1):
+ dp[0][j] = j
+ for i in range(1,m+1):
+ for j in range(1,n+1):
+ if word1[i-1] == word2[j-1]:
+ dp[i][j] = dp[i-1][j-1]
+ else:
+ dp[i][j] = min(dp[i][j-1],dp[i-1][j],dp[i-1][j-1])+1
+ return dp[-1][-1]
\ No newline at end of file
diff --git "a/Week09/[746]\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257.py" "b/Week09/[746]\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257.py"
new file mode 100644
index 000000000..f57ab371c
--- /dev/null
+++ "b/Week09/[746]\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257.py"
@@ -0,0 +1,16 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/4 1:02 AM
+
+class Solution:
+ def minCostClimbingStairs(self, cost: List[int]) -> int:
+ size = len(cost)
+ # if size <= 2: return min(cost)
+ # dp = [0] * size
+ # dp[0], dp[1] = cost[0], cost[1]
+ # for i in range(2,size):#要想到达最后一位,只可能是从i-1和i-2来的,所以总共的开销如下
+ # dp[i] = min(dp[i-1],dp[i-2])+cost[i]#到达i处花费的最少开销
+ # return min(dp[-1],dp[-2])
+ for i in range(2,size):
+ cost[i] = min(cost[i-1],cost[i-2]) + cost[i]
+ return min(cost[-1],cost[-2])
\ No newline at end of file
diff --git "a/Week09/[771]\345\256\235\347\237\263\344\270\216\347\237\263\345\244\264.py" "b/Week09/[771]\345\256\235\347\237\263\344\270\216\347\237\263\345\244\264.py"
new file mode 100644
index 000000000..b922f32e0
--- /dev/null
+++ "b/Week09/[771]\345\256\235\347\237\263\344\270\216\347\237\263\345\244\264.py"
@@ -0,0 +1,21 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/5 12:14 AM
+
+
+class Solution:
+ def numJewelsInStones(self, J: str, S: str) -> int:
+ # 暴力法
+ # count = 0
+ # for ch in J:
+ # count += S.count(ch)
+ # return count
+ # hash表记录宝石 遍历待查字符串 这种题hash表解法一定不能忘!!!!!!!!!
+ hashmap = set()
+ count = 0
+ for ch in J:
+ hashmap.add(ch)
+ for ch in S:
+ if ch in hashmap:
+ count += 1
+ return count
\ No newline at end of file
diff --git "a/Week09/[8]\345\255\227\347\254\246\344\270\262\350\275\254\346\225\264\346\225\260.py" "b/Week09/[8]\345\255\227\347\254\246\344\270\262\350\275\254\346\225\264\346\225\260.py"
new file mode 100644
index 000000000..18e58dc89
--- /dev/null
+++ "b/Week09/[8]\345\255\227\347\254\246\344\270\262\350\275\254\346\225\264\346\225\260.py"
@@ -0,0 +1,18 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/5 12:37 AM
+
+class Solution:
+ def myAtoi(self, strs: str) -> int:
+ res, sign = 0, 1
+ strs = strs.strip()
+ for i in range(len(strs)):
+ ch = strs[i]
+ if i == 0 and (ch == '-' or ch == '+'):
+ if ch == '-': sign = -1
+ if ch == '+': sign = 1
+ continue # 应对-123,是+-号之后就不用判断是否数字了
+ if not ch.isdigit(): break # 如果不是数字
+ res = 10 * res + ord(ch) - ord('0')
+ # 如果下越界 就返回-2**31 如果上越界返回2**31-1
+ return max(-2 ** 31, -1 * res) if sign == -1 else min(2 ** 31 - 1, res)
diff --git "a/Week09/[917]\344\273\205\344\273\205\345\217\215\350\275\254\345\255\227\346\257\215.py" "b/Week09/[917]\344\273\205\344\273\205\345\217\215\350\275\254\345\255\227\346\257\215.py"
new file mode 100644
index 000000000..b85e6707c
--- /dev/null
+++ "b/Week09/[917]\344\273\205\344\273\205\345\217\215\350\275\254\345\255\227\346\257\215.py"
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/8 11:08 AM
+
+
+class Solution:
+ def reverseOnlyLetters(self, strs: str) -> str:
+ tmp = list(strs)
+ left, right = 0, len(strs) - 1
+ while left < right:
+ while left < right and not tmp[left].isalpha():
+ left = left + 1
+ while left < right and not tmp[right].isalpha():
+ right = right - 1
+ tmp[left], tmp[right] = tmp[right], tmp[left]
+ left, right = left + 1, right - 1
+ return ''.join(tmp)
\ No newline at end of file
diff --git "a/Week09/[93]\345\244\215\345\216\237IP\345\234\260\345\235\200.py" "b/Week09/[93]\345\244\215\345\216\237IP\345\234\260\345\235\200.py"
new file mode 100644
index 000000000..e8176065f
--- /dev/null
+++ "b/Week09/[93]\345\244\215\345\216\237IP\345\234\260\345\235\200.py"
@@ -0,0 +1,78 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/14 10:28 PM
+
+from typing import List
+
+
+class Solution:
+ def restoreIpAddresses(self, s: str) -> List[str]:
+ size = len(s)
+ if size < 4 or size > 12:
+ return []
+ path = []
+ res = []
+ self.__dfs(s, size, 0, 0, path, res)
+ return res
+
+ def __dfs(self, s, size, split_times, begin, path, res):
+ if begin == size:
+ if split_times == 4:
+ res.append('.'.join(path))
+ return
+ # 如果剩余长度不够划分、如果剩余长度太长
+ if size - begin < (4 - split_times) or size - begin > 3 * (4 - split_times):
+ return
+ for i in range(3):
+ if begin + i >= size:
+ break
+ ip_segment = self.__judge_if_ip_segment(s, begin, begin + i)
+ if ip_segment != -1:
+ path.append(str(ip_segment))
+ self.__dfs(s, size, split_times + 1, begin + i + 1, path, res)
+ path.pop()
+
+ def __judge_if_ip_segment(self, s, left, right):
+ size = right - left + 1
+ if size > 1 and s[left] == '0':
+ return -1
+ res = int(s[left:right + 1])
+ if res > 255:
+ return - 1
+ return res
+
+
+class SolutionI:
+ def restoreIpAddresses(self, s: str) -> List[str]:
+ # 定义查找符合条件的数字个数
+ def _dfs(start, path):
+ # recursion terminator
+ # 如果ip地址已4位,但字符串没用尽,不符合题目意思
+ if len(path) == 4 and start < len(s)-1:
+ return
+ # 什么时候加入到res中??? 当整个字符串已经遍历完成的时候
+ if start>=len(s):
+ if len(path) == 4:
+ res.append('.'.join(path))
+ return
+ # 如果当前位为0,不能扩展
+ # 下面的层数返回结果,此时0不能向右扩展,只能向上return
+ if s[start] == '0':
+ path.append(s[start])
+ _dfs(start+1, path)
+ path.pop()
+ return
+ for i in range(start,len(s)):
+ if 0 <= int(s[start:i+1]) <= 255:
+ path.append(s[start:i+1])
+ _dfs(i+1,path)
+ path.pop()
+ else:
+ break #后面的不用再继续判断
+ res = []
+ _dfs(0,[])
+ return res
+
+s = Solution()
+res = s.restoreIpAddresses("25525511135")
+print(res)
diff --git "a/Week09/\344\272\214\345\210\206\346\237\245\346\211\276\347\273\217\345\205\270\351\242\230\347\233\256.md" "b/Week09/\344\272\214\345\210\206\346\237\245\346\211\276\347\273\217\345\205\270\351\242\230\347\233\256.md"
new file mode 100644
index 000000000..a0f12007f
--- /dev/null
+++ "b/Week09/\344\272\214\345\210\206\346\237\245\346\211\276\347\273\217\345\205\270\351\242\230\347\233\256.md"
@@ -0,0 +1,10 @@
+
+#### 二分查找模板
+
+#### 查找第一个值等于给定值的元素
+
+#### 查找最后一个值等于给定值的元素
+
+#### 查找第一个大于等于给定值的元素
+
+#### 查找最后一个小于等于给定值的元素
diff --git "a/Week09/\345\212\250\346\200\201\350\247\204\345\210\222.md" "b/Week09/\345\212\250\346\200\201\350\247\204\345\210\222.md"
new file mode 100644
index 000000000..3a2da7120
--- /dev/null
+++ "b/Week09/\345\212\250\346\200\201\350\247\204\345\210\222.md"
@@ -0,0 +1,141 @@
+### 最长系列
+#### 最长公共自序列
+```
+dp[i][i] = dp[i-1][j-1]+1 if word1[i-1]==word2[j-1]
+dp[i][j] = max(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])
+```
+#### 最长公共子串
+```
+dp[i][j] = dp[i-1][j-1]+1 if word1[i-1]==word2[j-1]
+dp[i][j] = 0
+return max(dp)
+```
+#### 最长回文串
+```
+枚举起点和长度,得到终点j
+dp[i][j] = dp[i+1][j-1] if word[i]==word[j]
+更新res长度为len(res,s[i:j+1])
+```
+#### 最长有效括号
+```
+if i-dp[i-1]-1>=0 and s[i-dp[i-1]-1] == '(' and s[i]==')'
+dp[i][j] = 2+dp[i-1]+dp[i-dp[i-1]-2]
+return max(dp)
+```
+
+#### 无重复最长子串
+```
+滑动窗口,a不在队列里 就入并更新最大长度,如果在,队列出元素,直到a不在,
+可以用set()优化
+```
+#### 最长上升子序列
+```
+维护单调栈,入栈,如果a比栈顶大,继续入,如果小于栈顶元素,则找到它该在的位置(可以用二分优化)-->可以输出最长的子序列
+也可以
+for i in range(size): for j in range(i):i表示终点、j表示起点
+dp[i] = max(d[i],dp[j]+1) if nums[i]>nums[j]
+```
+#### 最长重复子数组 没做
+
+#### 编辑距离
+```
+dp[i][j] = dp[i-1][j-1] if word1[i-1] == word2[j-1]
+dp[i][j = min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1]) + 1
+```
+
+#### 不同的子序列
+```
+dp[0][j] = 1
+dp[i][j] = dp[i-1][j-1]+dp[i][j-1] if word1[i-1] == word2[j-1]
+dp[i][j] = dp[i][j-1]
+```
+
+
+
+#### 62 不同路径
+一个机器人位于一个 m x n 网格的左上角 只能像右或向下走
+```python
+class Solution:
+ def uniquePaths(self, m: int, n: int) -> int:
+ # return int(math.factorial(m+n-2)/math.factorial(m-1)/math.factorial(n-1))
+ dp = [[1]*n for _ in range(m)]
+ for i in range(1,m):
+ for j in range(1,n):
+ dp[i][j] = dp[i-1][j] + dp[i][j-1]
+ return dp[m-1][n-1]
+```
+#### 不同路径II
+```python
+class Solution:
+ def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
+ m, n = len(obstacleGrid), len(obstacleGrid[0])
+ if obstacleGrid[0][0] == 1 or obstacleGrid[m-1][n-1] == 1:
+ return 0
+ dp = [[0]*n for _ in range(m)]
+ dp[0][0] = 1
+ for j in range(1,n):
+ dp[0][j] = dp[0][j-1] if obstacleGrid[0][j] == 0 else 0
+ for i in range(1,m):
+ dp[i][0] = dp[i-1][0] if obstacleGrid[i][0] == 0 else 0
+ for i in range(1,m):
+ for j in range(1,n):
+ if obstacleGrid[i][j] == 1: dp[i][j] == 0
+ else:
+ dp[i][j] = dp[i-1][j] + dp[i][j-1]
+ return dp[m-1][n-1]
+```
+
+#### 不同的二叉搜索树
+假设有i个节点,自动分配到左右子树 dp[i] = dp[j]*dp[i-j]
+```python
+class Solution:
+ def numTrees(self, n: int) -> int:
+ dp = [0]*(n+1)
+ dp[0], dp[1] = 1, 1
+ for i in range(2,n+1):
+ for j in range(1,i+1):#左边为0右边也可能为0
+ dp[i] += dp[j-1]*dp[i-j]
+ return dp[-1]
+```
+
+#### 不同的二叉搜索树
+求n个节点,生成所有不同的二叉搜索树
+那这只能用回溯法来做了
+```python
+class TreeNode:
+ def __init__(self, val=0, left=None, right=None):
+ self.val = val
+ self.left = left
+ self.right = right
+class Solution:
+ def generateTrees(self, n):
+ def generate_trees(start,end):
+ if start > end: return [None]#空树
+ trees = []
+ for i in range(start, end+1):
+ ltree = generate_trees(start,i-1)
+ rtree = generate_trees(i+1,end)
+ for lnode in ltree:#选出左子树
+ for rnode in rtree:#选出右子树
+ cur = TreeNode(i)
+ cur.left = lnode
+ cur.right = rnode
+ trees.append(cur)
+ return trees
+ return generate_trees(1,n) if n else []
+
+```
+
+#### 三角形最小路径和
+
+#### 72 编辑距离
+一条包含字母 A-Z 的消息通过以下方式进行了编码A-1 Z-26
+求解可行解
+明显的s[i] = s[i-1]+s[i-2],每次可以通过1位或两位得到s[i]
+什么情形dp[i] = dp[i+1]呢?
+s[i]
+
+
+
+
+#### 518 零钱兑换II
diff --git "a/Week09/\345\233\236\346\272\257\347\256\227\346\263\225\344\271\240\351\242\230\351\233\206.md" "b/Week09/\345\233\236\346\272\257\347\256\227\346\263\225\344\271\240\351\242\230\351\233\206.md"
new file mode 100644
index 000000000..b1310c11f
--- /dev/null
+++ "b/Week09/\345\233\236\346\272\257\347\256\227\346\263\225\344\271\240\351\242\230\351\233\206.md"
@@ -0,0 +1,226 @@
+### DFS/回溯算法习题集
+
+#### 78 子集
+给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集[幂集] 解集不能包含重复的子集
+对于给定的例题,就能看出这个题明显的回溯痕迹,子集的长度从0-len(nums),对于每一个长度,都有不同的取值
+就能联想到多叉树的不同深度对应的路径 每一层,都可以取原始list中的其他元素,所以需要回溯 在长度等于这一层的值时 加入res中
+时间复杂度是O(Nx2^N)
+```python
+from typing import List
+class Solution:
+ def subsets(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(first=0,tmp=[]):
+ res.append(tmp[:])
+ for i in range(first,size):
+ tmp.append(nums[i])
+ backtrace(i+1,tmp)#恰好这里的i+1可以当做边界条件,加入到res中
+ tmp.pop()
+ res, size = [], len(nums)
+ backtrace()
+ return res
+```
+
+#### 77 组合
+给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合
+[1,2,3,4]-2 -->[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]
+观察 所有子集长度都为k,且这个组合的构型是left List[List[int]]:
+ def backtrace(first=1,tmp=[]):
+ if len(tmp) == k:
+ res.append(tmp[:])
+ for i in range(first, n+1):
+ tmp.append(i)
+ backtrace(i+1,tmp)
+ tmp.pop()
+ res = []
+ backtrace()
+ return res
+```
+
+#### 46 全排列
+给定一个**没有重复**数字的序列,返回其所有可能的全排列。
+[1,2,3]--> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
+观察得到,第一层选择时,可以选择任何一个元素 这里的限定也是不包含这一层选的参数
+所以 可以在递归时,只传入还可选择的元素
+```python
+class Solution:
+ def permute(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums,tmp):
+ # if len(nums) == len(tmp):
+ if not nums:
+ res.append(tmp[:])
+ for i in range(len(nums)):#这里的nums会变化的
+ backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]])
+ # tmp.append(nums[i])
+ # backtrace(nums,tmp)
+ # tmp.pop()
+ res, size = [], len(nums)
+ backtrace(nums,[])
+ return res
+```
+
+#### 47 全排列II
+给定一个可包含重复数字的序列,返回所有不重复的全排列
+[1,1,2]--> [[1,1,2],[1,2,1],[2,1,1]]
+这一题主要考的是剪枝 很明显的 这里在第一层取值的时候就只取到了1,2两个值 另外重复的1在这一层不能被选取
+也即是 同一层不能选取重复的元素 **同层去重**
+刚开始的想法比较淳朴,就是全部结果生成之后,在加入到res时去重,多了一个for循环
+```python
+class Solution:
+ def permuteUnique(self, nums: List[int]) -> List[List[int]]:
+ # def backtrace(nums,tmp):
+ # if len(tmp) == size:
+ # if tmp not in res: #这个时间复杂度有点高,因为需要在程序里逻辑判重
+ # res.append(tmp[:])
+ # for i in range(len(nums)):
+ # backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]])
+ # res, size = [], len(nums)
+ # backtrace(nums,[])
+ # return res
+```
+后面改进,前剪枝 利用set来做,但是逻辑不够清楚 【个人觉得,虽然这种方法在其他剪枝类的题目中也有效】
+但是不用提前排序
+```python
+class Solution:
+ def permuteUnique(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums,tmp):
+ if not nums:
+ res.append(tmp[:])
+ visited = set()
+ for i in range(len(nums)):
+ if nums[i] in visited: continue
+ visited.add(nums[i])
+ backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]])
+ res, size = [], len(nums)
+ backtrace(nums,[])
+ return res
+```
+还看到一种专门解决同层去重的,但是需要先对已知序列进行排序
+```python
+class Solution:
+ def permuteUnique(self, nums: List[int]) -> List[List[int]]:
+ def backtrace(nums,tmp):
+ if not nums:
+ res.append(tmp[:])
+ for i in range(len(nums)):
+ if i>0 and nums[i-1] == nums[i]: continue
+ backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]])
+ res, size = [], len(nums)
+ nums.sort()
+ backtrace(nums,[])
+ return res
+```
+
+
+
+#### 31 下一个排列
+
+
+#### 60 第k个排列
+
+#### 39 组合总和I
+给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
+candidates 中的数字可以无限制重复被选取 但解集不能包含重复的组合 [candidates全是正整数]
+由于可以重复使用元素,所以递归时传入的数组无需调整
+很明显,还是树的深度优先遍历 由于是输出组合,肯定也涉及到回溯
+看个例子吧 看有哪些地方要优化
+```python
+# [1,3,2,7] 5
+# [[1,1,1,1,1],[1,1,1,2],[1,1,3],[1,1,2,1],[1,3,1],[1,2,1,1],[1,2,2],[3,1,1],[3,2],[2,1,1,1],[2,1,2],[2,3],[2,2,1]]
+# [[1,1,1,1,1],[1,1,1,2],[1,1,3],[1,2,2],[2,3]]
+```
+可以看到,解集的差异在于 对于[1,1,1,2]有不同的组合顺序,对于这一种 重复 剪枝方式通常是 在遍历可选择项的时候,加一个start
+```python
+class Solution:
+ def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
+ def dfs(candidates, target, tmp, start):
+ if target<0: return
+ if target == 0:
+ res.append(tmp)
+ for i in range(start, len(candidates)):
+ dfs(candidates, target-candidates[i], tmp+[candidates[i]], i)
+ res = []
+ dfs(candidates, target, [],0)
+ return res
+```
+
+#### 40 组合总和II
+在39的基础上,每个元素只能用一次
+这里有可能对于一组数[1,2,3,4,5] - 6,在递归过程中可能会产生[2,4]和[4,2]两种解 --> 遍历时加一个start
+对于同一层 可能的重复值选取 使用`if i>0 and nums[i-1] == nums[i]: continue`消除
+```python
+class Solution:
+ def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
+ def dfs(candidates,target,tmp,start):
+ if target < 0: return
+ if target == 0: res.append(tmp)
+ # visited = set()
+ for i in range(start, len(candidates)):
+ if i>0 and candidates[i-1] == candidates[i]: continue
+ # if cur in visited: continue
+ # visited.add(cur)
+ dfs(candidates[:i]+candidates[i+1:],target-candidates[i],tmp+[candidates[i]], i)
+ res = []
+ candidates.sort()
+ dfs(candidates,target,[],0)
+ return res
+```
+
+#### 216 组合总和III
+这里只要去除同一组解的重复排列即可 所以加上start即可
+```python
+class Solution:
+ def combinationSum3(self, k: int, target: int) -> List[List[int]]:
+ def dfs(cur, k, tmp, start):
+ if k < 0: return
+ if cur == target and k==0 : res.append(tmp)
+ # visited = set()
+ for i in range(start, 10):
+ # if i in visited: continue
+ # visited.add(i)
+ dfs(cur+i,k-1,tmp+[i],i+1)
+ res = []
+ dfs(0,k,[],1)
+ return res
+```
+
+#### 377 组合总和IV
+给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数
+顺序不同的序列被视作不同的组合
+```python
+class Solution:
+ def combinationSum4(self, nums: List[int], target: int) -> int:
+ def dfs(cur,tmp):
+ if cur > target: return
+ if cur == target: res.append(tmp)
+ for i in range(len(nums)):
+ dfs(cur+nums[i],tmp+[nums[i]])
+ res = []
+ dfs(0,[])
+ return len(res)
+```
+但是很不幸的 超时了 所以 要引入更高级的做法 动态规划!
+```python
+class Solution:
+ def combinationSum4(self, nums: List[int], target: int) -> int:
+ dp = [0]*(target+1)
+ dp[0] = 1
+ for i in range(target+1):
+ for j in range(len(nums)):
+ if i >= nums[j]:
+ dp[i] += dp[i-nums[j]]
+ return dp[-1]
+```
+
+这里总结一下
+给定[1,1,2,3,4] 求 target=6
+如果1,1在同一层中不能使用,那么就要使用set或者先sort然后在for循环里面判断nums[i-1]==nums[i]
+或者 对于不同路径产生的结果 [2,4]和[4,2]不能相容 则 在for循环中加入起始位置
+
+最后分一下回溯算法的时间复杂度
+
+
diff --git "a/Week09/\345\244\232\347\272\277\347\250\213\346\211\223\345\215\2600-100.py" "b/Week09/\345\244\232\347\272\277\347\250\213\346\211\223\345\215\2600-100.py"
new file mode 100644
index 000000000..e0fde158b
--- /dev/null
+++ "b/Week09/\345\244\232\347\272\277\347\250\213\346\211\223\345\215\2600-100.py"
@@ -0,0 +1,31 @@
+import threading
+import time
+
+
+# 第一个线程,打印奇数
+def threada(n):
+ for i in range(1, n + 1):
+ if i & 1:
+ lockb.acquire()#先请求b锁,保证不会打印偶数
+ print(i)
+ locka.release()
+
+# 第二个线程,打印偶数
+def threadb(n):
+ for i in range(2, n + 1):
+ if i & 1 == 0:
+ locka.acquire()#先请求a锁,使得打印偶数过程不会打印奇数
+ print(i),
+ lockb.release()
+
+if __name__ == "__main__":
+ locka = threading.Lock()
+ lockb = threading.Lock()
+
+ ta = threading.Thread(target=threada,args=(100,))
+ tb = threading.Thread(target=threadb,args=(100,))
+
+ locka.acquire() # 保证a先执行
+
+ ta.start()
+ tb.start()
diff --git "a/Week09/\346\225\260\347\273\204\343\200\201\351\223\276\350\241\250\343\200\201\345\255\227\347\254\246\344\270\262\351\242\230\347\233\256.md" "b/Week09/\346\225\260\347\273\204\343\200\201\351\223\276\350\241\250\343\200\201\345\255\227\347\254\246\344\270\262\351\242\230\347\233\256.md"
new file mode 100644
index 000000000..de176458c
--- /dev/null
+++ "b/Week09/\346\225\260\347\273\204\343\200\201\351\223\276\350\241\250\343\200\201\345\255\227\347\254\246\344\270\262\351\242\230\347\233\256.md"
@@ -0,0 +1,193 @@
+### 链表
+#### 2.两数相加
+两个数字倒序以链表存储每一位数字,返回最终结果的链表头指针
+解题主要考虑进位,以及如果最后结果产生多的位数时的情形 如[5]、[5] -- [0,1]
+```python
+class Solution:
+ def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
+ pre = ListNode(-1)
+ head, carry = pre, 0
+ while l1 or l2:
+ x = l1.val if l1 else 0
+ y = l2.val if l2 else 0
+ cur = x + y + carry
+ carry = cur//10
+ head.next =ListNode(cur%10)
+ if l1: l1 = l1.next
+ if l2: l2 = l2.next
+ head = head.next
+ if carry == 1:
+ head.next = ListNode(1)
+ return pre.next
+```
+
+#### 25 k个一组翻转链表
+如果翻转过程中,长度小于k,不变化
+这题的思路和翻转链表一致,主要是要界定的条件比较多
+首先找到此轮中需要翻转的链表部分的首尾指针,然后进行翻转 返回这个k串翻转之后的头尾指针
+翻转之后要连接到原来的链表中,所以要一个pre和下一个k串的头指针
+对于组内翻转 也需要一个pre节点,注意到 这里不能用空节点 而是用下一个k串的头结点
+最后要返回翻转后的首尾节点 翻转前先记录 方便函数返回
+```python
+# Definition for singly-linked list.
+# class ListNode:
+# def __init__(self, x):
+# self.val = x
+# self.next = None
+
+class Solution:
+ # 翻转一个子链表,并且返回新的头与尾
+ def reverseKGroup(self, head, k):
+ dummy = ListNode(-1)
+ dummy.next = head
+ pre = dummy
+ while head:
+ tail = pre
+ for i in range(k):#先找到此时要翻转哪些节点,记录首尾指针
+ tail = tail.next
+ if not tail:#如果不够k个
+ return dummy.next
+ next_head = tail.next #记录翻转后的下一个节点
+ head, tail = self.reverseList(head,tail)#翻转链表
+ pre.next = head
+ tail.next = next_head
+ head = next_head
+ pre = tail
+ return dummy.next
+ def reverseList(self,head,tail):
+ # 如何原地翻转
+ pre = tail.next#记录那个空节点【】
+ tail_node = head #记录翻转后的尾节点
+ while pre!=tail: #tail是刚进来的尾节点,用它来判断是否组内翻转完毕
+ tmp = head.next
+ head.next = pre
+ pre = head
+ head = tmp
+ return pre, tail_node
+```
+---
+
+### 数组
+
+
+#### 4.寻找两个正序数组的中位数
+刚开始就想着用python内置的合并数组然后根据奇偶返回中位数嘛 但是时间复杂度是O(M+N)log(M+N),空间复杂度是O(M+N)
+取决于排序方法
+2.归并排序
+3.双指针 排除数组中k//2个数
+题目要求是O(log(M+N)),所以在探查的时候应当用二分查找
+```python
+
+```
+
+
+#### 88 合并两个有序数组
+1.合并后排序,没有利用原始数组已排序的特点 O((M+N)log(M+N))
+2.双指针 从前往后 需要涉及大量元素的移动,且需要额外空间
+3.双指针 从后往前 无需挪动元素 O(M+N)
+```python
+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.
+ """
+ # 把大的都往nums1后面放
+ i, j = m-1, n-1#从后往前判断
+ store_id = m + n - 1
+ while i >= 0 and j >= 0:
+ if nums1[i] >= nums2[j]:
+ nums1[store_id] = nums1[i]
+ i, store_id = i - 1, store_id - 1
+ else:
+ nums1[store_id] = nums2[j]
+ j, store_id = j - 1, store_id - 1
+ nums1[:j+1] = nums2[:j+1]#if nums2 still have elems
+```
+
+
+#### 27 移除元素
+给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度
+元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素
+双指针解法,用left记录不相同值的位置
+```python
+class Solution:
+ def removeElement(self, nums: List[int], val: int) -> int:
+ left, size = 0, len(nums)
+ for i in range(size):
+ if nums[i] != val:
+ nums[left] = nums[i]
+ left += 1
+ return left
+```
+
+#### 31.下一个排列
+
+
+----
+### 字符串
+
+#### 3.无重复字符的最长子串
+给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度
+刚开始想的就是用队列记录最长子串,有相同的就一直出队列 直到将该元素出队列为止
+但是在双向队列或list里面判断是否在不在是O(N)的,所以可以用set优化一下
+优化后,整体的时间复杂度是O(N)
+```python
+class Solution:
+ def lengthOfLongestSubstring(self, strs: str) -> int:
+ if not strs: return 0
+ visited = set()
+ max_len, cur_len, left = 0, 0, 0
+ for i in range(len(strs)):
+ while strs[i] in visited:
+ visited.remove(strs[left])
+ left = left + 1
+ cur_len -= 1
+ visited.add(strs[i])
+ cur_len += 1
+ max_len = max(max_len, cur_len)
+ return max_len
+```
+
+
+#### 剑指offer67 字符串转数字
+```python
+class Solution:
+ def strToInt(self, strs: str) -> int:
+ strs =''.join(strs.lstrip(' '))
+ # +-1234
+ # +-1234lmq
+ # +-1234-+
+ # lmq1234
+ # lmq 1234
+ # 碰到空格/字符--->0 第二次碰到+-截断
+ # pass
+ res, flag = 0 ,1
+ strs = strs.strip()
+ for i in range(len(strs)):
+ ch = strs[i]
+ if (ch == '-' or ch == '+') and i == 0:
+ if ch == '-': flag = -1
+ if ch == '+': flag = 1
+ continue
+ if not ch.isdigit(): break
+ res = 10 * res + ord(ch) - ord('0')
+ if res == '+' or res == '-': return 0
+ return max(-2**31,-1*res) if flag == -1 else min(2**31-1,res)
+
+```
+
+#### 392 判断子序列
+1.双指针,匹配时同时后移,不匹配母串指针后移 O(M+N)
+2.动态规划 唯实是没看懂
+```python
+class Solution:
+ def isSubsequence(self, s: str, t: str) -> bool:
+ if not s: return True#与面试官沟通
+ i, j = 0,0
+ while i=b
+ if a%b == 0: return b
+ else:
+ return gcd(b,a%b)
+def lcm(a,b):
+ return a*b/gcd(a,b)
+
+res = lcm(2,4)
+print(res)
diff --git "a/Week09/\346\234\200\351\225\277\345\255\220\345\272\217\345\210\227\343\200\201\345\255\220\344\270\262\343\200\201\345\211\215\347\274\200.md" "b/Week09/\346\234\200\351\225\277\345\255\220\345\272\217\345\210\227\343\200\201\345\255\220\344\270\262\343\200\201\345\211\215\347\274\200.md"
new file mode 100644
index 000000000..7615d8162
--- /dev/null
+++ "b/Week09/\346\234\200\351\225\277\345\255\220\345\272\217\345\210\227\343\200\201\345\255\220\344\270\262\343\200\201\345\211\215\347\274\200.md"
@@ -0,0 +1,112 @@
+
+#### 5.最长回文子串
+```python
+class Solution:
+ def longestPalindrome(self, s: str) -> str:
+ # 暴力法 时间复杂度O(N^3)
+ # 中心扩散 最坏O(N^2)
+ # size = len(s)
+ # left, right = 0, 0
+ # def extend(left,right):#要一直向外扩展,就和快排、验证回文串II 一样要一直找一直找
+ # 扩散是有条件的 不能越界
+ # while left>=0 and right < size and s[left] == s[right]:
+ # left, right = left - 1, right + 1
+ # return left + 1, right - 1
+ # for i in range(size):
+ # l1, r1 = extend(i,i)
+ # l2, r2 = extend(i,i+1)
+ # if r1 - l1 > right - left:
+ # left, right = l1, r1
+ # if r2 - l2 > right - left:
+ # left, right = l2, r2
+ # return s[left:right+1]
+
+ size = len(s)
+ res = ''
+ dp = [[False]*size for _ in range(size)]
+ for l in range(size):#枚举长度
+ for i in range(size):#枚举起点
+ j = i + l
+ if j >= size: break
+ elif l == 0: dp[i][j] = True
+ elif l == 1: dp[i][j] = (s[i]==s[j])
+ else:
+ #i-j是否为回文首先要判断s[i],s[j]是否相等
+ dp[i][j] = (dp[i+1][j-1] and s[i]==s[j])
+ if dp[i][j] and l >= len(res):
+ res = s[i:j+1]
+ return res
+```
+
+#### 1143 最长公共子序列
+```python
+class Solution:
+ def longestCommonSubsequence(self, text1: str, text2: str) -> int:
+ # 看题目和之前那道最长公共回文串,很类似,这里用动态规划做,
+ # 但是要注意 这里是最长公共子序列,是可以间断的
+ if not text1 and not text2: return 0
+ m, n = len(text1), len(text2)
+ dp = [[0]*(n+1) for _ in range(m+1)]
+ for i in range(1,m+1):
+ for j in range(1,n+1):
+ if text1[i-1] == text2[j-1]:
+ dp[i][j] = dp[i-1][j-1] + 1
+ else:
+ dp[i][j] = max(dp[i-1][j],dp[i][j-1])
+ return dp[-1][-1]
+```
+
+#### 32 最长有效括号
+```python
+class Solution:
+ def longestValidParentheses(self, strs: str) -> int:
+ #先和面试官讨论清楚,最长有效括号是否是连续的
+ # pass
+ #中心扩散???-->NO
+ if not strs: return 0
+ dp = [0]*len(strs)#表示下标为i的有效括号长度
+ for i in range(len(strs)):
+ if strs[i] == ')' and strs[i-dp[i-1]-1]=='(' and i-dp[i-1]-1>=0:#自身是否为有效括号
+ dp[i] = 2 + dp[i-1] + dp[i-dp[i-1]-2]#自身+内有效括号+外有效括号
+ return max(dp)
+ # if not strs: return 0
+ # stack,max_len,len1 = [-1], 0, 0
+ # for i in range(len(strs)):
+ # if strs[i] == '(':
+ # stack.append(i)
+ # else:
+ # stack.pop()
+ # if not stack:
+ # stack.append(i)
+ # else:
+ # len1 = i - stack[-1]
+ # max_len = max(max_len,len1)
+ # return max_len
+```
+
+#### 最长公共前缀
+```python
+class Solution:
+ def longestCommonPrefix(self, strs: List[str]) -> str:
+ # if not strs: return ''
+ # min_size = min([len(x) for x in strs])#公共前缀最长只会这么长
+ # 枚举最长公共前缀长度
+ # for i in range(min_size, 0, -1):
+ # tmp = strs[0][:i] # 当前待比较的公共前缀子串
+ # if all(s[:i]==tmp for s in strs):
+ # return tmp
+ # return ''
+ # 分治
+ def lcp(start, end):
+ if start == end:
+ return strs[start]
+ mid = (start + end) // 2
+ lcpLeft, lcpRight = lcp(start, mid), lcp(mid + 1, end)
+ minLength = min(len(lcpLeft), len(lcpRight))
+ for i in range(minLength):
+ if lcpLeft[i] != lcpRight[i]:
+ return lcpLeft[:i]
+ return lcpLeft[:minLength]
+ return "" if not strs else lcp(0, len(strs) - 1)
+```
+
diff --git "a/Week09/\346\240\210\345\222\214\345\215\225\350\260\203\346\240\210.py" "b/Week09/\346\240\210\345\222\214\345\215\225\350\260\203\346\240\210.py"
new file mode 100644
index 000000000..84d82d3bc
--- /dev/null
+++ "b/Week09/\346\240\210\345\222\214\345\215\225\350\260\203\346\240\210.py"
@@ -0,0 +1,3 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/7/25 9:56 PM
\ No newline at end of file
diff --git "a/Week09/\347\211\233\345\256\242_\346\266\202\346\224\271\346\234\250\346\235\277.py" "b/Week09/\347\211\233\345\256\242_\346\266\202\346\224\271\346\234\250\346\235\277.py"
new file mode 100644
index 000000000..3bd90994b
--- /dev/null
+++ "b/Week09/\347\211\233\345\256\242_\346\266\202\346\224\271\346\234\250\346\235\277.py"
@@ -0,0 +1,26 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/6 9:44 PM
+
+#
+#
+# @param n int整型
+# @param m int整型
+# @param a int整型一维数组
+# @return int整型
+#
+class Solution:
+ def solve(self, n, m, nums):
+ # write code here
+ # 6,1, [1,0,0,1,1,1]
+ # 设dp[i][j]是第i次染色,到第j块能拿到的最大板子长度
+ # dp[0] = nums[:]
+ # dp[i][0] = 1
+ # for i in range(1,m+1)
+ # dp[i][j] = max(dp[i-1][j],dp[i][j-1]+1)
+
+
+s = Solution()
+nums = [1,0,0,1,1,1]
+res = s.solve(6,2,nums)
+print(res)
\ No newline at end of file
diff --git a/test.py b/test.py
new file mode 100644
index 000000000..4453034f7
--- /dev/null
+++ b/test.py
@@ -0,0 +1,97 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/11 8:20 PM
+
+
+# def decode(stack):
+# val1 = stack.pop()
+# val2 = stack.pop()
+# ch = chr(int(val1+val2,16))
+# if ch == '%':
+# stack = decode(stack)
+# else:
+# stack.append(ch)
+# return stack
+# def main():
+# N = int(input())
+# for i in range(N):
+# s = str(input())
+# stack = []
+# for c in s[::-1]:
+# if c != '%':#%%32F
+# stack.append(c)
+# else:
+# stack = decode(stack)
+# print("".join(stack[::-1]))
+# main()
+# class Solution:
+# def minCost(self,x,a,b):
+# size = int((x+251)/500)#减少开辟的内存空间
+# dp = [0]*(size+1)
+# for i in range(1,3):
+# dp[i] = dp[i-1] + a
+# print(dp)
+# for i in range(3, size+1):
+# dp[i] = min(dp[i-3]+b, dp[i-1]+a)
+# return dp
+# s = Solution()
+# res = s.minCost(4999,5,10)
+# print(res)
+# def min_cost(x,a,b):
+# if x == 0: return 0
+# size = int((x+251)/500)
+# dp = [0]*(size+1)
+# for i in range(1,3):
+# dp[i] = dp[i-1] + a
+# for i in range(1,size+1):
+# dp[i] = min(dp[i-1]+a, dp[i-3]+b)
+# return dp[-1]
+
+# def min_cost(x,a,b):
+# if 3*a <= b:
+# return x//500 * a#全部买小瓶的
+# else:#买1500ml均价更低
+# #先确定大瓶数量、在确定小瓶数量
+# m = x // 1500 + 1 if x % 1500 != 0 else x // 1500
+# # 1. 全买大瓶
+# cost1 = m * b
+# # 2. 尽可能买大瓶,剩下买小的
+# x = x - 1500 * (m - 1)
+# n = x // 500 + 1 if x % 500 != 0 else x // 500
+# cost2 = (m - 1) * b + n * a
+# return min(cost1, cost2)
+# while True:
+# try:
+# N = int(input())
+# for i in range(N):
+# [x,a,b] = list(map(int,str(input()).split()))
+# res = min_cost(x,a,b)
+# print(res)
+# except:
+# break
+
+
+# def cost(x, a, b):
+# if 3 * a < b:
+# n = x // 500 + 1 if x % 500 != 0 else x // 500
+# return n * a
+# else:
+# m = x // 1500 + 1 if x % 1500 != 0 else x // 1500
+# cost1 = m * b
+# x = x - 1500 * (m - 1)
+# n = x // 500 + 1 if x % 500 != 0 else x // 500
+# cost2 = (m - 1) * b + n * a
+# return min(cost1, cost2)
+#
+# while True:
+# try:
+# n = int(input())
+# for i in range(n):
+# [x, a, b] = list(map(int, input().split()))
+# print(cost(x, a, b))
+# except:
+# break
+s= input().split(',')
+print(s)
+# a,b = list(map(int,[s1[1:-2],s2[:-2]]))
+# print(a,b)
\ No newline at end of file
diff --git "a/\345\244\232\347\272\247\345\217\260\351\230\266\351\227\256\351\242\230.py" "b/\345\244\232\347\272\247\345\217\260\351\230\266\351\227\256\351\242\230.py"
new file mode 100644
index 000000000..cb054ebc0
--- /dev/null
+++ "b/\345\244\232\347\272\247\345\217\260\351\230\266\351\227\256\351\242\230.py"
@@ -0,0 +1,27 @@
+# -*- coding:utf-8 -*-
+# Author : Ray
+# Data : 2020/8/12 11:27 AM
+
+# 小明那题应该是
+# dp[i]表示走上第i级台阶有多少种走法
+# #0表示走1阶,1表示走两阶,由于连续两次不能重复,
+# 所以如果你这次想走1个台阶,只能是你之前从i-2个台阶走两阶;
+# 如果你这次想走2个台阶,(你之前只能走1个台阶)只能从i-1个台阶走过来
+# dp[0][0] = 0 dp[0][1] = 0
+# dp[1][0] = 1 dp[1][1] = 0
+# dp[2][0] = 0 dp[2][1] = 1
+# 那么现在 如果想走到三级台阶,有几种走法???1. 2+1 2.1+2 仅两种
+# dp[i][0] = dp[i-2][1] + 1 #dp[2][0] = dp[i-dp[i-1]][1]+1 = 0+1 = 1
+# dp[i][1] = dp[i-2][0] + 1# dp[2][1] = dp[0][0]+1 = 0
+# dp[3][0]
+# dp[i][0,1]表示以走0或1(+1)的方式走上第i级台阶的方法
+# 如果想走到n级台阶,有两种走法,走1阶,走两阶
+# 1.确定此时走两阶 那么之前只能走一阶 dp[i][1] = dp[i-1][0] + 1
+# 2.确定此时只能走一阶 那么此前只能走两阶 dp[i][0] = dp[i-2][1] + 1
+# dp[0][0] = 0 dp[0][1] = 0
+# dp[1][0] = 1 dp[1][1] = 0
+# dp[2][0] = 0 dp[2][1] = 1
+# 如果要上三级台阶 1+2 或者2+1
+# dp[3][0] = dp[2][1] + 1= 2
+# dp[3][1] = dp[1][0] + 1 = 2
+# 最后返回max(dp[-1])
\ No newline at end of file