�Ѷ�:Easy**
+**难度: Easy**
-## ˢ������
-> ԭ������
+## 刷题内容
-* https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/
+> 原题连接
-> ��������
+* https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/
+
+> 内容描述
```
+
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).
@@ -36,20 +38,21 @@ Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
```
-> ˼·
-******- ʱ�临�Ӷ�: O(N)******- �ռ临�Ӷ�: O(1)******
-
-�ñ����Ľⷨ�ܿ�Ϳ������������⣬�������ǿ����ø��õķ�����O(N)��ʱ�临�ӶȽ�����⡣����i = 1���������顣��� prices[i] > prices[i - 1]��ans += ��prices[i] - prices[i - 1]����
-
-```cpp
-class Solution {
-public:
- int maxProfit(vector& prices) {
- int maxRet = 0;
- for(int i = 1;i < prices.size();++i)
- if(prices[i] > prices[i - 1])
- maxRet += (prices[i] - prices[i - 1]);
- return maxRet;
- }
-};
-```
\ No newline at end of file
+## 解题方案
+
+> 思路 1
+
+因为不限制买卖次数,所以对于除了最后一天的每一天,我们只需要看看它是否比明天价格低即可,
+如果是的话那我们就今天买入明天卖出(注意:前后两天价格相等的话我们不做买卖操作,因为可能会减少后面可以赚钱的操作数),这样一直操作下去叠加即可
+
+```python
+class Solution(object):
+ def maxProfit(self, prices):
+ """
+ :type prices: List[int]
+ :rtype: int
+ """
+ if not prices or len(prices) == 0:
+ return 0
+ return sum([max(prices[i+1]-prices[i], 0) for i in range(len(prices)-1)])
+```
diff --git a/docs/leetcode/python/124._Binary_Tree_Maximum_Path_Sum.md b/docs/Leetcode_Solutions/Python/124._Binary_Tree_Maximum_Path_Sum.md
similarity index 100%
rename from docs/leetcode/python/124._Binary_Tree_Maximum_Path_Sum.md
rename to docs/Leetcode_Solutions/Python/124._Binary_Tree_Maximum_Path_Sum.md
diff --git a/docs/Leetcode_Solutions/Python/125._valid_palindrome.md b/docs/Leetcode_Solutions/Python/125._valid_palindrome.md
new file mode 100644
index 000000000..460a40df5
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/125._valid_palindrome.md
@@ -0,0 +1,100 @@
+# 125. Valid Palindrome
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/valid-palindrome/description/
+
+> 内容描述
+
+```
+Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
+
+Note: For the purpose of this problem, we define empty string as valid palindrome.
+
+Example 1:
+
+Input: "A man, a plan, a canal: Panama"
+Output: true
+Example 2:
+
+Input: "race a car"
+Output: false
+```
+
+## 解题方案
+
+> 思路 1
+
+就是比较reversed string 和原本的是否相等.
+
+
+```python
+class Solution(object):
+ def isPalindrome(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ new = ''
+ s = s.lower()
+
+ for i in s:
+ if '0' <= i <= '9' or 'a' <= i <= 'z':
+ new += i
+ return new == new[::-1]
+```
+这样写更简单
+
+```python
+class Solution:
+ def isPalindrome(self, s):
+ s = ''.join(e for e in s if e.isalnum()).lower()
+ return s==s[::-1]
+```
+
+> 思路 2
+
+或者用正则,详见[re.sub()用法](http://blog.csdn.net/geekleee/article/details/75309433)
+瞬间```beats 97.71%```
+
+```python
+class Solution(object):
+ def isPalindrome(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ s = re.sub('[^0-9a-zA-Z]+', '', s ).lower()
+ return s == s[::-1]
+```
+
+> 思路 3
+
+
+双指针in-place
+
+时间复杂度还是O(n), 但是空间优化到了O(1)
+```python
+class Solution(object):
+ def isPalindrome(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ l, r = 0, len(s)-1
+ while l < r:
+ while l < r and not s[l].isalnum():
+ l += 1
+ while l < r and not s[r].isalnum():
+ r -= 1
+ if s[l].lower() != s[r].lower():
+ return False
+ l +=1
+ r -= 1
+ return True
+```
+
diff --git a/docs/leetcode/python/126._Word_Ladder_II.md b/docs/Leetcode_Solutions/Python/126. Word Ladder II.md
similarity index 100%
rename from docs/leetcode/python/126._Word_Ladder_II.md
rename to docs/Leetcode_Solutions/Python/126. Word Ladder II.md
diff --git a/docs/Leetcode_Solutions/Python/127._word_ladder.md b/docs/Leetcode_Solutions/Python/127._word_ladder.md
new file mode 100644
index 000000000..b852e9b11
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/127._word_ladder.md
@@ -0,0 +1,81 @@
+# 127. Word Ladder
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/word-ladder/description/
+
+> 内容描述
+
+```
+Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
+
+Only one letter can be changed at a time.
+Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
+Note:
+
+Return 0 if there is no such transformation sequence.
+All words have the same length.
+All words contain only lowercase alphabetic characters.
+You may assume no duplicates in the word list.
+You may assume beginWord and endWord are non-empty and are not the same.
+Example 1:
+
+Input:
+beginWord = "hit",
+endWord = "cog",
+wordList = ["hot","dot","dog","lot","log","cog"]
+
+Output: 5
+
+Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
+return its length 5.
+Example 2:
+
+Input:
+beginWord = "hit"
+endWord = "cog"
+wordList = ["hot","dot","dog","lot","log"]
+
+Output: 0
+
+Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
+
+```
+
+## 解题方案
+
+> 思路 1
+
+tag可以算BFS,其实就是求shortest path的变体
+
+Reference from [kamyu104](https://github.com/kamyu104/LeetCode/blob/71e0ba555ee49befa01fcd9fc78c3528e2ab63a9/Python/word-ladder.py)
+
+```python
+class Solution(object):
+ def ladderLength(self, beginWord, endWord, wordList):
+ """
+ :type beginWord: str
+ :type endWord: str
+ :type wordList: List[str]
+ :rtype: int
+ """
+ distance, stack, visited, lookup = 0, [beginWord], set([beginWord]), set(wordList)
+ while stack:
+ next_stack = []
+ for word in stack:
+ if word == endWord:
+ return distance + 1
+ for i in range(len(word)):
+ for char in 'abcdefghijklmnopqrstuvwxyz':
+ trans_word = word[:i] + char + word[i+1:]
+ if trans_word not in visited and trans_word in lookup:
+ next_stack.append(trans_word)
+ visited.add(trans_word)
+ distance += 1
+ stack = next_stack
+ return 0
+```
diff --git a/docs/leetcode/python/128._Longest_Consecutive_Sequence.md b/docs/Leetcode_Solutions/Python/128._Longest_Consecutive_Sequence.md
similarity index 100%
rename from docs/leetcode/python/128._Longest_Consecutive_Sequence.md
rename to docs/Leetcode_Solutions/Python/128._Longest_Consecutive_Sequence.md
diff --git a/docs/leetcode/python/129._sum_root_to_leaf_numbers.md b/docs/Leetcode_Solutions/Python/129._sum_root_to_leaf_numbers.md
similarity index 100%
rename from docs/leetcode/python/129._sum_root_to_leaf_numbers.md
rename to docs/Leetcode_Solutions/Python/129._sum_root_to_leaf_numbers.md
diff --git a/docs/leetcode/python/130._surrounded_regions.md b/docs/Leetcode_Solutions/Python/130._surrounded_regions.md
similarity index 100%
rename from docs/leetcode/python/130._surrounded_regions.md
rename to docs/Leetcode_Solutions/Python/130._surrounded_regions.md
diff --git a/docs/leetcode/python/131._palindrome_partitioning.md b/docs/Leetcode_Solutions/Python/131._palindrome_partitioning.md
similarity index 100%
rename from docs/leetcode/python/131._palindrome_partitioning.md
rename to docs/Leetcode_Solutions/Python/131._palindrome_partitioning.md
diff --git a/docs/leetcode/python/133._clone_graph.md b/docs/Leetcode_Solutions/Python/133._clone_graph.md
similarity index 100%
rename from docs/leetcode/python/133._clone_graph.md
rename to docs/Leetcode_Solutions/Python/133._clone_graph.md
diff --git a/docs/leetcode/python/136._single_number.md b/docs/Leetcode_Solutions/Python/136._single_number.md
similarity index 51%
rename from docs/leetcode/python/136._single_number.md
rename to docs/Leetcode_Solutions/Python/136._single_number.md
index 18540da0f..97778eaa8 100644
--- a/docs/leetcode/python/136._single_number.md
+++ b/docs/Leetcode_Solutions/Python/136._single_number.md
@@ -1,17 +1,36 @@
-### 136. Single Number
+# 136. Single Number
+**难度: Easy**
+## 刷题内容
-题目:
-
+> 原题连接
+* https://leetcode.com/problems/single-number/description/
-难度:
+> 内容描述
-Easy
+```
+Given a non-empty array of integers, every element appears twice except for one. Find that single one.
+
+Note:
+
+Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
+
+Example 1:
+Input: [2,2,1]
+Output: 1
+Example 2:
-思路:
+Input: [4,1,2,1,2]
+Output: 4
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
位运算,终于要take it了
@@ -24,7 +43,7 @@ Easy
Python的位操作:
-神奇的解法:
+
```python
diff --git a/docs/Leetcode_Solutions/Python/137._Single_Number_II.md b/docs/Leetcode_Solutions/Python/137._Single_Number_II.md
new file mode 100644
index 000000000..9c26ff3a5
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/137._Single_Number_II.md
@@ -0,0 +1,85 @@
+# 137. Single Number II
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/single-number-ii/description/
+
+> 内容描述
+
+```
+Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
+
+Note:
+
+Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
+
+Example 1:
+
+Input: [2,2,3,2]
+Output: 3
+Example 2:
+
+Input: [0,1,0,1,0,1,99]
+Output: 99
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+一行,算出set和的三倍,然后减去总的sum,就是所求数字的2倍
+
+beats 100%
+```python
+class Solution(object):
+ def singleNumber(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ return int((3 * sum(set(nums)) - sum(nums)) // 2)
+```
+
+
+
+
+
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+参考文章:
+
+1. [[Leetcode]找到出现不同次数的数字(通用解法)](https://www.cnblogs.com/bjwu/p/9323808.html)
+2. [bron 【中文】简短又通俗的理解](https://leetcode.com/problems/single-number-ii/discuss/167343/topic)
+3. [leetcode-137-Single Number II-第二种解法](https://cloud.tencent.com/developer/article/1131945)
+
+```python
+class Solution(object):
+ def singleNumber(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ a = b = 0
+ for num in nums:
+ b = b ^ num & ~a
+ a = a ^ num & ~b
+ return a | b
+```
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/139._word_break.md b/docs/Leetcode_Solutions/Python/139._word_break.md
new file mode 100644
index 000000000..815737dec
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/139._word_break.md
@@ -0,0 +1,59 @@
+### 139. Word Break
+
+题目:
+
+
+
+难度:
+
+Medium
+
+
+
+```ok[i]``` tells whether ```s[:i]``` can be built.
+
+```python
+class Solution(object):
+ def wordBreak(self, s, wordDict):
+ """
+ :type s: str
+ :type wordDict: List[str]
+ :rtype: bool
+ """
+ ok = [True]
+ for i in range(1, len(s)+1):
+ ok += [any(ok[j] and s[j:i] in wordDict for j in range(i))]
+ return ok[-1]
+```
+
+但是往list里面加数据的方法有快有慢,下面是对比:
+```
+>>> from timeit import timeit
+>>> timeit('x.append(1)', 'x = []', number=10000000)
+1.9880003412529277
+>>> timeit('x += 1,', 'x = []', number=10000000)
+1.2676891852971721
+>>> timeit('x += [1]', 'x = []', number=10000000)
+3.361207239950204
+```
+因此我们可以将代码直接换成下面的格式
+```python
+ok += any(ok[j] and s[j:i] in wordDict for j in range(i)) # 会报错
+```
+但是这样会报错,TypeError: 'bool' object is not iterable,因此bool类型数据不能这样加,别的可以(list类型本身当然要注意哈)
+
+因此在这个例子中我们这样:
+```python
+class Solution(object):
+ def wordBreak(self, s, wordDict):
+ """
+ :type s: str
+ :type wordDict: List[str]
+ :rtype: bool
+ """
+ ok = [True]
+ for i in range(1, len(s)+1):
+ ok += any(ok[j] and s[j:i] in wordDict for j in range(i)),
+ return ok[-1]
+```
+代码里面的那个逗号构建了一个tuple,也会快一点
diff --git a/docs/leetcode/python/140._word_break_ii.md b/docs/Leetcode_Solutions/Python/140._word_break_ii.md
similarity index 100%
rename from docs/leetcode/python/140._word_break_ii.md
rename to docs/Leetcode_Solutions/Python/140._word_break_ii.md
diff --git a/docs/leetcode/python/141._linked_list_cycle.md b/docs/Leetcode_Solutions/Python/141._linked_list_cycle.md
similarity index 95%
rename from docs/leetcode/python/141._linked_list_cycle.md
rename to docs/Leetcode_Solutions/Python/141._linked_list_cycle.md
index 49417387a..2d50901e9 100644
--- a/docs/leetcode/python/141._linked_list_cycle.md
+++ b/docs/Leetcode_Solutions/Python/141._linked_list_cycle.md
@@ -1,105 +1,105 @@
-### 141. Linked List Cycle
-
-题目:
-
-
-
-
-难度:
-
-Easy
-
-
-想法一:
-
-直接超时
-
-```
-class Solution(object):
- def hasCycle(self, head):
- """
- :type head: ListNode
- :rtype: bool
- """
- if head == None: return False
- lst = []
- cur = head
- while cur:
- if cur in lst:
- return True
- lst.append(cur)
- cur = cur.next
- return False
-```
-
-
-
-想法二:相当用boolean array记录某个点是否被访问过,时间,空间复杂度都是O(n)
-
-```
-class Solution(object):
- def hasCycle(self, head):
- """
- :type head: ListNode
- :rtype: bool
- """
- if head == None: return False
- dictx = {}
- cur = head
- while cur:
- if cur in dictx:
- return True
- dictx[cur] = 1
- cur = cur.next
- return False
-```
-
-结果这种方法的run time还比较快
-
-查了一下,有解答说可以有空间复杂度O(1),时间复杂度O(n)。两个指针,一个快一个慢,快的每次走两步,慢的每次走一步,如果有环,最终会在某处相遇。这也是一个算法。这种快慢指针配合已经不是第一次遇到了,比如找linklist中间的node。
-
-
-
-但是并没有觉得这样的算法是O(n), worst case time complexity is O(N+K), which is O(n).
-
-
-```python
-python
-class Solution(object):
- def hasCycle(self, head):
- """
- :type head: ListNode
- :rtype: bool
- """
- slow = head
- fast = head
- while fast and fast.next:
- slow = slow.next
- fast = fast.next.next
- if slow == fast:
- return True
- return False
-```
-
-
-```java
-java
-public class Solution {
- public boolean hasCycle(ListNode head) {
- if (head == null){
- return false;
- }
- ListNode fast = head;
- ListNode slow = head;
- while (fast != null && slow != null && fast.next != null){
- fast = fast.next.next;
- slow = slow.next;
- if (slow == fast){
- return true;
- }
- }
- return false;
- }
-}
-```
-
+### 141. Linked List Cycle
+
+题目:
+
+
+
+
+难度:
+
+Easy
+
+
+想法一:
+
+直接超时
+
+```
+class Solution(object):
+ def hasCycle(self, head):
+ """
+ :type head: ListNode
+ :rtype: bool
+ """
+ if head == None: return False
+ lst = []
+ cur = head
+ while cur:
+ if cur in lst:
+ return True
+ lst.append(cur)
+ cur = cur.next
+ return False
+```
+
+
+
+想法二:相当用boolean array记录某个点是否被访问过,时间,空间复杂度都是O(n)
+
+```
+class Solution(object):
+ def hasCycle(self, head):
+ """
+ :type head: ListNode
+ :rtype: bool
+ """
+ if head == None: return False
+ dictx = {}
+ cur = head
+ while cur:
+ if cur in dictx:
+ return True
+ dictx[cur] = 1
+ cur = cur.next
+ return False
+```
+
+结果这种方法的run time还比较快
+
+查了一下,有解答说可以有空间复杂度O(1),时间复杂度O(n)。两个指针,一个快一个慢,快的每次走两步,慢的每次走一步,如果有环,最终会在某处相遇。这也是一个算法。这种快慢指针配合已经不是第一次遇到了,比如找linklist中间的node。
+
+
+
+但是并没有觉得这样的算法是O(n), worst case time complexity is O(N+K), which is O(n).
+
+
+```python
+python
+class Solution(object):
+ def hasCycle(self, head):
+ """
+ :type head: ListNode
+ :rtype: bool
+ """
+ slow = head
+ fast = head
+ while fast and fast.next:
+ slow = slow.next
+ fast = fast.next.next
+ if slow == fast:
+ return True
+ return False
+```
+
+
+```java
+java
+public class Solution {
+ public boolean hasCycle(ListNode head) {
+ if (head == null){
+ return false;
+ }
+ ListNode fast = head;
+ ListNode slow = head;
+ while (fast != null && slow != null && fast.next != null){
+ fast = fast.next.next;
+ slow = slow.next;
+ if (slow == fast){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+```
+
diff --git a/docs/leetcode/python/142_Linked_List_Cycle_II.md b/docs/Leetcode_Solutions/Python/142_Linked_List_Cycle_II.md
similarity index 100%
rename from docs/leetcode/python/142_Linked_List_Cycle_II.md
rename to docs/Leetcode_Solutions/Python/142_Linked_List_Cycle_II.md
diff --git a/docs/Leetcode_Solutions/Python/143._reorder_list.md b/docs/Leetcode_Solutions/Python/143._reorder_list.md
new file mode 100644
index 000000000..3bf56c53c
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/143._reorder_list.md
@@ -0,0 +1,133 @@
+# 143. Reorder List
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/reorder-list/description/
+
+> 内容描述
+
+```
+Given a singly linked list L: L0→L1→…→Ln-1→Ln,
+reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
+
+You may not modify the values in the list's nodes, only nodes itself may be changed.
+
+Example 1:
+
+Given 1->2->3->4, reorder it to 1->4->2->3.
+Example 2:
+
+Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+找到后半段反转后,再merge
+
+```python
+class Solution(object):
+ def reorderList(self, head):
+ """
+ :type head: ListNode
+ :rtype: void Do not return anything, modify head in-place instead.
+ """
+ if not head or not head.next or not head.next.next:
+ return
+
+ # calculate the length
+ n = 0
+ dummy1 = head
+ while dummy1:
+ n += 1
+ dummy1 = dummy1.next
+
+ # find the start point of the second half
+ m = n // 2 + 1
+ dummy2 = head
+ for i in range(m-1):
+ dummy2 = dummy2.next
+ dummy3 = dummy2.next
+ dummy2.next = None
+
+ # reverse second half
+ prev = None
+ while dummy3:
+ nxt = dummy3.next
+ dummy3.next = prev
+ prev = dummy3
+ dummy3= nxt
+
+ # merge two half
+ dummy4 = head
+ # print(head.next.next.val)
+ for i in range(n-m):
+ nxt_head = dummy4.next
+ nxt_prev = prev.next
+ dummy4.next = prev
+ prev.next = nxt_head
+ prev = nxt_prev
+ dummy4 = nxt_head
+```
+
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+取巧的办法是,用快慢指针找到后半段,这样不用计算链表长度
+
+找到中间节点,断开,把后半截linked list reverse,然后合并两段
+
+```python
+class Solution(object):
+ def reorderList(self, head):
+ """
+ :type head: ListNode
+ :rtype: void Do not return anything, modify head in-place instead.
+ """
+ if head == None or head.next == None or head.next.next == None:
+ return
+
+ slow = head
+ fast = head
+ prev = None
+
+ while fast and fast.next:
+ prev = slow
+ slow = slow.next
+ fast = fast.next.next
+ prev.next = None
+
+ slow = self.reverseList(slow)
+
+ cur = head
+ while cur.next:
+ nxt = cur.next
+ cur.next = slow
+ slow = slow.next
+ cur.next.next = nxt
+ cur = nxt
+ cur.next = slow
+
+ def reverseList(self, head):
+ """
+ :type head: ListNode
+ :rtype: ListNode
+ """
+ prev = None
+ cur = head
+ while cur:
+ nxt = cur.next
+ cur.next = prev
+ prev = cur
+ cur = nxt
+ return prev
+```
+
diff --git a/docs/leetcode/python/144._binary_tree_preorder_traversal.md b/docs/Leetcode_Solutions/Python/144._binary_tree_preorder_traversal.md
similarity index 96%
rename from docs/leetcode/python/144._binary_tree_preorder_traversal.md
rename to docs/Leetcode_Solutions/Python/144._binary_tree_preorder_traversal.md
index 8dd38e7fe..b81890681 100644
--- a/docs/leetcode/python/144._binary_tree_preorder_traversal.md
+++ b/docs/Leetcode_Solutions/Python/144._binary_tree_preorder_traversal.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/binary-tree-preorder-traversal
+* https://leetcode.com/problems/binary-tree-preorder-traversal/description/
> 内容描述
diff --git a/docs/leetcode/python/145._binary_tree_postorder_traversal.md b/docs/Leetcode_Solutions/Python/145._binary_tree_postorder_traversal.md
similarity index 96%
rename from docs/leetcode/python/145._binary_tree_postorder_traversal.md
rename to docs/Leetcode_Solutions/Python/145._binary_tree_postorder_traversal.md
index c62edbaf0..2729d4973 100644
--- a/docs/leetcode/python/145._binary_tree_postorder_traversal.md
+++ b/docs/Leetcode_Solutions/Python/145._binary_tree_postorder_traversal.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/binary-tree-postorder-traversal
+* https://leetcode.com/problems/binary-tree-postorder-traversal/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/146._LRU_Cache.md b/docs/Leetcode_Solutions/Python/146._LRU_Cache.md
new file mode 100644
index 000000000..2bdea0395
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/146._LRU_Cache.md
@@ -0,0 +1,158 @@
+# 146. LRU Cache
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/lru-cache/description/
+
+> 内容描述
+
+```
+Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
+
+get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
+put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
+
+Follow up:
+Could you do both operations in O(1) time complexity?
+
+Example:
+
+LRUCache cache = new LRUCache( 2 /* capacity */ );
+
+cache.put(1, 1);
+cache.put(2, 2);
+cache.get(1); // returns 1
+cache.put(3, 3); // evicts key 2
+cache.get(2); // returns -1 (not found)
+cache.put(4, 4); // evicts key 1
+cache.get(1); // returns -1 (not found)
+cache.get(3); // returns 3
+cache.get(4); // returns 4
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(1)******- 空间复杂度: O(N)******
+
+
+LRU cache 相当于要维护一个跟时间顺序相关的数据结构
+
+那么能找到最早更新元素的数据结构有 queue,heap和LinkedList这几种
+
+1. 首先,我们需要能够快速的访问到指点的元素,这一点LinkedList要用O(n)遍历,但是我们可以通过一个字典来对应key和node的信息,这样就是O(1)了
+2. 其次,由于要随时插入和删除找到的node,双向链表 doubly LinkedList 显然更好一些
+
+然后我们可以开始想接下来的逻辑了
+
+1. LRU Cache里面维护一个cache字典对应key和node的信息,一个cap表示最大容量,一个双向链表,其中head.next是most recently的node,
+tail.prev是least recently的node(即容量满了被删除的那个node)
+2. 对于get方法
+ - 1. 如果key在cache字典中,说明node在链表中
+ - 根据key从cache字典中拿到对应的node,删除这个node,再重新插入这个node(插入逻辑包含了更新到最新的位置)
+ - 2. 如果不在直接返回 -1
+3. 对于put方法
+ - 1. 如果key在cache字典中,说明node在链表中
+ - 根据key从cache字典中拿到对应的node,删除这个node,再重新插入这个node(插入逻辑包含了更新到最新的位置)
+ - 2. 如果key不在cache字典中,说明是一个新的node
+ - 如果此时容量还没满的话:
+ - 生成新node,插入链表中,放入cache中
+ - 如果此时容量满了的话:
+ - 从链表中删除tail.prev,即least recently的node
+ - 从cache中删除这个node的信息
+ - 生成新node,插入链表中,放入cache中
+
+
+下面是AC代码,其中逻辑3中如果key不在cache字典中的代码可以优化,生成新node,插入链表中,放入cache中这一步是重复的
+
+beats 95.66%
+
+```python
+class Node(object):
+ def __init__(self, key, val):
+ self.key = key
+ self.val = val
+ self.next = None
+ self.prev = None
+
+
+class LRUCache(object):
+ def __init__(self, capacity):
+ """
+ :type capacity: int
+ """
+ self.cache = {}
+ self.cap = capacity
+ self.head = Node(None, None)
+ self.tail = Node(None, None)
+ self.head.next = self.tail
+ self.tail.prev = self.head
+
+
+ def remove(self, node):
+ n = node.next
+ p = node.prev
+ p.next = n
+ n.prev = p
+ node.next = None
+ node.prev = None
+
+
+ def insert(self, node):
+ n = self.head.next
+ self.head.next = node
+ node.next = n
+ n.prev = node
+ node.prev = self.head
+
+
+ def get(self, key):
+ """
+ :type key: int
+ :rtype: int
+ """
+ if key in self.cache:
+ node = self.cache[key]
+ self.remove(node)
+ self.insert(node)
+ return node.val
+ else:
+ return -1
+
+
+ def put(self, key, value):
+ """
+ :type key: int
+ :type value: int
+ :rtype: void
+ """
+ if key in self.cache:
+ node = self.cache[key]
+ node.val = value
+ self.remove(node)
+ self.insert(node)
+ else:
+ if len(self.cache) == self.cap:
+ delete_node = self.tail.prev
+ del self.cache[delete_node.key]
+ self.remove(delete_node)
+ node = Node(key, value)
+ self.insert(node)
+ self.cache[key] = node
+
+
+# Your LRUCache object will be instantiated and called as such:
+# obj = LRUCache(capacity)
+# param_1 = obj.get(key)
+# obj.put(key,value)
+```
+
+
+
+
+
+
diff --git a/docs/leetcode/python/147._insertion_sort_list.md b/docs/Leetcode_Solutions/Python/147._insertion_sort_list.md
similarity index 100%
rename from docs/leetcode/python/147._insertion_sort_list.md
rename to docs/Leetcode_Solutions/Python/147._insertion_sort_list.md
diff --git a/docs/leetcode/python/148._sort_list.md b/docs/Leetcode_Solutions/Python/148._sort_list.md
similarity index 100%
rename from docs/leetcode/python/148._sort_list.md
rename to docs/Leetcode_Solutions/Python/148._sort_list.md
diff --git a/docs/leetcode/python/150._evaluate_reverse_polish_notation.md b/docs/Leetcode_Solutions/Python/150._evaluate_reverse_polish_notation.md
similarity index 100%
rename from docs/leetcode/python/150._evaluate_reverse_polish_notation.md
rename to docs/Leetcode_Solutions/Python/150._evaluate_reverse_polish_notation.md
diff --git a/docs/leetcode/python/151._reverse_words_in_a_string.md b/docs/Leetcode_Solutions/Python/151._reverse_words_in_a_string.md
similarity index 100%
rename from docs/leetcode/python/151._reverse_words_in_a_string.md
rename to docs/Leetcode_Solutions/Python/151._reverse_words_in_a_string.md
diff --git a/docs/leetcode/python/152._maximum_product_subarray.md b/docs/Leetcode_Solutions/Python/152._maximum_product_subarray.md
similarity index 100%
rename from docs/leetcode/python/152._maximum_product_subarray.md
rename to docs/Leetcode_Solutions/Python/152._maximum_product_subarray.md
diff --git a/docs/leetcode/python/153._find_minimum_in_rotated_sorted_array.md b/docs/Leetcode_Solutions/Python/153._find_minimum_in_rotated_sorted_array.md
similarity index 100%
rename from docs/leetcode/python/153._find_minimum_in_rotated_sorted_array.md
rename to docs/Leetcode_Solutions/Python/153._find_minimum_in_rotated_sorted_array.md
diff --git a/docs/leetcode/python/155._min_stack.md b/docs/Leetcode_Solutions/Python/155._min_stack.md
similarity index 100%
rename from docs/leetcode/python/155._min_stack.md
rename to docs/Leetcode_Solutions/Python/155._min_stack.md
diff --git a/docs/leetcode/python/157._Read_N_Characters_Given_Read4.md b/docs/Leetcode_Solutions/Python/157._Read_N_Characters_Given_Read4.md
similarity index 97%
rename from docs/leetcode/python/157._Read_N_Characters_Given_Read4.md
rename to docs/Leetcode_Solutions/Python/157._Read_N_Characters_Given_Read4.md
index e390ca0e3..447051ff7 100644
--- a/docs/leetcode/python/157._Read_N_Characters_Given_Read4.md
+++ b/docs/Leetcode_Solutions/Python/157._Read_N_Characters_Given_Read4.md
@@ -6,7 +6,7 @@
> 原题连接
-* https://leetcode.com/problems/read-n-characters-given-read4
+* https://leetcode.com/problems/read-n-characters-given-read4/description/
> 内容描述
diff --git a/docs/leetcode/python/158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md b/docs/Leetcode_Solutions/Python/158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md
similarity index 98%
rename from docs/leetcode/python/158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md
rename to docs/Leetcode_Solutions/Python/158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md
index a3826eafd..ec2c8cce8 100644
--- a/docs/leetcode/python/158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md
+++ b/docs/Leetcode_Solutions/Python/158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md
@@ -6,7 +6,7 @@
> 原题连接
-* https://leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times
+* https://leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/description/
> 内容描述
diff --git a/docs/leetcode/python/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md b/docs/Leetcode_Solutions/Python/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md
similarity index 54%
rename from docs/leetcode/python/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md
rename to docs/Leetcode_Solutions/Python/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md
index 7d65fb605..128abbe66 100644
--- a/docs/leetcode/python/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md
+++ b/docs/Leetcode_Solutions/Python/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md
@@ -1,11 +1,34 @@
-### 159. Longest Substring with At Most Two Distinct Characters
+# 159. Longest Substring with At Most Two Distinct Characters
-题目:
-
+**难度: Hard**
+## 刷题内容
-难度 : Hard
+> 原题连接
+* https://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/description/
+
+> 内容描述
+
+```
+Given a string s , find the length of the longest substring t that contains at most 2 distinct characters.
+
+Example 1:
+
+Input: "eceba"
+Output: 3
+Explanation: t is "ece" which its length is 3.
+Example 2:
+
+Input: "ccaabbb"
+Output: 5
+Explanation: t is "aabbb" which its length is 5.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
```python
@@ -30,3 +53,5 @@ class Solution(object):
length = max(length, end - begin) # 因此这里是```end - begin```而不是```end - begin + 1```
return length
```
+
+
diff --git a/docs/leetcode/python/160._intersection_of_two_linked_lists.md b/docs/Leetcode_Solutions/Python/160._intersection_of_two_linked_lists.md
similarity index 100%
rename from docs/leetcode/python/160._intersection_of_two_linked_lists.md
rename to docs/Leetcode_Solutions/Python/160._intersection_of_two_linked_lists.md
diff --git a/docs/leetcode/python/162._find_peak_element.md b/docs/Leetcode_Solutions/Python/162._find_peak_element.md
similarity index 100%
rename from docs/leetcode/python/162._find_peak_element.md
rename to docs/Leetcode_Solutions/Python/162._find_peak_element.md
diff --git a/docs/leetcode/python/165._compare_version_numbers.md b/docs/Leetcode_Solutions/Python/165._compare_version_numbers.md
similarity index 100%
rename from docs/leetcode/python/165._compare_version_numbers.md
rename to docs/Leetcode_Solutions/Python/165._compare_version_numbers.md
diff --git a/docs/Leetcode_Solutions/Python/166._Fraction_to_Recurring_Decimal.md b/docs/Leetcode_Solutions/Python/166._Fraction_to_Recurring_Decimal.md
new file mode 100644
index 000000000..2045b3362
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/166._Fraction_to_Recurring_Decimal.md
@@ -0,0 +1,83 @@
+# 166. Fraction to Recurring Decimal
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/fraction-to-recurring-decimal/description/
+
+> 内容描述
+
+```
+Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
+
+If the fractional part is repeating, enclose the repeating part in parentheses.
+
+Example 1:
+
+Input: numerator = 1, denominator = 2
+Output: "0.5"
+Example 2:
+
+Input: numerator = 2, denominator = 1
+Output: "2"
+Example 3:
+
+Input: numerator = 2, denominator = 3
+Output: "0.(6)"
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: hard to say****** - 空间复杂度: O(1)******
+
+
+- 先处理正负号
+- 再处理整数部分
+- 最后处理小数部分,利用字典来判断是否循环
+
+***note:对于小数处理部分,必须先进行将没有处理过的r加入到m中去***
+
+这是因为:
+```
+例如输入为4, 333
+如果我们将已经处理过的r加入到m中去的话,重复数字当次就被加入m中了,下一次循环判断的时候r肯定已经在里面了
+```
+
+
+```python
+class Solution(object):
+ def fractionToDecimal(self, numerator, denominator):
+ """
+ :type numerator: int
+ :type denominator: int
+ :rtype: str
+ """
+ if numerator == 0: # zero numerator
+ return '0'
+ res = ''
+ if numerator * denominator < 0: # determine the sign
+ res += '-'
+ numerator, denominator = abs(numerator), abs(denominator) # remove sign of operands
+ res += str(numerator / denominator) # append integer part
+ if numerator % denominator == 0: # in case no fractional part
+ return res
+ res += '.'
+ r = numerator % denominator
+ m = {}
+ while r: # simulate the division process
+ if r in m: # meet a known remainder
+ res = res[:m[r]] + '(' + res[m[r]:] + ')' # so we reach the end of the repeating part
+ break
+ m[r] = len(res) # if the remainder is first seen, remember next r/denominator index in res
+ r *= 10
+ res += str(r/denominator) # append the quotient digit
+ r %= denominator
+
+ return res
+```
+
+
diff --git a/docs/leetcode/python/167._two_sum_ii_-_input_array_is_sorted.md b/docs/Leetcode_Solutions/Python/167._two_sum_ii_-_input_array_is_sorted.md
similarity index 100%
rename from docs/leetcode/python/167._two_sum_ii_-_input_array_is_sorted.md
rename to docs/Leetcode_Solutions/Python/167._two_sum_ii_-_input_array_is_sorted.md
diff --git a/docs/leetcode/python/168._excel_sheet_column_title.md b/docs/Leetcode_Solutions/Python/168._excel_sheet_column_title.md
similarity index 97%
rename from docs/leetcode/python/168._excel_sheet_column_title.md
rename to docs/Leetcode_Solutions/Python/168._excel_sheet_column_title.md
index 1746fa858..547f083ee 100644
--- a/docs/leetcode/python/168._excel_sheet_column_title.md
+++ b/docs/Leetcode_Solutions/Python/168._excel_sheet_column_title.md
@@ -12,17 +12,17 @@ Easy
依旧26进制的反击,不过这个反击我做的没之前那个好,看了hint
```
-class Solution(object):
- def convertToTitle(self, n):
- """
- :type n: int
- :rtype: str
- """
- ans = ''
- while n :
- ans = chr(ord('A') + (n - 1) % 26) + ans
- n = (n - 1) // 26
- return ans
+class Solution(object):
+ def convertToTitle(self, n):
+ """
+ :type n: int
+ :rtype: str
+ """
+ ans = ''
+ while n :
+ ans = chr(ord('A') + (n - 1) % 26) + ans
+ n = (n - 1) // 26
+ return ans
```
diff --git a/docs/leetcode/python/169._majority_element.md b/docs/Leetcode_Solutions/Python/169._majority_element.md
similarity index 100%
rename from docs/leetcode/python/169._majority_element.md
rename to docs/Leetcode_Solutions/Python/169._majority_element.md
diff --git a/docs/leetcode/python/171._excel_sheet_column_number.md b/docs/Leetcode_Solutions/Python/171._excel_sheet_column_number.md
similarity index 97%
rename from docs/leetcode/python/171._excel_sheet_column_number.md
rename to docs/Leetcode_Solutions/Python/171._excel_sheet_column_number.md
index 0a92b3808..4521f737c 100644
--- a/docs/leetcode/python/171._excel_sheet_column_number.md
+++ b/docs/Leetcode_Solutions/Python/171._excel_sheet_column_number.md
@@ -13,22 +13,22 @@ Easy
26进制的反击
```
-class Solution(object):
- def titleToNumber(self, s):
- """
- :type s: str
- :rtype: int
- """
- maps = {}
- for i in range(65,91):
- maps[chr(i)] = i - 64
-
- lst = list(s)
- lst.reverse()
- num = 0
- for idx,item in enumerate(lst):
- num += maps[item] * (26 ** idx)
- return num
+class Solution(object):
+ def titleToNumber(self, s):
+ """
+ :type s: str
+ :rtype: int
+ """
+ maps = {}
+ for i in range(65,91):
+ maps[chr(i)] = i - 64
+
+ lst = list(s)
+ lst.reverse()
+ num = 0
+ for idx,item in enumerate(lst):
+ num += maps[item] * (26 ** idx)
+ return num
```
diff --git a/docs/Leetcode_Solutions/Python/172._Factorial_Trailing_Zeroes.md b/docs/Leetcode_Solutions/Python/172._Factorial_Trailing_Zeroes.md
new file mode 100644
index 000000000..c7e98eefa
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/172._Factorial_Trailing_Zeroes.md
@@ -0,0 +1,58 @@
+# 172. Factorial Trailing Zeroes
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/factorial-trailing-zeroes/description/
+
+> 内容描述
+
+```
+Given an integer n, return the number of trailing zeroes in n!.
+
+Example 1:
+
+Input: 3
+Output: 0
+Explanation: 3! = 6, no trailing zero.
+Example 2:
+
+Input: 5
+Output: 1
+Explanation: 5! = 120, one trailing zero.
+Note: Your solution should be in logarithmic time complexity.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
+
+思路就是开始看我们有多少个5,多少个25,多少个125,这些数字成为base,直到这个base比我们的n大了,我们就不继续加了。那这是为什么呢?
+
+因为我们知道想让后面多个0,那一定要是偶数乘以5的形式,我们知道偶数一定是比5多的,所以完全够用,所以直接一直加就行了。
+
+
+开始我还想复杂了,每次算出最前的base_val,即1有0个0,5有1个0,25有6个0,我是通过算出所在区间然后再叠加,这样显然可以,
+但是不如上面的想法来得直接来得快。
+
+前后想了一个小时,真蠢啊!!!
+
+```python
+class Solution(object):
+ def trailingZeroes(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ base, res = 5, 0
+ while n >= base:
+ res += n // base
+ base *= 5
+ return res
+```
+
+
diff --git a/docs/leetcode/python/173._binary_search_tree_iterator.md b/docs/Leetcode_Solutions/Python/173._binary_search_tree_iterator.md
similarity index 100%
rename from docs/leetcode/python/173._binary_search_tree_iterator.md
rename to docs/Leetcode_Solutions/Python/173._binary_search_tree_iterator.md
diff --git a/docs/Leetcode_Solutions/Python/176._Second_Highest_Salary.md b/docs/Leetcode_Solutions/Python/176._Second_Highest_Salary.md
new file mode 100644
index 000000000..71cf29950
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/176._Second_Highest_Salary.md
@@ -0,0 +1,50 @@
+# 176. Second Highest Salary
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/second-highest-salary/description/
+
+> 内容描述
+
+```
+Write a SQL query to get the second highest salary from the Employee table.
+
++----+--------+
+| Id | Salary |
++----+--------+
+| 1 | 100 |
+| 2 | 200 |
+| 3 | 300 |
++----+--------+
+For example, given the above Employee table, the query should return 200 as the second highest salary. If there is no second highest salary, then the query should return null.
+
++---------------------+
+| SecondHighestSalary |
++---------------------+
+| 200 |
++---------------------+
+```
+
+## 解题方案
+
+> 思路 1
+
+```sql
+select Salary SecondHighestSalary from Employee
+union
+select null
+order by SecondHighestSalary desc limit 1, 1
+```
+
+
+> 思路 2
+
+```sql
+select (
+ select distinct Salary from Employee order by Salary Desc limit 1, 1
+)as SecondHighestSalary
+```
diff --git a/docs/leetcode/python/179._Largest_Number.md b/docs/Leetcode_Solutions/Python/179._Largest_Number.md
similarity index 100%
rename from docs/leetcode/python/179._Largest_Number.md
rename to docs/Leetcode_Solutions/Python/179._Largest_Number.md
diff --git a/docs/leetcode/python/182._duplicate_emails.md b/docs/Leetcode_Solutions/Python/182._duplicate_emails.md
similarity index 92%
rename from docs/leetcode/python/182._duplicate_emails.md
rename to docs/Leetcode_Solutions/Python/182._duplicate_emails.md
index 1e77debe3..f000e80cd 100644
--- a/docs/leetcode/python/182._duplicate_emails.md
+++ b/docs/Leetcode_Solutions/Python/182._duplicate_emails.md
@@ -7,7 +7,7 @@
> 原题连接
* https://leetcode.com/problems/duplicate-emails
-* https://leetcode-cn.com/problems/duplicate-emails
+* https://leetcode-cn.com/problems/duplicate-emails/description
> 内容描述
diff --git a/docs/leetcode/python/189._rotate_array.md b/docs/Leetcode_Solutions/Python/189._rotate_array.md
similarity index 95%
rename from docs/leetcode/python/189._rotate_array.md
rename to docs/Leetcode_Solutions/Python/189._rotate_array.md
index ff9d5457f..b00de8752 100644
--- a/docs/leetcode/python/189._rotate_array.md
+++ b/docs/Leetcode_Solutions/Python/189._rotate_array.md
@@ -1,42 +1,42 @@
-###189. Rotate Array
-
-题目:
-
-
-
-难度 : Easy
-
-首先,要知道一点,```k```如果大于```nums```的长度了,那么其实进行 ```k % len(nums)``` 次就行了
-
-其次,要注意```k 为0```的情况
-
-```python
-class Solution(object):
- def rotate(self, nums, k):
- """
- :type nums: List[int]
- :type k: int
- :rtype: void Do not return anything, modify nums in-place instead.
- """
- k = k % len(nums)
- if k != 0:
- tmp = nums[-k:]
- for j in range(len(nums)-1, k-1, -1):
- nums[j] = nums[j-k]
- nums[:k] = tmp
-```
-
-
-还有作弊大法,贼🐂批
-
-```python
-class Solution(object):
- def rotate(self, nums, k):
- """
- :type nums: List[int]
- :type k: int
- :rtype: void Do not return anything, modify nums in-place instead.
- """
- k %= len(nums)
- nums[:] = nums[-k:] + nums[:-k]
-```
+###189. Rotate Array
+
+题目:
+
+
+
+难度 : Easy
+
+首先,要知道一点,```k```如果大于```nums```的长度了,那么其实进行 ```k % len(nums)``` 次就行了
+
+其次,要注意```k 为0```的情况
+
+```python
+class Solution(object):
+ def rotate(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: void Do not return anything, modify nums in-place instead.
+ """
+ k = k % len(nums)
+ if k != 0:
+ tmp = nums[-k:]
+ for j in range(len(nums)-1, k-1, -1):
+ nums[j] = nums[j-k]
+ nums[:k] = tmp
+```
+
+
+还有作弊大法,贼🐂批
+
+```python
+class Solution(object):
+ def rotate(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: void Do not return anything, modify nums in-place instead.
+ """
+ k %= len(nums)
+ nums[:] = nums[-k:] + nums[:-k]
+```
diff --git a/docs/leetcode/python/191._number_of_1_bits.md b/docs/Leetcode_Solutions/Python/191._number_of_1_bits.md
similarity index 100%
rename from docs/leetcode/python/191._number_of_1_bits.md
rename to docs/Leetcode_Solutions/Python/191._number_of_1_bits.md
diff --git a/docs/Leetcode_Solutions/Python/198._house_robber.md b/docs/Leetcode_Solutions/Python/198._house_robber.md
new file mode 100644
index 000000000..950868ea6
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/198._house_robber.md
@@ -0,0 +1,81 @@
+# 198. House Robber
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/house-robber/description/
+
+> 内容描述
+
+```
+You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
+
+Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
+
+Example 1:
+
+Input: [1,2,3,1]
+Output: 4
+Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
+ Total amount you can rob = 1 + 3 = 4.
+Example 2:
+
+Input: [2,7,9,3,1]
+Output: 12
+Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
+ Total amount you can rob = 2 + 9 + 1 = 12.
+```
+
+## 解题方案
+
+> 思路 1
+
+
+状态转移方程:
+
+dp[i] = max(dp[i-1], dp[i-2] + nums[i])
+
+
+AC 代码
+
+```python
+class Solution(object):
+ def rob(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ n = len(nums)
+ if n == 0 : return 0
+ elif n == 1 : return nums[0]
+ elif n == 2 : return max(nums[0], nums[1])
+ else:
+ dp = [0 for i in range(n)]
+ dp[0] = nums[0]
+ dp[1] = max(nums[0],nums[1])
+ for i in range(2,n):
+ dp[i] = max(dp[i-1], dp[i-2] + nums[i])
+ return dp[n-1]
+```
+
+> 思路 2
+
+迭代
+
+```python
+class Solution(object):
+ def rob(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ last, now = 0, 0
+ for num in nums:
+ last, now = now, max(last+num, now)
+ return now
+```
+
+
diff --git a/docs/leetcode/python/199._binary_tree_right_side_view.md b/docs/Leetcode_Solutions/Python/199._binary_tree_right_side_view.md
similarity index 100%
rename from docs/leetcode/python/199._binary_tree_right_side_view.md
rename to docs/Leetcode_Solutions/Python/199._binary_tree_right_side_view.md
diff --git a/docs/Leetcode_Solutions/Python/200._number_of_islands.md b/docs/Leetcode_Solutions/Python/200._number_of_islands.md
new file mode 100644
index 000000000..fe0420dbd
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/200._number_of_islands.md
@@ -0,0 +1,59 @@
+# 200. Number of Islands
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/number-of-islands/description/
+
+> 内容描述
+
+```
+Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
+
+Example 1:
+
+Input:
+11110
+11010
+11000
+00000
+
+Output: 1
+Example 2:
+
+Input:
+11000
+11000
+00100
+00011
+
+Output: 3
+```
+
+## 解题方案
+
+> 思路 1
+
+厉害的解法:Sink and count the islands.
+
+就是说从(0,0)这个点开始,只要一碰到1就将我们最终island数加1,并且同时将其周围临近的所有1全部都变成0,这样后面就不会重复计算了
+
+```python
+class Solution(object):
+ def numIslands(self, grid):
+ """
+ :type grid: List[List[str]]
+ :rtype: int
+ """
+ def sink(i, j):
+ if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == '1':
+ grid[i][j] = '0'
+ map(sink, (i+1, i-1, i, i), (j, j, j+1, j-1))
+ return 1
+ return 0
+ return sum(sink(i, j) for i in range(len(grid)) for j in range(len(grid[0])))
+```
+
diff --git a/docs/Leetcode_Solutions/Python/201._Bitwise_AND_of_Numbers_Range.md b/docs/Leetcode_Solutions/Python/201._Bitwise_AND_of_Numbers_Range.md
new file mode 100644
index 000000000..a7c1d4bb7
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/201._Bitwise_AND_of_Numbers_Range.md
@@ -0,0 +1,93 @@
+# 201. Bitwise AND of Numbers Range
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/bitwise-and-of-numbers-range/description/
+
+> 内容描述
+
+```
+Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.
+
+Example 1:
+
+Input: [5,7]
+Output: 4
+Example 2:
+
+Input: [0,1]
+Output: 0
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(1)******- 空间复杂度: O(1)******
+
+我们知道你从m一直&到n,那么m和n二进制位后面不一样的地方肯定都会变成0
+```
+譬如n = 101111,m = 101011,当中经过101100。
+m & n抹除common prefix右边第一位上的1,中间经过那个数抹除所有更低位的1。
+```
+所以我们找到m和n的最长相同前缀,然后补齐二进制的32位(即往右边贴'0')
+
+自己写的一行版本!
+
+
+```python
+import os
+class Solution(object):
+ def rangeBitwiseAnd(self, m, n):
+ """
+ :type m: int
+ :type n: int
+ :rtype: int
+ """
+ return int(os.path.commonprefix([bin(m)[2:].zfill(32), bin(n)[2:].zfill(32)])[::-1].zfill(32)[::-1], 2)
+```
+
+
+> 思路 2
+******- 时间复杂度: O(1)******- 空间复杂度: O(1)******
+
+
+别人的一行版本!
+
+
+```python
+class Solution(object):
+ def rangeBitwiseAnd(self, m, n):
+ """
+ :type m: int
+ :type n: int
+ :rtype: int
+ """
+ return self.rangeBitwiseAnd(m, n & n-1) if m < n else n
+```
+
+
+> 思路
+******- 时间复杂度: O(1)******- 空间复杂度: O(1)******
+
+
+bit移位操作版本
+
+```python
+class Solution(object):
+ def rangeBitwiseAnd(self, m, n):
+ """
+ :type m: int
+ :type n: int
+ :rtype: int
+ """
+ diff = 0
+ while m != n:
+ m >>= 1
+ n >>= 1
+ diff += 1
+ return m << diff
+```
diff --git a/docs/leetcode/python/203._remove_linked_list_elements.md b/docs/Leetcode_Solutions/Python/203._remove_linked_list_elements.md
similarity index 96%
rename from docs/leetcode/python/203._remove_linked_list_elements.md
rename to docs/Leetcode_Solutions/Python/203._remove_linked_list_elements.md
index 7dcb32ee2..15aa10efa 100644
--- a/docs/leetcode/python/203._remove_linked_list_elements.md
+++ b/docs/Leetcode_Solutions/Python/203._remove_linked_list_elements.md
@@ -13,26 +13,26 @@ AC代码如下:
-```
-class Solution(object):
- def removeElements(self, head, val):
- """
- :type head: ListNode
- :type val: int
- :rtype: ListNode
- """
- dummy = ListNode(-1)
- dummy.next = head
-
- cur = dummy
-
- while cur.next:
- if cur.next.val == val:
- cur.next = cur.next.next
- else:
- cur = cur.next
-
- return dummy.next
+```
+class Solution(object):
+ def removeElements(self, head, val):
+ """
+ :type head: ListNode
+ :type val: int
+ :rtype: ListNode
+ """
+ dummy = ListNode(-1)
+ dummy.next = head
+
+ cur = dummy
+
+ while cur.next:
+ if cur.next.val == val:
+ cur.next = cur.next.next
+ else:
+ cur = cur.next
+
+ return dummy.next
```
\ No newline at end of file
diff --git a/docs/leetcode/python/204._count_primes.md b/docs/Leetcode_Solutions/Python/204._count_primes.md
similarity index 100%
rename from docs/leetcode/python/204._count_primes.md
rename to docs/Leetcode_Solutions/Python/204._count_primes.md
diff --git a/docs/leetcode/python/205._isomorphic_strings.md b/docs/Leetcode_Solutions/Python/205._isomorphic_strings.md
similarity index 97%
rename from docs/leetcode/python/205._isomorphic_strings.md
rename to docs/Leetcode_Solutions/Python/205._isomorphic_strings.md
index 9e4b6f178..47b0ab772 100644
--- a/docs/leetcode/python/205._isomorphic_strings.md
+++ b/docs/Leetcode_Solutions/Python/205._isomorphic_strings.md
@@ -10,29 +10,29 @@
AC之法,用dictionary,因为限制,所以确保s 和 t 是isomorphic 同时 t 和 s 是
-```
-class Solution(object):
- def isIsomorphic(self, s, t):
- """
- :type s: str
- :type t: str
- :rtype: bool
- """
+```
+class Solution(object):
+ def isIsomorphic(self, s, t):
+ """
+ :type s: str
+ :type t: str
+ :rtype: bool
+ """
return self.iso(s,t) and self.iso(t,s)
-
- def iso(self,s, t):
- """
- :type s: str
- :type t: str
- :rtype: bool
- """
- mapx = {}
- for i in range(len(s)):
- if s[i] not in mapx:
- mapx[s[i]] = t[i]
- elif s[i] in mapx:
- if t[i] != mapx[s[i]]:
- return False
+
+ def iso(self,s, t):
+ """
+ :type s: str
+ :type t: str
+ :rtype: bool
+ """
+ mapx = {}
+ for i in range(len(s)):
+ if s[i] not in mapx:
+ mapx[s[i]] = t[i]
+ elif s[i] in mapx:
+ if t[i] != mapx[s[i]]:
+ return False
return True
diff --git a/docs/Leetcode_Solutions/Python/206._reverse_linked_list.md b/docs/Leetcode_Solutions/Python/206._reverse_linked_list.md
new file mode 100644
index 000000000..5c05edc02
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/206._reverse_linked_list.md
@@ -0,0 +1,95 @@
+# 206. Reverse Linked List
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/reverse-linked-list/description/
+
+> 内容描述
+
+```
+Reverse a singly linked list.
+
+Example:
+
+Input: 1->2->3->4->5->NULL
+Output: 5->4->3->2->1->NULL
+Follow up:
+
+A linked list can be reversed either iteratively or recursively. Could you implement both?
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+用三个指针,分别指向prev,cur 和 nxt,然后loop一圈还算比较简单.
+
+
+```python
+class Solution(object):
+ def reverseList(self, head):
+ """
+ :type head: ListNode
+ :rtype: ListNode
+ """
+ prev = None
+ cur = head
+ while cur:
+ nxt = cur.next
+ cur.next = prev
+ prev = cur
+ cur = nxt
+ return prev
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+其实不用cur也可以
+
+```python
+class Solution(object):
+ def reverseList(self, head):
+ """
+ :type head: ListNode
+ :rtype: ListNode
+ """
+ if not head:
+ return head
+ prev = None
+ while head.next:
+ nxt = head.next
+ head.next = prev
+ prev = head
+ head = nxt
+ head.next = prev
+ return head
+```
+
+递归版本,可以再消化一下.
+
+> 思路 3
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+```python
+class Solution(object):
+ def reverseList(self, head):
+ """
+ :type head: ListNode
+ :rtype: ListNode
+ """
+ def helper(head, new_head):
+ if head:
+ nxt = head.next
+ head.next = new_head
+ return helper(nxt, head)
+ else:
+ return new_head
+
+ return helper(head, None)
+```
diff --git a/docs/leetcode/python/207._course_schedule.md b/docs/Leetcode_Solutions/Python/207._course_schedule.md
similarity index 100%
rename from docs/leetcode/python/207._course_schedule.md
rename to docs/Leetcode_Solutions/Python/207._course_schedule.md
diff --git a/docs/leetcode/python/208._implement_trie_(prefix_tree).md b/docs/Leetcode_Solutions/Python/208._implement_trie_(prefix_tree).md
similarity index 95%
rename from docs/leetcode/python/208._implement_trie_(prefix_tree).md
rename to docs/Leetcode_Solutions/Python/208._implement_trie_(prefix_tree).md
index a828b2fd5..8ee06db58 100644
--- a/docs/leetcode/python/208._implement_trie_(prefix_tree).md
+++ b/docs/Leetcode_Solutions/Python/208._implement_trie_(prefix_tree).md
@@ -1,89 +1,89 @@
-### 208. Implement Trie (Prefix Tree)
-
-题目:
-
-
-
-
-难度:
-
-Medium
-
-这个Python实现也太精美了吧,谷歌复写之
-
-然后还unlock了一个solution,to read
-
-Trie整个都需要 to read,精美,可爱😊
-
-
-
-
-```python
-class TrieNode(object):
- def __init__(self):
- """
- Initialize your data structure here.
- """
- self.childs = dict()
- self.isWord = False
-
-
-
-class Trie(object):
-
- def __init__(self):
- self.root = TrieNode()
-
- def insert(self, word):
- """
- Inserts a word into the trie.
- :type word: str
- :rtype: void
- """
- node = self.root
- for letter in word:
- child = node.childs.get(letter)
- if child is None:
- child = TrieNode()
- node.childs[letter] = child
- node = child
- node.isWord = True
-
- def search(self, word):
- """
- Returns if the word is in the trie.
- :type word: str
- :rtype: bool
- """
- node = self.root
- for i in word:
- child = node.childs.get(i)
- if child is None:
- return False
- node = child
- return node.isWord
-
-
- def startsWith(self, prefix):
- """
- Returns if there is any word in the trie
- that starts with the given prefix.
- :type prefix: str
- :rtype: bool
- """
- node = self.root
- for letter in prefix:
- child = node.childs.get(letter)
- if child is None:
- return False
- node = child
- return True
-
-
-# Your Trie object will be instantiated and called as such:
-# trie = Trie()
-# trie.insert("somestring")
-# trie.search("key")
-
-```
-
+### 208. Implement Trie (Prefix Tree)
+
+题目:
+
+
+
+
+难度:
+
+Medium
+
+这个Python实现也太精美了吧,谷歌复写之
+
+然后还unlock了一个solution,to read
+
+Trie整个都需要 to read,精美,可爱😊
+
+
+
+
+```python
+class TrieNode(object):
+ def __init__(self):
+ """
+ Initialize your data structure here.
+ """
+ self.childs = dict()
+ self.isWord = False
+
+
+
+class Trie(object):
+
+ def __init__(self):
+ self.root = TrieNode()
+
+ def insert(self, word):
+ """
+ Inserts a word into the trie.
+ :type word: str
+ :rtype: void
+ """
+ node = self.root
+ for letter in word:
+ child = node.childs.get(letter)
+ if child is None:
+ child = TrieNode()
+ node.childs[letter] = child
+ node = child
+ node.isWord = True
+
+ def search(self, word):
+ """
+ Returns if the word is in the trie.
+ :type word: str
+ :rtype: bool
+ """
+ node = self.root
+ for i in word:
+ child = node.childs.get(i)
+ if child is None:
+ return False
+ node = child
+ return node.isWord
+
+
+ def startsWith(self, prefix):
+ """
+ Returns if there is any word in the trie
+ that starts with the given prefix.
+ :type prefix: str
+ :rtype: bool
+ """
+ node = self.root
+ for letter in prefix:
+ child = node.childs.get(letter)
+ if child is None:
+ return False
+ node = child
+ return True
+
+
+# Your Trie object will be instantiated and called as such:
+# trie = Trie()
+# trie.insert("somestring")
+# trie.search("key")
+
+```
+
diff --git a/docs/leetcode/python/210._course_schedule_ii.md b/docs/Leetcode_Solutions/Python/210._course_schedule_ii.md
similarity index 100%
rename from docs/leetcode/python/210._course_schedule_ii.md
rename to docs/Leetcode_Solutions/Python/210._course_schedule_ii.md
diff --git a/docs/leetcode/python/211._Add_and_Search_Word_-_Data_structure_design.md b/docs/Leetcode_Solutions/Python/211. Add and Search Word - Data structure design.md
similarity index 100%
rename from docs/leetcode/python/211._Add_and_Search_Word_-_Data_structure_design.md
rename to docs/Leetcode_Solutions/Python/211. Add and Search Word - Data structure design.md
diff --git a/docs/leetcode/python/213._house_robber_ii.md b/docs/Leetcode_Solutions/Python/213._house_robber_ii.md
similarity index 100%
rename from docs/leetcode/python/213._house_robber_ii.md
rename to docs/Leetcode_Solutions/Python/213._house_robber_ii.md
diff --git a/docs/Leetcode_Solutions/Python/215._Kth_Largest_Element_in_an_Array.md b/docs/Leetcode_Solutions/Python/215._Kth_Largest_Element_in_an_Array.md
new file mode 100644
index 000000000..cf3fbfc32
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/215._Kth_Largest_Element_in_an_Array.md
@@ -0,0 +1,148 @@
+# 215. Kth Largest Element in an Array
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/kth-largest-element-in-an-array/description/
+
+> 内容描述
+
+```
+Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
+
+Example 1:
+
+Input: [3,2,1,5,6,4] and k = 2
+Output: 5
+Example 2:
+
+Input: [3,2,3,1,2,4,5,5,6] and k = 4
+Output: 4
+Note:
+You may assume k is always valid, 1 ≤ k ≤ array's length.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
+
+先全部放到一个最大堆中去,然后返回第k个就行了
+
+因为python实现的heapq插入操作的时间复杂度是O(lgN),所以最终时间复杂度是O(NlgN)
+
+```
+1. bisect
+根据insort_left 的文档:
+
+Keep in mind that the O(log n) search is dominated by the slow O(n) insertion step.
+
+也就是说,单次 insort_left 的时间复杂度是 O(n),自然 sort1 的复杂度就变成了 O(n^2),它最慢是应当的。
+
+2. sort
+文档说是 O(n log n) 的复杂度。从 listsort 详细文档来看,开发人员着实没少下了工夫。
+
+3. heappush
+根据维基百科,插入操作的时间复杂度是 O(log n),所以总的时间复杂度仍然是 O(n log n)。不过有一点值得注意,插入操作的平均时间是 O(1),所以有可能会稍微快一点。
+
+Python vs. PyPy
+CPython 2.7
+
+sort1 : bisect 2.617674
+sort2 :lst.sort 0.295187
+sort3 : heapq 0.39279
+PyPy 2.4
+
+sort1 : bisect 1.31
+sort2 :lst.sort 0.043
+sort3 : heapq 0.029
+注,我把你的调用部分复制了一遍,执行了两次,结果为第二次的输出。
+
+可以看得出,O(n log n) 算法的耗时是在同一个数量级上的,但 CPython 中 sort 胜出,PyPy 中 heapq 胜出。
+```
+
+详细可见:
+1. [heapq数据结构](https://love.ranshy.com/heapq-%E5%A0%86%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/)
+2. [序列的sort方法 与 bisect.insort, heapq.heappush 效率比较](https://segmentfault.com/q/1010000000664272)
+
+
+```python
+class Solution(object):
+ def findKthLargest(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: int
+ """
+ from heapq import heappush, heappop
+ topk = []
+ heap = []
+ for i in range(len(nums)):
+ heappush(heap, -nums[i])
+ for i in range(k):
+ if i == k-1:
+ return -heappop(heap)
+ heappop(heap)
+```
+
+
+> 思路 1
+******- 时间复杂度: O(NlgN)******- 空间复杂度: O(k)******
+
+前面的思路是全部放进去以后再pop k次
+
+现在打算只维护一个容量为k的最大堆,最终堆顶的值就是结果
+
+
+```python
+class Solution(object):
+ def findKthLargest(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: int
+ """
+ if not nums:
+ return 0
+ from heapq import *
+ heap = []
+ for i in range(len(nums)):
+ heappush(heap,nums[i])
+ if len(heap) > k:
+ heappop(heap)
+ return heap[0]
+```
+
+
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(n)******
+
+二分+quick sort的思想,随机取一个pivot,大于小于等于它的分别放起来,然后看看大于它的有没有k个,没有就可能在等于或者小于里面
+
+二分是O(lgN),但是找大于小于等于是O(N),所以最终时间复杂度是O(N)
+
+```python
+class Solution(object):
+ def findKthLargest(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: int
+ """
+ pivot = nums[0]
+ smaller = [num for num in nums if num < pivot]
+ equal = [num for num in nums if num == pivot]
+ greater = [num for num in nums if num > pivot]
+
+ if len(greater) >= k:
+ return self.findKthLargest(greater, k) #k may be there
+ elif len(equal) >= (k - len(greater)): # k may be in equal or smaller
+ return equal[0] # any number from equal
+ else:
+ return self.findKthLargest(smaller, k - len(greater) - len(equal))
+```
+
diff --git a/docs/leetcode/python/216._combination_sum_iii.md b/docs/Leetcode_Solutions/Python/216._combination_sum_iii.md
similarity index 100%
rename from docs/leetcode/python/216._combination_sum_iii.md
rename to docs/Leetcode_Solutions/Python/216._combination_sum_iii.md
diff --git a/docs/leetcode/python/217._contains_duplicate.md b/docs/Leetcode_Solutions/Python/217._contains_duplicate.md
similarity index 100%
rename from docs/leetcode/python/217._contains_duplicate.md
rename to docs/Leetcode_Solutions/Python/217._contains_duplicate.md
diff --git a/docs/leetcode/python/218._The_Skyline_Problem.md b/docs/Leetcode_Solutions/Python/218._The _Skyline_Problem .md
similarity index 98%
rename from docs/leetcode/python/218._The_Skyline_Problem.md
rename to docs/Leetcode_Solutions/Python/218._The _Skyline_Problem .md
index e11d460f8..34d9c9176 100644
--- a/docs/leetcode/python/218._The_Skyline_Problem.md
+++ b/docs/Leetcode_Solutions/Python/218._The _Skyline_Problem .md
@@ -131,4 +131,4 @@ Author: Keqi Huang
If you like it, please spread your support
-
+
diff --git a/docs/leetcode/python/219._contains_duplicate_ii.md b/docs/Leetcode_Solutions/Python/219._contains_duplicate_ii.md
similarity index 96%
rename from docs/leetcode/python/219._contains_duplicate_ii.md
rename to docs/Leetcode_Solutions/Python/219._contains_duplicate_ii.md
index 7ffcf2427..050dd932e 100644
--- a/docs/leetcode/python/219._contains_duplicate_ii.md
+++ b/docs/Leetcode_Solutions/Python/219._contains_duplicate_ii.md
@@ -1,99 +1,99 @@
-# 219. Contains Duplicate II
-**难度: 简单**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/contains-duplicate-ii/
-
-> 内容描述
-
-```
-Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
-
-Example 1:
-
-Input: nums = [1,2,3,1], k = 3
-Output: true
-Example 2:
-
-Input: nums = [1,0,1,1], k = 1
-Output: true
-Example 3:
-
-Input: nums = [1,2,3,1,2,3], k = 2
-Output: false
-```
-
-## 解题方案
-
-> 思路 1
-
-
-这道题虽然看似简单,但是我还是经历几次失败
-
-第一次我打算用最粗暴的方法来做,直接 Time Limit Exceeded,代码如下:
-```
-class Solution(object):
- def containsNearbyDuplicate(self, nums, k):
- """
- :type nums: List[int]
- :type k: int
- :rtype: bool
- """
- if k == 0:
- return False
- if k >= len(nums):
- return len(nums) != len(set(nums))
- for i in range(len(nums)-k):
- for j in range(1, k+1):
- if nums[i] == nums[i+j]:
- return True
- for i in range(len(nums)-k, len(nums)):
- for j in range(i+1, len(nums)):
- if nums[i] == nums[j]:
- return True
- return False
-```
-然后我打算用第 217 题的方法来一遍,还是报 Time Limit Exceeded 这个错,代码如下L:
-```
-class Solution(object):
- def containsNearbyDuplicate(self, nums, k):
- """
- :type nums: List[int]
- :type k: int
- :rtype: bool
- """
- if k == 0:
- return False
- if k >= len(nums):
- return len(nums) != len(set(nums))
- for i in range(len(nums)-k):
- if len(nums[i:i+k+1]) != len(set(nums[i:i+k+1])):
- return True
- return len(nums[-k:]) != len(set(nums[-k:]))
-```
-
-终于我想到了用字典来存,这个元素还没出现过,就以 的形式存进字典里,如果 num 再次出现了,计算相邻距离,小于等于 k 则 return true,否则更新字典中元素的位置,
-
-
-```python
-class Solution(object):
- def containsNearbyDuplicate(self, nums, k):
- """
- :type nums: List[int]
- :type k: int
- :rtype: bool
- """
- lookup = {}
- for i in range(len(nums)):
- if nums[i] not in lookup:
- lookup[nums[i]] = i
- else:
- if i - lookup[nums[i]] <= k:
- return True
- else:
- lookup[nums[i]] = i
- return False
-```
+# 219. Contains Duplicate II
+**难度: 简单**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/contains-duplicate-ii/
+
+> 内容描述
+
+```
+Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
+
+Example 1:
+
+Input: nums = [1,2,3,1], k = 3
+Output: true
+Example 2:
+
+Input: nums = [1,0,1,1], k = 1
+Output: true
+Example 3:
+
+Input: nums = [1,2,3,1,2,3], k = 2
+Output: false
+```
+
+## 解题方案
+
+> 思路 1
+
+
+这道题虽然看似简单,但是我还是经历几次失败
+
+第一次我打算用最粗暴的方法来做,直接 Time Limit Exceeded,代码如下:
+```
+class Solution(object):
+ def containsNearbyDuplicate(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: bool
+ """
+ if k == 0:
+ return False
+ if k >= len(nums):
+ return len(nums) != len(set(nums))
+ for i in range(len(nums)-k):
+ for j in range(1, k+1):
+ if nums[i] == nums[i+j]:
+ return True
+ for i in range(len(nums)-k, len(nums)):
+ for j in range(i+1, len(nums)):
+ if nums[i] == nums[j]:
+ return True
+ return False
+```
+然后我打算用第 217 题的方法来一遍,还是报 Time Limit Exceeded 这个错,代码如下L:
+```
+class Solution(object):
+ def containsNearbyDuplicate(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: bool
+ """
+ if k == 0:
+ return False
+ if k >= len(nums):
+ return len(nums) != len(set(nums))
+ for i in range(len(nums)-k):
+ if len(nums[i:i+k+1]) != len(set(nums[i:i+k+1])):
+ return True
+ return len(nums[-k:]) != len(set(nums[-k:]))
+```
+
+终于我想到了用字典来存,这个元素还没出现过,就以 的形式存进字典里,如果 num 再次出现了,计算相邻距离,小于等于 k 则 return true,否则更新字典中元素的位置,
+
+
+```python
+class Solution(object):
+ def containsNearbyDuplicate(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: bool
+ """
+ lookup = {}
+ for i in range(len(nums)):
+ if nums[i] not in lookup:
+ lookup[nums[i]] = i
+ else:
+ if i - lookup[nums[i]] <= k:
+ return True
+ else:
+ lookup[nums[i]] = i
+ return False
+```
diff --git a/docs/leetcode/python/221._maximal_square.md b/docs/Leetcode_Solutions/Python/221._maximal_square.md
similarity index 100%
rename from docs/leetcode/python/221._maximal_square.md
rename to docs/Leetcode_Solutions/Python/221._maximal_square.md
diff --git a/docs/leetcode/python/222._count_complete_tree_nodes.md b/docs/Leetcode_Solutions/Python/222._count_complete_tree_nodes.md
similarity index 100%
rename from docs/leetcode/python/222._count_complete_tree_nodes.md
rename to docs/Leetcode_Solutions/Python/222._count_complete_tree_nodes.md
diff --git a/docs/leetcode/python/223._rectangle_area.md b/docs/Leetcode_Solutions/Python/223._rectangle_area.md
similarity index 89%
rename from docs/leetcode/python/223._rectangle_area.md
rename to docs/Leetcode_Solutions/Python/223._rectangle_area.md
index 1f5dd34c5..90a69fa37 100644
--- a/docs/leetcode/python/223._rectangle_area.md
+++ b/docs/Leetcode_Solutions/Python/223._rectangle_area.md
@@ -1,51 +1,51 @@
-# 223. Rectangle Area
-**难度: 中等**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/rectangle-area
-
-> 内容描述
-
-```
-Find the total area covered by two rectilinear rectangles in a 2D plane.
-
-Each rectangle is defined by its bottom left corner and top right corner as shown in the figure.
-
-Rectangle Area
-
-Example:
-
-Input: A = -3, B = 0, C = 3, D = 4, E = 0, F = -1, G = 9, H = 2
-Output: 45
-Note:
-
-Assume that the total area is never beyond the maximum possible value of int.
-```
-
-## 解题方案
-
-> 思路 1
-
-sb题没什么好说的
-
-```python
-class Solution(object):
- def computeArea(self, A, B, C, D, E, F, G, H):
- """
- :type A: int
- :type B: int
- :type C: int
- :type D: int
- :type E: int
- :type F: int
- :type G: int
- :type H: int
- :rtype: int
- """
- return (C - A) * (D - B) + (H - F) * (G - E) - max(min(C, G) - max(A, E), 0) * max(min(D, H) - max(B, F), 0)
-```
-
-
+# 223. Rectangle Area
+**难度: 中等**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/rectangle-area/description/
+
+> 内容描述
+
+```
+Find the total area covered by two rectilinear rectangles in a 2D plane.
+
+Each rectangle is defined by its bottom left corner and top right corner as shown in the figure.
+
+Rectangle Area
+
+Example:
+
+Input: A = -3, B = 0, C = 3, D = 4, E = 0, F = -1, G = 9, H = 2
+Output: 45
+Note:
+
+Assume that the total area is never beyond the maximum possible value of int.
+```
+
+## 解题方案
+
+> 思路 1
+
+sb题没什么好说的
+
+```python
+class Solution(object):
+ def computeArea(self, A, B, C, D, E, F, G, H):
+ """
+ :type A: int
+ :type B: int
+ :type C: int
+ :type D: int
+ :type E: int
+ :type F: int
+ :type G: int
+ :type H: int
+ :rtype: int
+ """
+ return (C - A) * (D - B) + (H - F) * (G - E) - max(min(C, G) - max(A, E), 0) * max(min(D, H) - max(B, F), 0)
+```
+
+
diff --git a/docs/leetcode/python/224._Basic_Calculator.md b/docs/Leetcode_Solutions/Python/224. Basic Calculator .md
similarity index 100%
rename from docs/leetcode/python/224._Basic_Calculator.md
rename to docs/Leetcode_Solutions/Python/224. Basic Calculator .md
diff --git a/docs/leetcode/python/225._implement_stack_using_queues.md b/docs/Leetcode_Solutions/Python/225._implement_stack_using_queues.md
similarity index 99%
rename from docs/leetcode/python/225._implement_stack_using_queues.md
rename to docs/Leetcode_Solutions/Python/225._implement_stack_using_queues.md
index 9f61d9722..10a1ac200 100644
--- a/docs/leetcode/python/225._implement_stack_using_queues.md
+++ b/docs/Leetcode_Solutions/Python/225._implement_stack_using_queues.md
@@ -13,7 +13,7 @@ Easy
又到了作弊神预言Python的强项
-```
+```
class Stack(object):
def __init__(self):
"""
diff --git a/docs/Leetcode_Solutions/Python/226._invert_binary_tree.md b/docs/Leetcode_Solutions/Python/226._invert_binary_tree.md
new file mode 100644
index 000000000..afcb20bea
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/226._invert_binary_tree.md
@@ -0,0 +1,60 @@
+# 226. Invert Binary Tree
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/invert-binary-tree/description/
+
+> 内容描述
+
+```
+Invert a binary tree.
+
+Example:
+
+Input:
+
+ 4
+ / \
+ 2 7
+ / \ / \
+1 3 6 9
+Output:
+
+ 4
+ / \
+ 7 2
+ / \ / \
+9 6 3 1
+Trivia:
+This problem was inspired by this original tweet by Max Howell:
+
+Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+典型的递归题
+
+
+```python
+class Solution(object):
+ def invertTree(self, root):
+ """
+ :type root: TreeNode
+ :rtype: TreeNode
+ """
+ if not root:
+ return root
+ root.left, root.right = root.right, root.left
+ self.invertTree(root.left)
+ self.invertTree(root.right)
+ return root
+```
+
diff --git a/docs/leetcode/python/227._basic_calculator_ii.md b/docs/Leetcode_Solutions/Python/227._basic_calculator_ii.md
similarity index 100%
rename from docs/leetcode/python/227._basic_calculator_ii.md
rename to docs/Leetcode_Solutions/Python/227._basic_calculator_ii.md
diff --git a/docs/leetcode/python/228._summary_ranges.md b/docs/Leetcode_Solutions/Python/228._summary_ranges.md
similarity index 96%
rename from docs/leetcode/python/228._summary_ranges.md
rename to docs/Leetcode_Solutions/Python/228._summary_ranges.md
index 27486605e..ce9dce0f9 100644
--- a/docs/leetcode/python/228._summary_ranges.md
+++ b/docs/Leetcode_Solutions/Python/228._summary_ranges.md
@@ -1,58 +1,58 @@
-### 228. Summary Ranges
-
-题目:
-
-
-
-难度:
-
-Medium
-
-
-Just collect the ranges, then format and return them.
-
-```python
-class Solution(object):
- def summaryRanges(self, nums):
- """
- :type nums: List[int]
- :rtype: List[str]
- """
- ranges = []
- for i in nums:
- if not ranges or i > ranges[-1][-1] + 1:
- ranges += [],
- ranges[-1][1:] = i,
- return ['->'.join(map(str, r)) for r in ranges]
-```
-About the commas :-)
-
-```
-ranges += [],
-r[1:] = n,
-```
-Why the trailing commas? Because it turns the right hand side into a tuple and I get the same effects as these more common alternatives:
-```
-ranges += [[]]
-or
-ranges.append([])
-
-r[1:] = [n]
-```
-Without the comma, …
-
-- ranges += [] wouldn’t add [] itself but only its elements, i.e., nothing.
-- r[1:] = n wouldn’t work, because my n is not an iterable.
-
-Why do it this way instead of the more common alternatives I showed above? Because it’s shorter and faster (according to tests I did a while back).
-
-写到这里可能又有疑问了🤔️,为什么不可以直接写```ranges[-1][1] = i```呢,当然是会报```IndexError: list assignment index out of range```错误啦,那为什么```ranges[-1][1:] = i,```可以呢?
-
-简单来说
-
-L1=L 与 L1=L[:]
-- L1和L 都是对同一个对象的引用(所谓绑定的意思)。
-- L[:] 是生成了一个和L不同的新的对象,L1 变为了L[:] 这个对象的引用。
-
-
-参考[stefan](https://leetcode.com/problems/summary-ranges/discuss/63193)
+### 228. Summary Ranges
+
+题目:
+
+
+
+难度:
+
+Medium
+
+
+Just collect the ranges, then format and return them.
+
+```python
+class Solution(object):
+ def summaryRanges(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: List[str]
+ """
+ ranges = []
+ for i in nums:
+ if not ranges or i > ranges[-1][-1] + 1:
+ ranges += [],
+ ranges[-1][1:] = i,
+ return ['->'.join(map(str, r)) for r in ranges]
+```
+About the commas :-)
+
+```
+ranges += [],
+r[1:] = n,
+```
+Why the trailing commas? Because it turns the right hand side into a tuple and I get the same effects as these more common alternatives:
+```
+ranges += [[]]
+or
+ranges.append([])
+
+r[1:] = [n]
+```
+Without the comma, …
+
+- ranges += [] wouldn’t add [] itself but only its elements, i.e., nothing.
+- r[1:] = n wouldn’t work, because my n is not an iterable.
+
+Why do it this way instead of the more common alternatives I showed above? Because it’s shorter and faster (according to tests I did a while back).
+
+写到这里可能又有疑问了🤔️,为什么不可以直接写```ranges[-1][1] = i```呢,当然是会报```IndexError: list assignment index out of range```错误啦,那为什么```ranges[-1][1:] = i,```可以呢?
+
+简单来说
+
+L1=L 与 L1=L[:]
+- L1和L 都是对同一个对象的引用(所谓绑定的意思)。
+- L[:] 是生成了一个和L不同的新的对象,L1 变为了L[:] 这个对象的引用。
+
+
+参考[stefan](https://leetcode.com/problems/summary-ranges/discuss/63193)
diff --git a/docs/leetcode/python/229._majority_element_ii.md b/docs/Leetcode_Solutions/Python/229._majority_element_ii.md
similarity index 100%
rename from docs/leetcode/python/229._majority_element_ii.md
rename to docs/Leetcode_Solutions/Python/229._majority_element_ii.md
diff --git a/docs/Leetcode_Solutions/Python/230._kth_smallest_element_in_a_bst.md b/docs/Leetcode_Solutions/Python/230._kth_smallest_element_in_a_bst.md
new file mode 100644
index 000000000..3a14adb30
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/230._kth_smallest_element_in_a_bst.md
@@ -0,0 +1,113 @@
+# 230. Kth Smallest Element in a BST
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/
+
+> 内容描述
+
+```
+Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.
+
+Note:
+You may assume k is always valid, 1 ≤ k ≤ BST's total elements.
+
+Example 1:
+
+Input: root = [3,1,4,null,2], k = 1
+ 3
+ / \
+ 1 4
+ \
+ 2
+Output: 1
+Example 2:
+
+Input: root = [5,3,6,2,4,null,null,1], k = 3
+ 5
+ / \
+ 3 6
+ / \
+ 2 4
+ /
+ 1
+Output: 3
+Follow up:
+What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+跟昨天做的一道题类似,一上来就走取巧之路。
+
+InOrder排序,输出,当然也完全可以用昨天的binary tree iterator,入stack,出stack,直到输出第k位
+
+
+```python
+class Solution(object):
+ def kthSmallest(self, root, k):
+ """
+ :type root: TreeNode
+ :type k: int
+ :rtype: int
+ """
+ self.root = root
+ self.lst = []
+ self.inOrder(root)
+ return self.lst[k-1]
+
+ def inOrder(self, root):
+ if root == None:
+ return
+ self.inOrder(root.left)
+ self.lst.append(root.val)
+ self.inOrder(root.right)
+```
+
+> 思路 2
+******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
+
+现在看到kth 就条件反射的想用divide & conquer, 扫root的左子树看nodes量,如果nodes数量是k-1,那么root就刚好是第k个,如果大于k > 左子树数量,扫右子树,同时更新root为root.right。
+
+看到的言论:
+
+> If we can change the BST node structure, We can add a new Integer to mark the number of element in the left sub-tree.
+
+when the node is not null.
+
+- if k == node.leftNum + 1, return node
+- if k > node.leftNum + 1, make k -= node.leftNum + 1, and then node = node.right
+- otherwise, node = node.left
+
+
+```python
+class Solution:
+ def kthSmallest(self, root, k):
+ """
+ :type root: TreeNode
+ :type k: int
+ :rtype: int
+ """
+ def count(node):
+ if not node:
+ return 0
+ return count(node.left) + count(node.right) + 1
+
+ if not root:
+ return None
+ left = count(root.left)
+ if left == k - 1:
+ return root.val
+ elif left > k - 1:
+ return self.kthSmallest(root.left, k)
+ else:
+ return self.kthSmallest(root.right, k - left - 1)
+```
diff --git a/docs/leetcode/python/231._Power_of_Two.md b/docs/Leetcode_Solutions/Python/231. _Power_of_Two.md
similarity index 100%
rename from docs/leetcode/python/231._Power_of_Two.md
rename to docs/Leetcode_Solutions/Python/231. _Power_of_Two.md
diff --git a/docs/leetcode/python/232._implement_queue_using_stacks.md b/docs/Leetcode_Solutions/Python/232._implement_queue_using_stacks.md
similarity index 100%
rename from docs/leetcode/python/232._implement_queue_using_stacks.md
rename to docs/Leetcode_Solutions/Python/232._implement_queue_using_stacks.md
diff --git a/docs/leetcode/python/234._palindrome_linked_list.md b/docs/Leetcode_Solutions/Python/234._palindrome_linked_list.md
similarity index 100%
rename from docs/leetcode/python/234._palindrome_linked_list.md
rename to docs/Leetcode_Solutions/Python/234._palindrome_linked_list.md
diff --git a/docs/Leetcode_Solutions/Python/235._lowest_common_ancestor_of_a_binary_search_tree.md b/docs/Leetcode_Solutions/Python/235._lowest_common_ancestor_of_a_binary_search_tree.md
new file mode 100644
index 000000000..4e6a02622
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/235._lowest_common_ancestor_of_a_binary_search_tree.md
@@ -0,0 +1,71 @@
+# 235. Lowest Common Ancestor of a Binary Search Tree
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/
+
+> 内容描述
+
+```
+Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
+
+According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
+
+Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
+
+ _______6______
+ / \
+ ___2__ ___8__
+ / \ / \
+ 0 _4 7 9
+ / \
+ 3 5
+Example 1:
+
+Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
+Output: 6
+Explanation: The LCA of nodes 2 and 8 is 6.
+Example 2:
+
+Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
+Output: 2
+Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself
+ according to the LCA definition.
+Note:
+
+All of the nodes' values will be unique.
+p and q are different and both values will exist in the BST.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+- 两个node,一个大于root,一个小于root,那么它们必定在root两边,共同的ancestor是root
+- 两个node,都比node小,到左边去寻找,那么先找到那个必定是common ancestor
+- 两个node,都比node大,类似....
+
+
+
+```python
+class Solution(object):
+ def lowestCommonAncestor(self, root, p, q):
+ """
+ :type root: TreeNode
+ :type p: TreeNode
+ :type q: TreeNode
+ :rtype: TreeNode
+ """
+ if not root:
+ return root
+ if root.val > p.val and root.val > q.val:
+ return self.lowestCommonAncestor(root.left, p, q)
+ if root.val < p.val and root.val < q.val:
+ return self.lowestCommonAncestor(root.right, p, q)
+ return root
+```
diff --git a/docs/Leetcode_Solutions/Python/236._lowest_common_ancestor_of_a_binary_tree.md b/docs/Leetcode_Solutions/Python/236._lowest_common_ancestor_of_a_binary_tree.md
new file mode 100644
index 000000000..244969559
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/236._lowest_common_ancestor_of_a_binary_tree.md
@@ -0,0 +1,108 @@
+# 236. Lowest Common Ancestor of a Binary Tree
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/
+
+> 内容描述
+
+```
+Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
+
+According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
+
+Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
+
+ _______3______
+ / \
+ ___5__ ___1__
+ / \ / \
+ 6 _2 0 8
+ / \
+ 7 4
+Example 1:
+
+Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
+Output: 3
+Explanation: The LCA of of nodes 5 and 1 is 3.
+Example 2:
+
+Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
+Output: 5
+Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself
+ according to the LCA definition.
+Note:
+
+All of the nodes' values will be unique.
+p and q are different and both values will exist in the binary tree.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+1. Find path from root to n1 and store it in a vector or array.
+2. Find path from root to n2 and store it in another vector or array.
+3. Traverse both paths till the values in arrays are same. Return the common element just before the mismatch.
+
+时间复杂度worst case 是O(N),空间is the same
+```python
+class Solution(object):
+ def lowestCommonAncestor(self, root, p, q):
+ """
+ :type root: TreeNode
+ :type p: TreeNode
+ :type q: TreeNode
+ :rtype: TreeNode
+ """
+ def findPath(root, path, node):
+ if not root:
+ return False
+ path.append(root)
+ if root == node:
+ return True
+ if (root.left and findPath(root.left, path, node)) or (root.right and findPath(root.right, path, node)):
+ return True
+ path.pop()
+ return False
+ path_p, path_q = [], []
+ if not findPath(root, path_p, p) or not findPath(root, path_q, q):
+ return -1
+ i = 0
+ while i < len(path_p) and i < len(path_q):
+ if path_p[i] != path_q[i]:
+ break
+ i += 1
+ return path_p[i-1]
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+看代码才是最容易懂的,直接看吧
+
+```python
+class Solution(object):
+ pathp, pathq = [], []
+ def lowestCommonAncestor(self, root, p, q):
+ """
+ :type root: TreeNode
+ :type p: TreeNode
+ :type q: TreeNode
+ :rtype: TreeNode
+ """
+ if not root or root == p or root == q:
+ return root
+ left = self.lowestCommonAncestor(root.left, p, q)
+ right = self.lowestCommonAncestor(root.right, p, q)
+ if left and right:
+ return root
+ return left or right
+```
diff --git a/docs/leetcode/python/237._delete_node_in_a_linked_list.md b/docs/Leetcode_Solutions/Python/237._delete_node_in_a_linked_list.md
similarity index 96%
rename from docs/leetcode/python/237._delete_node_in_a_linked_list.md
rename to docs/Leetcode_Solutions/Python/237._delete_node_in_a_linked_list.md
index cd8be88c9..d401e090d 100644
--- a/docs/leetcode/python/237._delete_node_in_a_linked_list.md
+++ b/docs/Leetcode_Solutions/Python/237._delete_node_in_a_linked_list.md
@@ -1,52 +1,52 @@
-### 237. Delete Node in a Linked List
-
-题目:
-
-
-
-难度:
-Easy
-
-
-
-这道题,第一感觉,像删链表一样来删,把所有的node val前移一个,但是有个问题,为什么tail那个node还是存在?哼(ˉ(∞)ˉ)唧..
-
-已经被解答:
-
-
-
-
-
-另外一个O(1)的办法更好,把后一个node的val移到待删这个节点,并且把node.next = node.next.next
-
-题目说了不会删最后一个点,所以node.next.next一定存在,所以直接让node的val等于它next的val,然后让node的next指向它的next的next,举个例子:
- 1->2->3->4->5->None,要删除第四个节点,就让4变成5,然后让第四个节点指向第五个节点的next,
-这样原来的第四个节点就不存在了,虽然原来的第五个节点仍然存在且指向None,变成了1->2->3->5->None-<5
-
-
-
-```python
-O(1)时间
-class Solution(object):
- def deleteNode(self, node):
- """
- :type node: ListNode
- :rtype: void Do not return anything, modify node in-place instead.
- """
- node.val = node.next.val
- node.next = node.next.next
-```
-```python
-O(n)时间
-class Solution(object):
- def deleteNode(self, node):
- """
- :type node: ListNode
- :rtype: void Do not return anything, modify node in-place instead.
- """
- while node.next:
- node.val = node.next.val
- prev, node = node, node.next
- # clear reference to tail
- prev.next = None
-```
+### 237. Delete Node in a Linked List
+
+题目:
+
+
+
+难度:
+Easy
+
+
+
+这道题,第一感觉,像删链表一样来删,把所有的node val前移一个,但是有个问题,为什么tail那个node还是存在?哼(ˉ(∞)ˉ)唧..
+
+已经被解答:
+
+
+
+
+
+另外一个O(1)的办法更好,把后一个node的val移到待删这个节点,并且把node.next = node.next.next
+
+题目说了不会删最后一个点,所以node.next.next一定存在,所以直接让node的val等于它next的val,然后让node的next指向它的next的next,举个例子:
+ 1->2->3->4->5->None,要删除第四个节点,就让4变成5,然后让第四个节点指向第五个节点的next,
+这样原来的第四个节点就不存在了,虽然原来的第五个节点仍然存在且指向None,变成了1->2->3->5->None-<5
+
+
+
+```python
+O(1)时间
+class Solution(object):
+ def deleteNode(self, node):
+ """
+ :type node: ListNode
+ :rtype: void Do not return anything, modify node in-place instead.
+ """
+ node.val = node.next.val
+ node.next = node.next.next
+```
+```python
+O(n)时间
+class Solution(object):
+ def deleteNode(self, node):
+ """
+ :type node: ListNode
+ :rtype: void Do not return anything, modify node in-place instead.
+ """
+ while node.next:
+ node.val = node.next.val
+ prev, node = node, node.next
+ # clear reference to tail
+ prev.next = None
+```
diff --git a/docs/leetcode/python/238._product_of_array_except_self.md b/docs/Leetcode_Solutions/Python/238._product_of_array_except_self.md
similarity index 100%
rename from docs/leetcode/python/238._product_of_array_except_self.md
rename to docs/Leetcode_Solutions/Python/238._product_of_array_except_self.md
diff --git a/docs/leetcode/python/240._search_a_2d_matrix_ii.md b/docs/Leetcode_Solutions/Python/240._search_a_2d_matrix_ii.md
similarity index 100%
rename from docs/leetcode/python/240._search_a_2d_matrix_ii.md
rename to docs/Leetcode_Solutions/Python/240._search_a_2d_matrix_ii.md
diff --git a/docs/leetcode/python/242._valid_anagram.md b/docs/Leetcode_Solutions/Python/242._valid_anagram.md
similarity index 100%
rename from docs/leetcode/python/242._valid_anagram.md
rename to docs/Leetcode_Solutions/Python/242._valid_anagram.md
diff --git a/docs/leetcode/python/249._Group_Shifted_Strings.md b/docs/Leetcode_Solutions/Python/249._Group_Shifted_Strings.md
similarity index 95%
rename from docs/leetcode/python/249._Group_Shifted_Strings.md
rename to docs/Leetcode_Solutions/Python/249._Group_Shifted_Strings.md
index 2c31ed30c..1ad1c478d 100644
--- a/docs/leetcode/python/249._Group_Shifted_Strings.md
+++ b/docs/Leetcode_Solutions/Python/249._Group_Shifted_Strings.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/group-shifted-strings
+* https://leetcode.com/problems/group-shifted-strings/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/251._Flatten_2D_Vector.md b/docs/Leetcode_Solutions/Python/251._Flatten_2D_Vector.md
new file mode 100644
index 000000000..4032191c8
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/251._Flatten_2D_Vector.md
@@ -0,0 +1,71 @@
+# 251. Flatten 2D Vector
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/flatten-2d-vector/discuss/67653/My-Python-Solution
+
+> 内容描述
+
+```
+Implement an iterator to flatten a 2d vector.
+
+Example:
+
+Input: 2d vector =
+[
+ [1,2],
+ [3],
+ [4,5,6]
+]
+Output: [1,2,3,4,5,6]
+Explanation: By calling next repeatedly until hasNext returns false,
+ the order of elements returned by next should be: [1,2,3,4,5,6].
+```
+
+## 解题方案
+
+> 思路 1
+
+
+```python
+class Vector2D(object):
+
+ def __init__(self, vec2d):
+ """
+ Initialize your data structure here.
+ :type vec2d: List[List[int]]
+ """
+ self.row = 0
+ self.col = 0
+ self.vec = vec2d
+
+
+ def next(self):
+ """
+ :rtype: int
+ """
+ res = self.vec[self.row][self.col]
+ self.col += 1
+ return res
+
+
+ def hasNext(self):
+ """
+ :rtype: bool
+ """
+ while self.row < len(self.vec):
+ if self.col < len(self.vec[self.row]):
+ return True
+ self.col = 0
+ self.row += 1
+ return False
+
+
+# Your Vector2D object will be instantiated and called as such:
+# i, v = Vector2D(vec2d), []
+# while i.hasNext(): v.append(i.next())
+```
diff --git a/docs/Leetcode_Solutions/Python/252._Meeting_Rooms.md b/docs/Leetcode_Solutions/Python/252._Meeting_Rooms.md
new file mode 100644
index 000000000..7f434db8d
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/252._Meeting_Rooms.md
@@ -0,0 +1,50 @@
+# 252. Meeting Rooms
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/meeting-rooms/description/
+
+> 内容描述
+
+```
+Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all meetings.
+
+Example 1:
+
+Input: [[0,30],[5,10],[15,20]]
+Output: false
+Example 2:
+
+Input: [[7,10],[2,4]]
+Output: true
+```
+
+## 解题方案
+
+> 思路 1
+
+
+排个序然后看看后面meeting的start会不会比前面meeting的end小,如果有立刻就返回False,全都没有那就返回True
+
+
+
+
+```python
+class Solution(object):
+ def canAttendMeetings(self, intervals):
+ """
+ :type intervals: List[Interval]
+ :rtype: bool
+ """
+ if not intervals or len(intervals) < 2:
+ return True
+ intervals = sorted(intervals, key=lambda x:(x.start, x.end))
+ for i in range(1, len(intervals)):
+ if intervals[i].start < intervals[i-1].end:
+ return False
+ return True
+```
diff --git a/docs/Leetcode_Solutions/Python/253._Meeting_Rooms_II.md b/docs/Leetcode_Solutions/Python/253._Meeting_Rooms_II.md
new file mode 100644
index 000000000..890a2f6d2
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/253._Meeting_Rooms_II.md
@@ -0,0 +1,69 @@
+# 253. Meeting Rooms II
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/meeting-rooms-ii/description/
+
+> 内容描述
+
+```
+Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of conference rooms required.
+
+Example 1:
+
+Input: [[0, 30],[5, 10],[15, 20]]
+Output: 2
+Example 2:
+
+Input: [[7,10],[2,4]]
+Output: 1
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+想象一下,现实生活中,先开始的会议还没结束前我们就又要开始一个会议的话,此时我们需要一个新的会议室
+
+如果前面一堆先开始的会议都先于我们的新会议开始之前结束了,我们不需要新会议室
+
+换句话说,如果前面一堆新开始的会议中结束最早的那个会议如果在新开始的会议之前结束了的话,我们不需要会议室
+
+
+所以我们的思路是,先按照会议开始的时间排序,然后维护一个会议结束时间的最小堆,堆顶就是前面结束最早的那个会议的结束时间
+
+那么对于一个新的会议出现时:
+- 如果堆顶元素比新会议的开始时间更小的话,我们不需要新会议室。同时因为后面出现的新会议的开始时间更大了,
+所以目前最先结束的会议永远不可能比后面新出现的会议的开始时间更大,因此我们可以pop目前最先结束的会议,即pop堆顶元素,并且将新会议的结束时间放进堆中
+- 如果堆顶元素比新会议的开始时间更大的话,我们知道我们需要一个新的会议室,此时直接将新会议的结束时间放进堆中
+
+最终堆的size就是我们需要的会议室数量
+
+```python
+from heapq import heappush, heappop
+class Solution(object):
+ def minMeetingRooms(self, intervals):
+ """
+ :type intervals: List[Interval]
+ :rtype: int
+ """
+ if not intervals:
+ return 0
+
+ intervals.sort(key = lambda x:x.start)
+ end = []
+ for it in intervals:
+ # if the first finished meeting m1 ends before the next meeting
+ # we can directly pop m1, because there is no need to add a new room
+ if end and end[0] <= it.start:
+ heappop(end)
+ heappush(end, it.end)
+
+ return len(end)
+```
diff --git a/docs/Leetcode_Solutions/Python/254._Factor_Combinations.md b/docs/Leetcode_Solutions/Python/254._Factor_Combinations.md
new file mode 100644
index 000000000..c3e0ff5ae
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/254._Factor_Combinations.md
@@ -0,0 +1,144 @@
+# 254. Factor Combinations
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/factor-combinations/description/
+
+> 内容描述
+
+```
+Numbers can be regarded as product of its factors. For example,
+
+8 = 2 x 2 x 2;
+ = 2 x 4.
+Write a function that takes an integer n and return all possible combinations of its factors.
+
+Note:
+
+You may assume that n is always positive.
+Factors should be greater than 1 and less than n.
+Example 1:
+
+Input: 1
+Output: []
+Example 2:
+
+Input: 37
+Output:[]
+Example 3:
+
+Input: 12
+Output:
+[
+ [2, 6],
+ [2, 2, 3],
+ [3, 4]
+]
+Example 4:
+
+Input: 32
+Output:
+[
+ [2, 16],
+ [2, 2, 8],
+ [2, 2, 2, 4],
+ [2, 2, 2, 2, 2],
+ [2, 4, 4],
+ [4, 8]
+]
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+
+就每次遍历到sqrt(n)就够了,再往后面过去其实重复了, beats 62.6%
+
+```python
+class Solution(object):
+ def getFactors(self, n):
+ """
+ :type n: int
+ :rtype: List[List[int]]
+ """
+ from math import sqrt
+ if n < 4:
+ return []
+ res = []
+ for i in range(2, int(sqrt(n))+1):
+ if n % i == 0 and i <= n / i:
+ res.append([i]+[n/i])
+ for j in self.getFactors(n/i):
+ if j and i <= j[0]:
+ res.append([i]+j)
+ return res
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+想着用一下memorization会更快一点,果然beats 100%
+
+```python
+class Solution(object):
+ cache = {}
+ def getFactors(self, n):
+ """
+ :type n: int
+ :rtype: List[List[int]]
+ """
+ from math import sqrt
+ if n < 4:
+ return []
+ if n in self.cache:
+ return self.cache[n]
+ else:
+ res = []
+ for i in range(2, int(sqrt(n))+1):
+ if n % i == 0 and i <= n / i:
+ res.append([i]+[n/i])
+ for j in self.getFactors(n/i):
+ if j and i <= j[0]:
+ res.append([i]+j)
+ self.cache[n] = res
+ return res
+```
+
+
+
+> 思路 3
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+换个思路,每次都先直接append一个最大到res中,然后递归部分只增加一个更大的factor,但其实这种也不是很快,只beats 62.61,跟思路1一样一样的。
+
+一直觉得这种类似递归的算法看code最能理解了,我就不多说了,打球去了!
+
+
+```python
+class Solution(object):
+ def getFactors(self, n):
+ """
+ :type n: int
+ :rtype: List[List[int]]
+ """
+ def helper(n, prev):
+ # for each recursive part, at least append a larger factor
+ start = 2 if not prev else prev[-1]
+ for i in range(start, int(pow(n, 0.5))+1):
+ if n % i == 0:
+ helper(n/i, prev+[i])
+ if prev: # drectly append the cur largest factor
+ self.res.append(prev+[n])
+
+ self.res = []
+ helper(n, [])
+ return self.res
+```
diff --git a/docs/leetcode/python/255._Verify_Preorder_Sequence_in_Binary_Search_Tree.md b/docs/Leetcode_Solutions/Python/255._Verify_Preorder_Sequence_in_Binary_Search_Tree.md
similarity index 100%
rename from docs/leetcode/python/255._Verify_Preorder_Sequence_in_Binary_Search_Tree.md
rename to docs/Leetcode_Solutions/Python/255._Verify_Preorder_Sequence_in_Binary_Search_Tree.md
diff --git a/docs/leetcode/python/256._Paint_House.md b/docs/Leetcode_Solutions/Python/256. Paint House.md
similarity index 100%
rename from docs/leetcode/python/256._Paint_House.md
rename to docs/Leetcode_Solutions/Python/256. Paint House.md
diff --git a/docs/leetcode/python/257._binary_tree_paths.md b/docs/Leetcode_Solutions/Python/257._binary_tree_paths.md
similarity index 90%
rename from docs/leetcode/python/257._binary_tree_paths.md
rename to docs/Leetcode_Solutions/Python/257._binary_tree_paths.md
index ff642ec54..c1191e275 100644
--- a/docs/leetcode/python/257._binary_tree_paths.md
+++ b/docs/Leetcode_Solutions/Python/257._binary_tree_paths.md
@@ -1,83 +1,83 @@
-# 257. Binary Tree Paths
-**难度: 简单**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/binary-tree-paths
-
-> 内容描述
-
-```
-Given a binary tree, return all root-to-leaf paths.
-
-Note: A leaf is a node with no children.
-
-Example:
-
-Input:
-
- 1
- / \
-2 3
- \
- 5
-
-Output: ["1->2->5", "1->3"]
-
-Explanation: All root-to-leaf paths are: 1->2->5, 1->3
-```
-
-## 解题方案
-
-> 思路 1
-
-递归+DFS
-
-```python
-class Solution(object):
- def binaryTreePaths(self, root):
- """
- :type root: TreeNode
- :rtype: List[str]
- """
- def helper(node, cur_path):
- if not node.left and not node.right: ## 到leaf了
- res.append(cur_path+[node.val])
- return
- if node.left:
- helper(node.left, cur_path+[node.val])
- if node.right:
- helper(node.right, cur_path+[node.val])
-
- res = []
- if not root:
- return res
- helper(root, [])
-
- return ['->'.join([str(val) for val in path]) for path in res]
-```
-注意一点,很多人可能看到这里有好几次cur_path+[node.val],觉得干嘛不直接写在最开头了,事实是这样做的话cur_path就已经变化了,因为要执行完if node.left才去执行if node.right,此时cur_path就不是原来的cur_path了。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+# 257. Binary Tree Paths
+**难度: 简单**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/binary-tree-paths/description/
+
+> 内容描述
+
+```
+Given a binary tree, return all root-to-leaf paths.
+
+Note: A leaf is a node with no children.
+
+Example:
+
+Input:
+
+ 1
+ / \
+2 3
+ \
+ 5
+
+Output: ["1->2->5", "1->3"]
+
+Explanation: All root-to-leaf paths are: 1->2->5, 1->3
+```
+
+## 解题方案
+
+> 思路 1
+
+递归+DFS
+
+```python
+class Solution(object):
+ def binaryTreePaths(self, root):
+ """
+ :type root: TreeNode
+ :rtype: List[str]
+ """
+ def helper(node, cur_path):
+ if not node.left and not node.right: ## 到leaf了
+ res.append(cur_path+[node.val])
+ return
+ if node.left:
+ helper(node.left, cur_path+[node.val])
+ if node.right:
+ helper(node.right, cur_path+[node.val])
+
+ res = []
+ if not root:
+ return res
+ helper(root, [])
+
+ return ['->'.join([str(val) for val in path]) for path in res]
+```
+注意一点,很多人可能看到这里有好几次cur_path+[node.val],觉得干嘛不直接写在最开头了,事实是这样做的话cur_path就已经变化了,因为要执行完if node.left才去执行if node.right,此时cur_path就不是原来的cur_path了。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/leetcode/python/258._Add_Digits.md b/docs/Leetcode_Solutions/Python/258_ Add_Digits.md
similarity index 100%
rename from docs/leetcode/python/258._Add_Digits.md
rename to docs/Leetcode_Solutions/Python/258_ Add_Digits.md
diff --git a/docs/leetcode/python/261._Graph_Valid_Tree.md b/docs/Leetcode_Solutions/Python/261. Graph Valid Tree.md
similarity index 100%
rename from docs/leetcode/python/261._Graph_Valid_Tree.md
rename to docs/Leetcode_Solutions/Python/261. Graph Valid Tree.md
diff --git a/docs/leetcode/python/263._ugly_number.md b/docs/Leetcode_Solutions/Python/263._ugly_number.md
similarity index 100%
rename from docs/leetcode/python/263._ugly_number.md
rename to docs/Leetcode_Solutions/Python/263._ugly_number.md
diff --git a/docs/leetcode/python/264._ugly_number_ii.md b/docs/Leetcode_Solutions/Python/264._ugly_number_ii.md
similarity index 98%
rename from docs/leetcode/python/264._ugly_number_ii.md
rename to docs/Leetcode_Solutions/Python/264._ugly_number_ii.md
index cece144eb..ba1546b9e 100644
--- a/docs/leetcode/python/264._ugly_number_ii.md
+++ b/docs/Leetcode_Solutions/Python/264._ugly_number_ii.md
@@ -102,39 +102,39 @@ class Solution(object):
还可以优化:
根据页面hint 来做的
-
-```
-class Solution(object):
- def nthUglyNumber(self, n):
- """
- :type n: int
- :rtype: int
- """
- if n == 1:
- return 1
- else:
- import collections
- q2 = collections.deque()
- q3 = collections.deque()
- q5 = collections.deque()
- q2.append(2)
- q3.append(3)
- q5.append(5)
- while n > 1:
- x = min(q2[0],q3[0],q5[0])
- if x == q2[0]:
- x = q2.popleft()
- q2.append(2*x)
- q3.append(3*x)
- q5.append(5*x)
- elif x == q3[0]:
- x = q3.popleft()
- q3.append(3*x)
- q5.append(5*x)
- else:
- x = q5.popleft()
- q5.append(5*x)
- n -= 1
- return x
+
+```
+class Solution(object):
+ def nthUglyNumber(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ if n == 1:
+ return 1
+ else:
+ import collections
+ q2 = collections.deque()
+ q3 = collections.deque()
+ q5 = collections.deque()
+ q2.append(2)
+ q3.append(3)
+ q5.append(5)
+ while n > 1:
+ x = min(q2[0],q3[0],q5[0])
+ if x == q2[0]:
+ x = q2.popleft()
+ q2.append(2*x)
+ q3.append(3*x)
+ q5.append(5*x)
+ elif x == q3[0]:
+ x = q3.popleft()
+ q3.append(3*x)
+ q5.append(5*x)
+ else:
+ x = q5.popleft()
+ q5.append(5*x)
+ n -= 1
+ return x
```
diff --git a/docs/leetcode/python/265._Paint_House_II.md b/docs/Leetcode_Solutions/Python/265. Paint House II.md
similarity index 100%
rename from docs/leetcode/python/265._Paint_House_II.md
rename to docs/Leetcode_Solutions/Python/265. Paint House II.md
diff --git a/docs/leetcode/python/266._Palindrome_Permutation.md b/docs/Leetcode_Solutions/Python/266. Palindrome Permutation.md
similarity index 100%
rename from docs/leetcode/python/266._Palindrome_Permutation.md
rename to docs/Leetcode_Solutions/Python/266. Palindrome Permutation.md
diff --git a/docs/leetcode/python/267._Palindrome_Permutation_II.md b/docs/Leetcode_Solutions/Python/267. Palindrome Permutation II.md
similarity index 100%
rename from docs/leetcode/python/267._Palindrome_Permutation_II.md
rename to docs/Leetcode_Solutions/Python/267. Palindrome Permutation II.md
diff --git a/docs/Leetcode_Solutions/Python/268._missing_number.md b/docs/Leetcode_Solutions/Python/268._missing_number.md
new file mode 100644
index 000000000..3b41c9adb
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/268._missing_number.md
@@ -0,0 +1,99 @@
+# 268. Missing Number
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/missing-number/description/
+
+> 内容描述
+
+```
+Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.
+
+Example 1:
+
+Input: [3,0,1]
+Output: 2
+Example 2:
+
+Input: [9,6,4,2,3,5,7,0,1]
+Output: 8
+Note:
+Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
+```
+
+## 解题方案
+
+> 思路 1
+
+
+
+
+等差数列前n项和减去数组之和,一行瞬秒
+```(注意题目input从0开始取值)```
+
+
+```python
+class Solution(object):
+ def missingNumber(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ return len(nums) * (len(nums) + 1) / 2 - sum(nums)
+```
+
+> 思路 2
+
+位运算(异或运算)
+
+
+
+```python
+class Solution(object):
+ def missingNumber(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ res = n = len(nums)
+ for i in range(n):
+ res ^= i
+ res ^= nums[i]
+ return res
+```
+
+> 思路 3
+
+
+让每一个元素都放在正确的index上面,感谢微信上大神 Jay kay的思路,这样写只要给出的nums是非负的就行,应用性更强,
+但是这个代码还是无法用于[leetcode 41题:First missing positive](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/041._First_Missing_Positive.md)
+
+最后元素不等于其index的就是返回值
+```python
+class Solution(object):
+ def missingNumber(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ if not nums or len(nums) == 0:
+ return 0
+ if len(nums) == 1:
+ return 1 if nums[0] == 0 else 0
+ for i in range(len(nums)):
+ tmp = nums[i]
+ while tmp < len(nums) and nums[tmp] != tmp:
+ nums[tmp], tmp = tmp, nums[tmp]
+ for i in range(len(nums)):
+ if nums[i] != i:
+ return i
+ return len(nums)
+```
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/269._Alien_Dictionary.md b/docs/Leetcode_Solutions/Python/269._Alien_Dictionary.md
new file mode 100644
index 000000000..a88f2f2ad
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/269._Alien_Dictionary.md
@@ -0,0 +1,135 @@
+# 269. Alien Dictionary
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/alien-dictionary/description/
+
+> 内容描述
+
+```
+There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
+
+Example 1:
+
+Input:
+[
+ "wrt",
+ "wrf",
+ "er",
+ "ett",
+ "rftt"
+]
+
+Output: "wertf"
+Example 2:
+
+Input:
+[
+ "z",
+ "x"
+]
+
+Output: "zx"
+Example 3:
+
+Input:
+[
+ "z",
+ "x",
+ "z"
+]
+
+Output: ""
+
+Explanation: The order is invalid, so return "".
+Note:
+
+You may assume all letters are in lowercase.
+You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
+If the order is invalid, return an empty string.
+There may be multiple valid order of letters, return any one of them is fine.
+```
+
+## 解题方案
+
+> 思路 1
+
+参考大神[seanmsha](https://leetcode.com/problems/alien-dictionary/discuss/156130/Python-Solution-with-Detailed-Explanation-(91))的思路
+
+
+```
+We want to build a DAG graph so that we can get a possible order that doesn't have any invalid dependencies. First we initialize all of the words with degree 0 (which means that they're the first value in sorted order). We compare every letter by adjacent words (word i and word i+1) Once we find a different letter, we know that the letter in word i+1 is greater than word i so it comes later. We add a degree to the letter in i+1 and add an entry to the letter in word i's dictionary/hashmap signifying that theres an arrow from the letter in word i to the letter in word i+1. We break the loop on the adjacent words because we already found out the reason why word i is before word i+1 (we only get information about at most 1 letter per word). Once we have our degree counts, we traverse the graph (similar to a BFS) from the nodes with degree 0. When we visit a node, we append it to the result string. We subtract one from all of the words repeatedly until all of the words have had degree 0 and have been added to the result string.
+In summary:
+
+1. Initialize all letters in words with degree 0
+
+2. For each word i and word i+1 where i+1 原题连接
-* https://leetcode.com/problems/closest-binary-search-tree-value
+* https://leetcode.com/problems/closest-binary-search-tree-value/description/
> 内容描述
diff --git a/docs/leetcode/python/276._Paint_Fence.md b/docs/Leetcode_Solutions/Python/276. Paint Fence.md
similarity index 100%
rename from docs/leetcode/python/276._Paint_Fence.md
rename to docs/Leetcode_Solutions/Python/276. Paint Fence.md
diff --git a/docs/Leetcode_Solutions/Python/277. Find the Celebrity.md b/docs/Leetcode_Solutions/Python/277. Find the Celebrity.md
new file mode 100644
index 000000000..1eb3cf29b
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/277. Find the Celebrity.md
@@ -0,0 +1,76 @@
+# 277. Find the Celebrity
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/find-the-celebrity/description/
+
+> 内容描述
+
+```
+Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist one celebrity. The definition of a celebrity is that all the other n - 1 people know him/her but he/she does not know any of them.
+
+Now you want to find out who the celebrity is or verify that there is not one. The only thing you are allowed to do is to ask questions like: "Hi, A. Do you know B?" to get information of whether A knows B. You need to find out the celebrity (or verify there is not one) by asking as few questions as possible (in the asymptotic sense).
+
+You are given a helper function bool knows(a, b) which tells you whether A knows B. Implement a function int findCelebrity(n), your function should minimize the number of calls to knows.
+
+Note: There will be exactly one celebrity if he/she is in the party. Return the celebrity's label if there is a celebrity in the party. If there is no celebrity, return -1.
+```
+
+## 解题方案
+
+> 思路 1
+
+celebrity 是 每个人都知道他,而他不认识任何别的人。
+
+如果用图来看,那就每个别的人都有箭头指向c,而c没有任何出去的箭头。
+
+O(N^2)的代码还是还是很容易想到的
+
+但是我们可以有提升,那么就是可以check `knows(a,b)`,如果 a knows b,那么可以排除a是celebrity,否则可以排除b是celebrity.
+
+最后还要确认一遍是否这个是真的celebrity
+
+
+
+总的思路就是说先假设0就是celebrity,然后我们依次遍历下去,第一个不认识cele的人new成为新的cele,因为new不认识原来的cele,并且我们知道如果有的cele的话,那么有且只能有一个cele,所以既然new不认识cele,那cele肯定不是真正的cele,所以目前先假设new是新的cele,继续判断下去。最后我们需要遍历再判断一遍,如果任意cele认识某人或者某人不认识cele的情况出现,就说明没有cele了。
+
+
+AC代码
+
+时间复杂度: O(n)
+空间复杂度: O(1)
+
+```python
+# The knows API is already defined for you.
+# @param a, person a
+# @param b, person b
+# @return a boolean, whether a knows b
+# def knows(a, b):
+
+class Solution(object):
+ def findCelebrity(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ if n == 0:
+ return -1
+ cele = 0
+ for i in range(1, n):
+ if not knows(i, cele):
+ cele = i
+ for i in range(n):
+ if cele != i:
+ if not knows(i, cele) or knows(cele, i):
+ return -1
+ return cele
+```
+
+
+
+
+
diff --git a/docs/leetcode/python/278._First_Bad_Version.md b/docs/Leetcode_Solutions/Python/278._First_Bad _Version.md
similarity index 100%
rename from docs/leetcode/python/278._First_Bad_Version.md
rename to docs/Leetcode_Solutions/Python/278._First_Bad _Version.md
diff --git a/docs/Leetcode_Solutions/Python/279._perfect_squares.md b/docs/Leetcode_Solutions/Python/279._perfect_squares.md
new file mode 100644
index 000000000..f4d8bd50f
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/279._perfect_squares.md
@@ -0,0 +1,116 @@
+
+### 279. Perfect Squares
+
+
+题目:
+
+
+
+难度:
+
+Medium
+
+### 思路一:
+DP, 状态转移方程:
+
+```dp[i] = min(dp[i], dp[i - j * j] + 1)```
+
+
+
+
+```python
+class Solution(object):
+ def numSquares(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ dp = [0] * (n+1)
+ for i in range(n+1):
+ dp[i] = i
+ j = 1
+ while j * j <= i:
+ dp[i] = min(dp[i], dp[i-j*j] + 1)
+ j += 1
+ return dp[-1]
+```
+但是这个方法贼慢,beats 12%, 有时候提交甚至会超时,有时候又不会。。。。因此想别的办法
+
+### 思路二:
+
+Static DP, beats 90.39%
+
+```python
+class Solution(object):
+ dp = [0]
+ def numSquares(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ while len(self.dp) <= n:
+ m = len(self.dp)
+ inf = float('inf')
+ i = 1
+ while i * i <= m:
+ inf = min(inf, self.dp[m-i*i] + 1)
+ i += 1
+ self.dp.append(inf)
+ return self.dp[n]
+```
+
+进一步简化可以写成:
+```python
+class Solution(object):
+ dp = [0]
+ def numSquares(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ while len(self.dp) <= n:
+ self.dp += min(self.dp[-j*j] + 1 for j in range(1, int(len(self.dp)**0.5+1))),
+ return self.dp[n]
+```
+这里有个问题现在还没搞明白,以后再好好想一下,写成```return self.dp[-1]```提交就失败,
+```
+Submission Result: Wrong Answer
+Input: 1024
+Output: 4
+Expected: 1
+```
+
+### 思路三:
+
+还是慢,有个数学方法, runtime beats 98.48%
+```python
+import math
+class Solution(object):
+ def numSquares(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ def isSquare(num):
+ tmp = int(math.sqrt(num))
+ return tmp * tmp == num
+ while n & 3 == 0: # n % 4 == 0
+ n >>= 2
+ if n & 7 == 7: # n % 8 == 7
+ return 4
+ if isSquare(n):
+ return 1
+ sqrt_n = int(math.sqrt(n))
+ for i in range(1, sqrt_n + 1):
+ if isSquare(n-i*i):
+ return 2
+ return 3
+```
+in order to understand, I suggest u read:
+
+here is the [Lagrange's Four Square theorem](https://en.wikipedia.org/wiki/Lagrange%27s_four-square_theorem
+) - Limit the result to <= 4:
+
+And this [article](http://www.alpertron.com.ar/4SQUARES.HTM), in which you can also find the way to present a number as a sum of four squares:
+
+
diff --git a/docs/Leetcode_Solutions/Python/280._Wiggle_Sort.md b/docs/Leetcode_Solutions/Python/280._Wiggle_Sort.md
new file mode 100644
index 000000000..13a97f476
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/280._Wiggle_Sort.md
@@ -0,0 +1,88 @@
+# 280. Wiggle Sort
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/wiggle-sort/description/
+
+> 内容描述
+
+```
+Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] <= nums[3]....
+
+Example:
+
+Input: nums = [3,5,2,1,6,4]
+Output: One possible answer is [3,5,1,6,2,4]
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
+
+
+
+想的是比如bubble sort或者任何简单的比较sort,只是放数字的时候是按这样的大小顺序放:
+
+1, n, 2, n-1,3, n-2….
+
+或者每个pass其实做两个sort,找出最大的和最小的。然后分别放在头尾。
+
+
+
+这样的写法TLE:
+
+```
+class Solution(object):
+ def wiggleSort(self, nums): # 此法超时
+ """
+ :type nums: List[int]
+ :rtype: void Do not return anything, modify nums in-place instead.
+ """
+ n = len(nums)
+ for i in range(n):
+ # small bubble sort
+ if i % 2 == 0:
+ for j in range(n - 1, i - 1, -1):
+ if nums[j] > nums[j - 1]:
+ nums[j], nums[j - 1] = nums[j - 1], nums[j]
+ else:
+ for j in range(n - 1, i - 1, -1):
+ if nums[j] < nums[j - 1]:
+ nums[j], nums[j - 1] = nums[j - 1], nums[j]
+```
+
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+但是貌似想复杂了,其实对于这个简单化,要求只有一个:
+
+1. 如果i是奇数,nums[i] >= nums[i - 1]
+2. 如果i是偶数,nums[i] <= nums[i - 1]
+
+所以我们只要遍历一遍数组,把不符合的情况交换一下就行了。具体来说,如果nums[i] > nums[i - 1], 则交换以后肯定有nums[i] <= nums[i - 1]。
+
+
+
+AC 代码
+
+```python
+class Solution(object):
+ def wiggleSort(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: void Do not return anything, modify nums in-place instead.
+ """
+ for i in range(1, len(nums)):
+ if (i & 1 == 0 and nums[i] > nums[i-1]) or (i & 1 != 0 and nums[i] < nums[i-1]):
+ nums[i], nums[i-1] = nums[i-1], nums[i]
+```
+
+
+
diff --git a/docs/leetcode/python/283._move_zeroes.md b/docs/Leetcode_Solutions/Python/283._move_zeroes.md
similarity index 78%
rename from docs/leetcode/python/283._move_zeroes.md
rename to docs/Leetcode_Solutions/Python/283._move_zeroes.md
index a5e887c05..26d868112 100644
--- a/docs/leetcode/python/283._move_zeroes.md
+++ b/docs/Leetcode_Solutions/Python/283._move_zeroes.md
@@ -1,19 +1,35 @@
-### 283. Move Zeroes
+# 283. Move Zeroes
+**难度: Easy**
-题目:
-
+## 刷题内容
+> 原题连接
-难度:
-Easy
+* https://leetcode.com/problems/move-zeroes/description/
+> 内容描述
-思路:
+```
+Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.
-### 思路一:暴力
+Example:
-```python
+Input: [0,1,0,3,12]
+Output: [1,3,12,0,0]
+Note:
+
+You must do this in-place without making a copy of the array.
+Minimize the total number of operations.
+```
+
+## 解题方案
+
+> 思路 1
+
+这个思路不符合题目意思,题目要求in-place
+
+```
class Solution(object):
def moveZeroes(self, nums):
"""
@@ -26,13 +42,10 @@ class Solution(object):
i += 1
nums.extend([0]*i)
```
-
-### 思路二:
+> 思路 2
一旦遇到不是0的就把它往前移动,移动非0完成,剩下的全部填0,看例子
-
-
```
0 1 0 3 12
@@ -50,6 +63,13 @@ class Solution(object):
```
1 3 0 3 12
```
+然后变成
+```
+1 3 12 3 12
+ ^ ^
+ cur idx
+```
+
这样知道变换完成,简直逆天啊,因为cur 总是小于idx,所以总可以保持这样的稳定性
@@ -71,11 +91,10 @@ class Solution(object):
while cur < len(nums):
nums[cur] = 0
cur += 1
-
```
-### 思路三:
+> 思路 3
传统的双指针,参考这里
@@ -106,9 +125,11 @@ class Solution(object):
相反,我觉得这样双指针反而没有上面的代码容易理解
-### 思路四:
+> 思路 4
一个比较巧妙的方法:
+
+这个思路符合题目意思in-place,但是时间复杂度是O(nlgn)
```python
class Solution(object):
def moveZeroes(self, nums):
diff --git a/docs/leetcode/python/285._inorder_successor_in_bst.md b/docs/Leetcode_Solutions/Python/285._inorder_successor_in_bst.md
similarity index 97%
rename from docs/leetcode/python/285._inorder_successor_in_bst.md
rename to docs/Leetcode_Solutions/Python/285._inorder_successor_in_bst.md
index b3a941587..aafca56c7 100644
--- a/docs/leetcode/python/285._inorder_successor_in_bst.md
+++ b/docs/Leetcode_Solutions/Python/285._inorder_successor_in_bst.md
@@ -6,7 +6,7 @@
> 原题连接
-* https://leetcode.com/problems/inorder-successor-in-bst
+* https://leetcode.com/problems/inorder-successor-in-bst/description/
> 内容描述
diff --git a/docs/leetcode/python/286._Walls_and_Gates.md b/docs/Leetcode_Solutions/Python/286. Walls and Gates.md
similarity index 100%
rename from docs/leetcode/python/286._Walls_and_Gates.md
rename to docs/Leetcode_Solutions/Python/286. Walls and Gates.md
diff --git a/docs/Leetcode_Solutions/Python/287._Find_the_Duplicate_Number.md b/docs/Leetcode_Solutions/Python/287._Find_the_Duplicate_Number.md
new file mode 100644
index 000000000..9b8d8b014
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/287._Find_the_Duplicate_Number.md
@@ -0,0 +1,161 @@
+# 287. Find the Duplicate Number
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/find-the-duplicate-number/description/
+
+> 内容描述
+
+```
+
+Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
+
+Example 1:
+
+Input: [1,3,4,2,2]
+Output: 2
+Example 2:
+
+Input: [3,1,3,4,2]
+Output: 3
+Note:
+
+You must not modify the array (assume the array is read only).
+You must use only constant, O(1) extra space.
+Your runtime complexity should be less than O(n2).
+There is only one duplicate number in the array, but it could be repeated more than once.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(NlgN)******- 空间复杂度: O(1)******
+
+参考[小瑶大神](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/287._Find_the_Duplicate_Number.ipynb
+)的思路
+
+二分枚举答案范围,使用鸽笼原理进行检验
+
+根据鸽笼原理,给定 n+1 个范围为 [1, n]的整数,其中一定存在数字出现至少两次。
+假设枚举的数字为 n / 2 :
+遍历数组,若数组中不大于 n / 2 的数字个数超过 n / 2 ,则可以确定 [1, n/2] 范围内一定有解,否则可以确定解落在 (n/2, n]范围内。
+也可以这样分析一下:
+
+
+如果n 是5,那么就会有1 2 3 4 5 一共5个数字的可能,而array size 是6,那么其中一个数字肯定会至少出现两次。
+
+如果没有重复的数字,小于等于1的数字 出现的次数 等于 1;
+
+小于等于2的数字 出现的次数 等于 2;
+
+... 同理3;4;5。
+
+如果有重复的数字,如果重复的是1,那么 小于等于1的数字 出现的次数 肯定大于1;
+
+基于这个理论,我们可以在1 2 3 4 5 选出一个 mid, 遍历array来count 小于等于mid 的数字个数 小于等于 它自己mid 还是 大于 mid?
+
+如果count 小于等于mid, 说明 1 到 mid 这些数字 没有重复项, 重复项在 右半边 mid 到n, 所以缩小到右半边继续搜索;
+
+如果count 大于mid, 说明 1 到 mid 这些数字中 有重复项,缩小到 左半边继续搜索。
+
+```python
+class Solution(object):
+ def findDuplicate(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ l, r = 0, len(nums) - 1
+ while l <= r:
+ mid = l +((r-l) >> 2)
+ count = sum(num <= mid for num in nums)
+ if count > mid:
+ r = mid - 1
+ else:
+ l = mid + 1
+ return l
+```
+
+> 思路 2
+******- 时间复杂度: O(NlgN)******- 空间复杂度: O(1)******
+
+参考[haitao7](https://leetcode.com/haitao7/)大神的思路
+
+我们可以用bit的思路来做,basic idea就是,重复出现的那个数字会使得我们在某一位上出现1的次数是异常的
+
+比如说[1,3,4,2,2]跟[1, 2, 3, 4]对比:
+
+- [1, 3, 4, 2, 2] == [001, 011, 100, 010, 010]
+- [1, 2, 3, 4] == [001, 010, 011, 100]
+
+从最小位开始看起,[1, 3, 4, 2, 2]有2个数,1和3,在最小位上是1,[1, 2, 3, 4]也一样。
+
+但是在从右往左数第二位,[1, 3, 4, 2, 2]就有3个数[3, 2, 2] == [011, 010, 010],在那个bit上是1;而[1, 2, 3, 4]只有[2, 3]两个。
+
+每当发现一个数位上,nums里在那个数位上为1的元素个数,超过了1到n在那个数位上为1的元素个数,我们就可以确定,重复的那个数,在那个数位上肯定是1。如果数位上的1个数相等,则本来那个重复的数字该数位上也是0,不管重复的那个数重复出现多少次,只要多了该数位就是1,没多该数位就是0。
+
+
+这个算法还是有点慢,可能大家用的都是接下来的这个思路,只beats 了 2%
+
+```python
+class Solution(object):
+ def findDuplicate(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ import math
+
+ bits_count = int(math.log(len(nums), 2)) # this is the bits we have
+ base, duplicate = 1, 0
+ for i in range(bits_count+1): # O(logn) for loop
+ normal, real = 0, 0
+ for j in range(len(nums)): # O(n) for loop
+ normal += (j >> i) & 1
+ real += (nums[j] >> i) & 1
+ if real > normal:
+ duplicate += base
+ base <<= 1
+ return duplicate
+```
+
+
+
+
+
+> 思路 3
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+快慢指针,先快慢轮询一遍,再慢慢轮询一遍,就找到了,beats 99.7%
+```python
+class Solution(object):
+ def findDuplicate(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ # The "tortoise and hare" step. We start at the end of the array and try
+ # to find an intersection point in the cycle.
+ slow, fast = 0, 0
+ # Keep advancing 'slow' by one step and 'fast' by two steps until they
+ # meet inside the loop.
+ while True:
+ slow = nums[slow]
+ fast = nums[nums[fast]]
+ if slow == fast:
+ break
+ # Start up another pointer from the end of the array and march it forward
+ # until it hits the pointer inside the array.
+ finder = 0
+ while True:
+ slow = nums[slow]
+ finder = nums[finder]
+ # If the two hit, the intersection index is the duplicate element.
+ if slow == finder:
+ return slow
+```
diff --git a/docs/leetcode/python/289._game_of_life.md b/docs/Leetcode_Solutions/Python/289._game_of_life.md
similarity index 100%
rename from docs/leetcode/python/289._game_of_life.md
rename to docs/Leetcode_Solutions/Python/289._game_of_life.md
diff --git a/docs/leetcode/python/290._word_pattern.md b/docs/Leetcode_Solutions/Python/290._word_pattern.md
similarity index 100%
rename from docs/leetcode/python/290._word_pattern.md
rename to docs/Leetcode_Solutions/Python/290._word_pattern.md
diff --git a/docs/leetcode/python/292._nim_game.md b/docs/Leetcode_Solutions/Python/292._nim_game.md
similarity index 100%
rename from docs/leetcode/python/292._nim_game.md
rename to docs/Leetcode_Solutions/Python/292._nim_game.md
diff --git a/docs/leetcode/python/293._Flip_Game.md b/docs/Leetcode_Solutions/Python/293._Flip_Game.md
similarity index 100%
rename from docs/leetcode/python/293._Flip_Game.md
rename to docs/Leetcode_Solutions/Python/293._Flip_Game.md
diff --git a/docs/leetcode/python/296._Best_Meeting_Point.md b/docs/Leetcode_Solutions/Python/296. Best Meeting Point.md
similarity index 100%
rename from docs/leetcode/python/296._Best_Meeting_Point.md
rename to docs/Leetcode_Solutions/Python/296. Best Meeting Point.md
diff --git a/docs/leetcode/python/298._Binary_Tree_Longest_Consecutive_Sequence.md b/docs/Leetcode_Solutions/Python/298. Binary Tree Longest Consecutive Sequence.md
similarity index 100%
rename from docs/leetcode/python/298._Binary_Tree_Longest_Consecutive_Sequence.md
rename to docs/Leetcode_Solutions/Python/298. Binary Tree Longest Consecutive Sequence.md
diff --git a/docs/leetcode/python/299._bulls_and_cows.md b/docs/Leetcode_Solutions/Python/299._bulls_and_cows.md
similarity index 98%
rename from docs/leetcode/python/299._bulls_and_cows.md
rename to docs/Leetcode_Solutions/Python/299._bulls_and_cows.md
index 1d6818460..8b6cbe468 100644
--- a/docs/leetcode/python/299._bulls_and_cows.md
+++ b/docs/Leetcode_Solutions/Python/299._bulls_and_cows.md
@@ -13,38 +13,38 @@ Easy
我花了很久时间来AC,因为想了边界条件
-```
-class Solution(object):
- def getHint(self, secret, guess):
- """
- :type secret: str
- :type guess: str
- :rtype: str
- """
- maps = {}
- for i in range(len(secret)):
- if secret[i] not in maps:
- maps[secret[i]] = [i]
- else:
- maps[secret[i]].append(i)
- mapg = {}
- for i in range(len(guess)):
- if guess[i] not in mapg:
- mapg[guess[i]] = [i]
- else:
- mapg[guess[i]].append(i)
-
- print maps, mapg
-
- a,b = 0,0
- for key in maps.keys():
- if key in mapg.keys():
- common = list(set(mapg[key]) & set(maps[key]))
- #check for bull
- a += len(common)
- mapg[key] = [item for item in mapg[key] if item not in common]
- maps[key] = [item for item in maps[key] if item not in common]
- b += min(len(maps[key]), len(mapg[key]))
+```
+class Solution(object):
+ def getHint(self, secret, guess):
+ """
+ :type secret: str
+ :type guess: str
+ :rtype: str
+ """
+ maps = {}
+ for i in range(len(secret)):
+ if secret[i] not in maps:
+ maps[secret[i]] = [i]
+ else:
+ maps[secret[i]].append(i)
+ mapg = {}
+ for i in range(len(guess)):
+ if guess[i] not in mapg:
+ mapg[guess[i]] = [i]
+ else:
+ mapg[guess[i]].append(i)
+
+ print maps, mapg
+
+ a,b = 0,0
+ for key in maps.keys():
+ if key in mapg.keys():
+ common = list(set(mapg[key]) & set(maps[key]))
+ #check for bull
+ a += len(common)
+ mapg[key] = [item for item in mapg[key] if item not in common]
+ maps[key] = [item for item in maps[key] if item not in common]
+ b += min(len(maps[key]), len(mapg[key]))
return str(a) + 'A' + str(b) + 'B'
```
diff --git a/docs/Leetcode_Solutions/Python/300._longest_increasing_subsequence.md b/docs/Leetcode_Solutions/Python/300._longest_increasing_subsequence.md
new file mode 100644
index 000000000..556041d7a
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/300._longest_increasing_subsequence.md
@@ -0,0 +1,138 @@
+# 300. Longest Increasing Subsequence
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/longest-increasing-subsequence/description/
+
+> 内容描述
+
+```
+Given an unsorted array of integers, find the length of longest increasing subsequence.
+
+Example:
+
+Input: [10,9,2,5,3,7,101,18]
+Output: 4
+Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
+Note:
+
+There may be more than one LIS combination, it is only necessary for you to return the length.
+Your algorithm should run in O(n2) complexity.
+Follow up: Could you improve it to O(n log n) time complexity?
+```
+
+## 解题方案
+
+> 思路 1
+
+典型DP
+
+递推关系式:
+
+对于以num[i]结束的longest increasing subsequence的长度
+
+dp[i] = dp[j] + 1 if num[i] > num[j] else dp[i], which 0 <= j < i
+
+loop一圈,求出最长的
+
+AC 代码, 时间复杂度为O(n^2)
+
+```python
+class Solution(object):
+ def lengthOfLIS(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ if not nums or len(nums) == 0:
+ return 0
+ dp = [1] * len(nums)
+ for i in range(len(nums)):
+ for j in range(i):
+ if nums[i] > nums[j]:
+ dp[i] = max(dp[j]+1, dp[i])
+ return max(dp)
+```
+
+
+## Follow up
+
+Could you improve it to O(n log n) time complexity?
+
+> 思路 1
+
+参考这篇🐂p的[博客](https://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/):
+
+自己写二分
+
+```python
+class Solution(object):
+ def lengthOfLIS(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ def binarySearch(nums, l, r, target):
+ while l <= r:
+ mid = l + ((r-l) >> 1)
+ if nums[mid] < target:
+ l = mid + 1
+ else:
+ r = mid - 1
+ return l
+
+ if not nums or len(nums) == 0:
+ return 0
+
+ tails = [0 for i in range(len(nums)+1)]
+ tails[0] = nums[0]
+ # always points empty slot
+ length = 1
+ for i in range(1, len(nums)):
+ if (nums[i] < tails[0]):
+ # new smallest value
+ tails[0] = nums[i]
+ elif (nums[i] > tails[length-1]):
+ # A[i] wants to extend
+ # largest subsequence
+ tails[length] = nums[i]
+ length+=1
+ else:
+ # A[i] wants to be current
+ # end candidate of an existing
+ # subsequence. It will replace
+ # ceil value in tailTable
+ tails[binarySearch(tails, 0, length-1, nums[i])] = nums[i]
+
+ return length
+```
+
+
+> 思路 2
+
+调用自带的二分,并且不维护整个tails,只是慢慢往上面append元素,这样二分查找时不需要手动输入left和right
+
+```python
+class Solution(object):
+ def lengthOfLIS(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ if not nums or len(nums) == 0:
+ return 0
+
+ lis = [nums[0]]
+ for i in range(1, len(nums)):
+ if nums[i] > lis[-1]:
+ lis.append(nums[i])
+ else:
+ # 要用bisect_left,因为如果插入到右边就相当于多append了一个,而不再是replace了
+ lis[bisect.bisect_left(lis, nums[i])] = nums[i]
+
+ return len(lis)
+```
diff --git a/docs/leetcode/python/303._range_sum_query_-_immutable.md b/docs/Leetcode_Solutions/Python/303._range_sum_query_-_immutable.md
similarity index 100%
rename from docs/leetcode/python/303._range_sum_query_-_immutable.md
rename to docs/Leetcode_Solutions/Python/303._range_sum_query_-_immutable.md
diff --git a/docs/Leetcode_Solutions/Python/305._Number_of_Islands_II.md b/docs/Leetcode_Solutions/Python/305._Number_of_Islands_II.md
new file mode 100644
index 000000000..d4e1c25a6
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/305._Number_of_Islands_II.md
@@ -0,0 +1,95 @@
+# 305. Number of Islands II
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/number-of-islands-ii/description/
+
+> 内容描述
+
+```
+A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand operation which turns the water at position (row, col) into a land. Given a list of positions to operate, count the number of islands after each addLand operation. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
+
+Example:
+
+Input: m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]]
+Output: [1,1,2,3]
+Explanation:
+
+Initially, the 2d grid grid is filled with water. (Assume 0 represents water and 1 represents land).
+
+0 0 0
+0 0 0
+0 0 0
+Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.
+
+1 0 0
+0 0 0 Number of islands = 1
+0 0 0
+Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.
+
+1 1 0
+0 0 0 Number of islands = 1
+0 0 0
+Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.
+
+1 1 0
+0 0 1 Number of islands = 2
+0 0 0
+Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.
+
+1 1 0
+0 0 1 Number of islands = 3
+0 1 0
+Follow up:
+
+Can you do it in time complexity O(k log mn), where k is the length of the positions?
+```
+
+## 解题方案
+
+> 思路 1
+
+对于positions中的每一个点,我们把他认为是一个单独的岛屿的root,然后我们看看他周围有没有value为1的点(即陆地),如果有,那么那一块陆地的root也是当前点
+
+然后每次结束一个点,我们就可以算一下当前一共有几个岛屿,即有几个不同的root,在代码中为```island_groups```的长度
+
+这个解法也称为并查集算法,可以去看看[union-find](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/Summarization/union_find.md)
+
+
+```python
+class Solution(object):
+ def numIslands2(self, m, n, positions):
+ """
+ :type m: int
+ :type n: int
+ :type positions: List[List[int]]
+ :rtype: List[int]
+ """
+ # find the root of a point
+ def find(x, uf):
+ while x != uf[x]:
+ uf[x] = uf[uf[x]]
+ x = uf[x]
+ return uf[x]
+
+ island_groups, res, uf, idx = set(), [], {}, 1
+ for i, j in positions:
+ uf[(i, j)] = uf[idx] = idx
+ for x, y in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)):
+ # when neighbor == 1, we make cur_point as the root
+ if (x, y) in uf:
+ root = find(uf[(x, y)], uf)
+ island_groups.discard(root)
+ uf[root] = idx
+ island_groups.add(idx)
+ idx += 1
+ res.append(len(island_groups))
+ return res
+```
+
+
+```因为并查集的查找时间复杂度是O(lgN),由于这里N就是m*n,所以我们总的时间复杂度就是O(k*lgmn)```
diff --git a/docs/Leetcode_Solutions/Python/311._Sparse_Matrix_Multiplication.md b/docs/Leetcode_Solutions/Python/311._Sparse_Matrix_Multiplication.md
new file mode 100644
index 000000000..e8f33c212
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/311._Sparse_Matrix_Multiplication.md
@@ -0,0 +1,78 @@
+# 311. Sparse Matrix Multiplication
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/sparse-matrix-multiplication/description/
+
+> 内容描述
+
+```
+Given two sparse matrices A and B, return the result of AB.
+
+You may assume that A's column number is equal to B's row number.
+
+Example:
+
+Input:
+
+A = [
+ [ 1, 0, 0],
+ [-1, 0, 3]
+]
+
+B = [
+ [ 7, 0, 0 ],
+ [ 0, 0, 0 ],
+ [ 0, 0, 1 ]
+]
+
+Output:
+
+ | 1 0 0 | | 7 0 0 | | 7 0 0 |
+AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 |
+ | 0 0 1 |
+```
+
+## 解题方案
+
+> 思路 1
+
+
+
+直接搞一个完全的稀疏矩阵然后一个一个地去看,这样万一内存不够怎么办,所以我们基于A建一个非0的新list,然后对应的求出结果,这样操作数会少一些,
+并且对内存的要求也没有那么高,借用一句话```I think, in perspective of Big4, they would have a HUGE sparse dataset.
+And would like to process them in a machine.
+So memory does not fit without the Table representation of sparse matrix.
+And this is efficient since can be loaded into a one machine```
+
+```python
+class Solution(object):
+ def multiply(self, A, B):
+ """
+ :type A: List[List[int]]
+ :type B: List[List[int]]
+ :rtype: List[List[int]]
+ """
+ m, n, nB = len(A), len(A[0]), len(B[0])
+ res = [[0] * nB for i in range(m)]
+
+ idxA = []
+ for i in range(len(A)):
+ tmp = []
+ for j in range(len(A[0])):
+ if A[i][j] != 0:
+ tmp.append(j)
+ idxA.append(tmp)
+ print(idxA)
+
+ for i in range(len(idxA)):
+ for j in idxA[i]:
+ for k in range(nB):
+ res[i][k] += A[i][j] * B[j][k]
+
+ return res
+```
diff --git a/docs/leetcode/python/316._Remove_Duplicate_Letters.md b/docs/Leetcode_Solutions/Python/316._Remove_Duplicate_Letters.md
similarity index 100%
rename from docs/leetcode/python/316._Remove_Duplicate_Letters.md
rename to docs/Leetcode_Solutions/Python/316._Remove_Duplicate_Letters.md
diff --git a/docs/leetcode/python/319._Bulb_Switcher.md b/docs/Leetcode_Solutions/Python/319._Bulb_Switcher.md
similarity index 60%
rename from docs/leetcode/python/319._Bulb_Switcher.md
rename to docs/Leetcode_Solutions/Python/319._Bulb_Switcher.md
index 840cce518..c764bbd30 100644
--- a/docs/leetcode/python/319._Bulb_Switcher.md
+++ b/docs/Leetcode_Solutions/Python/319._Bulb_Switcher.md
@@ -1,15 +1,35 @@
-### 319. Bulb Switcher
+# 319. Bulb Switcher
-题目:
-
+**难度: Medium**
+## 刷题内容
-难度:
+> 原题连接
-Medium
+* https://leetcode.com/problems/bulb-switcher/description/
+> 内容描述
-思路
+```
+There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it's off or turning off if it's on). For the i-th round, you toggle every i bulb. For the n-th round, you only toggle the last bulb. Find how many bulbs are on after n rounds.
+
+Example:
+
+Input: 3
+Output: 1
+Explanation:
+At first, the three bulbs are [off, off, off].
+After first round, the three bulbs are [on, on, on].
+After second round, the three bulbs are [on, off, on].
+After third round, the three bulbs are [on, off, off].
+
+So you should return 1, because there is only one bulb is on.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******
bulb代表第一轮结束后的所有灯亮灭的情况,从第二轮开始
- 如果是最后一轮,则bulb的最后一个灯要switch
@@ -34,6 +54,9 @@ class Solution(object):
return bulb.count(1)
```
+> 思路 2
+******- 时间复杂度: O(1)******- 空间复杂度: O(1)******
+
原来,这是一道智商碾压题:
> A bulb ends up on iff it is switched an odd number of times.
@@ -55,6 +78,10 @@ and double divisor 6. So bulb >i ends up on iff and only if i is a square. So ju
所以编号为12的灯,在第1次,第12次;第2次,第6次;第3次,第4次一定会被执行Switch操作,这样的话,编号为12的灯执行偶数次switch,肯定为灭。
这样推出,完全平方数一定是亮着的,因为它有两个相同的因子,总因子数为奇数,如36 = 6 * 6,所以本题的关键在于找完全平方数的个数。
+为什么时间复杂度是O(1)呢,因为追溯到最底层,求开方就是O(1)的,详细见
+1. [求平方根sqrt()函数的底层算法效率问题](http://www.nowamagic.net/algorithm/algorithm_EfficacyOfFunctionSqrt.php)
+2. [Time complexity of Math.Sqrt()?](https://stackoverflow.com/questions/34580158/time-complexity-of-math-sqrt)
+
```python
class Solution(object):
def bulbSwitch(self, n):
@@ -62,7 +89,7 @@ class Solution(object):
type n: int
rtype: int
"""
- # The number of full squares.
+ # The number of full/perfect squares.
return int(math.sqrt(n))
```
diff --git a/docs/Leetcode_Solutions/Python/322._Coin_Change.md b/docs/Leetcode_Solutions/Python/322._Coin_Change.md
new file mode 100644
index 000000000..dc7d8fc58
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/322._Coin_Change.md
@@ -0,0 +1,56 @@
+# 322. Coin Change
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/coin-change/description/
+
+> 内容描述
+
+```
+You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
+
+Example 1:
+
+Input: coins = [1, 2, 5], amount = 11
+Output: 3
+Explanation: 11 = 5 + 5 + 1
+Example 2:
+
+Input: coins = [2], amount = 3
+Output: -1
+Note:
+You may assume that you have an infinite number of each kind of coin.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N*amount)******- 空间复杂度: O(amount)******
+
+DP入门
+
+递推方程式: dp[i] = min(dp[i], dp[i-coins[j]]+1), coins[j] 是硬币的面额
+
+
+
+```python
+class Solution(object):
+ def coinChange(self, coins, amount):
+ """
+ :type coins: List[int]
+ :type amount: int
+ :rtype: int
+ """
+ dp = [amount+1] * (amount+1)
+ dp[0] = 0
+ for i in range(1, amount+1):
+ for j in range(len(coins)):
+ if coins[j] <= i:
+ dp[i] = min(dp[i], dp[i-coins[j]]+1)
+ return -1 if dp[-1] > amount else dp[-1]
+```
+
diff --git a/docs/leetcode/python/323._number_of_connected_components_in_an_undirected_graph.md b/docs/Leetcode_Solutions/Python/323._number_of_connected_components_in_an_undirected_graph.md
similarity index 97%
rename from docs/leetcode/python/323._number_of_connected_components_in_an_undirected_graph.md
rename to docs/Leetcode_Solutions/Python/323._number_of_connected_components_in_an_undirected_graph.md
index 9527b47df..c7d282ae4 100644
--- a/docs/leetcode/python/323._number_of_connected_components_in_an_undirected_graph.md
+++ b/docs/Leetcode_Solutions/Python/323._number_of_connected_components_in_an_undirected_graph.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph
+* https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/description/
> 内容描述
diff --git a/docs/leetcode/python/324._Wiggle_Sort_II.md b/docs/Leetcode_Solutions/Python/324._Wiggle_Sort_II.md
similarity index 100%
rename from docs/leetcode/python/324._Wiggle_Sort_II.md
rename to docs/Leetcode_Solutions/Python/324._Wiggle_Sort_II.md
diff --git a/docs/leetcode/python/326._power_of_three.md b/docs/Leetcode_Solutions/Python/326._power_of_three.md
similarity index 94%
rename from docs/leetcode/python/326._power_of_three.md
rename to docs/Leetcode_Solutions/Python/326._power_of_three.md
index 0059d10a4..9cd035d9c 100644
--- a/docs/leetcode/python/326._power_of_three.md
+++ b/docs/Leetcode_Solutions/Python/326._power_of_three.md
@@ -28,7 +28,7 @@ class Solution(object):
```
-有一个follow up,可否不用 loop/recursion
+有一个follow up,可否不用 loop/recusion
看到了取巧的办法,因为是Given an integer,是有范围的(<2147483648),存在能输入的最大的3的幂次,即 3^19=1162261467。
diff --git a/docs/leetcode/python/328._odd_even_linked_list.md b/docs/Leetcode_Solutions/Python/328._odd_even_linked_list.md
similarity index 99%
rename from docs/leetcode/python/328._odd_even_linked_list.md
rename to docs/Leetcode_Solutions/Python/328._odd_even_linked_list.md
index 893314630..b628ab241 100644
--- a/docs/leetcode/python/328._odd_even_linked_list.md
+++ b/docs/Leetcode_Solutions/Python/328._odd_even_linked_list.md
@@ -52,26 +52,26 @@ class Solution(object):
看别人的优雅代码
-```
-class Solution(object):
- def oddEvenList(self, head):
- """
- :type head: ListNode
- :rtype: ListNode
- """
- if head == None:
- return head
-
- # odd used to keep track of the tail of odd nodes
- odd = oddHead = head
- # record how many swaps happend
- even = evenHead = head.next
- while even and even.next:
- odd.next = even.next
- odd = odd.next
- even.next = odd.next
- even = even.next
- odd.next = evenHead
+```
+class Solution(object):
+ def oddEvenList(self, head):
+ """
+ :type head: ListNode
+ :rtype: ListNode
+ """
+ if head == None:
+ return head
+
+ # odd used to keep track of the tail of odd nodes
+ odd = oddHead = head
+ # record how many swaps happend
+ even = evenHead = head.next
+ while even and even.next:
+ odd.next = even.next
+ odd = odd.next
+ even.next = odd.next
+ even = even.next
+ odd.next = evenHead
return head
```
diff --git a/docs/leetcode/python/334._increasing_triplet_subsequence.md b/docs/Leetcode_Solutions/Python/334._increasing_triplet_subsequence.md
similarity index 100%
rename from docs/leetcode/python/334._increasing_triplet_subsequence.md
rename to docs/Leetcode_Solutions/Python/334._increasing_triplet_subsequence.md
diff --git a/docs/leetcode/python/337._house_robber_iii.md b/docs/Leetcode_Solutions/Python/337._house_robber_iii.md
similarity index 100%
rename from docs/leetcode/python/337._house_robber_iii.md
rename to docs/Leetcode_Solutions/Python/337._house_robber_iii.md
diff --git a/docs/Leetcode_Solutions/Python/338._Counting_Bits.md b/docs/Leetcode_Solutions/Python/338._Counting_Bits.md
new file mode 100644
index 000000000..e96e70c79
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/338._Counting_Bits.md
@@ -0,0 +1,132 @@
+# 338. Counting Bits
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/counting-bits/description/
+
+> 内容描述
+
+```
+Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.
+
+Example 1:
+
+Input: 2
+Output: [0,1,1]
+Example 2:
+
+Input: 5
+Output: [0,1,1,2,1,2]
+Follow up:
+
+It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
+Space complexity should be O(n).
+Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N*k) k is number of bits in num******- 空间复杂度: O(N)******
+
+
+
+**O(n\*sizeof(integer))** 算法,其实就是把count of 1 bit拿来用:
+
+```python
+class Solution(object):
+ def countBits(self, num):
+ """
+ :type num: int
+ :rtype: List[int]
+ """
+ def hammingWeight(n):
+ cnt = 0
+ while n != 0:
+ n &= n -1
+ cnt += 1
+ return cnt
+
+ res = []
+ for i in range(num+1):
+ res.append(hammingWeight(i))
+ return res
+
+```
+
+
+## Follow up:
+
+```It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
+Space complexity should be O(n).
+Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
+```
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+DP 算法
+
+DP 的思路其实不难,就是“把每天当成是末日来相待”,并且这一天发生的事能记下来就记下来。
+转换到实际问题上,就是把每一步都当时是最后一步来操作,然后沿途记下一些以后需要的数据即可。
+
+本题是求二进制数中`1`的个数,首先,创建一个数组`dp`,数组的索引`i`就是数字`i`,索引`i`对应的值就是数字`i`二进制数的`1`的个数。
+
+我们知道,任何一个十进制数字`num`都可以转换成二进制,并且,转换后的二进制长度是`x = floor(log(num, 2)) + 1`位,这`x`位数字除了第一位是`1`之外,其他位都是`0`或`1`。
+
+所以,可以把`num`拆成两个数的和,其中第一个数是`p = 2**(x-1)`,第二个数就是`num - p`。如果`num == p`, 因为`p = 2**(x-1)`中数字`1`的个数是`1`,那么此时`num`的二进制数中的`1`的个数就是`1`,即`dp[num] = 1`,否则,`dp[num] = dp[p] + dp[num-p]`(`num-p`一定小于`p`)。
+
+总结一下,关键点在于`c = a + b`,如何找到合适的`a`、`b`.
+
+
+
+首先只有一轮循环,在每一轮循环里面有log函数,但是基本上可以忽略不计,所以总时间复杂度为O(N),空间也为O(N)
+
+```python
+class Solution(object):
+ def countBits(self, num):
+ """
+ :type num: int
+ :rtype: List[int]
+ """
+ from math import floor, log
+ dp = [0] * (num+1)
+ for i in range(1, num+1):
+ x = floor(log(i, 2)) + 1
+ p = int(pow(2, x-1))
+ if p == i:
+ dp[i] = 1
+ else:
+ dp[i] = dp[p] + dp[i-p]
+ return dp
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+dp的另外一种方法,状态方程为 ```P(x) = P(x&(x-1)) + 1```
+
+beats 95.17%
+
+```python
+class Solution(object):
+ def countBits(self, num):
+ """
+ :type num: int
+ :rtype: List[int]
+ """
+ dp = [0] * (num+1)
+ for i in range(1, num+1):
+ dp[i] = dp[i&(i-1)] + 1
+ return dp
+```
+
+
+
+
+
+
diff --git a/docs/leetcode/python/339._Nested_List_Weight_Sum.md b/docs/Leetcode_Solutions/Python/339. Nested List Weight Sum.md
similarity index 100%
rename from docs/leetcode/python/339._Nested_List_Weight_Sum.md
rename to docs/Leetcode_Solutions/Python/339. Nested List Weight Sum.md
diff --git a/docs/Leetcode_Solutions/Python/340._Longest_Substring_with_At_Most_K_Distinct_Characters.md b/docs/Leetcode_Solutions/Python/340._Longest_Substring_with_At_Most_K_Distinct_Characters.md
new file mode 100644
index 000000000..832857c02
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/340._Longest_Substring_with_At_Most_K_Distinct_Characters.md
@@ -0,0 +1,59 @@
+# 340. Longest Substring with At Most K Distinct Characters
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/description/
+
+> 内容描述
+
+```
+
+Given a string, find the length of the longest substring T that contains at most k distinct characters.
+
+Example 1:
+
+Input: s = "eceba", k = 2
+Output: 3
+Explanation: T is "ece" which its length is 3.
+Example 2:
+
+Input: s = "aa", k = 1
+Output: 2
+Explanation: T is "aa" which its length is 2.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+思路见第159题
+
+```python
+class Solution(object):
+ def lengthOfLongestSubstringKDistinct(self, s, k):
+ """
+ :type s: str
+ :type k: int
+ :rtype: int
+ """
+ maps = {}
+ begin, end, counter, length = 0, 0, 0, 0
+ while end < len(s):
+ maps[s[end]] = maps.get(s[end], 0) + 1
+ if maps[s[end]] == 1:
+ counter += 1
+ end += 1 # end 永远指向下一个待处理的字符
+ while counter > k:
+ maps[s[begin]] -= 1
+ if maps[s[begin]] == 0:
+ counter -= 1
+ begin += 1
+ length = max(length, end - begin) # 因此这里是```end - begin```而不是```end - begin + 1```
+ return length
+```
diff --git a/docs/Leetcode_Solutions/Python/341._Flatten_Nested_List_Iterator.md b/docs/Leetcode_Solutions/Python/341._Flatten_Nested_List_Iterator.md
new file mode 100644
index 000000000..4ac6ac6c7
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/341._Flatten_Nested_List_Iterator.md
@@ -0,0 +1,115 @@
+# 341. Flatten Nested List Iterator
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/flatten-nested-list-iterator/description/
+
+> 内容描述
+
+```
+Given a nested list of integers, implement an iterator to flatten it.
+
+Each element is either an integer, or a list -- whose elements may also be integers or other lists.
+
+Example 1:
+
+Input: [[1,1],2,[1,1]]
+Output: [1,1,2,1,1]
+Explanation: By calling next repeatedly until hasNext returns false,
+ the order of elements returned by next should be: [1,1,2,1,1].
+Example 2:
+
+Input: [1,[4,[6]]]
+Output: [1,4,6]
+Explanation: By calling next repeatedly until hasNext returns false,
+ the order of elements returned by next should be: [1,4,6].
+```
+
+## 解题方案
+
+> 思路 1
+
+这个思路就是先把nestedList里面所有的Integer全部拿出来放到一个stack里面,next()就是简单的拿出下一个,hasNext()就是简单的看看还有没有下一个,但是这样会有一个不好的地方就是如果在现实中,我们的nestedList很大很大,然后我们可能只调用一次next(),那岂不是很亏吗。后面的解法会解决这个问题
+
+
+```python
+class NestedIterator(object):
+
+ def __init__(self, nestedList):
+ """
+ Initialize your data structure here.
+ :type nestedList: List[NestedInteger]
+ """
+ def dfs(nestedList):
+ for item in nestedList:
+ if item.isInteger():
+ self.stack.append(item.getInteger())
+ else:
+ dfs(item.getList())
+ self.stack = []
+ dfs(nestedList)
+
+
+ def next(self):
+ """
+ :rtype: int
+ """
+ if self.hasNext():
+ return self.stack.pop(0)
+
+
+ def hasNext(self):
+ """
+ :rtype: bool
+ """
+ return self.stack != []
+```
+
+> 思路 2
+
+参考大神[StefanPochmann](https://leetcode.com/problems/flatten-nested-list-iterator/discuss/80146/Real-iterator-in-Python-Java-C++)
+其实还是有一个stack,但是每次只把当前非空的nestedList加进来,然后递归嵌套调用的思想,取出最后一个。
+
+
+```python
+class NestedIterator(object):
+
+ def __init__(self, nestedList):
+ """
+ Initialize your data structure here.
+ :type nestedList: List[NestedInteger]
+ """
+ self.stack = [[nestedList, 0]]
+
+
+ def next(self):
+ """
+ :rtype: int
+ """
+ cur_nestedList, i = self.stack[-1]
+ self.stack[-1][1] += 1
+ return cur_nestedList[i]
+
+
+ def hasNext(self):
+ """
+ :rtype: bool
+ """
+ s = self.stack
+ while s:
+ cur_nestedList, i = s[-1]
+ if i == len(cur_nestedList):
+ s.pop()
+ else:
+ x = cur_nestedList[i]
+ if x.isInteger(): # x is a Integer
+ return True
+ else: # x is still a nestedList
+ s[-1][1] += 1
+ s.append([x.getList(), 0])
+ return False
+```
diff --git a/docs/leetcode/python/342._Power_of_Four.md b/docs/Leetcode_Solutions/Python/342._Power_of_Four.md
similarity index 100%
rename from docs/leetcode/python/342._Power_of_Four.md
rename to docs/Leetcode_Solutions/Python/342._Power_of_Four.md
diff --git a/docs/leetcode/python/344._reverse_string.md b/docs/Leetcode_Solutions/Python/344._reverse_string.md
similarity index 94%
rename from docs/leetcode/python/344._reverse_string.md
rename to docs/Leetcode_Solutions/Python/344._reverse_string.md
index 2346c22e6..0e4c0f4fb 100644
--- a/docs/leetcode/python/344._reverse_string.md
+++ b/docs/Leetcode_Solutions/Python/344._reverse_string.md
@@ -1,47 +1,47 @@
-### 344. Reverse String
-
-
-
-题目:
-
-
-
-难度:
-Easy
-
-思路:
-
-不要脸的python AC code:
-
-
-```python
-class Solution(object):
- def reverseString(self, s):
- """
- :type s: str
- :rtype: str
- """
- return s[::-1]
-```
-
-因为python不支持item assignment
-
-所以如果非要用two pointer来做的话,那么会是这样
-
-```python
-class Solution(object):
- def reverseString(self, s):
- """
- :type s: str
- :rtype: str
- """
- lst = list(s)
- n = len(lst)
- start, end = 0, n - 1
-
- while start < end:
- lst[end], lst[start] = lst[start],lst[end]
- start += 1
- end -= 1
- return ''.join(lst)
-```
+### 344. Reverse String
+
+
+
+题目:
+
+
+
+难度:
+Easy
+
+思路:
+
+不要脸的python AC code:
+
+
+```python
+class Solution(object):
+ def reverseString(self, s):
+ """
+ :type s: str
+ :rtype: str
+ """
+ return s[::-1]
+```
+
+因为python不支持item assignment
+
+所以如果非要用two pointer来做的话,那么会是这样
+
+```python
+class Solution(object):
+ def reverseString(self, s):
+ """
+ :type s: str
+ :rtype: str
+ """
+ lst = list(s)
+ n = len(lst)
+ start, end = 0, n - 1
+
+ while start < end:
+ lst[end], lst[start] = lst[start],lst[end]
+ start += 1
+ end -= 1
+ return ''.join(lst)
+```
diff --git a/docs/leetcode/python/345._Reverse_Vowels_of_a_String.md b/docs/Leetcode_Solutions/Python/345._Reverse_Vowels_of_a_String.md
similarity index 100%
rename from docs/leetcode/python/345._Reverse_Vowels_of_a_String.md
rename to docs/Leetcode_Solutions/Python/345._Reverse_Vowels_of_a_String.md
diff --git a/docs/Leetcode_Solutions/Python/347._Top_K_Frequent_Elements.md b/docs/Leetcode_Solutions/Python/347._Top_K_Frequent_Elements.md
new file mode 100644
index 000000000..db073ec64
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/347._Top_K_Frequent_Elements.md
@@ -0,0 +1,92 @@
+# 347. Top K Frequent Elements
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/top-k-frequent-elements/description/
+
+> 内容描述
+
+```
+Given a non-empty array of integers, return the k most frequent elements.
+
+Example 1:
+
+Input: nums = [1,1,1,2,2,3], k = 2
+Output: [1,2]
+Example 2:
+
+Input: nums = [1], k = 1
+Output: [1]
+Note:
+
+You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
+Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
+```
+
+## 解题方案
+
+> 思路 1
+
+思路就是我们先把对应的数字和其出现频次放到一个map里面,然后对这个maps里面的value()集合做一个for loop,这样我们就可以得到一个list,
+list里面的每一个元素代表的就是count为该对应index的key(即数字)的集合
+
+例如:
+```
+k = 2
+nums = [1,1,1,2,2,3,4,4]时,
+
+我们的maps就是{1: 3, 2: 2, 3: 1},
+然后我们新建一个buckets,
+- count为3的数字有1,我们就令bucktes[3] = [1],
+- count为2的数字有2和4,我们就令buckets[2] = [2,4]
+- count为1的数字有3,我们就令buckets[1] = [3]
+
+
+最后我们从bucktes的最后一个元素开始遍历,如果该元素不为初始化的'*'的话,我们就把当前元素(type list)的元素全部extend到res中去,最后返回res
+```
+
+
+时间复杂度为O(n)
+
+```python
+class Solution(object):
+ def topKFrequent(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: List[int]
+ """
+ res, maps, buckets = [], collections.Counter(nums), ['*'] * (len(nums)+1)
+
+ for key in maps.keys():
+ count = maps.get(key)
+ if buckets[count] == '*':
+ buckets[count] = []
+ buckets[count].append(key)
+ i = len(nums)
+ while len(res) < k and i >= 0:
+ if buckets[i] != '*':
+ res.extend(buckets[i])
+ i -= 1
+ return res
+```
+
+> 思路 2
+
+如果题目没有要求时间复杂度必须要优于o(nlgn)的话,下面这个解法真的🐂p
+
+
+```python
+class Solution(object):
+ def topKFrequent(self, nums, K):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: List[int]
+ """
+ return [k for k,v in sorted(collections.Counter(nums).items(), key=lambda (k,v): -v)][:K]
+```
diff --git a/docs/leetcode/python/349._intersection_of_two_arrays.md b/docs/Leetcode_Solutions/Python/349._intersection_of_two_arrays.md
similarity index 94%
rename from docs/leetcode/python/349._intersection_of_two_arrays.md
rename to docs/Leetcode_Solutions/Python/349._intersection_of_two_arrays.md
index eb4052736..2f79b8dd9 100644
--- a/docs/leetcode/python/349._intersection_of_two_arrays.md
+++ b/docs/Leetcode_Solutions/Python/349._intersection_of_two_arrays.md
@@ -1,25 +1,25 @@
-### 349. Intersection of Two Arrays
-
-题目:
-
-
-
-难度:
-
-Easy
-
-
-
-Python一句话作弊
-
-```python
-class Solution(object):
- def intersection(self, nums1, nums2):
- """
- :type nums1: List[int]
- :type nums2: List[int]
- :rtype: List[int]
- """
- return list(set(nums1).intersection(nums2))
-```
-
+### 349. Intersection of Two Arrays
+
+题目:
+
+
+
+难度:
+
+Easy
+
+
+
+Python一句话作弊
+
+```python
+class Solution(object):
+ def intersection(self, nums1, nums2):
+ """
+ :type nums1: List[int]
+ :type nums2: List[int]
+ :rtype: List[int]
+ """
+ return list(set(nums1).intersection(nums2))
+```
+
diff --git a/docs/leetcode/python/350._intersection_of_two_arrays_ii.md b/docs/Leetcode_Solutions/Python/350._intersection_of_two_arrays_ii.md
similarity index 94%
rename from docs/leetcode/python/350._intersection_of_two_arrays_ii.md
rename to docs/Leetcode_Solutions/Python/350._intersection_of_two_arrays_ii.md
index b386d9179..d2a444772 100644
--- a/docs/leetcode/python/350._intersection_of_two_arrays_ii.md
+++ b/docs/Leetcode_Solutions/Python/350._intersection_of_two_arrays_ii.md
@@ -1,65 +1,65 @@
-### 350. Intersection of Two Arrays II
-
-题目:
-
-
-
-
-难度:
-
-Easy
-
-
-sort之后用了双指针来走和看
-
-
-```python
-class Solution(object):
- def intersect(self, nums1, nums2):
- """
- :type nums1: List[int]
- :type nums2: List[int]
- :rtype: List[int]
- """
- nums1.sort()
- nums2.sort()
-
- l1 = len(nums1)
- l2 = len(nums2)
-
- p1 = 0
- p2 = 0
-
- res = []
-
- while p1 < l1 and p2 < l2:
- if nums1[p1] < nums2[p2]:
- p1 += 1
- elif nums1[p1] > nums2[p2]:
- p2 += 1
- else:
- res.append(nums1[p1])
- p1 += 1
- p2 += 1
- return res
-```
-
-两行版本
-```python
-class Solution(object):
- def intersect(self, nums1, nums2):
- """
- :type nums1: List[int]
- :type nums2: List[int]
- :rtype: List[int]
- """
- a, b = map(collections.Counter, (nums1, nums2))
- return list((a & b).elements())
-```
-
-
-
-
-
-
-
+### 350. Intersection of Two Arrays II
+
+题目:
+
+
+
+
+难度:
+
+Easy
+
+
+sort之后用了双指针来走和看
+
+
+```python
+class Solution(object):
+ def intersect(self, nums1, nums2):
+ """
+ :type nums1: List[int]
+ :type nums2: List[int]
+ :rtype: List[int]
+ """
+ nums1.sort()
+ nums2.sort()
+
+ l1 = len(nums1)
+ l2 = len(nums2)
+
+ p1 = 0
+ p2 = 0
+
+ res = []
+
+ while p1 < l1 and p2 < l2:
+ if nums1[p1] < nums2[p2]:
+ p1 += 1
+ elif nums1[p1] > nums2[p2]:
+ p2 += 1
+ else:
+ res.append(nums1[p1])
+ p1 += 1
+ p2 += 1
+ return res
+```
+
+两行版本
+```python
+class Solution(object):
+ def intersect(self, nums1, nums2):
+ """
+ :type nums1: List[int]
+ :type nums2: List[int]
+ :rtype: List[int]
+ """
+ a, b = map(collections.Counter, (nums1, nums2))
+ return list((a & b).elements())
+```
+
+
+
+
+
+
+
diff --git a/docs/leetcode/python/353._Design_Snake_Game.md b/docs/Leetcode_Solutions/Python/353. Design Snake Game.md
similarity index 100%
rename from docs/leetcode/python/353._Design_Snake_Game.md
rename to docs/Leetcode_Solutions/Python/353. Design Snake Game.md
diff --git a/docs/leetcode/python/361._Bomb_Enemy.md b/docs/Leetcode_Solutions/Python/361._Bomb_Enemy.md
similarity index 100%
rename from docs/leetcode/python/361._Bomb_Enemy.md
rename to docs/Leetcode_Solutions/Python/361._Bomb_Enemy.md
diff --git a/docs/leetcode/python/364._Nested_List_Weight_Sum_II.md b/docs/Leetcode_Solutions/Python/364. Nested List Weight Sum II.md
similarity index 100%
rename from docs/leetcode/python/364._Nested_List_Weight_Sum_II.md
rename to docs/Leetcode_Solutions/Python/364. Nested List Weight Sum II.md
diff --git a/docs/leetcode/python/366._Find_Leaves_of_Binary_Tree.md b/docs/Leetcode_Solutions/Python/366. Find Leaves of Binary Tree.md
similarity index 100%
rename from docs/leetcode/python/366._Find_Leaves_of_Binary_Tree.md
rename to docs/Leetcode_Solutions/Python/366. Find Leaves of Binary Tree.md
diff --git a/docs/leetcode/python/367._valid_perfect_square.md b/docs/Leetcode_Solutions/Python/367._valid_perfect_square.md
similarity index 98%
rename from docs/leetcode/python/367._valid_perfect_square.md
rename to docs/Leetcode_Solutions/Python/367._valid_perfect_square.md
index c51099284..7bb7285d4 100644
--- a/docs/leetcode/python/367._valid_perfect_square.md
+++ b/docs/Leetcode_Solutions/Python/367._valid_perfect_square.md
@@ -14,19 +14,19 @@ Medium
```
-class Solution(object):
- def isPerfectSquare(self, num):
- """
- :type num: int
- :rtype: bool
- """
- if num == 1 or num == 4 : return True
- for i in xrange(num//2):
- if i*i == num:
- return True
- elif i*i > num:
- return False
- return False
+class Solution(object):
+ def isPerfectSquare(self, num):
+ """
+ :type num: int
+ :rtype: bool
+ """
+ if num == 1 or num == 4 : return True
+ for i in xrange(num//2):
+ if i*i == num:
+ return True
+ elif i*i > num:
+ return False
+ return False
```
diff --git a/docs/leetcode/python/369._Plus_One_Linked_List.md b/docs/Leetcode_Solutions/Python/369.Plus One Linked List.md
similarity index 100%
rename from docs/leetcode/python/369._Plus_One_Linked_List.md
rename to docs/Leetcode_Solutions/Python/369.Plus One Linked List.md
diff --git a/docs/leetcode/python/371._sum_of_two_integers.md b/docs/Leetcode_Solutions/Python/371._sum_of_two_integers.md
similarity index 99%
rename from docs/leetcode/python/371._sum_of_two_integers.md
rename to docs/Leetcode_Solutions/Python/371._sum_of_two_integers.md
index f7e949deb..675aa9724 100644
--- a/docs/leetcode/python/371._sum_of_two_integers.md
+++ b/docs/Leetcode_Solutions/Python/371._sum_of_two_integers.md
@@ -44,16 +44,16 @@ x y output
python没有左移,用c++来看
```
-class Solution {
-public:
- int getSum(int a, int b) {
- while (b != 0 ){
- int c = a & b;
- a = a ^ b;
- b = c << 1;
- }
- return a;
- }
+class Solution {
+public:
+ int getSum(int a, int b) {
+ while (b != 0 ){
+ int c = a & b;
+ a = a ^ b;
+ b = c << 1;
+ }
+ return a;
+ }
};
```
diff --git a/docs/leetcode/python/374._Guess_Number_Higher_or_Lower.md b/docs/Leetcode_Solutions/Python/374._Guess_Number_Higher_or_Lower.md
similarity index 100%
rename from docs/leetcode/python/374._Guess_Number_Higher_or_Lower.md
rename to docs/Leetcode_Solutions/Python/374._Guess_Number_Higher_or_Lower.md
diff --git a/docs/leetcode/python/377._combination_sum_iv.md b/docs/Leetcode_Solutions/Python/377._combination_sum_iv.md
similarity index 100%
rename from docs/leetcode/python/377._combination_sum_iv.md
rename to docs/Leetcode_Solutions/Python/377._combination_sum_iv.md
diff --git a/docs/leetcode/python/378._kth_smallest_element_in_a_sorted_matrix.md b/docs/Leetcode_Solutions/Python/378._kth_smallest_element_in_a_sorted_matrix.md
similarity index 100%
rename from docs/leetcode/python/378._kth_smallest_element_in_a_sorted_matrix.md
rename to docs/Leetcode_Solutions/Python/378._kth_smallest_element_in_a_sorted_matrix.md
diff --git a/docs/Leetcode_Solutions/Python/380._Insert_Delete_GetRandom_O(1).md b/docs/Leetcode_Solutions/Python/380._Insert_Delete_GetRandom_O(1).md
new file mode 100644
index 000000000..1b6113eaa
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/380._Insert_Delete_GetRandom_O(1).md
@@ -0,0 +1,147 @@
+# 380. Insert Delete GetRandom O(1)
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/insert-delete-getrandom-o1/description/
+
+> 内容描述
+
+```
+Design a data structure that supports all following operations in average O(1) time.
+
+insert(val): Inserts an item val to the set if not already present.
+remove(val): Removes an item val from the set if present.
+getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.
+Example:
+
+// Init an empty set.
+RandomizedSet randomSet = new RandomizedSet();
+
+// Inserts 1 to the set. Returns true as 1 was inserted successfully.
+randomSet.insert(1);
+
+// Returns false as 2 does not exist in the set.
+randomSet.remove(2);
+
+// Inserts 2 to the set, returns true. Set now contains [1,2].
+randomSet.insert(2);
+
+// getRandom should return either 1 or 2 randomly.
+randomSet.getRandom();
+
+// Removes 1 from the set, returns true. Set now contains [2].
+randomSet.remove(1);
+
+// 2 was already in the set, so return false.
+randomSet.insert(2);
+
+// Since 2 is the only number in the set, getRandom always return 2.
+randomSet.getRandom();
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(1)******- 空间复杂度: O(N)******
+
+
+
+因为对于插入,删除还有同可能性返回数都要O(1),我们知道以下几种典型的数据结构
+```
+dictionary
+list
+set
+LinkedList
+```
+想要删除确定数字必须要知道数字的index,所以list肯定需要,然后怎么通过O(1)时间得到要删除元素的index呢?
+
+mock的时候我没有想出来,墨汁大佬给了hint才想出来的
+
+然后我就想到用字典,key,value分别是element和其index
+
+然后想要O(1)时间同可能性返回数都要,必须要知道总共有多少个数字,那么就要维护一个self.length才行
+
+
+
+
+
+
+```python
+import random
+class RandomizedSet(object):
+
+ def __init__(self):
+ """
+ Initialize your data structure here.
+ """
+ self.cache = {}
+ self.lst = []
+ self.length = 0
+
+
+ def insert(self, val):
+ """
+ Inserts a value to the set. Returns true if the set did not already contain the specified element.
+ :type val: int
+ :rtype: bool
+ """
+ # if this element is not in our RandomizedSet
+ if val not in self.cache:
+ # just insert into both of our self.cache and self.lst
+ self.cache[val] = self.length
+ self.lst.append(val)
+ self.length += 1
+ return True
+ else:
+ return False
+
+
+ def remove(self, val):
+ """
+ Removes a value from the set. Returns true if the set contained the specified element.
+ :type val: int
+ :rtype: bool
+ """
+ # if the elment is in our RandomizedSet
+ if val in self.cache:
+ # get the index of element in our self.lst
+ idx = self.cache[val]
+ # use the index to update our self.lst
+ self.lst[idx] = self.lst[-1] # swap the value in index and self.length-1
+ # this should be done before pop() operation
+ # because we may only have one element is self.lst
+ self.cache[self.lst[idx]] = idx
+ self.lst.pop()
+ del self.cache[val]
+ self.length -= 1
+ return True
+ else:
+ return False
+
+
+ def getRandom(self):
+ """
+ Get a random element from the set.
+ :rtype: int
+ """
+ # 这种是常规方法
+ # idx = random.randint(0, self.length-1)
+ # return self.lst[idx]
+ # 神奇函数
+ return random.choice(self.lst)
+
+
+
+# Your RandomizedSet object will be instantiated and called as such:
+# obj = RandomizedSet()
+# param_1 = obj.insert(val)
+# param_2 = obj.remove(val)
+# param_3 = obj.getRandom()
+```
+
+
+
diff --git a/docs/leetcode/python/381._Insert_Delete_GetRandom_O(1)_-_Duplicates_allowed.md b/docs/Leetcode_Solutions/Python/381. Insert Delete GetRandom O(1) - Duplicates allowed.md
similarity index 100%
rename from docs/leetcode/python/381._Insert_Delete_GetRandom_O(1)_-_Duplicates_allowed.md
rename to docs/Leetcode_Solutions/Python/381. Insert Delete GetRandom O(1) - Duplicates allowed.md
diff --git a/docs/leetcode/python/382._linked_list_random_node.md b/docs/Leetcode_Solutions/Python/382._linked_list_random_node.md
similarity index 100%
rename from docs/leetcode/python/382._linked_list_random_node.md
rename to docs/Leetcode_Solutions/Python/382._linked_list_random_node.md
diff --git a/docs/leetcode/python/383._ransom_note.md b/docs/Leetcode_Solutions/Python/383._ransom_note.md
similarity index 95%
rename from docs/leetcode/python/383._ransom_note.md
rename to docs/Leetcode_Solutions/Python/383._ransom_note.md
index 82fc223d6..6a6ee16e7 100644
--- a/docs/leetcode/python/383._ransom_note.md
+++ b/docs/Leetcode_Solutions/Python/383._ransom_note.md
@@ -1,53 +1,53 @@
-### 383. Ransom Note
-
-题目:
-
-
-
-难度 : Easy
-
-
-
-略微想了一下,用了一个dictionary来存magazine里面的单字出现的个数,然后来对应check是否可以用来组成ransomNote
-
-
-```python
-class Solution(object):
- def canConstruct(self, ransomNote, magazine):
- """
- :type ransomNote: str
- :type magazine: str
- :rtype: bool
- """
- maps = {}
- for i in magazine:
- if i in maps:
- maps[i] += 1
- else:
- maps[i] = 1
- for i in ransomNote:
- if i not in maps:
- return False
- else:
- maps[i] -= 1
- if maps[i] < 0:
- return False
- return True
-```
-解法2:
-
-```python
-class Solution(object):
- def canConstruct(self, ransomNote, magazine):
- """
- :type ransomNote: str
- :type magazine: str
- :rtype: bool
- """
- magCounter = collections.Counter(magazine)
- ranCounter = collections.Counter(ransomNote)
- for k in ranCounter:
- if ranCounter.get(k) > magCounter.get(k):
- return False
- return True
-```
+### 383. Ransom Note
+
+题目:
+
+
+
+难度 : Easy
+
+
+
+略微想了一下,用了一个dictionary来存magazine里面的单字出现的个数,然后来对应check是否可以用来组成ransomNote
+
+
+```python
+class Solution(object):
+ def canConstruct(self, ransomNote, magazine):
+ """
+ :type ransomNote: str
+ :type magazine: str
+ :rtype: bool
+ """
+ maps = {}
+ for i in magazine:
+ if i in maps:
+ maps[i] += 1
+ else:
+ maps[i] = 1
+ for i in ransomNote:
+ if i not in maps:
+ return False
+ else:
+ maps[i] -= 1
+ if maps[i] < 0:
+ return False
+ return True
+```
+解法2:
+
+```python
+class Solution(object):
+ def canConstruct(self, ransomNote, magazine):
+ """
+ :type ransomNote: str
+ :type magazine: str
+ :rtype: bool
+ """
+ magCounter = collections.Counter(magazine)
+ ranCounter = collections.Counter(ransomNote)
+ for k in ranCounter:
+ if ranCounter.get(k) > magCounter.get(k):
+ return False
+ return True
+```
diff --git a/docs/leetcode/python/384._Shuffle_an_Array.md b/docs/Leetcode_Solutions/Python/384. Shuffle an Array.md
similarity index 100%
rename from docs/leetcode/python/384._Shuffle_an_Array.md
rename to docs/Leetcode_Solutions/Python/384. Shuffle an Array.md
diff --git a/docs/leetcode/python/386._Lexicographical_Numbers.md b/docs/Leetcode_Solutions/Python/386._Lexicographical_Numbers.md
similarity index 93%
rename from docs/leetcode/python/386._Lexicographical_Numbers.md
rename to docs/Leetcode_Solutions/Python/386._Lexicographical_Numbers.md
index 95eff4ca0..beceeab5a 100644
--- a/docs/leetcode/python/386._Lexicographical_Numbers.md
+++ b/docs/Leetcode_Solutions/Python/386._Lexicographical_Numbers.md
@@ -6,8 +6,8 @@
> 原题连接
-* https://leetcode.com/problems/lexicographical-numbers
-* https://leetcode-cn.com/problems/lexicographical-numbers
+* https://leetcode.com/problems/lexicographical-numbers/description/
+* https://leetcode-cn.com/problems/lexicographical-numbers/description/
> 内容描述
diff --git a/docs/leetcode/python/387._first_unique_character_in_a_string.md b/docs/Leetcode_Solutions/Python/387._first_unique_character_in_a_string.md
similarity index 100%
rename from docs/leetcode/python/387._first_unique_character_in_a_string.md
rename to docs/Leetcode_Solutions/Python/387._first_unique_character_in_a_string.md
diff --git a/docs/Leetcode_Solutions/Python/388._Longest_Absolute_File_Path.md b/docs/Leetcode_Solutions/Python/388._Longest_Absolute_File_Path.md
new file mode 100644
index 000000000..9e1d12614
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/388._Longest_Absolute_File_Path.md
@@ -0,0 +1,132 @@
+# 388. Longest Absolute File Path
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/longest-absolute-file-path/description/
+
+> 内容描述
+
+```
+Suppose we abstract our file system by a string in the following manner:
+
+The string "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" represents:
+
+dir
+ subdir1
+ subdir2
+ file.ext
+The directory dir contains an empty sub-directory subdir1 and a sub-directory subdir2 containing a file file.ext.
+
+The string "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" represents:
+
+dir
+ subdir1
+ file1.ext
+ subsubdir1
+ subdir2
+ subsubdir2
+ file2.ext
+The directory dir contains two sub-directories subdir1 and subdir2. subdir1 contains a file file1.ext and an empty second-level sub-directory subsubdir1. subdir2 contains a second-level sub-directory subsubdir2 containing a file file2.ext.
+
+We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length is 32 (not including the double quotes).
+
+Given a string representing the file system in the above format, return the length of the longest absolute path to file in the abstracted file system. If there is no file in the system, return 0.
+
+Note:
+The name of a file contains at least a . and an extension.
+The name of a directory or sub-directory will not contain a ..
+Time complexity required: O(n) where n is the size of the input string.
+
+Notice that a/aa/aaa/file1.txt is not the longest file path, if there is another path aaaaaaaaaaaaaaaaaaaaa/sth.png.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+我们首先观察到每个```文件夹```或者是```文件```前面都会有一个```'\n'```, 还有对应其层数个数的```'\t'```.
+- 所以首先根据```'\n'```分行,然后算出该```文件/文件夹```的层数```depth```
+- 如果是```文件```,我们需要更新```maxlen```
+- 如果是```文件夹```,我们需要更新该```depth```下的```pathlen```
+
+### 程序变量解释
+
+- ```maxlen``` 代表目前最大子串的长度
+- ```pathlen``` 每一个```depth```下对应的```path```长度
+
+#### 特别需要注意的是,```'\t'```的长度是1
+有的人仍然会有疑问,每次碰到文件夹都直接更新```pathlen```会不会导致本来长的反而变得短了,但是我们可以看到字符串的排版格式,每层```path```都是严格有自己的分级的,
+因此不会出现这样的问题。
+例如:
+- The string ```"dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"``` represents:
+```
+dir
+ subdir1
+ file1.ext
+ subsubdir1
+ subdir2
+ subsubdir2
+ file2.ext
+```
+其最大长度是```32```, ```"dir/subdir2/subsubdir2/file2.ext"```
+
+- 如果变成```"dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir20\n\t\tsubsubdir2\n\t\t\tfile2.ext"```,
+
+```
+dir
+ subdir1
+ file1.ext
+ subsubdir1
+ subdir20
+ subsubdir2
+ file2.ext
+```
+
+最大长度就是```33```,
+```"dir/subdir2/subsubdir20/file2.ext"```
+
+
+- 如果变成
+```"dir\n\tsubdir1000000000000\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"```
+
+```
+dir
+ subdir10000000000000
+ file1.ext
+ subsubdir1
+ subdir20
+ subsubdir2
+ file2.ext
+```
+
+最大长度就是```34```,```"dir/subdir10000000000000/file1.ext"```
+
+beats 99.66%
+
+```python
+class Solution(object):
+ def lengthLongestPath(self, input):
+ """
+ :type input: str
+ :rtype: int
+ """
+ lap = 0
+ depth_len = {0: 0}
+ for line in input.splitlines():
+ name = line.lstrip('\t')
+ # 前面有几个'\t', depth就是几, 因为'\t'的长度为1
+ depth = len(line) - len(name)
+ if '.' in name:
+ lap = max(lap, depth_len[depth]+len(name))
+ else:
+ # 加1是为了加上一个path分隔符'/'的长度
+ depth_len[depth+1] = depth_len[depth] + 1 + len(name)
+ return lap
+```
+
+
diff --git a/docs/leetcode/python/389._find_the_difference.md b/docs/Leetcode_Solutions/Python/389._find_the_difference.md
similarity index 100%
rename from docs/leetcode/python/389._find_the_difference.md
rename to docs/Leetcode_Solutions/Python/389._find_the_difference.md
diff --git a/docs/Leetcode_Solutions/Python/392._is_subsequence.md b/docs/Leetcode_Solutions/Python/392._is_subsequence.md
new file mode 100644
index 000000000..84297dd49
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/392._is_subsequence.md
@@ -0,0 +1,185 @@
+# 392. Is Subsequence
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/is-subsequence/description/
+
+> 内容描述
+
+```
+
+Given a string s and a string t, check if s is subsequence of t.
+
+You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).
+
+A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not).
+
+Example 1:
+s = "abc", t = "ahbgdc"
+
+Return true.
+
+Example 2:
+s = "axc", t = "ahbgdc"
+
+Return false.
+
+Follow up:
+If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(len(s)+len(t))******- 空间复杂度: O(1)******
+
+
+最naive的思路是递归,原来可以beats 53.74%
+
+
+但是今天上来发现多了case,超时过不了了
+
+时间复杂度为O(len(s)+len(t))
+
+
+
+
+```
+class Solution(object):
+ def isSubsequence(self, s, t):
+ """
+ :type s: str
+ :type t: str
+ :rtype: bool
+ """
+ if s == '':
+ return True
+ for i in range(len(t)):
+ if t[i] == s[0]:
+ return self.isSubsequence(s[1:],t[i+1:])
+
+ return False
+```
+
+> 思路 2
+******- 时间复杂度: O(max(len(s), len(t)))******- 空间复杂度: O(1)******
+
+因为递归操作以及对字符串的操作太过于昂贵,所以用index来处理,节省了时间和空间
+
+时间复杂度是O(max(len(s), len(t)))
+
+beats 40%
+
+
+```python
+class Solution(object):
+ def isSubsequence(self, s, t):
+ """
+ :type s: str
+ :type t: str
+ :rtype: bool
+ """
+ if s == '':
+ return True
+ ps, pt = 0, 0
+ while ps < len(s) and pt < len(t):
+ if s[ps] == t[pt]:
+ ps += 1
+ pt += 1
+ return ps >= len(s)
+```
+> 思路 3
+******- 时间复杂度: O(len(t))******- 空间复杂度: O(1)******
+
+
+想到说对于每一个s中的字符,看看在不在,找到了就记录一下t的当前位置idx,下次从t的idx+1后面开始找
+
+
+```python
+class Solution(object):
+ def isSubsequence(self, s, t):
+ """
+ :type s: str
+ :type t: str
+ :rtype: bool
+ """
+ idx = 0
+ for c in s:
+ idx = t.find(c, idx)
+ if idx == -1:
+ return False
+ idx += 1
+ return True
+```
+
+## follow up question
+```
+If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?
+```
+
+> 思路 1
+******- 时间复杂度: O(lt+k*ms*O(lg(lt)))******- 空间复杂度: O(lt)******
+
+我们可以先把t里面的所有字符和其出现的idx的list分别作为key和value放进一个字典里面
+
+然后对于s中的每个字符,我们要做两步判断:
+1. 如果这个字符不在字典里面,直接返回False
+2. 如果这个字符在字典里面,那我们就看看我们在这个字符在t里面出现的idx的list里面是不是有比上一个字符的idx更大的idx,
+
+例如对于输入
+```
+"abc"
+"ahbgdc"
+```
+
+```
+首先初始化idx为-1
+lookup = {'a': [0], 'c': [5], 'b': [2], 'd': [4], 'g': [3], 'h': [1]}
+我们先找字符a,发现a在lookup里面的list为[0],并且里面存在比idx -1更大的元素,所以我们找到了字符a,更新 idx为1,意味着下一个字符要从t的idx 1开始找
+开始找字符b,发现b在lookup里面的list为[2],并且里面存在比idx 1更大的元素,所以我们找到了字符b,更新idx 为3,意味着下一个字符要从t的idx 3开始找
+开始找字符c,发现c在lookup里面的list为[5],并且里面存在比idx 3更大的元素,所以我们找到了字符c,更新idx 为6,意味着下一个字符要从t的idx 6开始找
+
+但是此时所有字符都已经找到,直接返回True
+```
+
+假设t的长度为lt,s的长度为ls,一共有k个s(假设最长的一个s长度为ms)
+
+我们只需要最开始对整个t做一个遍历,时间复杂度为O(lt),同时用了一个字典,空间复杂度为O(lt),
+
+然后对于每一个s的每一个字符,我们都只需要进行一个二分查找,时间复杂度为O(lg(lt)),因为最坏有可能t只有一个字符,它在字典里面对应的list的长度就是lt
+
+因此最终的时间复杂度为O(lt+k*ms*O(lg(lt))),时间复杂度为O(lt)
+
+
+```python
+class Solution(object):
+ def isSubsequence(self, s, t):
+ """
+ :type s: str
+ :type t: str
+ :rtype: bool
+ """
+ lookup = {}
+ for i in range(len(t)):
+ if t[i] in lookup:
+ lookup[t[i]].append(i)
+ else:
+ lookup[t[i]] = [i]
+ idx = -1
+ for c in s:
+ if c not in lookup:
+ return False
+ else:
+ c_idx = bisect.bisect_left(lookup[c], idx)
+ if c_idx == len(lookup[c]): # this means we don't find next char of s in t
+ return False
+ idx = lookup[c][c_idx] + 1 # we have to find next char from the prev char's index + 1
+ return True
+```
+
+
+
+
diff --git a/docs/leetcode/python/394._decode_string.md b/docs/Leetcode_Solutions/Python/394._decode_string.md
similarity index 100%
rename from docs/leetcode/python/394._decode_string.md
rename to docs/Leetcode_Solutions/Python/394._decode_string.md
diff --git a/docs/Leetcode_Solutions/Python/400._Nth_Digit.md b/docs/Leetcode_Solutions/Python/400._Nth_Digit.md
new file mode 100644
index 000000000..5dd5f3ccb
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/400._Nth_Digit.md
@@ -0,0 +1,113 @@
+# 400. Nth Digit
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/nth-digit/description/
+
+> 内容描述
+
+```
+Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...
+
+Note:
+n is positive and will fit within the range of a 32-bit signed integer (n < 231).
+
+Example 1:
+
+Input:
+3
+
+Output:
+3
+Example 2:
+
+Input:
+11
+
+Output:
+0
+
+Explanation:
+The 11th digit of the sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... is a 0, which is part of the number 10.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(lgn)******- 空间复杂度: O(1)******
+
+
+
+这道简单题我服, tag是math,找规律
+
+```
+1- 9 : 9 → 只占1位 9
+10 - 99: 90 → 两位 90 * 2
+100 - 999: 900 → 三位 900 * 3
+1000 - 9999: 9000 → 四位 9000 * 4
+```
+参考微信大佬[caitao7](https://leetcode.com/haitao7/)的代码,加了注释,修改了变量名
+
+```python
+class Solution(object):
+ def findNthDigit(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ digits_count = 1 # 当前区间数字的位数
+ while n >= 9 * 10 ** (digits_count-1) * digits_count:
+ n -= 9 * 10 ** (digits_count-1) * digits_count
+ digits_count += 1
+ target_num = 10 ** (digits_count-1) - 1 + n // digits_count # 我们要从这个数字上面取digit
+ target_digit = n % digits_count # 我们要从这个数字上面取第几位digit
+ if target_digit == 0: # 取第0位digit其实就是说这个数字的个数位刚好到达我们的第n位digit
+ return target_num % 10
+ return ((target_num+1) / 10 ** (digits_count-target_digit)) % 10
+```
+
+
+> 思路 2
+******- 时间复杂度: O(lgn)******- 空间复杂度: O(1)******
+
+改进[agave](https://leetcode.com/problems/nth-digit/discuss/88417/4-liner-in-Python-and-complexity-analysis)大神的解法
+
+So we can "fast-skip" those numbers until we find the size of the number that will hold our digit.
+At the end of the loop, we will have:
+
+- start: first number of size size (will be power of 10)
+- n: will be the number of digits that we need to count after start
+
+How do we get the number that will hold the digit? It will be start + (n - 1) // size (we use n - 1 because we need zero-based index). Once we have that number, we can get the ```[(n - 1) % size]-th``` digit of that number, and that will be our result.
+
+```python
+class Solution(object):
+ def findNthDigit(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ start, size, step = 1, 1, 9
+ while n > size * step:
+ n -= size * step
+ start, size, step = start * 10, size + 1, step * 10
+ num = start + (n - 1) // size # 所要取的数字,(n - 1) % size为取该数字的第几位
+ mod = 0
+ for i in range(size - (n - 1) % size):
+ mod = num % 10
+ num /= 10
+ return mod
+```
+
+The while loop takes O(log(n)) time because a number n will have at most O(log(n)) digits. Then the return statement takes O(log(n)) time to convert the number to string. So total time complexity is O(log(n)), with O(1) extra space for the string.
+
+
+
+
+
+
+
diff --git a/docs/leetcode/python/401._binary_watch.md b/docs/Leetcode_Solutions/Python/401._binary_watch.md
similarity index 100%
rename from docs/leetcode/python/401._binary_watch.md
rename to docs/Leetcode_Solutions/Python/401._binary_watch.md
diff --git a/docs/Leetcode_Solutions/Python/403._Frog_Jump.md b/docs/Leetcode_Solutions/Python/403._Frog_Jump.md
new file mode 100644
index 000000000..df9f9038d
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/403._Frog_Jump.md
@@ -0,0 +1,161 @@
+# 403. Frog Jump
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/frog-jump/description/
+
+> 内容描述
+
+```
+A frog is crossing a river. The river is divided into x units and at each unit there may or may not exist a stone. The frog can jump on a stone, but it must not jump into the water.
+
+Given a list of stones' positions (in units) in sorted ascending order, determine if the frog is able to cross the river by landing on the last stone. Initially, the frog is on the first stone and assume the first jump must be 1 unit.
+
+If the frog's last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. Note that the frog can only jump in the forward direction.
+
+Note:
+
+The number of stones is ≥ 2 and is < 1,100.
+Each stone's position will be a non-negative integer < 231.
+The first stone's position is always 0.
+Example 1:
+
+[0,1,3,5,6,8,12,17]
+
+There are a total of 8 stones.
+The first stone at the 0th unit, second stone at the 1st unit,
+third stone at the 3rd unit, and so on...
+The last stone at the 17th unit.
+
+Return true. The frog can jump to the last stone by jumping
+1 unit to the 2nd stone, then 2 units to the 3rd stone, then
+2 units to the 4th stone, then 3 units to the 6th stone,
+4 units to the 7th stone, and 5 units to the 8th stone.
+Example 2:
+
+[0,1,2,3,4,8,9,11]
+
+Return false. There is no way to jump to the last stone as
+the gap between the 5th and 6th stone is too large.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N^3)******- 空间复杂度: O(N^2)******
+
+这个题目肯定要用dp来做的
+
+然后我开始找了一个方法,就是让dp[x][y]代表我们可以到达stone x,我们是否可以到达z
+
+所以初始值就是dp[0][1] = 1
+
+如果```dp[x][y] == 1```的话,并且对于一个```z```大于```y```,如果```abs((stones[z] - stones[y]) - (stones[y) - stones[x)) <= 1```,
+那么```dp[y][z] = 1```
+
+但是超时了
+
+```python
+class Solution(object):
+ def canCross(self, stones):
+ """
+ :type stones: List[int]
+ :rtype: bool
+ """
+ if stones[1] != 1:
+ return False
+
+ dp = [[0] * len(stones) for i in range(len(stones))]
+ dp[0][1] = 1
+ for y in range(1, len(stones)):
+ for x in range(y):
+ for z in range(y+1, len(stones)):
+ if not dp[x][y]:
+ continue
+ else:
+ if abs((stones[z]-stones[y])-(stones[y]-stones[x])) <= 1:
+ if z == len(stones)-1:
+ return True
+ dp[y][z] = 1
+ for i in range(len(dp)):
+ if dp[i][-1]:
+ return True
+ return False
+```
+
+
+
+
+
+> 思路 2
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N^2)******
+
+于是想到了另外一种dp,用一个字典,存的key和value分别是stone 的位置和从该位置能跳的步数的set
+
+初始值位置0的value只有1,那么初始位置1的value有(0,1,2)
+
+最后我们看看,如果有哪个位置和其value中的任意一个步数的和可以凑齐最后一个位置,那么最后一个位置可达
+
+但是这样不是很好判断,其实如果最后一个位置对应的value set非空的话也说明最后一个位置可达,因为不可达我们对其误操作,其value set必为空
+
+beats 66.77%
+```python
+class Solution(object):
+ def canCross(self, stones):
+ """
+ :type stones: List[int]
+ :rtype: bool
+ """
+ lookup = {}
+ for i in range(len(stones)):
+ lookup[stones[i]] = set()
+ lookup[0].add(1)
+
+ for i in range(len(stones)):
+ for step in lookup[stones[i]]:
+ if step > 0 and stones[i] + step in lookup:
+ # lookup[stones[i]+step] = lookup[stones[i]+step].union(set([step-1,step,step+1]))
+ lookup[stones[i]+step].update([step-1,step,step+1])
+ return len(lookup[stones[-1]]) > 0
+```
+
+或者将value看作可以到达该key的步数,beats 47.71%
+
+```python
+class Solution(object):
+ def canCross(self, stones):
+ """
+ :type stones: List[int]
+ :rtype: bool
+ """
+ lookup = {}
+ for i in range(len(stones)):
+ lookup[stones[i]] = set()
+ lookup[0].add(0)
+
+ for i in range(len(stones)):
+ for k in lookup[stones[i]]:
+ for step in (k-1,k,k+1):
+ if step > 0 and stones[i] + step in lookup:
+ lookup[stones[i]+step].add(step)
+ return len(lookup[stones[-1]]) > 0
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/leetcode/python/404._sum_of_left_leaves.md b/docs/Leetcode_Solutions/Python/404._sum_of_left_leaves.md
similarity index 100%
rename from docs/leetcode/python/404._sum_of_left_leaves.md
rename to docs/Leetcode_Solutions/Python/404._sum_of_left_leaves.md
diff --git a/docs/leetcode/python/405._Convert_a_Number_to_Hexadecimal.md b/docs/Leetcode_Solutions/Python/405. Convert a Number to Hexadecimal.md
similarity index 100%
rename from docs/leetcode/python/405._Convert_a_Number_to_Hexadecimal.md
rename to docs/Leetcode_Solutions/Python/405. Convert a Number to Hexadecimal.md
diff --git a/docs/leetcode/python/406._Queue_Reconstruction_by_Height.md b/docs/Leetcode_Solutions/Python/406._Queue_Reconstruction_by_Height.md
similarity index 100%
rename from docs/leetcode/python/406._Queue_Reconstruction_by_Height.md
rename to docs/Leetcode_Solutions/Python/406._Queue_Reconstruction_by_Height.md
diff --git a/docs/leetcode/python/412._fizz_buzz.md b/docs/Leetcode_Solutions/Python/412._fizz_buzz.md
similarity index 100%
rename from docs/leetcode/python/412._fizz_buzz.md
rename to docs/Leetcode_Solutions/Python/412._fizz_buzz.md
diff --git a/docs/leetcode/python/413._Arithmetic_Slices.md b/docs/Leetcode_Solutions/Python/413. Arithmetic Slices.md
similarity index 100%
rename from docs/leetcode/python/413._Arithmetic_Slices.md
rename to docs/Leetcode_Solutions/Python/413. Arithmetic Slices.md
diff --git a/docs/leetcode/python/414._third_maximum_number.md b/docs/Leetcode_Solutions/Python/414._third_maximum_number.md
similarity index 100%
rename from docs/leetcode/python/414._third_maximum_number.md
rename to docs/Leetcode_Solutions/Python/414._third_maximum_number.md
diff --git a/docs/leetcode/python/415._add_strings.md b/docs/Leetcode_Solutions/Python/415._add_strings.md
similarity index 94%
rename from docs/leetcode/python/415._add_strings.md
rename to docs/Leetcode_Solutions/Python/415._add_strings.md
index 4c7be7b0a..95663f8e2 100644
--- a/docs/leetcode/python/415._add_strings.md
+++ b/docs/Leetcode_Solutions/Python/415._add_strings.md
@@ -6,7 +6,7 @@
> 原题连接
-* https://leetcode.com/problems/add-strings
+* https://leetcode.com/problems/add-strings/description/
> 内容描述
diff --git a/docs/leetcode/python/416._Partition_Equal_Subset_Sum.md b/docs/Leetcode_Solutions/Python/416._Partition_Equal_Subset_Sum.md
similarity index 95%
rename from docs/leetcode/python/416._Partition_Equal_Subset_Sum.md
rename to docs/Leetcode_Solutions/Python/416._Partition_Equal_Subset_Sum.md
index 045089748..1dd92f5fa 100644
--- a/docs/leetcode/python/416._Partition_Equal_Subset_Sum.md
+++ b/docs/Leetcode_Solutions/Python/416._Partition_Equal_Subset_Sum.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/partition-equal-subset-sum
+* https://leetcode.com/problems/partition-equal-subset-sum/description/
> 内容描述
diff --git a/docs/leetcode/python/421._Maximum_XOR_of_Two_Numbers_in_an_Array.md b/docs/Leetcode_Solutions/Python/421._Maximum_XOR_of_Two_Numbers_in_an_Array.md
similarity index 100%
rename from docs/leetcode/python/421._Maximum_XOR_of_Two_Numbers_in_an_Array.md
rename to docs/Leetcode_Solutions/Python/421._Maximum_XOR_of_Two_Numbers_in_an_Array.md
diff --git a/docs/leetcode/python/422._Valid_Word_Square.md b/docs/Leetcode_Solutions/Python/422. Valid Word Square.md
similarity index 100%
rename from docs/leetcode/python/422._Valid_Word_Square.md
rename to docs/Leetcode_Solutions/Python/422. Valid Word Square.md
diff --git a/docs/Leetcode_Solutions/Python/424._Longest_Repeating_Character_Replacement.md b/docs/Leetcode_Solutions/Python/424._Longest_Repeating_Character_Replacement.md
new file mode 100644
index 000000000..5bebbafea
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/424._Longest_Repeating_Character_Replacement.md
@@ -0,0 +1,159 @@
+# 424. Longest Repeating Character Replacement
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/longest-repeating-character-replacement/description/
+
+> 内容描述
+
+```
+Given a string that consists of only uppercase English letters, you can replace any letter in the string with another letter at most k times. Find the length of a longest substring containing all repeating letters you can get after performing the above operations.
+
+Note:
+Both the string's length and k will not exceed 104.
+
+Example 1:
+
+Input:
+s = "ABAB", k = 2
+
+Output:
+4
+
+Explanation:
+Replace the two 'A's with two 'B's or vice versa.
+Example 2:
+
+Input:
+s = "AABABBA", k = 1
+
+Output:
+4
+
+Explanation:
+Replace the one 'A' in the middle with 'B' and form "AABBBBA".
+The substring "BBBB" has the longest repeating letters, which is 4.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+假设我们用来替换别的字符的那个字符是c,那么题目可以转变成这样一个问题,在一个window里面,最多有k个不为c的字符,这样才是满足条件的
+
+那么这样的字符c有哪些呢?毫无疑问是set(s)里面的这些字符。
+
+然后我们维护一个window,不断计算不为c的字符的个数counter,如果counter大于n了说明我们怎么替换也不行了,我们就要将start往前挪一格,否则一直挪end。
+每次挪完end之后都要记得更新这一轮的最大长度
+
+每个字符c循环后都要更新最终res。
+
+代码如下:只beats 15%
+
+
+```python
+class Solution(object):
+ def characterReplacement(self, s, k):
+ """
+ :type s: str
+ :type k: int
+ :rtype: int
+ """
+ res = 0
+ for c in set(s):
+ start, end, counter, length = 0, 0, 0, 0
+ while end < len(s):
+ if s[end] != c:
+ counter += 1
+ end += 1 # end 永远指向下一个待处理的字符
+ while counter > k:
+ if s[start] != c:
+ counter -= 1
+ start += 1
+ length = max(length, end - start) # 因此这里是```end - start```而不是```end - start + 1```
+ res = max(res, length)
+ return res
+```
+
+
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+
+我们不按照可能的字符来遍历了,我们每次维护一个当前的最大字符频率,如果```end - start + 1 - max_freq > k```我们就知道此时怎么替换都不行了
+
+这个时候我们就要将start往前挪一格,对应的东西全都更新一下
+
+
+
+beats 93.46%
+
+
+
+
+```python
+class Solution(object):
+ def characterReplacement(self, s, k):
+ """
+ :type s: str
+ :type k: int
+ :rtype: int
+ """
+ lookup = {}
+ start, end, max_freq, res = 0, 0, 0, 0
+ while end < len(s):
+ lookup[s[end]] = lookup.get(s[end], 0) + 1
+ max_freq = max(max_freq, lookup[s[end]])
+ if end - start + 1 - max_freq > k: # 这里为什么用if不用while呢?见下方解析
+ lookup[s[start]] -= 1
+ start += 1
+ end += 1
+ res = max(res, end - start)
+ return res
+```
+
+上面用if不用while是因为在接下来的变化当中,我们start肯定是要前进一位的,end和max_freq此时没有变化,那么也就是说
+```end - start + 1 - max_freq > k```在经过一次if后就一定不会再满足了,所以这个地方不用while直接用if即可。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/leetcode/python/434._number_of_segments_in_a_string.md b/docs/Leetcode_Solutions/Python/434._number_of_segments_in_a_string.md
similarity index 94%
rename from docs/leetcode/python/434._number_of_segments_in_a_string.md
rename to docs/Leetcode_Solutions/Python/434._number_of_segments_in_a_string.md
index a1aa617b2..424472a5a 100644
--- a/docs/leetcode/python/434._number_of_segments_in_a_string.md
+++ b/docs/Leetcode_Solutions/Python/434._number_of_segments_in_a_string.md
@@ -1,27 +1,27 @@
-### 434. Number of Segments in a String
-
-题目:
-
-
-
-难度:
-
-Easy
-
-
-作弊神器Python
-
-
-```python
-class Solution(object):
- def countSegments(self, s):
- """
- :type s: str
- :rtype: int
- """
- return len(s.split())
-```
-
-不过对于比如C++这种语言来说,应该是O(N),扫一圈应该也能得到正确答案
-
-总之拿Python做string的题目就是作弊啊
+### 434. Number of Segments in a String
+
+题目:
+
+
+
+难度:
+
+Easy
+
+
+作弊神器Python
+
+
+```python
+class Solution(object):
+ def countSegments(self, s):
+ """
+ :type s: str
+ :rtype: int
+ """
+ return len(s.split())
+```
+
+不过对于比如C++这种语言来说,应该是O(N),扫一圈应该也能得到正确答案
+
+总之拿Python做string的题目就是作弊啊
diff --git a/docs/leetcode/python/435._Non-overlapping_Intervals.md b/docs/Leetcode_Solutions/Python/435._Non-overlapping_Intervals.md
similarity index 97%
rename from docs/leetcode/python/435._Non-overlapping_Intervals.md
rename to docs/Leetcode_Solutions/Python/435._Non-overlapping_Intervals.md
index 581fb1982..b9f6f1dfd 100644
--- a/docs/leetcode/python/435._Non-overlapping_Intervals.md
+++ b/docs/Leetcode_Solutions/Python/435._Non-overlapping_Intervals.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/non-overlapping-intervals
+* https://leetcode.com/problems/non-overlapping-intervals/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/436._Find_Right_Interval.md b/docs/Leetcode_Solutions/Python/436._Find_Right_Interval.md
new file mode 100644
index 000000000..044cb3156
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/436._Find_Right_Interval.md
@@ -0,0 +1,153 @@
+# 436. Find Right Interval
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/find-right-interval/description/
+
+> 内容描述
+
+```
+Given a set of intervals, for each of the interval i, check if there exists an interval j whose start point is bigger than or equal to the end point of the interval i, which can be called that j is on the "right" of i.
+
+For any interval i, you need to store the minimum interval j's index, which means that the interval j has the minimum start point to build the "right" relationship for interval i. If the interval j doesn't exist, store -1 for the interval i. Finally, you need output the stored value of each interval as an array.
+
+Note:
+You may assume the interval's end point is always bigger than its start point.
+You may assume none of these intervals have the same start point.
+Example 1:
+Input: [ [1,2] ]
+
+Output: [-1]
+
+Explanation: There is only one interval in the collection, so it outputs -1.
+Example 2:
+Input: [ [3,4], [2,3], [1,2] ]
+
+Output: [-1, 0, 1]
+
+Explanation: There is no satisfied "right" interval for [3,4].
+For [2,3], the interval [3,4] has minimum-"right" start point;
+For [1,2], the interval [2,3] has minimum-"right" start point.
+Example 3:
+Input: [ [1,4], [2,3], [3,4] ]
+
+Output: [-1, 2, -1]
+
+Explanation: There is no satisfied "right" interval for [1,4] and [3,4].
+For [2,3], the interval [3,4] has minimum-"right" start point.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******
+
+
+打算先按照start,end排个序,然后只要往后面找就行,虽然是O(N^2),但是稍微小了点,但没想到结果超时。
+
+```
+class Solution(object):
+ def findRightInterval(self, intervals):
+ """
+ :type intervals: List[Interval]
+ :rtype: List[int]
+ """
+ res = [-1] * len(intervals)
+ new_intervals = sorted(intervals, key = lambda x: (x.start, x.end))
+ lookup = {}
+ for idx, interval in enumerate(intervals):
+ lookup[(interval.start, interval.end)] = idx
+
+ for i in range(len(new_intervals)):
+ for j in range(i+1, len(new_intervals)):
+ if new_intervals[j].start >= new_intervals[i].end:
+ look_interval = (new_intervals[i].start, new_intervals[i].end)
+ look_idx = lookup[look_interval]
+ next_interval = (new_intervals[j].start, new_intervals[j].end)
+ next_idx = lookup[next_interval]
+ res[look_idx] = next_idx
+ break
+ return res
+```
+
+> 思路 2
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******
+
+后面我想到既然所有的start都不一样,我不如搞一个list存排过序的start,然后这样就可以用二分查找来找到第一个大于某end的idx了,
+同样的用一个字典来存start和idx的信息。
+
+这个二分的思想就是找到第一个大于target的index,思路跟[leetcode第35题](https://github.com/apachecn/awesome-leetcode/blob/master/docs/Leetcode_Solutions/035._search_insert_position.md)一样
+
+```python
+class Solution(object):
+ def findRightInterval(self, intervals):
+ """
+ :type intervals: List[Interval]
+ :rtype: List[int]
+ """
+ res = [-1] * len(intervals)
+ starts = sorted([i.start for i in intervals])
+ lookup = {}
+ for idx, interval in enumerate(intervals):
+ lookup[interval.start] = idx
+ for i in range(len(intervals)):
+ if starts[-1] < intervals[i].end:
+ continue
+ else:
+ l, r = 0, len(starts) - 1
+ target = intervals[i].end
+ # print(i, l, r, target)
+ while l <= r:
+ mid = l + ((r-l) >> 1)
+ if starts[mid] < target:
+ l = mid + 1
+ else:
+ r = mid - 1
+ res[i] = lookup[starts[l]]
+ return res
+```
+
+
+
+
+
+
+## Follow up
+
+
+就是题目变成
+```
+Given a set of intervals, for each of the interval i,
+check if there exists an interval j whose start point is bigger than or equal to the start point of the interval i,
+which can be called that j is on the "right" of i.
+```
+
+
+> 思路 1
+******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
+
+
+```python
+class Solution(object):
+ def findRightInterval(self, intervals):
+ """
+ :type intervals: List[Interval]
+ :rtype: List[int]
+ """
+ res = [-1] * len(intervals)
+ new_intervals = sorted(intervals, key = lambda x: (x.start, x.end))
+ lookup = {}
+ for idx, interval in enumerate(intervals):
+ lookup[(interval.start, interval.end)] = idx
+ for i in range(len(new_intervals)-1):
+ look_interval = (new_intervals[i].start, new_intervals[i].end)
+ look_idx = lookup[look_interval]
+ next_interval = (new_intervals[i+1].start, new_intervals[i+1].end)
+ next_idx = lookup[next_interval]
+ res[look_idx] = next_idx
+ return res
+```
diff --git a/docs/leetcode/python/437._path_sum_iii.md b/docs/Leetcode_Solutions/Python/437._path_sum_iii.md
similarity index 100%
rename from docs/leetcode/python/437._path_sum_iii.md
rename to docs/Leetcode_Solutions/Python/437._path_sum_iii.md
diff --git a/docs/leetcode/python/438._Find_All_Anagrams_in_a_String.md b/docs/Leetcode_Solutions/Python/438._Find_All_Anagrams_in_a_String.md
similarity index 100%
rename from docs/leetcode/python/438._Find_All_Anagrams_in_a_String.md
rename to docs/Leetcode_Solutions/Python/438._Find_All_Anagrams_in_a_String.md
diff --git a/docs/leetcode/python/439._Ternary_Expression_Parser.md b/docs/Leetcode_Solutions/Python/439. Ternary Expression Parser.md
similarity index 100%
rename from docs/leetcode/python/439._Ternary_Expression_Parser.md
rename to docs/Leetcode_Solutions/Python/439. Ternary Expression Parser.md
diff --git a/docs/leetcode/python/441._arranging_coins.md b/docs/Leetcode_Solutions/Python/441._arranging_coins.md
similarity index 100%
rename from docs/leetcode/python/441._arranging_coins.md
rename to docs/Leetcode_Solutions/Python/441._arranging_coins.md
diff --git a/docs/Leetcode_Solutions/Python/442._Find_All_Duplicates_in_an_Array.md b/docs/Leetcode_Solutions/Python/442._Find_All_Duplicates_in_an_Array.md
new file mode 100644
index 000000000..c89c19a27
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/442._Find_All_Duplicates_in_an_Array.md
@@ -0,0 +1,89 @@
+# 442. Find All Duplicates in an Array
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/find-all-duplicates-in-an-array/description/
+
+> 内容描述
+
+```
+Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
+
+Find all the elements that appear twice in this array.
+
+Could you do it without extra space and in O(n) runtime?
+
+Example:
+Input:
+[4,3,2,7,8,2,3,1]
+
+Output:
+[2,3]
+```
+
+## 解题方案
+
+> 思路 1
+
+直接用个字典存一下key和出现次数,然后loop一遍
+
+- 时间复杂度O(n)
+- 空间复杂度O(n)
+
+```python
+class Solution(object):
+ def findDuplicates(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: List[int]
+ """
+ res, lookup = [], {}
+ for num in nums:
+ lookup[num] = lookup.get(num, 0) + 1
+ for key in lookup.keys():
+ if lookup[key] == 2:
+ res.append(key)
+ return res
+```
+
+
+> 思路 2
+
+把每个数字都放到正确的位置上去,a[0] = 1, a[1] = 2, a[2] = 3 ... etc. (1<=a[i]<=n).
+
+参考[ZhassanB](https://leetcode.com/problems/find-all-duplicates-in-an-array/discuss/92411/Java-O(1)-space-O(n)-time-solution-with-swapping)
+
+- 时间复杂度O(n)
+- 空间复杂度O(1)
+```python
+class Solution(object):
+ def findDuplicates(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: List[int]
+ """
+ if not nums or len(nums) == 0:
+ return []
+ res = []
+ i, n = 0, len(nums)
+ while i < n: # traverse the array till the end
+ if nums[i] == i+1: # if number stays at it's supposed position, just continue
+ i += 1
+ continue
+ cur = nums[i]
+ if cur == -1: # if the duplicate number in that position is already found continue
+ i += 1
+ continue
+ if nums[cur-1] == cur: # if current num is equals to the number at supposed position,
+ res.append(cur) # then it is duplicate.
+ nums[i] = -1 # mark this position, in order to denote that duplicate has found
+ i += 1
+ continue
+ # if current number's supposed position is occupied by another number swap and consider that number
+ nums[i], nums[cur-1] = nums[cur-1], nums[i]
+ return res
+```
diff --git a/docs/leetcode/python/448._Find_All_Numbers_Disappeared_in_an_Array.md b/docs/Leetcode_Solutions/Python/448._Find_All_Numbers_Disappeared_in_an_Array.md
similarity index 100%
rename from docs/leetcode/python/448._Find_All_Numbers_Disappeared_in_an_Array.md
rename to docs/Leetcode_Solutions/Python/448._Find_All_Numbers_Disappeared_in_an_Array.md
diff --git a/docs/leetcode/python/450._Delete_Node_in_a_BST.md b/docs/Leetcode_Solutions/Python/450. Delete Node in a BST.md
similarity index 100%
rename from docs/leetcode/python/450._Delete_Node_in_a_BST.md
rename to docs/Leetcode_Solutions/Python/450. Delete Node in a BST.md
diff --git a/docs/leetcode/python/453._Minimum_Moves_to_Equal_Array_Elements.md b/docs/Leetcode_Solutions/Python/453._Minimum_Moves_to_Equal_Array_Elements.md
similarity index 100%
rename from docs/leetcode/python/453._Minimum_Moves_to_Equal_Array_Elements.md
rename to docs/Leetcode_Solutions/Python/453._Minimum_Moves_to_Equal_Array_Elements.md
diff --git a/docs/Leetcode_Solutions/Python/457._Circular_Array_Loop.md b/docs/Leetcode_Solutions/Python/457._Circular_Array_Loop.md
new file mode 100644
index 000000000..22ef6f435
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/457._Circular_Array_Loop.md
@@ -0,0 +1,104 @@
+# 457. Circular Array Loop
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/circular-array-loop/description/
+
+> 内容描述
+
+```
+
+You are given an array of positive and negative integers. If a number n at an index is positive, then move forward n steps. Conversely, if it's negative (-n), move backward n steps. Assume the first element of the array is forward next to the last element, and the last element is backward next to the first element. Determine if there is a loop in this array. A loop starts and ends at a particular index with more than 1 element along the loop. The loop must be "forward" or "backward'.
+
+Example 1: Given the array [2, -1, 1, 2, 2], there is a loop, from index 0 -> 2 -> 3 -> 0.
+
+Example 2: Given the array [-1, 2], there is no loop.
+
+Note: The given array is guaranteed to contain no element "0".
+
+Can you do it in O(n) time complexity and O(1) space complexity?
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+快慢指针,然后要注意的是如果loop只有一个元素不算loop,每次找完一圈后发现没有找到的话要将这一路上经过的点全都设为0防止下次重复查找了
+
+
+```python
+class Solution(object):
+ def circularArrayLoop(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: bool
+ """
+ def get_next_idx(i):
+ n = len(nums)
+ return (i + nums[i] + n) % n
+
+ for i, val in enumerate(nums):
+ if val == 0:
+ continue
+
+ slow = i
+ fast = get_next_idx(i)
+ # make sure always forward or always backward
+ while nums[fast] * val > 0 and nums[get_next_idx(fast)] * val > 0:
+ if slow == fast:
+ # exclude for loop with only one element
+ if slow == get_next_idx(slow):
+ break
+ return True
+
+ slow = get_next_idx(slow)
+ fast = get_next_idx(get_next_idx(fast))
+
+ slow = i
+ # set all the element along the path to 0, avoiding repeated lookup
+ while nums[slow] * val > 0:
+ nxt = get_next_idx(slow)
+ nums[slow] = 0
+ slow = nxt
+
+ return False
+```
+
+或者最后的循环也可以改一下
+
+```python
+class Solution(object):
+ def circularArrayLoop(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: bool
+ """
+ def get_nxt_idx(i):
+ n = len(nums)
+ return (i+nums[i]+n) % n
+
+ for i, val in enumerate(nums):
+ slow = i
+ fast = get_nxt_idx(i)
+
+ while nums[fast] * val > 0 and nums[get_nxt_idx(fast)] * val > 0:
+ if slow == fast:
+ if slow == get_nxt_idx(slow):
+ break
+ return True
+
+ slow = get_nxt_idx(slow)
+ fast = get_nxt_idx(get_nxt_idx(fast))
+
+ fast = get_nxt_idx(i)
+ while nums[fast] * val > 0:
+ nxt = get_nxt_idx(get_nxt_idx(fast))
+ nums[fast] = 0
+ fast = nxt
+ return False
+```
diff --git a/docs/leetcode/python/459._Repeated_Substring_Pattern.md b/docs/Leetcode_Solutions/Python/459._Repeated_Substring_Pattern.md
similarity index 100%
rename from docs/leetcode/python/459._Repeated_Substring_Pattern.md
rename to docs/Leetcode_Solutions/Python/459._Repeated_Substring_Pattern.md
diff --git a/docs/leetcode/python/461._Hamming_Distance.md b/docs/Leetcode_Solutions/Python/461._Hamming Distance.md
similarity index 51%
rename from docs/leetcode/python/461._Hamming_Distance.md
rename to docs/Leetcode_Solutions/Python/461._Hamming Distance.md
index 4a8d63d81..32b2b3dd6 100644
--- a/docs/leetcode/python/461._Hamming_Distance.md
+++ b/docs/Leetcode_Solutions/Python/461._Hamming Distance.md
@@ -1,13 +1,41 @@
-### 461. Hamming Distance
+# 461. Hamming Distance
+**难度: Easy**
+## 刷题内容
-题目:
- 原题连接
+* https://leetcode.com/problems/hamming-distance/description/
+> 内容描述
-难度 : Easy
+```
+The Hamming distance between two integers is the number of positions at which the corresponding bits are different.
+
+Given two integers x and y, calculate the Hamming distance.
+
+Note:
+0 ≤ x, y < 231.
+
+Example:
+
+Input: x = 1, y = 4
+
+Output: 2
+
+Explanation:
+1 (0 0 0 1)
+4 (0 1 0 0)
+ ↑ ↑
+
+The above arrows point to positions where the corresponding bits are different.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
@@ -27,7 +55,7 @@ https://en.wikipedia.org/wiki/Hamming_distance
>
>
-
+beats 100%
一行无敌
```python
@@ -40,6 +68,14 @@ class Solution(object):
"""
return bin(x^y).count('1')
```
+
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+不用count,用位运算更快,虽然在这里全部都是beats 100%
+
AC代码
```python
diff --git a/docs/Leetcode_Solutions/Python/463._Island_Perimeter.md b/docs/Leetcode_Solutions/Python/463._Island_Perimeter.md
new file mode 100644
index 000000000..2897ca68e
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/463._Island_Perimeter.md
@@ -0,0 +1,53 @@
+# 463. Island Perimeter
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/island-perimeter/description/
+
+> 内容描述
+
+```
+You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water. Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells). The island doesn't have "lakes" (water inside that isn't connected to the water around the island). One cell is a square with side length 1. The grid is rectangular, width and height don't exceed 100. Determine the perimeter of the island.
+
+Example:
+
+[[0,1,0,0],
+ [1,1,1,0],
+ [0,1,0,0],
+ [1,1,0,0]]
+
+Answer: 16
+Explanation: The perimeter is the 16 yellow stripes in the image below:
+```
+
+## 解题方案
+
+> 思路 1
+
+
+```python
+class Solution(object):
+ def islandPerimeter(self, grid):
+ """
+ :type grid: List[List[int]]
+ :rtype: int
+ """
+ h = len(grid)
+ w = len(grid[0]) if h else 0
+ res = 0
+ # 每一个陆地单元格的周长为4,当两单元格上下或者左右相邻时,令周长减2
+ for i in range(h):
+ for j in range(w):
+ if grid[i][j] == 1:
+ res += 4
+ # 因为x+1还在后面,所以不需要考虑,即只需要考虑左边和上边,因为循环已经出现过该点了
+ if i > 0 and grid[i-1][j]:
+ res -= 2
+ if j > 0 and grid[i][j-1]:
+ res -= 2
+ return res
+```
diff --git a/docs/leetcode/python/467._Unique_Substrings_in_Wraparound_String.md b/docs/Leetcode_Solutions/Python/467._Unique_Substrings_in_Wraparound_String.md
similarity index 100%
rename from docs/leetcode/python/467._Unique_Substrings_in_Wraparound_String.md
rename to docs/Leetcode_Solutions/Python/467._Unique_Substrings_in_Wraparound_String.md
diff --git a/docs/leetcode/python/469._Convex_Polygon.md b/docs/Leetcode_Solutions/Python/469. Convex Polygon.md
similarity index 100%
rename from docs/leetcode/python/469._Convex_Polygon.md
rename to docs/Leetcode_Solutions/Python/469. Convex Polygon.md
diff --git a/docs/leetcode/python/476._Number_Complement.md b/docs/Leetcode_Solutions/Python/476._Number_Complement.md
similarity index 100%
rename from docs/leetcode/python/476._Number_Complement.md
rename to docs/Leetcode_Solutions/Python/476._Number_Complement.md
diff --git a/docs/leetcode/python/477._Total_Hamming_Distance.md b/docs/Leetcode_Solutions/Python/477._Total_Hamming_Distance.md
similarity index 100%
rename from docs/leetcode/python/477._Total_Hamming_Distance.md
rename to docs/Leetcode_Solutions/Python/477._Total_Hamming_Distance.md
diff --git a/docs/leetcode/python/485._Max_Consecutive_Ones.md b/docs/Leetcode_Solutions/Python/485._Max_Consecutive_Ones.md
similarity index 100%
rename from docs/leetcode/python/485._Max_Consecutive_Ones.md
rename to docs/Leetcode_Solutions/Python/485._Max_Consecutive_Ones.md
diff --git a/docs/leetcode/python/494._Target_Sum.md b/docs/Leetcode_Solutions/Python/494._Target_Sum.md
similarity index 98%
rename from docs/leetcode/python/494._Target_Sum.md
rename to docs/Leetcode_Solutions/Python/494._Target_Sum.md
index e9ef2f4ce..e9f1a9598 100644
--- a/docs/leetcode/python/494._Target_Sum.md
+++ b/docs/Leetcode_Solutions/Python/494._Target_Sum.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/target-sum
+* https://leetcode.com/problems/target-sum/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/496._Next_Greater_Element_I.md b/docs/Leetcode_Solutions/Python/496._Next_Greater_Element_I.md
new file mode 100644
index 000000000..74a6d8d79
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/496._Next_Greater_Element_I.md
@@ -0,0 +1,113 @@
+# 496. Next Greater Element I
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/next-greater-element-i/description/
+
+> 内容描述
+
+```
+You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of nums2. Find all the next greater numbers for nums1's elements in the corresponding places of nums2.
+
+The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, output -1 for this number.
+
+Example 1:
+Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
+Output: [-1,3,-1]
+Explanation:
+ For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
+ For number 1 in the first array, the next greater number for it in the second array is 3.
+ For number 2 in the first array, there is no next greater number for it in the second array, so output -1.
+Example 2:
+Input: nums1 = [2,4], nums2 = [1,2,3,4].
+Output: [3,-1]
+Explanation:
+ For number 2 in the first array, the next greater number for it in the second array is 3.
+ For number 4 in the first array, there is no next greater number for it in the second array, so output -1.
+Note:
+All elements in nums1 and nums2 are unique.
+The length of both nums1 and nums2 would not exceed 1000.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(len(findNums) * len(nums))******- 空间复杂度: O(len(nums))******
+
+
+
+用一个字典把nums里面的数字和其idx分别作为key和value存下来,然后对于findNums里面的每一个数字,我们只需要看看其在字典中的value,
+然后从nums的idx = value+1开始往后找,如果找到了更大的数字就append,没找到出来之后根据flag定位知道要append一个-1
+
+beats 57.92%
+
+```python
+class Solution(object):
+ def nextGreaterElement(self, findNums, nums):
+ """
+ :type findNums: List[int]
+ :type nums: List[int]
+ :rtype: List[int]
+ """
+ lookup = {}
+ for i in range(len(nums)):
+ lookup[nums[i]] = i
+
+ res = []
+ for num in findNums:
+ idx = lookup[num]
+ flag = False
+ for i in range(idx+1, len(nums)):
+ if nums[i] > num:
+ res.append(nums[i])
+ flag = True
+ break
+ if not flag:
+ res.append(-1)
+ return res
+```
+
+
+> 思路 2
+******- 时间复杂度: O(len(nums))******- 空间复杂度: O(len(nums))******
+
+遍历nums,用栈来存nums里面的数字
+
+- while 碰到比栈顶元素更大的元素,我们知道栈顶元素的next greater num就是当前nums[i],pop栈顶,别忘了push nums[i]
+- 如果当前栈顶元素比nums[i]更大,只需要push当前nums[i]
+
+beats 100%
+
+```python
+class Solution(object):
+ def nextGreaterElement(self, findNums, nums):
+ """
+ :type findNums: List[int]
+ :type nums: List[int]
+ :rtype: List[int]
+ """
+ if not nums:
+ return [] # because findNums is subset of nums
+ stack = [nums[0]]
+ lookup = {}
+ for i in range(1, len(nums)):
+ # meet larger(than the last number in stack) number
+ # pop(all the smaller numbers than the current number)
+ # and set their next greater num to nums[i]
+ while stack and stack[-1] < nums[i]:
+ lookup[stack[-1]] = nums[i]
+ stack = stack[:-1]
+ stack.append(nums[i]) # don't forget to push nums[i]
+ # all the nums left in stack has no greater num behind it
+ for num in stack:
+ lookup[num] = -1
+ res =[]
+ for num in findNums:
+ res.append(lookup[num])
+
+ return res
+```
diff --git a/docs/Leetcode_Solutions/Python/507._Perfect_Number.md b/docs/Leetcode_Solutions/Python/507._Perfect_Number.md
new file mode 100644
index 000000000..6fe9436fd
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/507._Perfect_Number.md
@@ -0,0 +1,51 @@
+# 507. Perfect Number
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/perfect-number/description/
+
+> 内容描述
+
+```
+We define the Perfect Number is a positive integer that is equal to the sum of all its positive divisors except itself.
+
+Now, given an integer n, write a function that returns true when it is a perfect number and false when it is not.
+Example:
+Input: 28
+Output: True
+Explanation: 28 = 1 + 2 + 4 + 7 + 14
+Note: The input number n will not exceed 100,000,000. (1e8)
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
+
+用了一个比较巧妙的方法,首先排除一些 corner case,num 小于等于1的时候直接返回 False
+
+然后后面开始这个方法,就是我们其实不需要对所有小于 num 的数字做遍历,只需要从 2 遍历到 int(sqrt(num)) 即可,
+然后每次可以整除的时候都加上当前数字 i 和 num//i,然后初始化的时候让 sums = 1 ,这样最后就是不包含自己的所有因子的和,最后 return sum == num
+
+
+beats 95.73%
+```python
+from math import sqrt
+class Solution(object):
+ def checkPerfectNumber(self, num):
+ """
+ :type num: int
+ :rtype: bool
+ """
+ if num <= 1:
+ return False
+ sums = 1
+ for i in range(2, int(sqrt(num))+1):
+ if num % i == 0:
+ sums += i + num // i
+ return sums == num
+```
diff --git a/docs/leetcode/python/536._Construct_Binary_Tree_from_String.md b/docs/Leetcode_Solutions/Python/536._Construct_Binary_Tree_from_String.md
similarity index 99%
rename from docs/leetcode/python/536._Construct_Binary_Tree_from_String.md
rename to docs/Leetcode_Solutions/Python/536._Construct_Binary_Tree_from_String.md
index d28194fab..3f000278e 100644
--- a/docs/leetcode/python/536._Construct_Binary_Tree_from_String.md
+++ b/docs/Leetcode_Solutions/Python/536._Construct_Binary_Tree_from_String.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/construct-binary-tree-from-string
+* https://leetcode.com/problems/construct-binary-tree-from-string/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/547._Friend_Circles.md b/docs/Leetcode_Solutions/Python/547._Friend_Circles.md
new file mode 100644
index 000000000..31369032e
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/547._Friend_Circles.md
@@ -0,0 +1,102 @@
+# 547. Friend Circles
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/friend-circles/description/
+
+> 内容描述
+
+```
+There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.
+
+Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.
+
+Example 1:
+Input:
+[[1,1,0],
+ [1,1,0],
+ [0,0,1]]
+Output: 2
+Explanation:The 0th and 1st students are direct friends, so they are in a friend circle.
+The 2nd student himself is in a friend circle. So return 2.
+Example 2:
+Input:
+[[1,1,0],
+ [1,1,1],
+ [0,1,1]]
+Output: 1
+Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends,
+so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1.
+Note:
+N is in range [1,200].
+M[i][i] = 1 for all students.
+If M[i][j] = 1, then M[j][i] = 1.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N^3)******- 空间复杂度: O(N)******
+
+发现一件事,只要是关于这种circle类的题目,
+- 第一印象如果是关于链表的那么就想到快慢指针
+- 第二印象如果是关于图的立马想到union-find
+
+思路就没什么好说的,把这道题看成求图中有多少个联通分量就可以了。
+
+时间复杂度是因为两个for loop,并且调用connected方法会调用find方法,find方法最差到O(n),所以最终是O(N^3)
+
+空间自然就是O(N)
+
+
+```python
+class UnionFind(object):
+ uf = [] # access to component id (site indexed)
+ count = 0 # number of components
+
+ def uf(self, n): # 初始化uf数组和组数目
+ self.count = n
+ self.uf = [i for i in range(n)]
+
+ def find(self, x): # 判断节点所属于的组
+ while x != self.uf[x]:
+ self.uf[x] = self.uf[self.uf[x]]
+ x = self.uf[x]
+ return self.uf[x]
+
+ def union(self, x, y): # 连接两个节点
+ x_root = self.find(x)
+ y_root = self.find(y)
+ self.uf[x_root] = y_root
+ self.count -= 1
+
+ def connected(self, x, y): # 判断两个节点是否联通
+ return self.find(x) == self.find(y)
+
+ def count(self): # 返回所有组的数目
+ return self.count
+
+
+class Solution(object):
+ def findCircleNum(self, grid):
+ """
+ :type M: List[List[int]]
+ :rtype: int
+ """
+ s = UnionFind()
+ s.uf(len(grid))
+ for i in range(len(grid)):
+ for j in range(len(grid[i])):
+ # 如果i等于j说明是自己,没必要判断
+ # 只有当该位置为1即互为朋友的时候才需要看是否联通
+ # 不联通才union,联通也union一来浪费时间二来可能会无故减小count
+ if j != i and grid[i][j] == 1 and not s.connected(j, i):
+ s.union(j, i)
+ return s.count
+```
+
+
diff --git a/docs/Leetcode_Solutions/Python/560._Subarray_Sum_Equals_K.md b/docs/Leetcode_Solutions/Python/560._Subarray_Sum_Equals_K.md
new file mode 100644
index 000000000..6821d7b3b
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/560._Subarray_Sum_Equals_K.md
@@ -0,0 +1,56 @@
+# 560. Subarray Sum Equals K
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/subarray-sum-equals-k/description/
+
+> 内容描述
+
+```
+Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.
+
+Example 1:
+Input:nums = [1,1,1], k = 2
+Output: 2
+Note:
+The length of the array is in range [1, 20,000].
+The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].
+```
+
+## 解题方案
+
+> 思路 1
+
+
+跟two sum一样的题目
+
+就不停维护一个当前和的变量,然后每次都check一下```当前和 - k```是否在字典里面,如果存在我们就知道了之前有一坨字符串和的值为```当前和 - k```,然后
+当前和的值就是当前和,所以最近接触的一坨字符串其和必为k
+
+例如在[1,2,3,4]里面找7,之前存过1+2在字典里面,然后循环到4的时候当前和为10,就看看3在不在字典里面,一看果然有,那么最近一坨的 3+4 = 7,找到了
+
+但是这里要注意光找到没用,我们要知道存在多少个,所以字典里面的value对应的就是当前和出现的次数
+
+AC 代码:
+
+```python
+class Solution(object):
+ def subarraySum(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: int
+ """
+ # 这是为了保证如果当前和的值就等于k的话,我们其实也相当于找到一次
+ lookup = {0:1}
+ res = cur_sum = 0
+ for num in nums:
+ cur_sum += num
+ res += lookup.get(cur_sum-k, 0)
+ lookup[cur_sum] = lookup.get(cur_sum, 0) + 1
+ return res
+```
diff --git a/docs/Leetcode_Solutions/Python/564._Find_the_Closest_Palindrome.md b/docs/Leetcode_Solutions/Python/564._Find_the_Closest_Palindrome.md
new file mode 100644
index 000000000..8d4312ddd
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/564._Find_the_Closest_Palindrome.md
@@ -0,0 +1,118 @@
+# 564. Find the Closest Palindrome
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/find-the-closest-palindrome/description/
+
+> 内容描述
+
+```
+Given an integer n, find the closest integer (not including itself), which is a palindrome.
+
+The 'closest' is defined as absolute difference minimized between two integers.
+
+Example 1:
+Input: "123"
+Output: "121"
+Note:
+The input n is a positive integer represented by string, whose length will not exceed 18.
+If there is a tie, return the smaller one as answer.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+前前后后搞了2天,感谢今天下午女朋友和我一起讨论,最终搞出来了。
+
+- 总共三种情况,算出后面的,前面的,还有当前的前半部分直接反转黏贴到后半部分。总结一下就是说[前半部分+1,前半部分-1,前半部分自身] + 前面得出结果的反转就是我们可能的结果之一。
+- 另外两种情况就是进位和减位,格式为1000..0001, 999...999
+
+5个部分看看哪个更近,唯一需要注意的是输入为10和11的时候handle不了,要在最前面手动处理一下。
+
+beats 100%,功夫不负有心人!
+
+```
+class Solution(object):
+ def nearestPalindromic(self, n):
+ """
+ :type n: str
+ :rtype: str
+ """
+ tmp = str(n)
+ if 9 < int(n) < 12:
+ return '9'
+ r_half_len = len(tmp) // 2
+ if len(tmp) & 1 == 0: # 长度为偶数
+ num_digits = len(str(int(tmp[:len(tmp)/2])))
+ half = tmp[:len(tmp)/2]
+ else: # 长度为奇数
+ num_digits = len(str(int(tmp[:(len(tmp)+1)/2])))
+ half = tmp[:(len(tmp)+1)/2]
+
+ if len(str(int(half)+1)) > num_digits: # 进位了
+ behind = '1' + '0' * (len(tmp)-1) + '1'
+ else:
+ behind = str(int(half) + 1)+ str(int(half) + 1)[:r_half_len][::-1]
+ if len(str(int(half)-1)) < num_digits: # 减位了
+ before = '9' * (len(tmp)-1)
+ else:
+ before = str(int(half) - 1)+ str(int(half) - 1)[:r_half_len][::-1]
+ # 当前的前半部分直接反转,如1002,变成了1001
+ cur = str(int(half))+ str(int(half))[:r_half_len][::-1]
+ if cur == tmp[::-1]:
+ return behind if abs(int(tmp)-int(behind)) < abs(int(tmp)-int(before)) else before
+ abss = map(lambda x: abs(int(x)-int(tmp)), [before, cur, behind])
+ selects = [before, cur, behind]
+ return selects[abss.index(min(abss))]
+```
+
+后面我觉得完全可以重构一下代码,behind和before不用非得算出来,我只要把所有的可能性全都放到一个list里面去,最后来判断就行了
+
+```python
+class Solution(object):
+ def nearestPalindromic(self, n):
+ """
+ :type n: str
+ :rtype: str
+ """
+ prefix = int(n[:(len(n)+1)//2])
+
+ candidates = set(['1' + '0' * (len(n)-1) + '1', '9' * (len(n)-1)]) # 进位减位可能性
+
+ for i in map(str, [prefix-1, prefix, prefix+1]): # 前半部分+1,-1,+0可能性
+ candidates.add(i + [i, i[:-1]][len(n) & 1][::-1])
+
+ candidates.discard(n) # 除去自身可能就是Palindrome的可能性
+ candidates.discard('') # 输入n为个位数的话,我们还会加入空字符串,必须要去掉
+
+ return min(candidates, key = lambda x: (abs(int(x) - int(n)), int(x)))
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/581._Shortest_Unsorted_Continuous_Subarray.md b/docs/Leetcode_Solutions/Python/581._Shortest_Unsorted_Continuous_Subarray.md
new file mode 100644
index 000000000..e53153d72
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/581._Shortest_Unsorted_Continuous_Subarray.md
@@ -0,0 +1,176 @@
+# 581. Shortest Unsorted Continuous Subarray
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/two-sum
+* https://leetcode-cn.com/problems/two-sum/description
+
+> 内容描述
+
+```
+给定 nums = [2, 7, 11, 15], target = 9
+
+因为 nums[0] + nums[1] = 2 + 7 = 9
+所以返回 [0, 1]
+```
+
+## 解题方案
+
+> 思路 1
+ ******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
+
+直接sort,然后找出sort前与sort后不同的数组长度
+
+
+```python
+class Solution(object):
+ def findUnsortedSubarray(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ start, end = 0, 0
+ sorted_nums = sorted(nums)
+
+ for i in range(len(nums)):
+ if nums[i] != sorted_nums[i]:
+ start = i
+ break
+ for i in range(len(nums)-1, -1, -1):
+ if nums[i] != sorted_nums[i]:
+ end = i
+ break
+
+ return end - start + 1 if start != end else 0
+```
+
+> 思路 2
+ ******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+要满足三个性质:
+
+1. nums[0, i - 1] and nums[j + 1, n - 1] are both sorted.
+2. nums[i] != nums_sorted[i] and nums[j] != nums_sorted[j].
+3. nums[i - 1] <= min and max <= nums[j + 1], where min and max are the minimum and maximum values of subarray nums[i, j].
+
+所以我们需要做的就是 find the two longest sorted subarrays starting at index 0 and ending at index n - 1
+
+- 从左到右找到第一个不满足nums[l] <= nums[l+1]的index l
+- 然后从右到左找到第一个不满足nums[r] >= nums[r-1]的 index r
+- 然后开始保证第三条性质,只要min(nums[l:r+1]) < nums[l],l就自减1;只要max(nums[l:r+1]) > nums[r], r就自增1;
+- 这两个index中间这一坨就是需要我们sort的最短subarray
+
+参考[fun4LeetCode](https://leetcode.com/problems/shortest-unsorted-continuous-subarray/discuss/103066/Ideas-behind-the-O(n)-two-pass-and-one-pass-solutions)
+
+two-pass,Finding the longest subarrays and the maximum and minimum values of the middle subarray takes one-pass.
+Ensuring the third property requires a second pass.
+
+```python
+class Solution(object):
+ def findUnsortedSubarray(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ l, r = 0, len(nums) - 1
+ while l < r and nums[l] <= nums[l+1]:
+ l += 1
+ if l >= r:
+ return 0
+ while nums[r] >= nums[r-1]:
+ r -= 1
+ max_num, min_num = -sys.maxsize, sys.maxsize
+
+ for k in range(l, r+1):
+ max_num = max(max_num, nums[k])
+ min_num = min(min_num, nums[k])
+
+ while l >= 0 and min_num < nums[l]:
+ l -= 1
+ while r < len(nums) and nums[r] < max_num:
+ r += 1
+
+ return r - l - 1
+```
+
+> 思路 3
+ ******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+这个方法我最推荐了,他其实和思路2一样,但是不用考虑那么多
+
+1. 从左到右找到最后一个不符合递增规律的index end
+2. 从右到左找到最后一个不符合递增规律的index start
+3. 直接返回max(end-start+1, 0), 因为end可能比start小,比如对于输入[1,2,3,3,3],end等于0,start等于4
+
+```python
+class Solution(object):
+ def findUnsortedSubarray(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ m = nums[0]
+ end = 0
+ for i in range(1, len(nums)):
+ if nums[i] >= m:
+ m = nums[i]
+ else:
+ end = i
+
+ m = nums[-1]
+ start = len(nums)-1
+ for i in range(len(nums)-1, -1, -1):
+ if nums[i] <= m:
+ m = nums[i]
+ else:
+ start = i
+
+ if start == end:
+ return 0
+
+ return max(end-start+1, 0)
+```
+
+
+
+
+> 思路 4
+ ******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+ one-pass
+
+ 这一次我们只需要找到
+
+- i is the smallest index such that nums[i] != min[i:]
+- j is the largest index such that nums[j] != max[:j+1]
+
+
+```python
+class Solution(object):
+ def findUnsortedSubarray(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ i, j = 0, -1
+ l, r = 0, len(nums) - 1
+ max_num, min_num = -sys.maxsize, sys.maxsize
+ while r >= 0:
+ min_num = min(min_num, nums[r])
+ # i is the smallest index such that nums[i] != min[i:]
+ if nums[r] != min_num:
+ i = r
+ max_num = max(max_num, nums[l])
+ # j is the largest index such that nums[j] != max[:j+1]
+ if nums[l] != max_num:
+ j = l
+ l += 1
+ r -= 1
+
+ return j-i+1
+```
+
diff --git a/docs/leetcode/python/587._Erect_the_Fence.md b/docs/Leetcode_Solutions/Python/587._Erect_the_Fence .md
similarity index 98%
rename from docs/leetcode/python/587._Erect_the_Fence.md
rename to docs/Leetcode_Solutions/Python/587._Erect_the_Fence .md
index 301c1c1b1..f61d75b3c 100644
--- a/docs/leetcode/python/587._Erect_the_Fence.md
+++ b/docs/Leetcode_Solutions/Python/587._Erect_the_Fence .md
@@ -130,4 +130,4 @@ Author: Keqi Huang
If you like it, please spread your support
-
+
diff --git a/docs/Leetcode_Solutions/Python/592._Fraction_Addition_and_Subtraction.md b/docs/Leetcode_Solutions/Python/592._Fraction_Addition_and_Subtraction.md
new file mode 100644
index 000000000..cef93a65d
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/592._Fraction_Addition_and_Subtraction.md
@@ -0,0 +1,115 @@
+# 592. Fraction Addition and Subtraction
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/fraction-addition-and-subtraction/description/
+
+> 内容描述
+
+```
+Given a string representing an expression of fraction addition and subtraction, you need to return the calculation result in string format. The final result should be irreducible fraction. If your final result is an integer, say 2, you need to change it to the format of fraction that has denominator 1. So in this case, 2 should be converted to 2/1.
+
+Example 1:
+Input:"-1/2+1/2"
+Output: "0/1"
+Example 2:
+Input:"-1/2+1/2+1/3"
+Output: "1/3"
+Example 3:
+Input:"1/3-1/2"
+Output: "-1/6"
+Example 4:
+Input:"5/3+1/3"
+Output: "2/1"
+Note:
+The input string only contains '0' to '9', '/', '+' and '-'. So does the output.
+Each fraction (input and output) has format ±numerator/denominator. If the first input fraction or the output is positive, then '+' will be omitted.
+The input only contains valid irreducible fractions, where the numerator and denominator of each fraction will always be in the range [1,10]. If the denominator is 1, it means this fraction is actually an integer in a fraction format defined above.
+The number of given fractions will be in the range [1,10].
+The numerator and denominator of the final result are guaranteed to be valid and in the range of 32-bit int.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+这个思路真的没啥好说的,就是最小公倍数和最大公约数稍微注意下怎么写就行,然后剩下的就是搬砖活了, 20分钟 bug free,一遍AC,莫名小自豪。。。。
+
+```python
+class Solution(object):
+ def fractionAddition(self, expression):
+ """
+ :type expression: str
+ :rtype: str
+ """
+ def gcd(a, b):
+ if a == 0:
+ return b
+ return gcd(b % a, a)
+
+ def gcm(num1, num2):
+ return num1 * num2 // gcd(num1, num2)
+
+ def is_sign(expression, index): # 判断符号'-'是否是描述负数的符号
+ if expression[i] == '-':
+ if i - 1 < 0 or expression[i - 1] in oprs:
+ return True
+ return False
+
+ oprs = '+-'
+ units = [] # 保存包含操作符和操作数的列表
+ start = 0 # 标记数字起点
+ for i in range(len(expression)):
+ if expression[i] in oprs:
+ if not is_sign(expression, i):
+ units.append(expression[start:i])
+ units.append(expression[i])
+ start = i + 1
+ units.append(expression[start:])
+ while len(units) > 1:
+ left, right = 0, 0
+ gcmm = gcm(int(units[0].split('/')[1]), int(units[2].split('/')[1]))
+ if units[0].split('/')[0][0] == '-':
+ left = int(units[0].split('/')[0].lstrip('-')) * gcmm // int(units[0].split('/')[1]) * (-1)
+ else:
+ left = int(units[0].split('/')[0].lstrip('-')) * gcmm // int(units[0].split('/')[1])
+ right = int(units[2].split('/')[0]) * gcmm // int(units[2].split('/')[1])
+ if units[1] == '+':
+ units = [str(left + right) + '/' + str(gcmm)] + units[3:]
+ else:
+ units = [str(left - right) + '/' + str(gcmm)] + units[3:]
+ if units[0].split('/')[0].lstrip('-') == '0':
+ res = units[0].split('/')[0] + '/1'
+ else:
+ gcdd = gcd(int(units[0].split('/')[0].lstrip('-')), int(units[0].split('/')[1]))
+ # print('gcdd',gcdd)
+ if units[0].split('/')[0][0] == '-':
+ res = '-' + str(int(units[0].split('/')[0].lstrip('-'))//gcdd) + '/' + str(int(units[0].split('/')[1])//gcdd)
+ else:
+ res = str(int(units[0].split('/')[0].lstrip('-'))//gcdd) + '/' + str(int(units[0].split('/')[1])//gcdd)
+
+ return res
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+我怕不是个智障吧,还小自豪,。。。。看了discuss里面[lee215](https://leetcode.com/problems/fraction-addition-and-subtraction/discuss/103387/Python-easy-understood-2-line-solution)大神的答案,我tm。。。。
+```python
+class Solution(object):
+ def fractionAddition(self, expression):
+ """
+ :type expression: str
+ :rtype: str
+ """
+ from fractions import Fraction
+ res = sum(map(Fraction, expression.replace('+', ' +').replace('-', ' -').split()))
+ return str(res.numerator) + '/' + str(res.denominator)
+```
diff --git a/docs/Leetcode_Solutions/Python/593._Valid_Square.md b/docs/Leetcode_Solutions/Python/593._Valid_Square.md
new file mode 100644
index 000000000..fb61b27fe
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/593._Valid_Square.md
@@ -0,0 +1,201 @@
+# 593. Valid Square
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/valid-square/description/
+
+> 内容描述
+
+```
+
+Given the coordinates of four points in 2D space, return whether the four points could construct a square.
+
+The coordinate (x,y) of a point is represented by an integer array with two integers.
+
+Example:
+Input: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,1]
+Output: True
+Note:
+
+All the input integers are in the range [-10000, 10000].
+A valid square has four equal sides with positive length and four equal angles (90-degree angles).
+Input points have no order.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******
+
+只要满足3个条件就行,
+
+1. 每个点都不相等,处理掉比如4个点都是(0, 0)啥的case
+2. 4条边相等
+3. 其中2条边夹角为90度
+
+
+或者,
+
+1. 每个点都不相等,处理掉比如4个点都是(0, 0)啥的case
+2. 有其中一组相邻边相等
+3. 有一对对角均为90度
+
+
+第一种方式代码如下:
+
+
+```python
+class Solution(object):
+ def validSquare(self, p1, p2, p3, p4):
+ """
+ :type p1: List[int]
+ :type p2: List[int]
+ :type p3: List[int]
+ :type p4: List[int]
+ :rtype: bool
+ """
+ # corner cases
+ points = [p1, p2, p3, p4]
+ for i in range(len(points)):
+ for j in range(i + 1, len(points)):
+ if points[i][0] == points[j][0] and points[i][1] == points[j][1]:
+ return False
+
+ points = sorted(points, key=lambda p: (p[0], p[1])) # []
+
+ import math
+
+ # for this part , we calculate the four sides
+ tmp = pow(points[-1][0] - points[1][0], 2) + pow(points[-1][1] - points[1][1], 2)
+ len_bottom = math.sqrt((tmp))
+
+ tmp = pow(points[-2][0] - points[0][0], 2) + pow(points[-2][1] - points[0][1], 2)
+ len_top = math.sqrt((tmp))
+
+ tmp = pow(points[1][0] - points[0][0], 2) + pow(points[1][1] - points[0][1], 2)
+ len_left = math.sqrt((tmp))
+
+ tmp = pow(points[-1][0] - points[-2][0], 2) + pow(points[-1][1] - points[-2][1], 2)
+ len_right = math.sqrt((tmp))
+
+ # now this is our angle part
+ vector_bottom = [points[-1][0] - points[1][0], points[-1][1] - points[1][1]]
+ vector_left = [points[1][0] - points[0][0], points[1][1] - points[0][1]]
+
+ dikall = vector_bottom[0] * vector_left[0] + vector_bottom[1] * vector_left[1]
+
+ if len_bottom == len_top == len_left == len_right and dikall == 0:
+ return True
+ return False
+```
+
+第二种代码如下:
+
+```python
+class Solution(object):
+ def validSquare(self, p1, p2, p3, p4):
+ """
+ :type p1: List[int]
+ :type p2: List[int]
+ :type p3: List[int]
+ :type p4: List[int]
+ :rtype: bool
+ """
+ # corner cases
+ points = [p1, p2, p3, p4]
+ for i in range(len(points)):
+ for j in range(i + 1, len(points)):
+ if points[i][0] == points[j][0] and points[i][1] == points[j][1]:
+ return False
+
+ points = sorted(points, key=lambda p: (p[0], p[1])) # []
+
+ import math
+
+ # for this part , we calculate the four sides
+ tmp = pow(points[-1][0] - points[1][0], 2) + pow(points[-1][1] - points[1][1], 2)
+ len_bottom = math.sqrt((tmp))
+
+ tmp = pow(points[1][0] - points[0][0], 2) + pow(points[1][1] - points[0][1], 2)
+ len_left = math.sqrt((tmp))
+
+ # now this is our angle part
+ vector_bottom = [points[-1][0] - points[1][0], points[-1][1] - points[1][1]]
+ vector_left = [points[1][0] - points[0][0], points[1][1] - points[0][1]]
+
+ vector_top = [points[2][0] - points[0][0], points[2][1] - points[0][1]]
+ vector_right = [points[2][0] - points[-1][0], points[2][1] - points[-1][1]]
+
+ vec_product1 = vector_bottom[0] * vector_left[0] + vector_bottom[1] * vector_left[1]
+ vec_product2 = vector_top[0] * vector_right[0] + vector_top[1] * vector_right[1]
+
+ if len_bottom == len_left and vec_product1 == vec_product2 == 0:
+ return True
+ return False
+```
+
+> 思路 2
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******
+
+这个思路是根据后面Follow up大佬告诉我的,根据三个点就可以算出正方形的第四个点了,然后我们需要考虑的就是下面的几个case
+
+1. 如果4个点中有两个点相等,那么肯定不行
+2. 如果是菱形,肯定不行,即夹角不为90度
+3. 如果相邻边长度不相等,那肯定不行
+
+满足以上3个条件,就返回True,否则返回False
+
+
+```python
+class Solution(object):
+ def validSquare(self, p1, p2, p3, p4):
+ """
+ :type p1: List[int]
+ :type p2: List[int]
+ :type p3: List[int]
+ :type p4: List[int]
+ :rtype: bool
+ """
+ points = [p1, p2, p3, p4]
+ points = sorted(points, key=lambda p: (p[0], p[1]))
+
+ for i in range(len(points)): # for same point case
+ for j in range(i + 1, len(points)):
+ if points[i][0] == points[j][0] and points[i][1] == points[j][1]:
+ return False
+
+ x4, y4 = points[2][0] + points[1][0] - points[0][0], points[1][1] - points[0][1] + points[2][1]
+
+ if x4 == points[-1][0] and y4 == points[-1][1]: # for point4 not exist case
+
+ distance_bottom = pow((x4-points[1][0]), 2) + pow((y4-points[1][1]), 2)
+ distance_left = pow((points[0][1]-points[1][1]), 2) + pow((points[0][0]-points[1][0]), 2)
+
+ if distance_bottom == distance_left: # for diamond case
+
+ vec_product = (x4-points[1][0]) * (points[0][0]-points[1][0]) + (y4-points[1][1]) * (points[0][1]-points[1][1])
+
+ if vec_product == 0: # for angle != 90 degree case
+ return True
+ return False
+```
+
+## Follow up
+
+如果给一个列表的点,返回一共能组成多少个正方形。input里面可能有重复的点
+
+
+开始我很sb的想着4 个 for loop取得4个点,然后用上面的函数判断是否可以组成正方形,最后叠加结果并且返回
+
+这里感谢微信墨汁大佬的指导,
+
+- 首先将input去重
+- 然后可以先将所有点放到一个字典里面去
+- 然后我们用2个for loop去确定好2个点,根据正方形的性质我们就可以自己算出正方形的另外两个点了
+- 随后我们判断这两个点是否在我们的字典里面
+
+这样我们最终的时间复杂度是O(N^2),空间复杂度是O(N),完美!!
diff --git a/docs/Leetcode_Solutions/Python/595._Big_Countries.md b/docs/Leetcode_Solutions/Python/595._Big_Countries.md
new file mode 100644
index 000000000..cf8cace79
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/595._Big_Countries.md
@@ -0,0 +1,45 @@
+# 595. Big Countries
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/big-countries/description/
+
+> 内容描述
+
+```
+There is a table World
+
++-----------------+------------+------------+--------------+---------------+
+| name | continent | area | population | gdp |
++-----------------+------------+------------+--------------+---------------+
+| Afghanistan | Asia | 652230 | 25500100 | 20343000 |
+| Albania | Europe | 28748 | 2831741 | 12960000 |
+| Algeria | Africa | 2381741 | 37100000 | 188681000 |
+| Andorra | Europe | 468 | 78115 | 3712000 |
+| Angola | Africa | 1246700 | 20609294 | 100990000 |
++-----------------+------------+------------+--------------+---------------+
+A country is big if it has an area of bigger than 3 million square km or a population of more than 25 million.
+
+Write a SQL solution to output big countries' name, population and area.
+
+For example, according to the above table, we should output:
+
++--------------+-------------+--------------+
+| name | population | area |
++--------------+-------------+--------------+
+| Afghanistan | 25500100 | 652230 |
+| Algeria | 37100000 | 2381741 |
++--------------+-------------+--------------+
+```
+
+## 解题方案
+
+> 思路 1
+
+```sql
+select name, population, area from World where area > 3000000 or population > 25000000;
+```
diff --git a/docs/leetcode/python/599._Minimum_Index_Sum_of_Two_Lists.md b/docs/Leetcode_Solutions/Python/599._Minimum_Index_Sum_of_Two_Lists.md
similarity index 94%
rename from docs/leetcode/python/599._Minimum_Index_Sum_of_Two_Lists.md
rename to docs/Leetcode_Solutions/Python/599._Minimum_Index_Sum_of_Two_Lists.md
index 819bcff9d..1682fab62 100644
--- a/docs/leetcode/python/599._Minimum_Index_Sum_of_Two_Lists.md
+++ b/docs/Leetcode_Solutions/Python/599._Minimum_Index_Sum_of_Two_Lists.md
@@ -55,4 +55,4 @@ Author: Keqi Huang
If you like it, please spread your support
-
+
diff --git a/docs/leetcode/python/606._Construct_String_from_Binary_Tree.md b/docs/Leetcode_Solutions/Python/606._Construct_String_from_Binary_Tree.md
similarity index 99%
rename from docs/leetcode/python/606._Construct_String_from_Binary_Tree.md
rename to docs/Leetcode_Solutions/Python/606._Construct_String_from_Binary_Tree.md
index cc67ceac0..df0b8af42 100644
--- a/docs/leetcode/python/606._Construct_String_from_Binary_Tree.md
+++ b/docs/Leetcode_Solutions/Python/606._Construct_String_from_Binary_Tree.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/construct-string-from-binary-tree
+* https://leetcode.com/problems/construct-string-from-binary-tree/description/
> 内容描述
diff --git a/docs/leetcode/python/611._Valid_Triangle_Number.md b/docs/Leetcode_Solutions/Python/611._Valid_Triangle_Number.md
similarity index 95%
rename from docs/leetcode/python/611._Valid_Triangle_Number.md
rename to docs/Leetcode_Solutions/Python/611._Valid_Triangle_Number.md
index 41c8831c7..f17d298e2 100644
--- a/docs/leetcode/python/611._Valid_Triangle_Number.md
+++ b/docs/Leetcode_Solutions/Python/611._Valid_Triangle_Number.md
@@ -6,8 +6,8 @@
> 原题连接
-* https://leetcode.com/problems/valid-triangle-number
-* https://leetcode-cn.com/problems/valid-triangle-number
+* https://leetcode.com/problems/valid-triangle-number/description/
+* https://leetcode-cn.com/problems/valid-triangle-number/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/613._Shortest_Distance_in_a_Line.md b/docs/Leetcode_Solutions/Python/613._Shortest_Distance_in_a_Line.md
new file mode 100644
index 000000000..de97e3de3
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/613._Shortest_Distance_in_a_Line.md
@@ -0,0 +1,41 @@
+# 613. Shortest Distance in a Line
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/shortest-distance-in-a-line/description/
+
+> 内容描述
+
+```
+Table point holds the x coordinate of some points on x-axis in a plane, which are all integers.
+Write a query to find the shortest distance between two points in these points.
+| x |
+|-----|
+| -1 |
+| 0 |
+| 2 |
+The shortest distance is '1' obviously, which is from point '-1' to '0'. So the output is as below:
+| shortest|
+|---------|
+| 1 |
+Note: Every point is unique, which means there is no duplicates in table point.
+Follow-up: What if all these points have an id and are arranged from the left most to the right most of x axis?
+```
+
+## 解题方案
+
+> 思路 1
+
+```sql
+select min(abs(p1.x-p2.x)) as shortest from point p1, point p2 where p1.x != p2.x;
+```
+
+> 思路 2
+
+```sql
+select min(p2.x-p1.x) shortest from point p1 inner join point p2 where p2.x > p1.x;
+```
diff --git a/docs/leetcode/python/646._Maximum_Length_of_Pair_Chain.md b/docs/Leetcode_Solutions/Python/646._Maximum_Length_of_Pair_Chain.md
similarity index 97%
rename from docs/leetcode/python/646._Maximum_Length_of_Pair_Chain.md
rename to docs/Leetcode_Solutions/Python/646._Maximum_Length_of_Pair_Chain.md
index 8cc8e6260..a294701e3 100644
--- a/docs/leetcode/python/646._Maximum_Length_of_Pair_Chain.md
+++ b/docs/Leetcode_Solutions/Python/646._Maximum_Length_of_Pair_Chain.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/maximum-length-of-pair-chain
+* https://leetcode.com/problems/maximum-length-of-pair-chain/description/
> 内容描述
diff --git a/docs/leetcode/python/647._Palindromic_Substrings.md b/docs/Leetcode_Solutions/Python/647._Palindromic_Substrings.md
similarity index 79%
rename from docs/leetcode/python/647._Palindromic_Substrings.md
rename to docs/Leetcode_Solutions/Python/647._Palindromic_Substrings.md
index 22791ab64..450acba5d 100644
--- a/docs/leetcode/python/647._Palindromic_Substrings.md
+++ b/docs/Leetcode_Solutions/Python/647._Palindromic_Substrings.md
@@ -1,12 +1,37 @@
-### 647. Palindromic Substrings
+# 647. Palindromic Substrings
-题目:
-
+**难度: Medium**
+## 刷题内容
-难度:
+> 原题连接
-Medium
+* https://leetcode.com/problems/palindromic-substrings/description/
+
+> 内容描述
+
+```
+
+Given a string, your task is to count how many palindromic substrings in this string.
+
+The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.
+
+Example 1:
+Input: "abc"
+Output: 3
+Explanation: Three palindromic strings: "a", "b", "c".
+Example 2:
+Input: "aaa"
+Output: 6
+Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
+Note:
+The input string length won't exceed 1000.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
思路
@@ -21,17 +46,17 @@ Manacher算法增加两个辅助变量id和mx,其中id表示最大回文子串
下面,令j = 2*id - i,也就是说j是i关于id的对称点。
- 当 mx - i > P[j] 的时候,以S[j]为中心的回文子串包含在以S[id]为中心的回文子串中,由于i和j对称,以S[i]为中心的回文子串必然包含在以S[id]为中心的回文子串中,所以必有P[i] = P[j];
-
+
- 当 P[j] >= mx - i 的时候,以S[j]为中心的回文子串不一定完全包含于以S[id]为中心的回文子串中,但是基于对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以S[i]为中心的回文子串,其向右至少会扩张到mx的位置,也就是说 P[i] >= mx - i。至于mx之后的部分是否对称,再具体匹配。
-
+
所以P[i] >= Min(P[2 * id - i], mx - i),因为以j为中心的绘回文子串的左边界可能会比mx关于id的对称点要大,此时只能证明P[i]=P[2 * id - i]
- 此外,对于 mx <= i 的情况,因为无法对 P[i]做更多的假设,只能让P[i] = 1,然后再去匹配。
此题还可以借鉴我leetcode第5题的解析,
[thining-in-lc-5](https://github.com/Lisanaaa/thinking_in_lc/blob/master/005._longest_palindromic_substring.md)
这道题的基本思想是将以每一个字符为中心的回文子串个数相加,还是用一个小例子来解释
-
+
其实,以‘#’为中心的回文子串就代表这个子串的长度是偶数,类似于'abba'这种
但是其实这个字符本身也是一个回文子串,所以叠加的形式是count += (P[i]+1)/2,为什么呢,以下是解释:
- 对于每一个以字符‘#’为中心的回文子串,其P值绝对是偶数,所以```(P[i]+1)/2 = P[i]/2```,并不影响
@@ -70,6 +95,10 @@ class Solution(object):
count += (P[i]+1)/2
return count
```
+
+> 思路 2
+
+
python无敌啊!!!有没有天理啊,手动滑稽😏😏😏😏!一行解法:
```python
class Solution(object):
diff --git a/docs/leetcode/python/657._Judge_Route_Circle.md b/docs/Leetcode_Solutions/Python/657._Judge_Route_Circle.md
similarity index 100%
rename from docs/leetcode/python/657._Judge_Route_Circle.md
rename to docs/Leetcode_Solutions/Python/657._Judge_Route_Circle.md
diff --git a/docs/leetcode/python/665._Non-decreasing_Array.md b/docs/Leetcode_Solutions/Python/665._Non-decreasing_Array.md
similarity index 58%
rename from docs/leetcode/python/665._Non-decreasing_Array.md
rename to docs/Leetcode_Solutions/Python/665._Non-decreasing_Array.md
index cf05d3c9e..bd5deb204 100644
--- a/docs/leetcode/python/665._Non-decreasing_Array.md
+++ b/docs/Leetcode_Solutions/Python/665._Non-decreasing_Array.md
@@ -1,15 +1,34 @@
-### 665. Non-decreasing Array
+# 665. Non-decreasing Array
-题目:
-
+**难度: Easy**
+## 刷题内容
-难度:
+> 原题连接
-Easy
+* https://leetcode.com/problems/non-decreasing-array/description/
+> 内容描述
-思路
+```
+Given an array with n integers, your task is to check if it could become non-decreasing by modifying at most 1 element.
+
+We define an array is non-decreasing if array[i] <= array[i + 1] holds for every i (1 <= i < n).
+
+Example 1:
+Input: [4,2,3]
+Output: True
+Explanation: You could modify the first 4 to 1 to get a non-decreasing array.
+Example 2:
+Input: [4,2,1]
+Output: False
+Explanation: You can't get a non-decreasing array by modify at most one element.
+Note: The n belongs to [1, 10,000].
+```
+
+## 解题方案
+
+> 思路 1
从index=1的元素依次检查,只要不符合规则则让count+1,如果count>1则肯定不符合返回False
但是我们在发现nums[i]小于nums[i-1]的时候,我们就必须要对原数组作出改变了,来让它的后面index部分尽可能满足条件
@@ -31,13 +50,15 @@ class Solution(object):
:type nums: List[int]
:rtype: bool
"""
+ if not nums or len(nums) <= 1:
+ return True
count = 0
- for i in range(1,len(nums)):
+ for i in range(1, len(nums)):
if nums[i] < nums[i-1]:
count += 1
if count > 1:
return False
- if i - 2 < 0 or nums[i-2] <= nums[i]:
+ if i-2 < 0 or nums[i-2] <= nums[i]:
nums[i-1] = nums[i]
else:
nums[i] = nums[i-1]
diff --git a/docs/leetcode/python/672._Bulb_Switcher_II.md b/docs/Leetcode_Solutions/Python/672._Bulb_Switcher_II.md
similarity index 57%
rename from docs/leetcode/python/672._Bulb_Switcher_II.md
rename to docs/Leetcode_Solutions/Python/672._Bulb_Switcher_II.md
index 2441178f4..3cad5b3ce 100644
--- a/docs/leetcode/python/672._Bulb_Switcher_II.md
+++ b/docs/Leetcode_Solutions/Python/672._Bulb_Switcher_II.md
@@ -1,15 +1,43 @@
-### 672. Bulb Switcher II
+# 672. Bulb Switcher II
-题目:
-
+**难度: Medium**
+## 刷题内容
-难度:
+> 原题连接
-Medium
+* https://leetcode.com/problems/bulb-switcher-ii/description/
+> 内容描述
-思路
+```
+There is a room with n lights which are turned on initially and 4 buttons on the wall. After performing exactly m unknown operations towards buttons, you need to return how many different kinds of status of the n lights could be.
+
+Suppose n lights are labeled as number [1, 2, 3 ..., n], function of these 4 buttons are given below:
+
+Flip all the lights.
+Flip lights with even numbers.
+Flip lights with odd numbers.
+Flip lights with (3k + 1) numbers, k = 0, 1, 2, ...
+Example 1:
+Input: n = 1, m = 1.
+Output: 2
+Explanation: Status can be: [on], [off]
+Example 2:
+Input: n = 2, m = 1.
+Output: 3
+Explanation: Status can be: [on, off], [off, on], [off, off]
+Example 3:
+Input: n = 3, m = 1.
+Output: 4
+Explanation: Status can be: [off, on, off], [on, off, on], [off, off, off], [off, on, on].
+Note: n and m both fit in range [0, 1000].
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(1)******- 空间复杂度: O(1)******
这道题又是一个数学题。找规律呀找规律。
我们只需要考虑当 n<=2 and m < 3 的特殊情形。因为当 n >2 and m >=3, 结果肯定是 8.
@@ -56,7 +84,11 @@ class Solution(object):
return 8
```
+> 思路 2
+
+
还有两位大佬的两行解法:
+
```python
class Solution(object):
def flipLights(self, n, m):
@@ -68,7 +100,6 @@ class Solution(object):
def flipLights(self, n, m):
n = min(n, 3)
return min(1<难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/valid-parenthesis-string/description/
+
+> 内容描述
+
+```
+
+Given a string containing only three types of characters: '(', ')' and '*', write a function to check whether this string is valid. We define the validity of a string by these rules:
+
+Any left parenthesis '(' must have a corresponding right parenthesis ')'.
+Any right parenthesis ')' must have a corresponding left parenthesis '('.
+Left parenthesis '(' must go before the corresponding right parenthesis ')'.
+'*' could be treated as a single right parenthesis ')' or a single left parenthesis '(' or an empty string.
+An empty string is also valid.
+Example 1:
+Input: "()"
+Output: True
+Example 2:
+Input: "(*)"
+Output: True
+Example 3:
+Input: "(*))"
+Output: True
+Note:
+The string size will be in the range [1, 100].
+```
+
+## 解题方案
+
+
+> 思路 1
+******- 时间复杂度: O(N^3)******- 空间复杂度: O(N^2)******
+
+```
+Let dp[i][j] be true if and only if the interval s[i], s[i+1], ..., s[j] can be made valid. Then dp[i][j] is true only if:
+
+s[i] is '*', and the interval s[i+1], s[i+2], ..., s[j] can be made valid;
+
+or, s[i] can be made to be '(', and there is some k in [i+1, j] such that s[k] can be made to be ')', plus the two intervals cut by s[k] (s[i+1: k] and s[k+1: j+1]) can be made valid;
+```
+因为文章要从垃圾算法写到好的算法,这不是我的第一解法
+
+但是是真的垃圾,才beats 2.75%
+```python
+class Solution(object):
+ def checkValidString(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ if not s or len(s) == 0:
+ return True
+
+ LEFTY, RIGHTY = '(*', ')*'
+
+ n = len(s)
+ dp = [[0] * n for _ in s]
+ for i in range(n):
+ if s[i] == '*':
+ dp[i][i] = 1
+ if i < n-1 and s[i] in LEFTY and s[i+1] in RIGHTY:
+ dp[i][i+1] = 1
+ for j in range(n):
+ for i in range(j-2, -1, -1):
+ if s[i] == '*' and dp[i+1][j]:
+ dp[i][j] = 1
+ elif s[i] in LEFTY:
+ for k in range(i+1, j+1):
+ if s[k] in RIGHTY and \
+ (k == i+1 or dp[i+1][k-1]) and \
+ (k == j or dp[k+1][j]):
+ dp[i][j] = 1
+
+ return True if dp[0][-1] else False
+```
+
+或者后面的循环按照子串的长度size来遍历,
+
+```python
+class Solution(object):
+ def checkValidString(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ if not s or len(s) == 0:
+ return True
+
+ LEFTY, RIGHTY = '(*', ')*'
+
+ n = len(s)
+ dp = [[False] * n for _ in s]
+ for i in range(n):
+ if s[i] == '*':
+ dp[i][i] = True
+ if i < n-1 and s[i] in LEFTY and s[i+1] in RIGHTY:
+ dp[i][i+1] = True
+
+ for size in range(2, n):
+ for i in range(n - size):
+ if s[i] == '*' and dp[i+1][i+size]:
+ dp[i][i+size] = True
+ elif s[i] in LEFTY:
+ for k in range(i+1, i+size+1):
+ if (s[k] in RIGHTY and \
+ (k == i+1 or dp[i+1][k-1]) and \
+ (k == i+size or dp[k+1][i+size])):
+ dp[i][i+size] = True
+
+ return dp[0][-1]
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+这是我的最初方法
+
+- Keep track of indices for unmatched '(' and available '*'.
+- After the loop we can check whether the index of any remaining '*' can match the unmatched '('.
+- If the index of star is greater than the index of '(' then they can match.
+
+beats 100%
+
+
+```python
+class Solution(object):
+ def checkValidString(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ if not s or len(s) == 0:
+ return True
+
+ stack, star = [], []
+ for i in range(len(s)):
+ if s[i] == '(':
+ stack.append(i)
+ elif s[i] == ')':
+ if stack:
+ stack.pop()
+ elif star:
+ star.pop()
+ else:
+ return False
+ else:
+ star.append(i)
+
+ while stack and star:
+ # 从后面开始比较,如果最后出现的'('的index比最后出现的'*'更大,那其实这个匹配不了,比如'*('
+ if stack[-1] > star[-1]:
+ return False
+ else:
+ stack.pop()
+ star.pop()
+
+ return not stack
+```
+
+> 思路 3
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+看到别人的解法,真的🐂p,贪心算法
+
+```
+We know that at each point in the string, '( 'count should never be bigger than ')' count, and in the end the difference of two counts should be 0.
+So we have two boundaries: lowerBond and higherBound, which respectively represents the minimun possible difference and maximum possbile difference, as long as
+
+higherBound is never below 0.
+in the end 0 is between lowerBond and higherBound
+in the string, when lowerbound is < 0, we make it back to 0.
+We know that the string is valid.
+```
+
+beats 100%
+
+```python
+class Solution(object):
+ def checkValidString(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ lower_bound = higher_bound = 0
+ for c in s:
+ lower_bound += 1 if c == '(' else -1
+ higher_bound += 1 if c != ')' else -1
+ if higher_bound < 0:
+ return False
+ lower_bound = max(lower_bound, 0)
+
+ return lower_bound == 0
+```
+
diff --git a/docs/Leetcode_Solutions/Python/680._Valid_Palindrome_II.md b/docs/Leetcode_Solutions/Python/680._Valid_Palindrome_II.md
new file mode 100644
index 000000000..b33597376
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/680._Valid_Palindrome_II.md
@@ -0,0 +1,111 @@
+# 680. Valid Palindrome II
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/valid-palindrome-ii/description/
+
+> 内容描述
+
+```
+
+Given a non-empty string s, you may delete at most one character. Judge whether you can make it a palindrome.
+
+Example 1:
+Input: "aba"
+Output: True
+Example 2:
+Input: "abca"
+Output: True
+Explanation: You could delete the character 'c'.
+Note:
+The string will only contain lowercase characters a-z. The maximum length of the string is 50000.
+```
+
+## 解题方案
+
+> 思路 1
+
+想直接来个 for loop,看看对应除去该index元素之后的字符串是否为 palindrome 即可
+
+但是直接 Time Limit Exceeded
+
+```python
+class Solution(object):
+ def validPalindrome(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ for i in range(len(s)):
+ if s[:i] + s[i+1:] == s[i+1:][::-1] + s[:i][::-1]:
+ return True
+ return False
+```
+
+
+> 思路 2
+
+我们先定义一个reverse变量作为字符串s的翻转版本,例如
+
+```
+s = 'abbbbbca'
+reverse = 'acbbbbba'
+```
+
+然后我们从第一个字符开始比较,直到两边的字符不相等的时候,比如上面的例子我们就是index为1的时候不相等,所以i = 1,此时我们就会面临两个选择:
+
+1. 我们可以舍弃s中index为i的这个元素看看是否可以使其成为palindrome,即让s变成'abbbbca',然后我们可以通过s[i+1:n-i] == reverse[i:n-i-1]来判断
+2. 我们可以舍弃reverse中index为i的这个元素(即s中index为n-1-i的这个元素),即让s变成'abbbbba',我们可以通过s[i:n-1-i] == reverse[i+1:n-i]来判断
+
+```python
+class Solution(object):
+ def validPalindrome(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ n = len(s)
+ if n < 3:
+ return True
+
+ reverse = s[::-1]
+ i = 0
+ while i < len(s) and s[i] == reverse[i]:
+ i += 1
+ return s[i:n-1-i] == reverse[i+1:n-i] or s[i+1:n-i] == reverse[i:n-i-1]
+```
+
+
+
+> 思路 3
+
+或者我们不搞reverse,直接在s上面原地判断即可
+
+
+```python
+class Solution(object):
+ def validPalindrome(self, s):
+ """
+ :type s: str
+ :rtype: bool
+ """
+ n = len(s)
+ if n < 3:
+ return True
+
+ l, r = 0, n - 1
+ while l < r and s[l] == s[r]:
+ l += 1
+ r -= 1
+ if l >= r:
+ return True
+ else:
+ return s[l+1:r+1] == s[l+1:r+1][::-1] or s[l:r] == s[l:r][::-1]
+```
+
+
+
diff --git a/docs/leetcode/python/681._Next_Closest_Time.md b/docs/Leetcode_Solutions/Python/681._Next_Closest_Time.md
similarity index 100%
rename from docs/leetcode/python/681._Next_Closest_Time.md
rename to docs/Leetcode_Solutions/Python/681._Next_Closest_Time.md
diff --git a/docs/leetcode/python/682._Baseball_Game.md b/docs/Leetcode_Solutions/Python/682._Baseball_Game.md
similarity index 100%
rename from docs/leetcode/python/682._Baseball_Game.md
rename to docs/Leetcode_Solutions/Python/682._Baseball_Game.md
diff --git a/docs/leetcode/python/685._Redundant_Connection_II.md b/docs/Leetcode_Solutions/Python/685._Redundant_Connection_II.md
similarity index 100%
rename from docs/leetcode/python/685._Redundant_Connection_II.md
rename to docs/Leetcode_Solutions/Python/685._Redundant_Connection_II.md
diff --git a/docs/leetcode/python/687._Longest_Univalue_Path.md b/docs/Leetcode_Solutions/Python/687._Longest_Univalue_Path.md
similarity index 100%
rename from docs/leetcode/python/687._Longest_Univalue_Path.md
rename to docs/Leetcode_Solutions/Python/687._Longest_Univalue_Path.md
diff --git a/docs/leetcode/python/693._Binary_Number_with_Alternating_Bits.md b/docs/Leetcode_Solutions/Python/693._Binary_Number_with_Alternating_Bits.md
similarity index 97%
rename from docs/leetcode/python/693._Binary_Number_with_Alternating_Bits.md
rename to docs/Leetcode_Solutions/Python/693._Binary_Number_with_Alternating_Bits.md
index 0fdbac4b1..f95ae536e 100644
--- a/docs/leetcode/python/693._Binary_Number_with_Alternating_Bits.md
+++ b/docs/Leetcode_Solutions/Python/693._Binary_Number_with_Alternating_Bits.md
@@ -6,8 +6,8 @@
> 原题连接
-* https://leetcode.com/problems/binary-number-with-alternating-bits
-* https://leetcode-cn.com/problems/binary-number-with-alternating-bits
+* https://leetcode.com/problems/binary-number-with-alternating-bits/description/
+* https://leetcode-cn.com/problems/binary-number-with-alternating-bits/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/695._Max_Area_of_Island.md b/docs/Leetcode_Solutions/Python/695._Max_Area_of_Island.md
new file mode 100644
index 000000000..f25827006
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/695._Max_Area_of_Island.md
@@ -0,0 +1,164 @@
+# 695. Max Area of Island
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/max-area-of-island/description/
+
+> 内容描述
+
+```
+Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.
+
+Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.)
+
+Example 1:
+[[0,0,1,0,0,0,0,1,0,0,0,0,0],
+ [0,0,0,0,0,0,0,1,1,1,0,0,0],
+ [0,1,1,0,1,0,0,0,0,0,0,0,0],
+ [0,1,0,0,1,1,0,0,1,0,1,0,0],
+ [0,1,0,0,1,1,0,0,1,1,1,0,0],
+ [0,0,0,0,0,0,0,0,0,0,1,0,0],
+ [0,0,0,0,0,0,0,1,1,1,0,0,0],
+ [0,0,0,0,0,0,0,1,1,0,0,0,0]]
+Given the above grid, return 6. Note the answer is not 11, because the island must be connected 4-directionally.
+Example 2:
+[[0,0,0,0,0,0,0,0]]
+Given the above grid, return 0.
+Note: The length of each dimension in the given grid does not exceed 50.
+```
+
+## 解题方案
+
+> 思路 1
+
+
+对于每一个点我们不停的dfs,然后每次碰到一个点是1我们就将当前area加1,然后把这个点变成0,每一次都更新我们的res,最终返回res
+
+```python
+class Solution(object):
+ def maxAreaOfIsland(self, grid):
+ """
+ :type grid: List[List[int]]
+ :rtype: int
+ """
+ if not grid or len(grid) == 0:
+ return 0
+ m = len(grid)
+ n = len(grid[0]) if m else 0
+
+ def dfs(i, j, area):
+ if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] != 1:
+ return area
+ else:
+ grid[i][j] = 0
+ area += 1
+ for x, y in ([(i, j+1), (i, j-1), (i+1, j), (i-1, j)]):
+ area = dfs(x, y, area)
+ return area
+
+ res = 0
+ for i in range(len(grid)):
+ for j in range(len(grid[0])):
+ area = dfs(i, j, 0)
+ res = max(res, area)
+ return res
+```
+
+
+
+## Follow up:
+
+If we still want the max area of the island, but if one land is surrrounded all by land,
+then it should not be part of our area, how can we solve it?
+
+
+
+
+比如:
+```
+1 0 0 1 1 1
+1 0 0 1 1 1
+0 0 0 0 1 1
+```
+
+这个我们要返回的是7而不是8,因为坐标为(1,4)的点被陆地包围,所以我们不算他的面积
+
+大概思路就是并查集,然后各大岛屿的坐标集合遍历一遍看看有没有没有点完全被包围,有的话就面积减1,然后最后算出来,
+参考[leetcode 200](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/200._number_of_islands.md)
+和 [leetcode 305](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/305._Number_of_Islands_II.md)
+
+```python
+def find(x, uf):
+ while x != uf[x]:
+ uf[x] = uf[uf[x]]
+ x = uf[x]
+ return uf[x]
+
+class Solution(object):
+ uf, idx = {}, 1
+ def numIslands(self, grid):
+ """
+ :type grid: List[List[str]]
+ :rtype: int
+ """
+ m = len(grid)
+ n = len(grid[0])
+
+
+
+ def sink(i, j):
+ if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == '1':
+ self.uf[(i,j)] = self.uf[self.idx] = self.idx
+ grid[i][j] = '0'
+ for x, y in [(i, j+1), (i, j-1), (i+1, j), (i-1, j)]:
+ if (x,y) in self.uf:
+ root = find(self.uf[(x,y)], self.uf)
+ self.uf[root] = self.idx
+ self.idx += 1
+ map(sink, (i+1, i-1, i, i), (j, j, j+1, j-1))
+
+ for i in range(len(grid)):
+ for j in range(len(grid[0])):
+ sink(i, j)
+ return self.uf
+
+grid = [["1","1","1","1","0"],["1","1","1","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]
+grid1 = [["1","1","1","1","0"],["1","1","1","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]
+# print(Solution().numIslands(grid))
+
+uf = Solution().numIslands(grid)
+print(uf)
+
+islands = {}
+for key in uf.keys():
+ if type(key).__name__ != 'int':
+ if find(key, uf) not in islands:
+ islands[find(key, uf)] = [key]
+ else:
+ islands[find(key, uf)].append(key)
+print(islands)
+
+print(grid)
+max_aera = -float('inf')
+for key in islands.keys():
+ aera = len(islands[key])
+ for i, j in islands[key]:
+ tmp = 0
+ for x, y in [(i, j + 1), (i, j - 1), (i + 1, j), (i - 1, j)]:
+ if 0 <= x < len(grid1) and 0 <= y < len(grid1[0]) and grid1[x][y] == '1':
+ tmp += 1
+ if tmp == 4:
+ aera -= 1
+ max_aera = max(max_aera, aera)
+print(max_aera)
+```
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/698._Partition_to_K_Equal_Sum_Subsets.md b/docs/Leetcode_Solutions/Python/698._Partition_to_K_Equal_Sum_Subsets.md
new file mode 100644
index 000000000..ebf2f58f6
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/698._Partition_to_K_Equal_Sum_Subsets.md
@@ -0,0 +1,61 @@
+# 698. Partition to K Equal Sum Subsets
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/partition-to-k-equal-sum-subsets/description/
+
+> 内容描述
+
+```
+Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal.
+
+Example 1:
+Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
+Output: True
+Explanation: It's possible to divide it into 4 subsets (5), (1, 4), (2,3), (2,3) with equal sums.
+Note:
+
+1 <= k <= len(nums) <= 16.
+0 < nums[i] < 10000.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N!)******- 空间复杂度: O(N)******
+
+
+
+将问题一步一步缩小到找一个subset的sum为target的问题,即剩下的整个数组的sum是否为target
+```python
+class Solution(object):
+ def canPartitionKSubsets(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: bool
+ """
+ def dfs(nums, target, num, k):
+ if k == 0:
+ return True
+ for i in range(len(nums)):
+ new_nums = nums[:i] + nums[i+1:]
+ if num + nums[i] == target:
+ if dfs(new_nums, target, 0, k-1):
+ return True
+ elif num + nums[i] < target:
+ if dfs(new_nums, target, num+nums[i], k):
+ return True
+ elif num == 0: # 有一个数比target还大,直接返回False
+ return False
+ return False
+ if sum(nums) % k != 0:
+ return False
+ target = sum(nums) / k
+ nums.sort(reverse = True) # 逆序排序,先从大的开始判断,速度会更快
+ return dfs(nums, target, 0, k)
+```
diff --git a/docs/leetcode/python/701._Insert_into_a_Binary_Search_Tree.md b/docs/Leetcode_Solutions/Python/701._Insert_into_a_Binary_Search_Tree.md
similarity index 100%
rename from docs/leetcode/python/701._Insert_into_a_Binary_Search_Tree.md
rename to docs/Leetcode_Solutions/Python/701._Insert_into_a_Binary_Search_Tree.md
diff --git a/docs/leetcode/python/707._Design_Linked_List.md b/docs/Leetcode_Solutions/Python/707._Design_Linked_List.md
similarity index 98%
rename from docs/leetcode/python/707._Design_Linked_List.md
rename to docs/Leetcode_Solutions/Python/707._Design_Linked_List.md
index 6b84db798..7623a50ac 100644
--- a/docs/leetcode/python/707._Design_Linked_List.md
+++ b/docs/Leetcode_Solutions/Python/707._Design_Linked_List.md
@@ -6,7 +6,7 @@
> 原题连接
-* https://leetcode.com/problems/design-linked-list
+* https://leetcode.com/problems/design-linked-list/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/713._Subarray_Product_Less_Than_K.md b/docs/Leetcode_Solutions/Python/713._Subarray_Product_Less_Than_K.md
new file mode 100644
index 000000000..926a87203
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/713._Subarray_Product_Less_Than_K.md
@@ -0,0 +1,95 @@
+# 713. Subarray Product Less Than K
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/subarray-product-less-than-k/description/
+
+> 内容描述
+
+```
+Your are given an array of positive integers nums.
+
+Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k.
+
+Example 1:
+Input: nums = [10, 5, 2, 6], k = 100
+Output: 8
+Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6].
+Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.
+Note:
+
+0 < nums.length <= 50000.
+0 < nums[i] < 1000.
+0 <= k < 10^6.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******
+
+跟第560题思路一样,维护一个当前积的常量,每次只要看之前有多少个积大于 cur_product/nums[i]的,如果有就说明最近出现的这个subarray product可以小于k
+
+但是超时了
+
+```
+class Solution(object):
+ def numSubarrayProductLessThanK(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: int
+ """
+ if k == 0:
+ n = nums.count(0)
+ return n*(n+1)/2
+ # 这是为了保证如果当前product的值就等于k的话,我们其实也相当于找到一次
+ lookup = {1:1}
+ res = 0
+ cur_product = 1
+ for num in nums:
+ cur_product *= num
+ res += sum(lookup[key] for key in lookup.keys() if key > cur_product/k)
+ # for key in lookup.keys():
+ # if key > cur_product / k:
+ # res += lookup.get(key)
+ lookup[cur_product] = lookup.get(cur_product, 0) + 1
+ return res
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+参考[gabbu](https://leetcode.com/problems/subarray-product-less-than-k/discuss/108846/Python-solution-with-detailed-explanation)
+```
+Initialize start and end to index 0. Initialize prod to 1. Iterate end from 0 to len(nums)-1.
+Now if prod * nums[end] is less than k, then all subarray between start and end contribute to the solution.
+Since we are moving from left to right, we would have already counted all valid subarrays from start to end-1.
+How many new subarrays with nums[end]? Answer: end-start. What will be the updated prod? Answer: prod * nums[end].
+
+```
+
+```python
+class Solution(object):
+ def numSubarrayProductLessThanK(self, nums, k):
+ """
+ :type nums: List[int]
+ :type k: int
+ :rtype: int
+ """
+ if k <= 1:
+ return 0
+ res, l, r, cur_product = 0, 0, 0, 1
+ while r < len(nums):
+ cur_product *= nums[r]
+ r += 1
+ while cur_product >= k:
+ cur_product /= nums[l]
+ l += 1
+ res += r - l
+ return res
+```
diff --git a/docs/Leetcode_Solutions/Python/724._Find_Pivot_Index.md b/docs/Leetcode_Solutions/Python/724._Find_Pivot_Index.md
new file mode 100644
index 000000000..04ab325d9
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/724._Find_Pivot_Index.md
@@ -0,0 +1,112 @@
+# 724. Find Pivot Index
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/find-pivot-index/description/
+
+> 内容描述
+
+```
+Given an array of integers nums, write a method that returns the "pivot" index of this array.
+
+We define the pivot index as the index where the sum of the numbers to the left of the index is equal to the sum of the numbers to the right of the index.
+
+If no such index exists, we should return -1. If there are multiple pivot indexes, you should return the left-most pivot index.
+
+Example 1:
+Input:
+nums = [1, 7, 3, 6, 5, 6]
+Output: 3
+Explanation:
+The sum of the numbers to the left of index 3 (nums[3] = 6) is equal to the sum of numbers to the right of index 3.
+Also, 3 is the first index where this occurs.
+Example 2:
+Input:
+nums = [1, 2, 3]
+Output: -1
+Explanation:
+There is no index that satisfies the conditions in the problem statement.
+Note:
+
+The length of nums will be in the range [0, 10000].
+Each element nums[i] will be an integer in the range [-1000, 1000].
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+
+前缀和数组+后缀和数组,实现时间复杂度O(n)和空间复杂度O(n),3分钟 bug free
+
+
+
+```python
+class Solution(object):
+ def pivotIndex(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ if not nums or len(nums) == 0:
+ return -1
+
+ prefix_sums = [nums[0]] * len(nums)
+ for i in range(1, len(nums)):
+ prefix_sums[i] = nums[i] + prefix_sums[i-1]
+
+ suffix_sums = [nums[-1]] * len(nums)
+ for i in range(len(nums)-2, -1, -1):
+ suffix_sums[i] = nums[i] + suffix_sums[i+1]
+
+ sums = sum(nums)
+ if sum(nums[1:]) == 0:
+ return 0
+ for i in range(1, len(nums)):
+ if prefix_sums[i] == suffix_sums[i]:
+ return i
+ return -1
+```
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+后面发现其实空间只要O(1)就可以了,就是用left_sum, right_sum分别代表左右两边的和,初始化为0和sum(nums)
+
+```python
+class Solution(object):
+ def pivotIndex(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ left_sum, right_sum = 0, sum(nums)
+ for idx, num in enumerate(nums):
+ right_sum -= num
+ if left_sum == right_sum:
+ return idx
+ left_sum += num
+ return -1
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/733._Flood_Fill.md b/docs/Leetcode_Solutions/Python/733._Flood_Fill.md
new file mode 100644
index 000000000..d1c54dceb
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/733._Flood_Fill.md
@@ -0,0 +1,80 @@
+# 733. Flood Fill
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/flood-fill/description/
+
+> 内容描述
+
+```
+An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535).
+
+Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newColor, "flood fill" the image.
+
+To perform a "flood fill", consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color as the starting pixel), and so on. Replace the color of all of the aforementioned pixels with the newColor.
+
+At the end, return the modified image.
+
+Example 1:
+Input:
+image = [[1,1,1],[1,1,0],[1,0,1]]
+sr = 1, sc = 1, newColor = 2
+Output: [[2,2,2],[2,2,0],[2,0,1]]
+Explanation:
+From the center of the image (with position (sr, sc) = (1, 1)), all pixels connected
+by a path of the same color as the starting pixel are colored with the new color.
+Note the bottom corner is not colored 2, because it is not 4-directionally connected
+to the starting pixel.
+Note:
+
+The length of image and image[0] will be in the range [1, 50].
+The given starting pixel will satisfy 0 <= sr < image.length and 0 <= sc < image[0].length.
+The value of each color in image[i][j] and newColor will be an integer in [0, 65535].
+
+```
+
+## 解题方案
+
+> 思路 1
+
+
+dfs, 多加了一层判断,只有周围color一样才放进stack里面
+
+```python
+class Solution(object):
+ def floodFill(self, image, sr, sc, newColor):
+ """
+ :type image: List[List[int]]
+ :type sr: int
+ :type sc: int
+ :type newColor: int
+ :rtype: List[List[int]]
+ """
+ row = len(image)
+ col = len(image[0]) if row else 0
+ directions = [[1,0], [-1,0], [0,1], [0,-1]]
+
+ def dfs(image, sr, sc, color):
+ stack, visited = [[sr, sc]], []
+ flood = []
+ while stack:
+ vertex = stack.pop()
+ if vertex not in visited:
+ flood.append(vertex)
+ visited.append(vertex)
+ x, y = vertex[0], vertex[1]
+ for dire in directions:
+ if 0 <= x+dire[0] < row and 0 <= y+dire[1] < col:
+ if [x+dire[0], y+dire[1]] not in visited:
+ if image[x+dire[0]][y+dire[1]] == color:
+ stack.append([x+dire[0], y+dire[1]])
+ return flood
+
+ for i in dfs(image, sr, sc, image[sr][sc]):
+ image[i[0]][i[1]] = newColor
+ return image
+```
diff --git a/docs/Leetcode_Solutions/Python/740._delete_and_earn.md b/docs/Leetcode_Solutions/Python/740._delete_and_earn.md
new file mode 100644
index 000000000..7d50fc5a8
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/740._delete_and_earn.md
@@ -0,0 +1,85 @@
+# 740. Delete and Earn
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/delete-and-earn/description/
+
+> 内容描述
+
+```
+Given an array nums of integers, you can perform operations on the array.
+
+In each operation, you pick any nums[i] and delete it to earn nums[i] points. After, you must delete every element equal to nums[i] - 1 or nums[i] + 1.
+
+You start with 0 points. Return the maximum number of points you can earn by applying such operations.
+
+Example 1:
+Input: nums = [3, 4, 2]
+Output: 6
+Explanation:
+Delete 4 to earn 4 points, consequently 3 is also deleted.
+Then, delete 2 to earn 2 points. 6 total points are earned.
+Example 2:
+Input: nums = [2, 2, 3, 3, 3, 4]
+Output: 9
+Explanation:
+Delete 3 to earn 3 points, deleting both 2's and the 4.
+Then, delete 3 again to earn 3 points, and 3 again to earn 3 points.
+9 total points are earned.
+Note:
+
+The length of nums is at most 20000.
+Each element nums[i] is an integer in the range [1, 10000].
+```
+
+## 解题方案
+
+> 思路 1
+
+典型dp,dp[i]代表的是数字i,然后我们将其变化为删除数字i我们可以得到的最大分数(已经处理过所有比i小的数字了)。
+
+推导公式为dp[i] = max(dp[i]+dp[i-2], dp[i-1]),
+
+- 即要么删除dp[i]得到所有数字i的和
+- 要么删除dp[i-1]不要dp[i]的分数
+
+又因为Each element nums[i] is an integer in the range [1, 10000],所以dp长度初始化为10001
+
+```python
+class Solution(object):
+ def deleteAndEarn(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ dp = [0] * 10001
+ for num in nums:
+ # now dp[num] = sum of the num in nums
+ dp[num] += num
+ for i in range(2, 10001):
+ dp[i] = max(dp[i]+dp[i-2], dp[i-1])
+ return dp[-1]
+```
+
+
+> 思路 2
+
+迭代
+
+```python
+class Solution(object):
+ def deleteAndEarn(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: int
+ """
+ last, now = 0, 0
+ for value in range(10001):
+ last, now = now, max(last + value * nums.count(value), now)
+ return now
+```
+
diff --git a/docs/leetcode/python/760._Find_Anagram_Mappings.md b/docs/Leetcode_Solutions/Python/760._Find_Anagram_Mappings.md
similarity index 100%
rename from docs/leetcode/python/760._Find_Anagram_Mappings.md
rename to docs/Leetcode_Solutions/Python/760._Find_Anagram_Mappings.md
diff --git a/docs/leetcode/python/774._Minimize_Max_Distance_to_Gas_Station.md b/docs/Leetcode_Solutions/Python/774._Minimize_Max_Distance_to_Gas_Station.md
similarity index 99%
rename from docs/leetcode/python/774._Minimize_Max_Distance_to_Gas_Station.md
rename to docs/Leetcode_Solutions/Python/774._Minimize_Max_Distance_to_Gas_Station.md
index 6dc7c9af6..e9c4c06b6 100644
--- a/docs/leetcode/python/774._Minimize_Max_Distance_to_Gas_Station.md
+++ b/docs/Leetcode_Solutions/Python/774._Minimize_Max_Distance_to_Gas_Station.md
@@ -5,7 +5,7 @@
> 原题连接
-* https://leetcode.com/problems/minimize-max-distance-to-gas-station
+* https://leetcode.com/problems/minimize-max-distance-to-gas-station/description/
> 内容描述
diff --git a/docs/leetcode/python/777._Swap_Adjacent_in_LR_String.md b/docs/Leetcode_Solutions/Python/777. Swap_Adjacent_in_LR_String.md
similarity index 96%
rename from docs/leetcode/python/777._Swap_Adjacent_in_LR_String.md
rename to docs/Leetcode_Solutions/Python/777. Swap_Adjacent_in_LR_String.md
index 77ee48e29..af0a30019 100644
--- a/docs/leetcode/python/777._Swap_Adjacent_in_LR_String.md
+++ b/docs/Leetcode_Solutions/Python/777. Swap_Adjacent_in_LR_String.md
@@ -6,8 +6,8 @@
> 原题连接
-* https://leetcode.com/problems/swap-adjacent-in-lr-string
-* https://leetcode-cn.com/problems/swap-adjacent-in-lr-string
+* https://leetcode.com/problems/swap-adjacent-in-lr-string/description/
+* https://leetcode-cn.com/problems/swap-adjacent-in-lr-string/description/
> 内容描述
diff --git a/docs/Leetcode_Solutions/Python/785._Is_Graph_Bipartite?.md b/docs/Leetcode_Solutions/Python/785._Is_Graph_Bipartite?.md
new file mode 100644
index 000000000..380db1feb
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/785._Is_Graph_Bipartite?.md
@@ -0,0 +1,80 @@
+# 785. Is Graph Bipartite?
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/is-graph-bipartite/description/
+
+> 内容描述
+
+```
+
+Given an undirected graph, return true if and only if it is bipartite.
+
+Recall that a graph is bipartite if we can split it's set of nodes into two independent subsets A and B such that every edge in the graph has one node in A and another node in B.
+
+The graph is given in the following form: graph[i] is a list of indexes j for which the edge between nodes i and j exists. Each node is an integer between 0 and graph.length - 1. There are no self edges or parallel edges: graph[i] does not contain i, and it doesn't contain any element twice.
+
+Example 1:
+Input: [[1,3], [0,2], [1,3], [0,2]]
+Output: true
+Explanation:
+The graph looks like this:
+0----1
+| |
+| |
+3----2
+We can divide the vertices into two groups: {0, 2} and {1, 3}.
+Example 2:
+Input: [[1,2,3], [0,2], [0,1,3], [0,2]]
+Output: false
+Explanation:
+The graph looks like this:
+0----1
+| \ |
+| \ |
+3----2
+We cannot find a way to divide the set of nodes into two independent subsets.
+
+
+Note:
+
+graph will have length in range [1, 100].
+graph[i] will contain integers in range [0, graph.length - 1].
+graph[i] will not contain i or duplicate values.
+The graph is undirected: if any element j is in graph[i], then i will be in graph[j].
+```
+
+## 解题方案
+
+> 思路 1
+
+
+
+```python
+class Solution:
+ def isBipartite(self, graph):
+ """
+ :type graph: List[List[int]]
+ :rtype: bool
+ """
+ visited = set()
+ for i in range(len(graph)):
+ if i in visited or len(graph[i]) == 0:
+ continue
+ level = {i}
+ while level:
+ next_level = set()
+ for j in level:
+ visited.add(j)
+ for n in graph[j]:
+ if n in level:
+ return False
+ if n not in visited:
+ next_level.add(n)
+ level = next_level
+ return True
+```
diff --git a/docs/Leetcode_Solutions/Python/792._Number_of_Matching_Subsequences.md b/docs/Leetcode_Solutions/Python/792._Number_of_Matching_Subsequences.md
new file mode 100644
index 000000000..334ddf5af
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/792._Number_of_Matching_Subsequences.md
@@ -0,0 +1,206 @@
+# 792. Number of Matching Subsequences
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/number-of-matching-subsequences/description/
+
+> 内容描述
+
+```
+Given string S and a dictionary of words words, find the number of words[i] that is a subsequence of S.
+
+Example :
+Input:
+S = "abcde"
+words = ["a", "bb", "acd", "ace"]
+Output: 3
+Explanation: There are three words in words that are a subsequence of S: "a", "acd", "ace".
+Note:
+
+All words in words and S will only consists of lowercase letters.
+The length of S will be in the range of [1, 50000].
+The length of words will be in the range of [1, 5000].
+The length of words[i] will be in the range of [1, 50].
+```
+
+## 解题方案
+
+假设words里面最长的word长度为m,words的长度为n,S的长度为s
+
+> 思路 1
+******- 时间复杂度: O(m*n*s)******- 空间复杂度: O(1)******
+
+暴力,超时
+```
+class Solution(object):
+ def numMatchingSubseq(self, S, words):
+ """
+ :type S: str
+ :type words: List[str]
+ :rtype: int
+ """
+ def match(word, S):
+ i, j = 0, 0
+ while i < len(word) and j < len(S):
+ if word[i] == S[j]:
+ i += 1
+ j += 1
+ else:
+ j += 1
+ return i == len(word)
+
+ res = 0
+ for word in words:
+ if match(word, S):
+ res += 1
+ return res
+```
+
+我觉得是不是多加一个判断,如果一个字符在S里面没有立马返回False这样会快一点,但是还是超时
+
+```
+class Solution(object):
+ def numMatchingSubseq(self, S, words):
+ """
+ :type S: str
+ :type words: List[str]
+ :rtype: int
+ """
+ def match(word, S):
+ i = 0
+ while S and i < len(word):
+ idx = S.find(word[i])
+ if idx == -1:
+ return False
+ S = S[idx+1:]
+ i += 1
+ return i == len(word)
+
+ res = 0
+ for word in words:
+ if match(word, S):
+ res += 1
+ return res
+```
+
+
+于是又觉得用自带的iter函数会不会快一点,结果还是超时
+
+
+```
+class Solution(object):
+ def numMatchingSubseq(self, S, words):
+ """
+ :type S: str
+ :type words: List[str]
+ :rtype: int
+ """
+ def match(word, S):
+ it = iter(S)
+ if all(c in it for c in word):
+ return True
+ return False
+
+ res = 0
+ for word in words:
+ if match(word, S):
+ res += 1
+ return res
+```
+
+
+> 思路 2
+******- 时间复杂度: O(m*n*s)******- 空间复杂度: O(N)******
+
+终于,我想到了用memorization,AC了,beats 70.4%
+
+```python
+class Solution(object):
+ def numMatchingSubseq(self, S, words):
+ """
+ :type S: str
+ :type words: List[str]
+ :rtype: int
+ """
+ def match(word, S):
+ it = iter(S)
+ if all(c in it for c in word):
+ return True
+ return False
+
+ res = 0
+ matched, unmatched = set(), set()
+ for word in words:
+ if word in matched:
+ res += 1
+ continue
+ elif word in unmatched:
+ continue
+ else:
+ if match(word, S):
+ res += 1
+ matched.add(word)
+ else:
+ unmatched.add(word)
+ return res
+```
+
+
+然后换了之前我觉得写的最好最快的match函数,beats 100%
+
+```python
+class Solution(object):
+ def numMatchingSubseq(self, S, words):
+ """
+ :type S: str
+ :type words: List[str]
+ :rtype: int
+ """
+ def match(sub, s):
+ idx = 0
+ for c in sub:
+ idx = s.find(c, idx) + 1
+ if idx == 0:
+ return False
+ return True
+
+ res = 0
+ matched, unmatched = set(), set()
+ for word in words:
+ if word in matched:
+ res += 1
+ continue
+ elif word in unmatched:
+ continue
+ else:
+ if match(word, S):
+ res += 1
+ matched.add(word)
+ else:
+ unmatched.add(word)
+ return res
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/796._Rotate_String.md b/docs/Leetcode_Solutions/Python/796._Rotate_String.md
new file mode 100644
index 000000000..1e08139be
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/796._Rotate_String.md
@@ -0,0 +1,46 @@
+# 796. Rotate String
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/rotate-string/description/
+
+> 内容描述
+
+```
+We are given two strings, A and B.
+
+A shift on A consists of taking string A and moving the leftmost character to the rightmost position. For example, if A = 'abcde', then it will be 'bcdea' after one shift on A. Return True if and only if A can become B after some number of shifts on A.
+
+Example 1:
+Input: A = 'abcde', B = 'cdeab'
+Output: true
+
+Example 2:
+Input: A = 'abcde', B = 'abced'
+Output: false
+Note:
+
+A and B will have length at most 100.
+```
+
+## 解题方案
+
+> 思路 1
+
+
+一行就够了,太简单了
+
+```python
+class Solution(object):
+ def rotateString(self, A, B):
+ """
+ :type A: str
+ :type B: str
+ :rtype: bool
+ """
+ return len(A) == len(B) and B in A * 2
+```
diff --git a/docs/Leetcode_Solutions/Python/801._Minimum_Swaps_To_Make_Sequences_Increasing.md b/docs/Leetcode_Solutions/Python/801._Minimum_Swaps_To_Make_Sequences_Increasing.md
new file mode 100644
index 000000000..df94d1a4d
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/801._Minimum_Swaps_To_Make_Sequences_Increasing.md
@@ -0,0 +1,67 @@
+# 801. Minimum Swaps To Make Sequences Increasing
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/description/
+
+> 内容描述
+
+```
+
+We have two integer sequences A and B of the same non-zero length.
+
+We are allowed to swap elements A[i] and B[i]. Note that both elements are in the same index position in their respective sequences.
+
+At the end of some number of swaps, A and B are both strictly increasing. (A sequence is strictly increasing if and only if A[0] < A[1] < A[2] < ... < A[A.length - 1].)
+
+Given A and B, return the minimum number of swaps to make both sequences strictly increasing. It is guaranteed that the given input always makes it possible.
+
+Example:
+Input: A = [1,3,5,4], B = [1,2,3,7]
+Output: 1
+Explanation:
+Swap A[3] and B[3]. Then the sequences are:
+A = [1, 3, 5, 7] and B = [1, 2, 3, 4]
+which are both strictly increasing.
+Note:
+
+A, B are arrays with the same length, and that length will be in the range [1, 1000].
+A[i], B[i] are integer values in the range [0, 2000].
+```
+
+## 解题方案
+
+> 思路 1
+
+
+参考大神[Luckypants](https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/discuss/119830/Python-14-line-O(1)-space-O(n)-time-DP-solution)的思路
+
+
+- dp[i][0] means the least swaps used to make A[:i+1] and B[:i+1] sorted having no swap at i-th position.
+- dp[i][1] means the least swaps used to make A[:i+1] and B[:i+1] sorted having swap at i-th position.
+
+```python
+class Solution(object):
+ def minSwap(self, A, B):
+ """
+ :type A: List[int]
+ :type B: List[int]
+ :rtype: int
+ """
+ n = len(A)
+ pre = [0, 1]
+ for i in range(1, n):
+ cur = [sys.maxsize, sys.maxsize]
+ if A[i]>A[i-1] and B[i]>B[i-1]:
+ cur[0] = min(cur[0], pre[0])
+ cur[1] = min(cur[1], pre[1]+1)
+ if A[i]>B[i-1] and B[i]>A[i-1]:
+ cur[0] = min(cur[0], pre[1])
+ cur[1] = min(cur[1], pre[0]+1)
+ pre = cur
+ return min(pre)
+```
diff --git a/docs/Leetcode_Solutions/Python/824._Goat_Latin.md b/docs/Leetcode_Solutions/Python/824._Goat_Latin.md
new file mode 100644
index 000000000..6d1ca175e
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/824._Goat_Latin.md
@@ -0,0 +1,72 @@
+# 824. Goat Latin
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/goat-latin/description/
+
+> 内容描述
+
+```
+A sentence S is given, composed of words separated by spaces. Each word consists of lowercase and uppercase letters only.
+
+We would like to convert the sentence to "Goat Latin" (a made-up language similar to Pig Latin.)
+
+The rules of Goat Latin are as follows:
+
+If a word begins with a vowel (a, e, i, o, or u), append "ma" to the end of the word.
+For example, the word 'apple' becomes 'applema'.
+
+If a word begins with a consonant (i.e. not a vowel), remove the first letter and append it to the end, then add "ma".
+For example, the word "goat" becomes "oatgma".
+
+Add one letter 'a' to the end of each word per its word index in the sentence, starting with 1.
+For example, the first word gets "a" added to the end, the second word gets "aa" added to the end and so on.
+Return the final sentence representing the conversion from S to Goat Latin.
+
+
+
+Example 1:
+
+Input: "I speak Goat Latin"
+Output: "Imaa peaksmaaa oatGmaaaa atinLmaaaaa"
+Example 2:
+
+Input: "The quick brown fox jumped over the lazy dog"
+Output: "heTmaa uickqmaaa rownbmaaaa oxfmaaaaa umpedjmaaaaaa overmaaaaaaa hetmaaaaaaaa azylmaaaaaaaaa ogdmaaaaaaaaaa"
+
+
+Notes:
+
+S contains only uppercase, lowercase and spaces. Exactly one space between each word.
+1 <= S.length <= 150.
+```
+
+## 解题方案
+
+> 思路 1
+
+
+sb题没什么好说的
+
+```python
+class Solution(object):
+ def toGoatLatin(self, S):
+ """
+ :type S: str
+ :rtype: str
+ """
+ res = ''
+ for index, word in enumerate(S.split()):
+ if(word[0] in 'aeiouAEIOU'):
+ word = word + 'ma'
+ else:
+ tmp = word[0]
+ word = word[1:] + tmp + 'ma'
+ word = word + 'a' * (index + 1)
+ res = res + ' ' + word
+ return res[1:]
+```
diff --git a/docs/Leetcode_Solutions/Python/844._Backspace_String_Compare.md b/docs/Leetcode_Solutions/Python/844._Backspace_String_Compare.md
new file mode 100644
index 000000000..d62ebc325
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/844._Backspace_String_Compare.md
@@ -0,0 +1,171 @@
+# 844. Backspace String Compare
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/backspace-string-compare/description/
+
+> 内容描述
+
+```
+Given two strings S and T, return if they are equal when both are typed into empty text editors. # means a backspace character.
+
+Example 1:
+
+Input: S = "ab#c", T = "ad#c"
+Output: true
+Explanation: Both S and T become "ac".
+Example 2:
+
+Input: S = "ab##", T = "c#d#"
+Output: true
+Explanation: Both S and T become "".
+Example 3:
+
+Input: S = "a##c", T = "#a#c"
+Output: true
+Explanation: Both S and T become "c".
+Example 4:
+
+Input: S = "a#c", T = "b"
+Output: false
+Explanation: S becomes "c" while T becomes "b".
+Note:
+
+1 <= S.length <= 200
+1 <= T.length <= 200
+S and T only contain lowercase letters and '#' characters.
+Follow up:
+
+Can you solve it in O(N) time and O(1) space?
+```
+
+## 解题方案
+
+> 思路 1
+
+就看一下两个字符串变化完之后是不是相等就行了,
+
+- 时间复杂度:O(n)
+- 空间复杂度:O(n)
+
+
+```python
+class Solution(object):
+ def backspaceCompare(self, S, T):
+ """
+ :type S: str
+ :type T: str
+ :rtype: bool
+ """
+ def afterChange(s):
+ res = ''
+ for i in s:
+ if i == '#':
+ res = '' if len(res) == 0 else res[:-1]
+ else:
+ res += i
+ return res
+ return afterChange(S) == afterChange(T)
+```
+
+> 思路 2
+
+deque
+
+- 时间复杂度:O(n)
+- 空间复杂度:O(n)
+
+```python
+class Solution:
+ def backspaceCompare(self, S, T):
+ """
+ :type S: str
+ :type T: str
+ :rtype: bool
+ """
+ q1 = collections.deque()
+ q2 = collections.deque()
+ for i in S:
+ if i != "#":
+ q1.append(i)
+ elif q1:
+ q1.pop()
+ else:
+ continue
+ for i in T:
+ if i != "#":
+ q2.append(i)
+ elif q2:
+ q2.pop()
+ else:
+ continue
+
+ return q1==q2
+```
+## Follow up
+
+Can you solve it in O(N) time and O(1) space?
+
+> 思路 2
+
+
+参考[angelina_not_jolie](https://leetcode.com/problems/backspace-string-compare/discuss/165435/Python-O(1)-space-solution-for-the-follow-up-beats-100-using-two-pointers)
+```
+The idea is we first need to find the first char in each string that was not deleted and compare equality.
+Corner case is that the number of '#' is larger than the number of chars in front, e.g. "ab#######c" ---> "c"
+So in my codes, the outter loop condition is as long as we haven't gone through both strings, we need to keep going. e.g. "ab#########c" vs. "a#c"
+The inner loops are to find the next char after deleting.
+
+There are only two cases we need to return False:
+1. Both pointers are at a char and these two chars are different.
+One pointer is pointing to a char but the other string has been deleted till index 0. i.e.
+2. compare a char to an empty string
+
+```
+- 时间复杂度:O(n)
+- 空间复杂度:O(1)
+
+```python
+class Solution(object):
+ def backspaceCompare(self, S, T):
+ """
+ :type S: str
+ :type T: str
+ :rtype: bool
+ """
+ i, poundS = len(S) - 1, 0; j, poundT = len(T) - 1, 0
+ while i >= 0 or j >= 0:
+ while i >= 0:
+ if S[i] == "#":
+ poundS += 1
+ elif poundS:
+ poundS -= 1
+ else: #found the first undeleted char
+ break
+ i -= 1
+
+ while j >= 0:
+ if T[j] == '#':
+ poundT += 1
+ elif poundT:
+ poundT -= 1
+ else:
+ break
+ j -= 1
+
+ #either both side are chars then we need to compare
+ if i >= 0 and j >= 0 and S[i] != T[j]:
+ return False
+ #compare a char with empty(have more # than actually char, we delete everything before #)
+ if (i >= 0) != (j >=0):
+ return False
+
+ i -= 1
+ j -= 1
+
+ return i == j
+```
diff --git a/docs/Leetcode_Solutions/Python/865._Smallest_Subtree_with_all_the_Deepest_Nodes.md b/docs/Leetcode_Solutions/Python/865._Smallest_Subtree_with_all_the_Deepest_Nodes.md
new file mode 100644
index 000000000..2c7b53625
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/865._Smallest_Subtree_with_all_the_Deepest_Nodes.md
@@ -0,0 +1,331 @@
+# 865. Smallest Subtree with all the Deepest Nodes
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/smallest-subtree-with-all-the-deepest-nodes/description/
+
+> 内容描述
+
+```
+Given a binary tree rooted at root, the depth of each node is the shortest distance to the root.
+
+A node is deepest if it has the largest depth possible among any node in the entire tree.
+
+The subtree of a node is that node, plus the set of all descendants of that node.
+
+Return the node with the largest depth such that it contains all the deepest nodes in its subtree.
+
+
+
+Example 1:
+
+Input: [3,5,1,6,2,0,8,null,null,7,4]
+Output: [2,7,4]
+Explanation:
+```
+
+
+
+```
+We return the node with value 2, colored in yellow in the diagram.
+The nodes colored in blue are the deepest nodes of the tree.
+The input "[3, 5, 1, 6, 2, 0, 8, null, null, 7, 4]" is a serialization of the given tree.
+The output "[2, 7, 4]" is a serialization of the subtree rooted at the node with value 2.
+Both the input and output have TreeNode type.
+
+Note:
+
+The number of nodes in the tree will be between 1 and 500.
+The values of each node are unique.
+```
+
+## 解题方案
+
+> 思路 1
+
+直接参考的[leetcode solution](https://leetcode.com/problems/smallest-subtree-with-all-the-deepest-nodes/solution/)
+- 首先将所有的node与其对应的depth记录下来
+- 然后,从root开始往下走,如果一个node的depth是最大的depth的话,就直接返回这个node,递归进行
+- 如果这个node的depth不是最大的depth,但是它的左孩子和右孩子的depth都最大的话也是直接返回这个node,递归进行
+
+```python
+class Solution(object):
+ def subtreeWithAllDeepest(self, root):
+ """
+ :type root: TreeNode
+ :rtype: TreeNode
+ """
+ depth = {
+ None: -1
+ }
+ def dfs(node, parent = None):
+ if node:
+ depth[node] = depth[parent] + 1
+ dfs(node.left, node)
+ dfs(node.right, node)
+
+ dfs(root)
+ max_depth = max(depth.values())
+
+ def decide(node):
+ if not node or depth[node] == max_depth:
+ return node
+ l, r = decide(node.left), decide(node.right)
+ return node if l and r else l or r
+ return decide(root)
+```
+
+> 思路 2
+
+The Result (on some subtree) returned by our (depth-first search) recursion will have two parts:
+- Result.node: the largest depth node that is equal to or an ancestor of all the deepest nodes of this subtree.
+- Result.depth: the number of nodes in the path from the root of this subtree, to the deepest node in this subtree.
+
+We can calculate these answers disjointly for dfs(node):
+
+To calculate the Result.node of our answer:
+
+- If one childResult has deeper nodes, then childResult.node will be the answer.
+
+- If they both have the same depth nodes, then node will be the answer.
+
+- The Result.depth of our answer is always 1 more than the largest childResult.depth we have.
+
+```python
+class Solution(object):
+ def subtreeWithAllDeepest(self, root):
+ """
+ :type root: TreeNode
+ :rtype: TreeNode
+ """
+ Result = collections.namedtuple('Result', ('node', 'depth'))
+ def dfs(node):
+ if not node:
+ return Result(None, 0)
+ l, r = dfs(node.left), dfs(node.right)
+ if l.depth > r.depth:
+ return Result(l.node, l.depth+1)
+ elif l.depth < r.depth:
+ return Result(r.node, r.depth+1)
+ else:
+ return Result(node, l.depth+1)
+ return dfs(root).node
+```
+
+> 思路 3
+
+自己的解法:
+
+```python
+class Solution(object):
+ def subtreeWithAllDeepest(self, root):
+ """
+ :type root: TreeNode
+ :rtype: TreeNode
+ """
+ def depth(node):
+ return 0 if not node else max(depth(node.left), depth(node.right)) + 1
+
+ tmp = depth(root.left) - depth(root.right)
+ if tmp == 0:
+ return root
+ elif tmp > 0:
+ return self.subtreeWithAllDeepest(root.left)
+ else:
+ return self.subtreeWithAllDeepest(root.right)
+```
+
+
+
+## Follow up
+
+如果每一个树节点可以拥有超过2个孩子怎么办:
+
+> 思路 1
+
+自己的解法,
+- 只要这个节点的孩子中有两个及以上的depth相等就直接返回这个node本身
+- 如果只有一个孩子的depth最大就返回那个孩子
+
+```python
+class TreeNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.children = []
+
+
+class Solution(object):
+ def subtreeWithAllDeepestForMoreChildren(self, root):
+ """
+ :type root: TreeNode
+ :rtype: TreeNode
+ """
+ # calculate a node's depth
+ def depth(node):
+ if not node:
+ return 0
+ tmp = [depth(child) for child in node.children]
+ if not tmp or len(tmp) == 0:
+ return 1
+ return max(tmp) + 1
+
+ if not root:
+ return None
+ tmp = [depth(child) for child in root.children]
+ if not tmp or len(tmp) == 0:
+ return root
+ # if 2 or more children have same depth, then return the node itself
+ if tmp.count(max(tmp)) > 1:
+ return root
+ # else recalculate the child who has largest depth
+ else:
+ return self.subtreeWithAllDeepestForMoreChildren(root.children[tmp.index(max(tmp))])
+```
+
+搞一下测试用例
+
+```python
+import unittest
+
+
+class TestSolution(unittest.TestCase):
+ def test_1(self):
+ root = TreeNode(0)
+
+ for i in range(1, 4):
+ root.children.append(TreeNode(i))
+
+ for i in range(4, 10):
+ root.children[1].children.append(TreeNode(i))
+ self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 2)
+
+ def test_2(self):
+ root = TreeNode(0)
+ self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 0)
+
+ def test_3(self):
+ root = TreeNode(0)
+
+ for i in range(1, 4):
+ root.children.append(TreeNode(i))
+
+ for i in range(4, 10):
+ root.children[1].children.append(TreeNode(i))
+
+ for i in range(10, 12):
+ root.children[2].children.append(TreeNode(i))
+ self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 0)
+
+ def test_4(self):
+ root = TreeNode(0)
+
+ for i in range(1, 3):
+ root.children.append(TreeNode(i))
+
+ for i in range(3, 5):
+ root.children[0].children.append(TreeNode(i))
+
+ for i in range(5, 7):
+ root.children[1].children.append(TreeNode(i))
+
+ for i in range(7, 9):
+ root.children[0].children[1].children.append(TreeNode(i))
+ self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 4)
+
+ def test_5(self):
+ root = TreeNode(0)
+
+ for i in range(1, 5):
+ root.children.append(TreeNode(i))
+ root.children[1].children.append(TreeNode(5))
+ root.children[2].children.append(TreeNode(6))
+ root.children[3].children.append(TreeNode(7))
+ self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 0)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
+
+
+.....
+----------------------------------------------------------------------
+Ran 5 tests in 0.000s
+
+OK
+```
+
+
+> 思路 2
+
+
+
+```python
+import collections
+import sys
+
+
+class TreeNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.children = []
+
+
+# Find the tree with largest depth among all nodes
+class Solution(object):
+ def subtreeWithAllDeepestForMoreChildren(self, root):
+ """
+ :type root: TreeNode
+ :rtype: TreeNode
+ """
+ if not root:
+ return None
+ Result = collections.namedtuple("Result", ("node", "depth"))
+
+ # return the Result of the subtree at this node
+ def dfs(node):
+ if not node:
+ return Result(None, 0)
+ if len(node.children) == 0:
+ return Result(node, 1)
+ largest_depth = 0
+ res = Result(None, 0)
+ for child in node.children:
+ cur = dfs(child) # cur is a Result type: store ('node','depth')
+ if cur.depth > abs(largest_depth):
+ largest_depth = cur.depth
+ res = cur
+ elif cur.depth == largest_depth:
+ # negative number means largestDepth occurs more than once
+ largest_depth = -largest_depth
+ if largest_depth > 0:
+ return Result(res.node, largest_depth + 1)
+ return Result(node, -largest_depth + 1)
+
+ return dfs(root).node
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/873._Length_of_Longest_Fibonacci_Subsequence.md b/docs/Leetcode_Solutions/Python/873._Length_of_Longest_Fibonacci_Subsequence.md
new file mode 100644
index 000000000..ea6f71248
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/873._Length_of_Longest_Fibonacci_Subsequence.md
@@ -0,0 +1,108 @@
+# 873. Length of Longest Fibonacci Subsequence
+
+**难度: Meidum**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/length-of-longest-fibonacci-subsequence/description/
+
+> 内容描述
+
+```
+A sequence X_1, X_2, ..., X_n is fibonacci-like if:
+
+n >= 3
+X_i + X_{i+1} = X_{i+2} for all i + 2 <= n
+Given a strictly increasing array A of positive integers forming a sequence, find the length of the longest fibonacci-like subsequence of A. If one does not exist, return 0.
+
+(Recall that a subsequence is derived from another sequence A by deleting any number of elements (including none) from A, without changing the order of the remaining elements. For example, [3, 5, 8] is a subsequence of [3, 4, 5, 6, 7, 8].)
+
+
+
+Example 1:
+
+Input: [1,2,3,4,5,6,7,8]
+Output: 5
+Explanation:
+The longest subsequence that is fibonacci-like: [1,2,3,5,8].
+Example 2:
+
+Input: [1,3,7,11,12,14,18]
+Output: 3
+Explanation:
+The longest subsequence that is fibonacci-like:
+[1,11,12], [3,11,14] or [7,11,18].
+
+
+Note:
+
+3 <= A.length <= 1000
+1 <= A[0] < A[1] < ... < A[A.length - 1] <= 10^9
+(The time limit has been reduced by 50% for submissions in Java, C, and C++.)
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N^2*LgN)******- 空间复杂度: O(N)******
+
+思路见[lee215](https://leetcode.com/problems/length-of-longest-fibonacci-subsequence/discuss/152343/C++JavaPython-Check-Pair)
+```
+Save array A to a hash set s.
+Start from base (A[i], A[j]) as the first two element in the sequence,
+we try to find the Fibonacci like subsequence as long as possible,
+
+Initial (a, b) = (A[i], A[j])
+While the set s contains a + b, we update (a, b) = (b, a + b).
+In the end we update the longest length we find.
+
+Time Complexity:
+O(N^2logM), where M is the max(A).
+```
+
+```python
+class Solution(object):
+ def lenLongestFibSubseq(self, A):
+ """
+ :type A: List[int]
+ :rtype: int
+ """
+ s, res = set(A), 0
+ for i in range(len(A)):
+ for j in range(i+1, len(A)):
+ a, b, l = A[i], A[j], 2
+ while a + b in s:
+ a, b, l = b, a + b, l + 1
+ res = max(res, l)
+ return res if res > 2 else 0
+```
+
+
+
+> 思路 2
+******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******
+
+```
+dp[a, b] represents the length of fibo sequence ends up with (a, b)
+Then we have dp[a, b] = dp[b - a, a] or 2
+The complexity reduce to O(N^2).
+```
+
+```python
+class Solution(object):
+ def lenLongestFibSubseq(self, A):
+ """
+ :type A: List[int]
+ :rtype: int
+ """
+ dp = {}
+ s, res = set(A), 0
+ for i in range(len(A)):
+ for j in range(i):
+ if A[i] - A[j] < A[j] and A[i] - A[j] in s:
+ dp[(A[j], A[i])] = dp.get((A[i]-A[j], A[j]), 2) + 1
+ res = max(res, dp[(A[j], A[i])])
+ return res if res > 2 else 0
+```
diff --git a/docs/Leetcode_Solutions/Python/878._Nth_Magical_Number.md b/docs/Leetcode_Solutions/Python/878._Nth_Magical_Number.md
new file mode 100644
index 000000000..c0be3ccd7
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/878._Nth_Magical_Number.md
@@ -0,0 +1,140 @@
+# 878. Nth Magical Number
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/nth-magical-number/description/
+
+> 内容描述
+
+```
+A positive integer is magical if it is divisible by either A or B.
+
+Return the N-th magical number. Since the answer may be very large, return it modulo 10^9 + 7.
+
+
+
+Example 1:
+
+Input: N = 1, A = 2, B = 3
+Output: 2
+Example 2:
+
+Input: N = 4, A = 2, B = 3
+Output: 6
+Example 3:
+
+Input: N = 5, A = 2, B = 4
+Output: 10
+Example 4:
+
+Input: N = 3, A = 6, B = 4
+Output: 8
+
+
+Note:
+
+1 <= N <= 10^9
+2 <= A <= 40000
+2 <= B <= 40000
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(A+B)******- 空间复杂度: O(1)******
+
+数学题直接看的[solution](https://leetcode.com/problems/nth-magical-number/solution/):
+
+* 从数据范围看来,N高达10^9,直接遍历不现实
+* 注意到魔法数是有循环的,我们令P=A和B的最小公倍数,那么在每P个数中,魔法数的数量和位置都是相同的,因此我们只需要计算1-P中间的魔法数
+* 1~P的魔法数数量是 P/A+P/B-1,注意到,P是A和B的最小公倍数,因此1~P中,既能被A整除,也能被B整除,只有一个数,就是P
+* 现在问题变成,在1~P中,求第n个魔法数
+
+注意到,我们在1~p中任取一个数x(x 思路 2
+******- 时间复杂度: O(log(N*max(A,B)))******- 空间复杂度: O(1)******
+
+
+从另外一个角度来看,如果我们知道了一个数字x,那么我们可以轻易算出有多少个magic number 是小于等于x的,
+即```x // A + x // B - x // L```, 其中```L = lcm(A, B)```, 我们可以通过二分法算出一个最小的数字num,小于等于num的magic number 数量是刚好是N,
+然后这个num就是我们要求的 Nth Magical Number
+
+时间复杂度为O(log(N∗max(A,B))), beats 100%
+
+```python
+class Solution(object):
+ def nthMagicalNumber(self, N, A, B):
+ """
+ :type N: int
+ :type A: int
+ :type B: int
+ :rtype: int
+ """
+ def gcd(a, b):
+ if b == 0:
+ return a
+ return gcd(b, a % b)
+
+ def lcm(a, b):
+ return a * b // gcd(a, b)
+
+ MOD = 10**9 + 7
+ L = lcm(A, B)
+
+ def magic_below_x(x):
+ # How many magical numbers are <= x?
+ return x // A + x // B - x // L
+
+ l, r = 0, N * max(A,B)
+ while l <= r:
+ mid = l + ((r-l) >> 1)
+ if magic_below_x(mid) < N:
+ l = mid + 1
+ else:
+ r = mid - 1
+
+ return l % MOD
+```
+
diff --git a/docs/Leetcode_Solutions/Python/890._Find_and_Replace_Pattern.md b/docs/Leetcode_Solutions/Python/890._Find_and_Replace_Pattern.md
new file mode 100644
index 000000000..edefe3380
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/890._Find_and_Replace_Pattern.md
@@ -0,0 +1,83 @@
+# 890. Find and Replace Pattern
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/find-and-replace-pattern/description/
+
+> 内容描述
+
+```
+You have a list of words and a pattern, and you want to know which words in words matches the pattern.
+
+A word matches the pattern if there exists a permutation of letters p so that after replacing every letter x in the pattern with p(x), we get the desired word.
+
+(Recall that a permutation of letters is a bijection from letters to letters: every letter maps to another letter, and no two letters map to the same letter.)
+
+Return a list of the words in words that match the given pattern.
+
+You may return the answer in any order.
+
+
+
+Example 1:
+
+Input: words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb"
+Output: ["mee","aqq"]
+Explanation: "mee" matches the pattern because there is a permutation {a -> m, b -> e, ...}.
+"ccc" does not match the pattern because {a -> c, b -> c, ...} is not a permutation,
+since a and b map to the same letter.
+
+
+Note:
+
+1 <= words.length <= 50
+1 <= pattern.length = words[i].length <= 20
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N*k)******- 空间复杂度: O(k)****** 这里k为最长的那个字符串的长度
+
+1. 定义一个convert函数
+ - 首先对于传进来的word做一个for loop
+ - 只要字符没有出现过就用一个全新的num来对应它
+ - 否则就用之前存在dict里面的它所对应num来对应它
+2. 比较每个word convert之后是否于pattern convert之后相等,相等就加入最终结果
+3. 返回最终结果
+
+
+```python
+class Solution(object):
+ def findAndReplacePattern(self, words, pattern):
+ """
+ :type words: List[str]
+ :type pattern: str
+ :rtype: List[str]
+ """
+ def convert(word):
+ lookup = {}
+ num = 0
+ word_convert = ''
+ for i in word:
+ if i not in lookup: # 第一次出现这个字符
+ num += 1 # 用一个全新的num来对应它
+ word_convert += str(num)
+ lookup[i] = num # 存进dict供给后面用
+ else:
+ word_convert += str(lookup[i]) # 之前出现过了这个字符那么就加上它之前对应的数字
+ return word_convert
+ pattern_convert = convert(pattern)
+ res = []
+ for word in words:
+ if convert(word) == pattern_convert:
+ res.append(word)
+ return res
+```
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/891._Sum_of_Subsequence_Widths.md b/docs/Leetcode_Solutions/Python/891._Sum_of_Subsequence_Widths.md
new file mode 100644
index 000000000..1f5297320
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/891._Sum_of_Subsequence_Widths.md
@@ -0,0 +1,104 @@
+# 891. Sum of Subsequence Widths
+
+**难度: Hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/sum-of-subsequence-widths/description/
+
+> 内容描述
+
+```
+
+Given an array of integers A, consider all non-empty subsequences of A.
+
+For any sequence S, let the width of S be the difference between the maximum and minimum element of S.
+
+Return the sum of the widths of all subsequences of A.
+
+As the answer may be very large, return the answer modulo 10^9 + 7.
+
+
+
+Example 1:
+
+Input: [2,1,3]
+Output: 6
+Explanation:
+Subsequences are [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3].
+The corresponding widths are 0, 0, 0, 1, 1, 2, 2.
+The sum of these widths is 6.
+
+
+Note:
+
+1 <= A.length <= 20000
+1 <= A[i] <= 20000
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
+
+
+设n为A数组的长度
+
+先给A排序,其中以A[0]为最小值的子序列的个数为2^(n-1),以A[0]为最大值的子序列的个数为2^(0),以此类推。
+
+开始写的代码如下:
+
+```
+class Solution(object):
+ def sumSubseqWidths(self, A):
+ """
+ :type A: List[int]
+ :rtype: int
+ """
+ A.sort()
+ res, n = 0, len(A)
+ for i in range(len(A)):
+ res -= A[i] * pow(2, n-1-i)
+ res += A[i] * pow(2, i)
+ res %= pow(10, 9) + 7
+ return res
+```
+
+
+但是一直超时,于是我觉得是因为pow()函数太费时间了,所以用空间换时间,先把所有2的0到(n-1)次方全部存起来,然后后面直接取就行了,果然AC
+
+beats 84.15%
+```python
+class Solution(object):
+ def sumSubseqWidths(self, A):
+ """
+ :type A: List[int]
+ :rtype: int
+ """
+ MOD = 10**9 + 7
+ res, n = 0, len(A)
+ A.sort()
+
+ pow2 = [1]
+ for i in xrange(1, n):
+ pow2.append(pow2[-1] * 2 % MOD)
+
+ for i, x in enumerate(A):
+ res -= x * pow2[n-1-i] % MOD
+ res += x * pow2[i] % MOD
+ return res % MOD
+```
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/900._RLE_Iterator.md b/docs/Leetcode_Solutions/Python/900._RLE_Iterator.md
new file mode 100644
index 000000000..3cc60284d
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/900._RLE_Iterator.md
@@ -0,0 +1,173 @@
+# 900. RLE Iterator
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/rle-iterator/description/
+
+> 内容描述
+
+```
+
+Write an iterator that iterates through a run-length encoded sequence.
+
+The iterator is initialized by RLEIterator(int[] A), where A is a run-length encoding of some sequence. More specifically, for all even i, A[i] tells us the number of times that the non-negative integer value A[i+1] is repeated in the sequence.
+
+The iterator supports one function: next(int n), which exhausts the next n elements (n >= 1) and returns the last element exhausted in this way. If there is no element left to exhaust, next returns -1 instead.
+
+For example, we start with A = [3,8,0,9,2,5], which is a run-length encoding of the sequence [8,8,8,5,5]. This is because the sequence can be read as "three eights, zero nines, two fives".
+
+
+
+Example 1:
+
+Input: ["RLEIterator","next","next","next","next"], [[[3,8,0,9,2,5]],[2],[1],[1],[2]]
+Output: [null,8,8,5,-1]
+Explanation:
+RLEIterator is initialized with RLEIterator([3,8,0,9,2,5]).
+This maps to the sequence [8,8,8,5,5].
+RLEIterator.next is then called 4 times:
+
+.next(2) exhausts 2 terms of the sequence, returning 8. The remaining sequence is now [8, 5, 5].
+
+.next(1) exhausts 1 term of the sequence, returning 8. The remaining sequence is now [5, 5].
+
+.next(1) exhausts 1 term of the sequence, returning 5. The remaining sequence is now [5].
+
+.next(2) exhausts 2 terms, returning -1. This is because the first term exhausted was 5,
+but the second term did not exist. Since the last term exhausted does not exist, we return -1.
+
+Note:
+
+0 <= A.length <= 1000
+A.length is an even integer.
+0 <= A[i] <= 10^9
+There are at most 1000 calls to RLEIterator.next(int n) per test case.
+Each call to RLEIterator.next(int n) will have 1 <= n <= 10^9.
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(len(A))******
+
+
+
+周赛的时候做的这道题,刚开始很sb,抱着试试的想法直接全部装起来然后一个个返回,果然太 naive
+
+
+```
+class RLEIterator(object):
+
+ def __init__(self, A):
+ """
+ :type A: List[int]
+ """
+ self.lst = A
+ self.tmp = []
+ for i in range(0, len(self.lst), 2):
+ self.tmp.extend([self.lst[i+1]]*self.lst[i])
+
+
+
+ def next(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ if len(self.tmp) < n:
+ return -1
+ else:
+ for i in range(n):
+ if i == n-1:
+ return self.tmp.pop(0)
+ self.tmp.pop(0)
+```
+
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(len(A))******
+
+
+然后写了半天,每次只取一个的逻辑,还是超时了。真的蠢。。。。
+
+```
+class RLEIterator(object):
+
+ def __init__(self, A):
+ """
+ :type A: List[int]
+ """
+ self.lst = A
+ self.tmp = []
+ self.cnt, self.num = 0, 0
+
+
+
+
+ def next(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ if self.tmp:
+ if n == 1:
+ return self.tmp.pop(0)
+ else:
+ self.tmp.pop(0)
+ return self.next(n-1)
+ else:
+ if self.cnt > 0:
+ self.tmp.append(self.num)
+ self.cnt -= 1
+ return self.next(n)
+ else:
+ if self.lst:
+ self.cnt, self.num = self.lst.pop(0), self.lst.pop(0)
+ return self.next(n)
+ else:
+ return -1
+```
+
+> 思路 3
+******- 时间复杂度: O(N)******- 空间复杂度: O(len(A))******
+
+
+利用python built-in数据结构deque的性质,直接AC, beats 100%
+
+```python
+class RLEIterator(object):
+
+ def __init__(self, A):
+ """
+ :type A: List[int]
+ """
+ self._deque = collections.deque(A)
+
+
+ def next(self, n):
+ """
+ :type n: int
+ :rtype: int
+ """
+ while self._deque and n:
+ count = self._deque.popleft()
+ val = self._deque[0]
+ if count >= n:
+ self._deque.appendleft(count-n)
+ return val
+ else:
+ n -= count
+ self._deque.popleft()
+ return -1
+
+
+
+
+# Your RLEIterator object will be instantiated and called as such:
+# obj = RLEIterator(A)
+# param_1 = obj.next(n)
+```
diff --git a/docs/Leetcode_Solutions/Python/902._Numbers_At_Most_N_Given_Digit_Set.md b/docs/Leetcode_Solutions/Python/902._Numbers_At_Most_N_Given_Digit_Set.md
new file mode 100644
index 000000000..c14134124
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/902._Numbers_At_Most_N_Given_Digit_Set.md
@@ -0,0 +1,88 @@
+# 902. Numbers At Most N Given Digit Set
+
+**难度: hard**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/numbers-at-most-n-given-digit-set/description/
+
+> 内容描述
+
+```
+We have a sorted set of digits D, a non-empty subset of {'1','2','3','4','5','6','7','8','9'}. (Note that '0' is not included.)
+
+Now, we write numbers using these digits, using each digit as many times as we want. For example, if D = {'1','3','5'}, we may write numbers such as '13', '551', '1351315'.
+
+Return the number of positive integers that can be written (using the digits of D) that are less than or equal to N.
+
+
+
+Example 1:
+
+Input: D = ["1","3","5","7"], N = 100
+Output: 20
+Explanation:
+The 20 numbers that can be written are:
+1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.
+Example 2:
+
+Input: D = ["1","4","9"], N = 1000000000
+Output: 29523
+Explanation:
+We can write 3 one digit numbers, 9 two digit numbers, 27 three digit numbers,
+81 four digit numbers, 243 five digit numbers, 729 six digit numbers,
+2187 seven digit numbers, 6561 eight digit numbers, and 19683 nine digit numbers.
+In total, this is 29523 integers that can be written using the digits of D.
+
+
+Note:
+
+D is a subset of digits '1'-'9' in sorted order.
+1 <= N <= 10^9
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(lgN)******- 空间复杂度: O(N)******
+
+
+这里时间复杂度为 O(lgN) 是因为我们把N看作是input里面N的大小
+
+并且pow(x, y)的时间复杂度为:
+
+1. For y < 2^63, there's a loop of size ceil(log_2(y)),
+2. but for larger y, the result is calculated using Exp(y * Log(x)).
+
+
+参见[lee215](https://leetcode.com/problems/numbers-at-most-n-given-digit-set/discuss/168279/Python-O(logN))
+```
+- N has n digits, so all numbers less than n digits are valid, which are: sum(len(D) ** i for i in range(1, n))
+- The loop is to deal with all numbers with n digits, considering from N[0], N[1] back to N[n-1].
+For example, N[0] is valid only for c in D if c <= N[0].
+If c < N[0], then N[1], ..., N[n-1] can take any number in D but if c == N[0], then we need consider N[1],
+and the iteration repeats. That's why if N[i] not in D, then we don't need to repeat the loop anymore.
+- Finally i==n is addressed at the end when there exists all c in D that matches N
+```
+
+```python
+class Solution(object):
+ def atMostNGivenDigitSet(self, D, N):
+ """
+ :type D: List[str]
+ :type N: int
+ :rtype: int
+ """
+ N = str(N)
+ n = len(N)
+ res = sum(pow(len(D), i) for i in range(1, n)) # 考虑少于n位的答案
+ i = 0
+ while i < n: # 开始考虑刚好为n位的答案
+ res += sum(c < N[i] for c in D) * pow(len(D), n-i-1) # 每次只考虑比N当前位置的数字小的数字
+ if N[i] not in D: # 如果N当前位置的数字都不在D里面了,我们考虑不了下一个位置
+ break
+ i += 1
+ return res + (i==n) # 如果N判断到最后一个位置的数字了,这个数字都还在D里面,我们就知道有一个刚好等于N的组合
+```
diff --git a/docs/Leetcode_Solutions/Python/904._Fruit_Into_Baskets.md b/docs/Leetcode_Solutions/Python/904._Fruit_Into_Baskets.md
new file mode 100644
index 000000000..7adabebb5
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/904._Fruit_Into_Baskets.md
@@ -0,0 +1,89 @@
+# 904. Fruit Into Baskets
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/contest/weekly-contest-102/problems/fruit-into-baskets/
+
+> 内容描述
+
+```
+In a row of trees, the i-th tree produces fruit with type tree[i].
+
+You start at any tree of your choice, then repeatedly perform the following steps:
+
+Add one piece of fruit from this tree to your baskets. If you cannot, stop.
+Move to the next tree to the right of the current tree. If there is no tree to the right, stop.
+Note that you do not have any choice after the initial choice of starting tree: you must perform step 1, then step 2, then back to step 1, then step 2, and so on until you stop.
+
+You have two baskets, and each basket can carry any quantity of fruit, but you want each basket to only carry one type of fruit each.
+
+What is the total amount of fruit you can collect with this procedure?
+
+
+
+Example 1:
+
+Input: [1,2,1]
+Output: 3
+Explanation: We can collect [1,2,1].
+Example 2:
+
+Input: [0,1,2,2]
+Output: 3
+Explanation: We can collect [1,2,2].
+If we started at the first tree, we would only collect [0, 1].
+Example 3:
+
+Input: [1,2,3,2,2]
+Output: 4
+Explanation: We can collect [2,3,2,2].
+If we started at the first tree, we would only collect [1, 2].
+Example 4:
+
+Input: [3,3,3,1,2,1,1,2,3,3,4]
+Output: 5
+Explanation: We can collect [1,2,1,1,2].
+If we started at the first tree or the eighth tree, we would only collect 4 fruits.
+
+
+Note:
+
+1 <= tree.length <= 40000
+0 <= tree[i] < tree.length
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+
+和第159一样的思路,时间复杂度最差为O(N),因为有可能整个列表只有两种不同的数字
+
+```python
+class Solution(object):
+ def totalFruit(self, A):
+ """
+ :type tree: List[int]
+ :rtype: int
+ """
+ maps = {}
+ begin, end, counter, res = 0, 0, 0, 0
+ while end < len(A):
+ maps[A[end]] = maps.get(A[end], 0) + 1
+ if maps[A[end]] == 1:
+ counter += 1
+ end += 1 # end points to the next fruit
+ while counter > 2:
+ maps[A[begin]] -= 1
+ if maps[A[begin]] == 0:
+ counter -= 1
+ begin += 1
+ res = max(res, end - begin)
+ return res
+```
diff --git a/docs/Leetcode_Solutions/Python/905._Sort_Array_By_Parity.md b/docs/Leetcode_Solutions/Python/905._Sort_Array_By_Parity.md
new file mode 100644
index 000000000..53439ccda
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/905._Sort_Array_By_Parity.md
@@ -0,0 +1,72 @@
+# 905. Sort Array By Parity
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/sort-array-by-parity/description/
+
+> 内容描述
+
+```
+Given an array A of non-negative integers, return an array consisting of all the even elements of A, followed by all the odd elements of A.
+
+You may return any answer array that satisfies this condition.
+
+
+
+Example 1:
+
+Input: [3,1,2,4]
+Output: [2,4,3,1]
+The outputs [4,2,3,1], [2,4,1,3], and [4,2,1,3] would also be accepted.
+
+
+Note:
+
+1 <= A.length <= 5000
+0 <= A[i] <= 5000
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+贼暴力思路
+
+```python
+class Solution(object):
+ def sortArrayByParity(self, A):
+ """
+ :type A: List[int]
+ :rtype: List[int]
+ """
+ return [i for i in A if i & 1 == 0] + [i for i in A if i & 1 == 1]
+```
+
+
+
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+优化空间,in-place AC!
+
+```python
+class Solution(object):
+ def sortArrayByParity(self, A):
+ """
+ :type A: List[int]
+ :rtype: List[int]
+ """
+ idx = 0 # idx 指向的永远是奇数的 candidate
+ for i in range(len(A)):
+ if A[i] & 1 == 0:
+ A[i], A[idx] = A[idx], A[i]
+ idx += 1
+ return A
+```
diff --git a/docs/Leetcode_Solutions/Python/907._Sum_of_Subarray_Minimums.md b/docs/Leetcode_Solutions/Python/907._Sum_of_Subarray_Minimums.md
new file mode 100644
index 000000000..190ec1a83
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/907._Sum_of_Subarray_Minimums.md
@@ -0,0 +1,163 @@
+# 907. Sum of Subarray Minimums
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/sum-of-subarray-minimums/description/
+
+> 内容描述
+
+```
+
+Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarray of A.
+
+Since the answer may be large, return the answer modulo 10^9 + 7.
+
+
+
+Example 1:
+
+Input: [3,1,2,4]
+Output: 17
+Explanation: Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4].
+Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1. Sum is 17.
+
+
+Note:
+
+1 <= A.length <= 30000
+1 <= A[i] <= 30000
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+
+对于A中的每一个元素,我们只需要计算出以它为最小值且以它为结束的子串的个数left[i],然后再计算出以它为最小值且以它为开始的子串的个数right[i],
+注意这其中不允许有重复(即一个优先原则,例如1,2,3,1,其中先出现的那个1才是最小值,这样可以避免我们重复计算子串)
+
+```
+然后假设我们的A为[3,2,1,2,3]
+
+那么对于中间的1来说,它的left[i]为3,right[i]也为3
+那么它一共涉及到多少个字串呢,我们枚举一下
+
+3,2,1
+2,1
+1
+3,2,1,2
+2,1,2
+1,2
+3,2,1,2,3
+2,1,2,3
+1,2,3
+
+
+一共涉及到9个,也就是说以A{i]为最小值的子串总数其实等于left[i] 和right[i]的乘积,这个也可以自己想出来,枚举只是为了看的更清晰
+```
+
+所以现在我们的目标变成了求以A中每一个元素为最小值的子串个数的list,命名为sub_counts
+
+例如还是上面的例子,我们的sub_counts = [1*1, 2*1, 3*3, 1*2, 1*1], 这里的对称性不是普遍的,因为我们的输入是对称的。
+
+所以我们的结果就是A中的每一个元素与其sub_count乘积的总和,即3*(1*1) + 2*(2*1) + 1*(3*3) + 2*(1*2) + 3*(1*1) = 23
+
+
+整个思路都是参考[寒神](https://leetcode.com/problems/sum-of-subarray-minimums/discuss/170750/C++JavaPython-Stack-Solution?page=2)的
+
+AC 代码如下:
+beats 53.98%
+
+
+```python
+class Solution(object):
+ def sumSubarrayMins(self, A):
+ """
+ :type A: List[int]
+ :rtype: int
+ """
+ stack_left, stack_right = [], []
+ # 分别代表左边和右边所涉及的子串个数的list
+ sub_left, sub_right = [0] * len(A), [0] * len(A)
+ for i in range(len(A)):
+ count = 1 # 初始都是1,因为自己本身算一个
+ while stack_left and stack_left[-1][0] > A[i]:
+ count += stack_left.pop()[1]
+ sub_left[i] = count # 其左边涉及子串个数为count
+ # stack—_left里面存的是A[i]这个元素前面有多少个严格比它小的数字
+ stack_left.append((A[i], count))
+ for i in range(len(A))[::-1]:
+ count = 1
+ while stack_right and stack_right[-1][0] >= A[i]:
+ count += stack_right.pop()[1]
+ sub_right[i] = count # 其右边涉及子串个数为count
+ # stack—_right里面存的是A[i]这个元素前面有多少个大于等于它的数字
+ stack_right.append((A[i], count))
+
+ return sum(a * l * r for a, l, r in zip(A, sub_left, sub_right)) % (10**9 + 7)
+```
+
+时间复杂度为O(N),因为对于A中的每一个元素我们都值进行了恰好两次push stack操作和最多2次pop stack的操作,因此是O(N)
+
+空间显然为O(N)
+
+
+> 思路 2
+******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
+
+
+看了下,别人说这两个stack可以one pass,一个stack就够了, beats 100%
+
+
+不得不说,其中```left = stack[-1] if stack else -1```这句代码真的精妙绝伦,至少我想不到
+代码如下:
+
+
+```python
+class Solution(object):
+ def sumSubarrayMins(self, A):
+ """
+ :type A: List[int]
+ :rtype: int
+ """
+ count, stack = 0, []
+ for i in range(len(A)):
+ while stack and A[stack[-1]] >= A[i]:
+ pos = stack.pop()
+ # 下面这句代码是整个代码中最精妙的一句了
+ left = stack[-1] if stack else -1
+ # 这里一次就把涉及A[i]的子串的和全部加上次
+ count += (i - pos) * (pos - left) * A[pos]
+ stack.append(i)
+
+ while stack:
+ pos = stack.pop()
+ left = stack[-1] if stack else -1
+ count += (pos - left) * (len(A) - pos) * A[pos]
+ return count % (10**9 + 7)
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/908._Smallest_Range.md b/docs/Leetcode_Solutions/Python/908._Smallest_Range.md
new file mode 100644
index 000000000..de79b5db6
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/908._Smallest_Range.md
@@ -0,0 +1,79 @@
+# 908. Smallest Range
+
+**难度: Easy**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/smallest-range-i/description/
+
+> 内容描述
+
+```
+Given an array A of integers, for each integer A[i] we may choose any x with -K <= x <= K, and add x to A[i].
+
+After this process, we have some array B.
+
+Return the smallest possible difference between the maximum value of B and the minimum value of B.
+
+
+
+Example 1:
+
+Input: A = [1], K = 0
+Output: 0
+Explanation: B = [1]
+Example 2:
+
+Input: A = [0,10], K = 2
+Output: 6
+Explanation: B = [2,8]
+Example 3:
+
+Input: A = [1,3,6], K = 3
+Output: 0
+Explanation: B = [3,3,3] or B = [4,4,4]
+
+
+Note:
+
+1 <= A.length <= 10000
+0 <= A[i] <= 10000
+0 <= K <= 10000
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+比赛起晚了,9点25惊醒,看到题目后 3 分钟多一点 bug free 一遍 AC
+
+这个题目这么简单就没必要说什么了
+
+
+```python
+class Solution(object):
+ def smallestRangeI(self, A, K):
+ """
+ :type A: List[int]
+ :type K: int
+ :rtype: int
+ """
+ max_num = max(A)
+ min_num = min(A)
+ if max_num - min_num > 2 * abs(K):
+ return max_num - min_num - 2 * abs(K)
+ elif max_num - min_num <= 2 * abs(K):
+ return 0
+```
+
+
+
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/910._Smallest_Range_II.md b/docs/Leetcode_Solutions/Python/910._Smallest_Range_II.md
new file mode 100644
index 000000000..eb6f06c3e
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/910._Smallest_Range_II.md
@@ -0,0 +1,83 @@
+# 910. Smallest Range II
+
+**难度: Medium**
+
+## 刷题内容
+
+> 原题连接
+
+* https://leetcode.com/problems/smallest-range-ii/description/
+
+> 内容描述
+
+```
+Given an array A of integers, for each integer A[i] we need to choose either x = -K or x = K, and add x to A[i] (only once).
+
+After this process, we have some array B.
+
+Return the smallest possible difference between the maximum value of B and the minimum value of B.
+
+
+
+Example 1:
+
+Input: A = [1], K = 0
+Output: 0
+Explanation: B = [1]
+Example 2:
+
+Input: A = [0,10], K = 2
+Output: 6
+Explanation: B = [2,8]
+Example 3:
+
+Input: A = [1,3,6], K = 3
+Output: 3
+Explanation: B = [4,6,3]
+
+
+Note:
+
+1 <= A.length <= 10000
+0 <= A[i] <= 10000
+0 <= K <= 10000
+```
+
+## 解题方案
+
+> 思路 1
+******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
+
+
+今天比赛睡晚了,总共只有35分钟,所以没什么时间,没有想出来,事后证明自己已经非常接近了
+
+这道题的AC率12%左右,其实有点难想出来的
+
+开始我想的是先算出max_num和min_num,再算出它们两的平均值avg_num,然后对于A中的所有数字,如果大于avg_num就减去K,如果小于等于avg_num就加上K。
+但是这样是不对的,毕竟这种东西跟我们的K也是有关的
+
+最后想到我们先把A排序,然后A前面一部分比较小的数字全部加上K,后面那部分比较大的数字全部减去K,这样找到一个临界值,使得我们最终的极值最小
+
+所以我们对排序后的A做一个遍历,然后每一轮的最大值会在```A[i]+K```和```A[-1]-K```之间取,最小值只会在```A[i+1]-K```和```A[0]+K```中取
+
+```python
+class Solution(object):
+ def smallestRangeII(self, A, K):
+ """
+ :type A: List[int]
+ :type K: int
+ :rtype: int
+ """
+ if not A or len(A) <= 1:
+ return 0
+ if len(A) == 2:
+ return min(A[-1]-A[0], abs(A[-1]-A[0]-2*K))
+
+ K = abs(K)
+ A.sort()
+ res = sys.maxsize
+ for i in range(len(A)-1):
+ tmp = max(A[i]+K, A[-1]-K) - min(A[i+1]-K, A[0]+K)
+ res = min(res, tmp)
+ return min(res, A[-1]-A[0])
+```
diff --git a/docs/Leetcode_Solutions/Python/README.md b/docs/Leetcode_Solutions/Python/README.md
new file mode 100644
index 000000000..c477b8c84
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/README.md
@@ -0,0 +1 @@
+# Leetcode solutions and summarizations!
diff --git a/docs/Leetcode_Solutions/Python/Summary/Binary Search.md b/docs/Leetcode_Solutions/Python/Summary/Binary Search.md
new file mode 100644
index 000000000..e935c0c3f
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/Summary/Binary Search.md
@@ -0,0 +1,42 @@
+### Binary Search
+
+
+```python
+def binarySearch(nums, target):
+ l, r = 0, len(nums) -1
+ while l <= r:
+ mid = l + ((r-l) >> 1)
+ if nums[mid] > target:
+ r = mid - 1
+ elif nums[mid] < target:
+ l = mid + 1
+ else:
+ return mid
+ return -1
+```
+
+
+wisdompeak大佬说,
+
+标准模板就两套:
+```
+while (left x的最小值
+
+ • 如果x所在的节点有一个非空的右子树,则右子树中的最小值就是答案
+
+ • 否则我们需要向上回溯,找到最近的一个祖先,使得该祖先的左侧孩子,也为x的祖 先。
+
+
+ - [x] 删除
+
+ • 如果x没有子节点,或者只有一个孩子,直接将x“切下”;
+
+ • 否则,x有两个孩子,我们用其右子树中的最小值替换掉x,然后将右子树中的这一最小值“切掉”。
+
+
+
+
+
+
+- [x] 递归
+ - [x] 入门
+
+ - 回文
+ - 阶乘 factorial, 慕指数
+ - 分形
+ - Tower of Hanoi
+
+ - [x] 排列 Permutation
+
+ - [x] 子集 Subsets
+
+ - [ ] backtracking
+
+
+- [x] dynamic programming
+
+ - coin change
+
+ - longest common subsequence
+
+ - edit distance
+
+
+
+
+
+
+-[ ] majority element
+
+
+
+- [ ] 随机
+ - 水塘抽样
+ - 洗牌
+
+
+-[ ] 荷兰旗问题
+
+
+-[ ] quick select
+
+
+-[ ] median of two sorted array
+-[ ] regular expression
+
diff --git a/docs/Leetcode_Solutions/Python/Summary/Dynamic Programming.md b/docs/Leetcode_Solutions/Python/Summary/Dynamic Programming.md
new file mode 100644
index 000000000..102d032c3
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/Summary/Dynamic Programming.md
@@ -0,0 +1,48 @@
+### Dynamic Programming
+
+
+
+- Fibonacci Numbers
+- Shortest Path (no cycles)
+
+
+
+
+
+
+
+- subproblems
+
+- guessing
+
+- relate subproblems
+
+- recurse & memoize (bulid DP table)
+
+- solve original problem
+
+
+
+
+
+
+
+
+
+
+
+
+感觉DP有几类:
+
+- 容易写出递推公式的
+
+- 画表更容易理解的
+
+
+
+* DP ≈ “controlled brute force”
+
+* DP ≈ recursion + re-use
+
+
+
diff --git "a/docs/Leetcode_Solutions/Python/Summary/Introduction to String Searching Algorithms \342\200\223 topcoder.pdf" "b/docs/Leetcode_Solutions/Python/Summary/Introduction to String Searching Algorithms \342\200\223 topcoder.pdf"
new file mode 100644
index 000000000..110950bf9
Binary files /dev/null and "b/docs/Leetcode_Solutions/Python/Summary/Introduction to String Searching Algorithms \342\200\223 topcoder.pdf" differ
diff --git "a/docs/Leetcode_Solutions/Python/Summary/Java\345\220\204\347\247\215\347\261\273\345\236\213\347\232\204\350\275\254\346\215\242.md" "b/docs/Leetcode_Solutions/Python/Summary/Java\345\220\204\347\247\215\347\261\273\345\236\213\347\232\204\350\275\254\346\215\242.md"
new file mode 100644
index 000000000..c1d3e5522
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/Java\345\220\204\347\247\215\347\261\273\345\236\213\347\232\204\350\275\254\346\215\242.md"
@@ -0,0 +1,239 @@
+之前在写java程序的时候,经常会遇到很多的需要需要转换基础数据类型的情况,然后我就一直去记录这些情况,今天做了一下总结,当然转换的方法肯定不止我写的这些,有的我可能只会写其中的一种,以后再遇到其他的情况的话,我会慢慢来补充,希望这篇文章会对大家能有所帮助。
+
+------
+
+# String的转换
+
+首先介绍一下String类型的转换,一般遇到的情况可能会有以下几种:Strng转int,String转long,String转byte数组,String转float,下面主要介绍这四种情况。
+
+## String转int
+
+把String类型转换为int类型,常用的有以下三种方法:
+
+```
+public class StringToInt {
+ public static void main(String[] args) {
+ String number = "123456";
+ int num1 = Integer.parseInt(number);//使用Integer的parseInt方法
+ int num2 = new Integer(number);//强制转换
+ int num3 = Integer.valueOf(number).intValue();//先转Integer类型,再调用intValue()转为int
+ }
+}
+```
+
+## String转long
+
+把String类型转换为long类型的方法跟上面的方法类似。
+
+```
+public class StringToLong {
+ public static void main(String[] args) {
+ String number = "1234567890";
+ long num1 = Long.parseLong(number);//调用Long类型的parseLong方法
+ long num2 = new Long(number);//强制转换
+ long num3 = Long.valueOf(number).longValue();//先转换Long类型,再使用longValue方法转为long
+ }
+}
+```
+
+## String转float
+
+把String类型转换为float类型的方法也跟上面的类似。
+
+```
+public class StringToFloat {
+ public static void main(String[] args) {
+ String number = "1234.202";
+ float num1 = Float.parseFloat(number);//调用Float的parseFloat方法
+ float num2 = new Float(number);//强制转换
+ float num3 = Float.valueOf(number).floatValue();//先转为Float类型再使用floatValue转为float
+ }
+}
+```
+
+## String转byte[]
+
+String类型转byte数组方法一般使用String类自带的`getBytes()`方法。
+
+```
+public class StringToByte {
+ public static void main(String[] args) {
+ byte[] num = new byte[200];
+ String number = "1234567890";
+ num = number.getBytes();
+ }
+}
+```
+
+这里补充一个path类型转换为String类型的方法:
+
+```
+String fileName=path.getFileName().toString();
+```
+
+------
+
+# long类型转换
+
+long类型的转换,这一部分用的情况也很多,下面介绍几种常见的情况。
+
+## long转String
+
+long类型转String类型,这里主要介绍三种方法:
+
+```
+public class LongToString {
+ public static void main(String[] args) {
+ long number = 1234567890l;
+ String num1 = Long.toString(number);//Long的tostring方法
+ String num2 = String.valueOf(number);//使用String的valueOf方法
+ String num3 = "" + number;//这个应该属于强制转换吧
+ }
+}
+```
+
+## long转int
+
+long类型转换为int类型,这里也主要介绍三种方法:
+
+```
+public class LongToInt {
+ public static void main(String[] args) {
+ long number = 121121121l;
+ int num1 = (int) number;// 强制类型转换
+ int num2 = new Long(number).intValue();// 调用intValue方法
+ int num3 = Integer.parseInt(String.valueOf(number));// 先把long转换位字符串String,然后转换为Integer
+ }
+}
+```
+
+## long与byte数组的相互转换
+
+一直都感觉byte数组转换比较繁琐,这里也不再叙述,我就给出一篇别人的博客让大家作为参考吧,这里面byte数组与多种数据类型的转换——[ java Byte和各数据类型(short,int,long,float,double)之间的转换](http://blog.csdn.net/cshichao/article/details/9813973)
+
+------
+
+# int类型的转换
+
+int类型的转换也是我们经常使用的情况,下面也主要介绍几种常见的情况。
+
+## int转String
+
+int类型转换为String类型与long转String的类似,一般也有以下三种方法。
+
+```
+public class IntToString {
+ public static void main(String[] args) {
+ int number = 121121;
+ String num1 = Integer.toString(number);//使用Integer的toString方法
+ String num2 = String.valueOf(number);//使用String的valueOf方法
+ String num3 = "" + number;//也是强制转换吧
+ }
+}
+```
+
+## int与Byte的相互转换
+
+关于int类型与byte[]数组的转换,一般情况下,我们使用条件都是在这里转换过来,在另外一个地方就要转换回来,这里介绍两种int与byte数组互相转换的方式。
+
+```
+//int类型转换为byte[]数组
+public static byte[] intToByteArray(int i) {
+ byte[] result = new byte[4];
+ // 由高位到低位
+ result[0] = (byte) ((i >> 24) & 0xFF);
+ result[1] = (byte) ((i >> 16) & 0xFF);
+ result[2] = (byte) ((i >> 8) & 0xFF);
+ result[3] = (byte) (i & 0xFF);
+ return result;
+}
+
+//byte数组转换为int类型
+public static int byteArrayToInt(byte[] bytes) {
+ int value = 0;
+ // 由高位到低位
+ for (int i = 0; i < 4; i++) {
+ int shift = (4 - 1 - i) * 8;
+ value += (bytes[i] & 0x000000FF) << shift;// 往高位游
+ }
+ return value;
+}
+```
+
+还有一种为:
+
+```
+//int类型转换为byte[]数组
+public static byte[] intToByteArray(int x) {
+ byte[] bb = new byte[4];
+ bb[3] = (byte) (x >> 24);
+ bb[2] = (byte) (x >> 16);
+ bb[1] = (byte) (x >> 8);
+ bb[0] = (byte) (x >> 0);
+ return bb;
+}
+
+//byte数组转换为int类型
+public static int byteArrayToInt(byte[] bb) {
+ return (int) ((((bb[3] & 0xff) << 24) | ((bb[2] & 0xff) << 16) | ((bb[1] & 0xff) << 8) | ((bb[0] & 0xff) << 0)));
+}
+```
+
+## int转long
+
+int类型转换为long类型的情况并不是大多,这里主要接收几种转换方法:
+
+```
+public class IntToLong {
+ public static void main(String[] args) {
+ int number = 123111;
+ long num1 = (long) number;//强制
+ long num2 = Long.parseLong(new Integer(number).toString());//先转String再进行转换
+ long num3 = Long.valueOf(number);
+ }
+}
+```
+
+## int转Interger
+
+int类型转换为Interger类型的情况,我是基本上每怎么遇到过,在这里也上网查询一些资料找到了两种方法。
+
+```
+public class IntToInterge {
+ public static void main(String[] args) {
+ int number = 123456;
+ Integer num1 = Integer.valueOf(number);
+ Integer num2 = new Integer(number);
+ }
+}
+```
+
+------
+
+# byte数组的转换
+
+关于byte数组的转换,上面有几个都是它们只见相互转换的,所以这里就不再介绍那么多,只介绍一个byte数组转换String类型的方法,其他的类型可以通过String类型再进行转换。
+
+byte数组转String类型的方法经常用的可能就是下面这种方法。
+
+```
+public class ByteToString {
+ public static void main(String[] args) {
+ byte[] number = "121121".getBytes();
+ String num1 = new String(number);
+ }
+}
+```
+
+------
+
+最后简单补充以下Java基本数据类型的一些知识:
+
+| 类型 | 字节数 | 类名称 | 范围 |
+| ------ | ---- | -------- | ---------------------------------------- |
+| int | 4字节 | Interger | -2147483648 ~ 2147483647 |
+| short | 2字节 | Short | -32768 ~ 32767 |
+| long | 8字节 | Long | -9223372036854775808 ~ 9223372036854775807 |
+| byte | 1字节 | Byte | -128 ~ 127 |
+| float | 4字节 | Float | |
+| double | 8字节 | Double | |
\ No newline at end of file
diff --git "a/docs/Leetcode_Solutions/Python/Summary/LinkedList\346\212\200\345\267\247.md" "b/docs/Leetcode_Solutions/Python/Summary/LinkedList\346\212\200\345\267\247.md"
new file mode 100644
index 000000000..677a083a2
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/LinkedList\346\212\200\345\267\247.md"
@@ -0,0 +1,118 @@
+# LinkedList
+
+结点定义如下:
+
+ class ListNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+
+
+可以使用的技巧包括:
+
+
+## Dummy head
+
+有的时候因为边界条件,需要判定是否是list的head,因为处理起来会有些不同,而创造一个dummy head则可以极大的解决一些问题。
+
+```
+ dummy = ListNode(-1)
+ dummy.next = head
+```
+
+## 双指针
+
+- 19. Remove Nth Node From End of List
+
+两个指针p,q, q先走n步,然后p和q一起走,直到q走到结点,删除p.next解决。
+
+理解: 先走了n步,q始终在p前方n个,这样q走到末尾,p的下一个则是距离尾端n个的,画个图还是容易理解。
+
+
+- 160. Intersection of Two Linked Lists
+
+如果两个linkedlist有intersection的话,可以看到,其实如果一开始我们就走到b2的话,那么我们就可以两个pointer一个一个的对比,到哪一个地址一样,接下来就是intersection部分。
+
+就一开始把长的那条list走掉多余部分。
+还有这里保证了是无环的状况
+
+
+
+```
+A: a1 → a2
+ ↘
+ c1 → c2 → c3
+ ↗
+B: b1 → b2 → b3
+```
+
+
+## 快慢指针
+
+- 141. Linked List Cycle
+
+用两个指针,一个每次走两步,一个每次走一步,如果慢的最终和快的相遇,那么说明有环,否则没有环,直观的理解是如果两个跑的速度不一的人进操场跑步,那么最终慢的会追上快的.
+
+
+
+## Reverse Linked List
+
+- 206. Reverse Linked List
+
+loop版本用prev, cur ,nxt 三个指针过一遍,recursion版本如下,可以再消化消化
+
+```
+class Solution(object):
+ def reverseList(self, head):
+ """
+ :type head: ListNode
+ :rtype: ListNode
+ """
+ return self.doReverse(head, None)
+
+
+ def doReverse(self, head, newHead):
+ if head == None:
+ return newHead
+ nxt = head.next
+ head.next = newHead
+ return self.doReverse(nxt, head)
+```
+
+
+## 寻找LinkedList中间项
+
+依旧使用双指针,快慢指针:快指针每次走两步,慢指针每次走一步,快指针如果到头了,那么慢指针也会在中间了,这个中间可以考量,如果是奇数的话必然是中间。
+
+如果是偶数则是偏前面的中间一项
+
+```
+1 -> 2 -> 3 -> 4: 2
+1 -> 2 -> 3 -> 4 -> 5 -> 6 : 3
+1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 : 4
+
+```
+
+算法:
+
+```
+
+def findMid(head):
+ if head == None or head.next == None:
+ return head
+
+ slow = head
+ fast = head
+
+ while fast.next and fast.next.next:
+ slow = slow.next
+ fast = fast.next.next
+
+ return slow
+```
+
+
+
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/Summary/Maximal Square.pdf b/docs/Leetcode_Solutions/Python/Summary/Maximal Square.pdf
new file mode 100644
index 000000000..235cd3b86
Binary files /dev/null and b/docs/Leetcode_Solutions/Python/Summary/Maximal Square.pdf differ
diff --git "a/docs/Leetcode_Solutions/Python/Summary/Python\345\210\267\351\242\230\346\212\200\345\267\247\347\254\224\350\256\260.md" "b/docs/Leetcode_Solutions/Python/Summary/Python\345\210\267\351\242\230\346\212\200\345\267\247\347\254\224\350\256\260.md"
new file mode 100644
index 000000000..c781932a3
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/Python\345\210\267\351\242\230\346\212\200\345\267\247\347\254\224\350\256\260.md"
@@ -0,0 +1,206 @@
+
+### python有无数奇技淫巧和许多人不知道的秘密,这里用简洁的语言一条条表述出来,不断更新, 大家一起贡献!
+```python
+# 1. python 排序
+# 用lst.sort() 而不是nlst = sorted(lst), 区别在于lst.sort()是 in-place sort,改变lst, sorted会创建新list,成本比较高。
+```
+```python
+# 2. xrange和range的区别
+# range会产生list存在memory中,xrange更像是生成器,generate on demand所以有的时候xrange会更快
+```
+```python
+# 3. python处理矩阵
+row = len(matrix)
+col = len(matrix[0]) if row else 0
+# 这样写通用的原因是, 当matrix = [], row = 0, col = 0
+```
+```python
+# 4. python列表生成式
+lst = [0 for i in range(3)] # lst = [0,0,0]
+lst = [[0 for i in range(3)] for j in range(2)] # lst = [[0, 0, 0], [0, 0, 0]]
+# 下面这种写法危险:
+# lst1 = [ 0, 0, 0 ]
+# lst2 = [lst1] * 2 # lst2 = [ [0,0,0] , [0,0,0] ]
+# lst2[0][0] = 1 # lst2 = [ [1,0,0], [1,0,0]]
+# 因为lst1是object,改一个相当于全改, 这样写会踩坑
+```
+```python
+# 5. D.get(key, default)
+# 如果这个key 没有在dict里面,给它一个默认值:
+D = {}
+if 1 in D:
+ val = D[1]
+else :
+ val = 0
+# 等同于这样写:
+val = D.get(1, 0)
+```
+```python
+# 6. 字典赋值
+if key in D:
+ D[key].append(1)
+else :
+ D[key] = []
+```
+```python
+# 7. 字符串反转和列表反转
+# python字符串没有reverse函数,只能str[::-1]
+string[::-1]
+# python的list可以直接reverse(),因此也可以借用这个特性
+"".join([string].reverse())
+
+测试了一下3种列表反转的速度
+tmp = [i for i in range(100000)]
+
+import datetime
+starttime = datetime.datetime.now()
+
+for i in range(100000):
+ tmp = tmp[::-1]
+endtime = datetime.datetime.now()
+print((endtime - starttime))
+
+starttime = datetime.datetime.now()
+for i in range(100000):
+ tmp = list(reversed(tmp))
+endtime = datetime.datetime.now()
+print((endtime - starttime))
+
+starttime = datetime.datetime.now()
+for i in range(100000):
+ tmp.reverse()
+endtime = datetime.datetime.now()
+print((endtime - starttime))
+
+
+
+
+输出:
+0:00:33.486971
+0:01:43.027222
+0:00:03.958400
+
+说明in-place反转最快,但是这样改变了原list,因此在不能改动原list的情况下,我们用分片会更好
+```
+```python
+# 8. 快速统计
+import collections
+lst = [1, 1, 1, 2, 3, 4, 5, 5]
+collections.Counter(lst) # Counter({1: 3, 5: 2, 2: 1, 3: 1, 4: 1})
+```
+```python
+# 9. python自带小顶堆heapq
+# Python有built-in heap, 默认min heap.
+heapq.heappush(heap, item) # 把item添加到heap中(heap是一个列表)
+
+heapq.heappop(heap) # 把堆顶元素弹出,返回的就是堆顶
+
+heapq.heappushpop(heap, item) # 先把item加入到堆中,然后再pop,比heappush()再heappop()要快得多
+
+heapq.heapreplace(heap, item) # 先pop,然后再把item加入到堆中,比heappop()再heappush()要快得多
+
+heapq.heapify(x) # 将列表x进行堆调整,默认的是小顶堆
+
+heapq.merge(*iterables) # 将多个列表合并,并进行堆调整,返回的是合并后的列表的迭代器
+
+heapq.nlargest(n, iterable, key=None) # 返回最大的n个元素(Top-K问题)
+
+heapq.nsmallest(n, iterable, key=None) # 返回最小的n个元素(Top-K问题)
+
+# 如何来用它实现max heap呢,看到过一个有意思的方法是把key取负,比如把100变成-100,5变成-5
+
+import heapq
+mylist = [1, 2, 3, 4, 5, 10, 9, 8, 7, 6]
+largest = heapq.nlargest(3, mylist) # [10, 9, 8]
+smallest = heapq.nsmallest(3, mylist) # [1, 2, 3]
+```
+```python
+# 10. 双端队列deque [http://stackoverflow.com/questions/4098179/anyone-know-this-python-data-structure]
+# 可以很简单的.popleft(), .popright(), .appendleft(), .appendright(),最关键的是时间是O(1), 而用list来模拟队列是O(n)的时间复杂度
+# 还有很好用的rotate函数,
+# 一个简单的跑马灯程序
+import sys
+import time
+from collections import deque
+
+fancy_loading = deque('>--------------------')
+
+while True:
+ print('\r%s' % ''.join(fancy_loading))
+ fancy_loading.rotate(1)
+ sys.stdout.flush()
+ time.sleep(0.08)
+```
+```python
+# 11. 用yield 不用return,可以返回一个generator
+```
+```python
+# 12. 符号~的巧妙应用
+for i in range(n):
+ # 这里的```[~i]``` 意思就是 ```[n-1-i]```
+ a[~i] = 1
+```
+```python
+# 13. 位运算判断奇偶数
+一般判断奇偶数是用 num % 2 == 0 来判断,如果为true则为偶数,为false则为奇数。
+偶数在二进制里面,最后一位为0,奇数则为1。所以可以通过与1做位与运算判断奇偶数。
+if (num & 1) == 0:
+ print('偶数')
+else:
+ print('奇数')
+如果结果为true则为偶数,为false则为奇数。效率比取余运算高的多。
+
+反正注意不要使用
+if num % 2 == 1
+来判断是否是奇数,因为如果是负奇数就不满足了
+
+最起码也要用if num % 2 != 0
+```
+
+
+```python
+# 14. pow(x, y)的时间复杂度为:
+
+For y < 2^63, there's a loop of size ceil(log_2(y)),
+but for larger y, the result is calculated using Exp(y * Log(x)).
+
+sqrt()函数平常认为是O(lgn)的
+但是追溯到最底层,sqrt()就是O(1)的,详细见
+```
+1. [求平方根sqrt()函数的底层算法效率问题](http://www.nowamagic.net/algorithm/algorithm_EfficacyOfFunctionSqrt.php)
+2. [Time complexity of Math.Sqrt()?](https://stackoverflow.com/questions/34580158/time-complexity-of-math-sqrt)
+
+
+```python
+# 15. python deque用法
+
+Operations on deque :
+
+1. append() :- This function is used to insert the value in its argument to the right end of deque.
+2. appendleft() :- This function is used to insert the value in its argument to the left end of deque.
+3. pop() :- This function is used to delete an argument from the right end of deque.
+4. popleft() :- This function is used to delete an argument from the left end of deque.
+5. index(ele, beg, end) :- This function returns the first index of the value mentioned in arguments, starting searching from beg till end index.
+6. insert(i, a) :- This function inserts the value mentioned in arguments(a) at index(i) specified in arguments.
+7. remove() :- This function removes the first occurrence of value mentioned in arguments.
+8. count() :- This function counts the number of occurrences of value mentioned in arguments.
+9. extend(iterable) :- This function is used to add multiple values at the right end of deque. The argument passed is an iterable.
+10. extendleft(iterable) :- This function is used to add multiple values at the left end of deque. The argument passed is an iterable. Order is reversed as a result of left appends.
+11. reverse() :- This function is used to reverse order of deque elements.
+12. rotate() :- This function rotates the deque by the number specified in arguments. If the number specified is negative, rotation occurs to left. Else rotation is to right.
+```
+[Deque in Python](https://www.geeksforgeeks.org/deque-in-python/)
+
+
+```python
+# 16. getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.
+
+# 这种是常规方法
+idx = random.randint(0, self.length-1)
+return self.lst[idx]
+# 神奇函数
+return random.choice(self.lst)
+```
+
+
+
diff --git a/docs/Leetcode_Solutions/Python/Summary/Range Sum Query 2D - Immutable.pdf b/docs/Leetcode_Solutions/Python/Summary/Range Sum Query 2D - Immutable.pdf
new file mode 100644
index 000000000..09410e209
Binary files /dev/null and b/docs/Leetcode_Solutions/Python/Summary/Range Sum Query 2D - Immutable.pdf differ
diff --git a/docs/Leetcode_Solutions/Python/Summary/Recusrion & BackTracking.md b/docs/Leetcode_Solutions/Python/Summary/Recusrion & BackTracking.md
new file mode 100644
index 000000000..16e0f9279
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/Summary/Recusrion & BackTracking.md
@@ -0,0 +1,237 @@
+#Recusrion & BackTracking
+
+##Recusrion
+
+### DrawFractal
+
+```
+void DrawFractal(double x, double y, double w, double h)
+{
+ DrawTriangel(x, y, w, h);
+ if(w < .2 || h < .2) return ;
+ double halfH = h/2;
+ double halfw = w/2;
+ DrawFractal(x, y, halfW, halfH);
+ DrawFractal(x + halfW/2, y + halfH, halfW, halfH);
+ DrawFractal(x + halfW, y, halfW, halfH);
+}
+```
+
+
+Sierpinski triangle更伪码的写法:
+
+```
+void DrawFractal (x, y, w, h){
+ if (too small) return ;
+ DrawTriangle(x, y, w, h);
+ DrawFractal(.left);
+ DrawFractal(.top);
+ DrawFractal(.right);
+}
+```
+
+实际上老师故意调了里面几句代码的顺序,让来看到虽然结果相同,但是画的过程是不一样的。
+
+然后老师还在黑板上画了过程树,分枝是怎样的,实际上当学到DFS的preOrder, inOrder 和 postOrder的时候会更印象深刻。
+
+一个分支走完之后再回去走另一些。
+
+
+### DrawMondrian
+
+
+
+```
+void DrawMondrian(double x, double y, double w, double h){
+
+ if(w < 1 || h < 1) return ;// base case
+
+ FillRectangle(x,y,w,h,RandomColor()); // fill background
+
+ switch(RandomInteger(0, 2)){
+ case 0: // do nothing
+ break;
+ case 1: // bisect vertically
+ double midX = RandomReal(0,w);
+ DrawBlackLine( x + midX, y, h);
+ DrawMondrian(x, y, midX, h);
+ DrawMondrian(x + midx, y, w- midX, h);
+ break;
+ case 2: // bisect horizontally
+ double midY = RandomReal(0,h);
+ DrawBlackLine( x, y+ midY, h);
+ DrawMondrian(x, y, w, midY);
+ DrawMondrian(x, y+midY,w, midY);
+ break;
+ }
+}
+```
+
+
+### The tower of Hanoi
+
+
+```
+void MoveTower(int n, char src, char dst, char tmp){
+ if (n > 0){
+ MoveTower(n - 1, src, tmp, dst );
+ MoveSingleDisk(src, dst);
+ MoveTower(n -1, tmp, dst, src);
+ }
+}
+
+```
+
+
+### Permutation
+
+老师说permutation 和 subset 是 mother problems of all recursion.
+
+
+given a string, print out its all permutations
+
+思路如下:
+
+- 使用了的string sofar,以及还未使用的string rest
+- 一开始rest就是给的string本身,然后sofar是空
+- 每次挑一个rest里面的char,然后递归的再把rest剩下的拿来permutation,这样每次都会有一个char从rest shuffle到sofar
+- n 次之后 rest为空,制造了一个permutation
+
+
+```
+void RecPermute(string sofar, string rest){
+ if(rest = ""){
+ cout << soFar << endl;
+ } else {
+ for(int i = 0 ; i < rest.length(); i++){
+ string next = soFar + rest[i];
+ string remaining = rest.substr(0,i) + rest.substr(i+1);
+ RecPermute(next, remaining);
+ }
+ }
+}
+
+
+// "wrapper" function
+void ListPermutations(string s)
+{
+ RecPermute("",s);
+}
+```
+
+
+老师的黑板图真的是击中要害。
+
+因为老师强调的是,也要用mind来trace它是如何操作的。
+
+
+
+### Subsets
+
+
+```
+void RecSubsets(string soFar, string rest)
+{
+ if(rest = "")
+ cout << soFar << endl;
+ else {
+ // add to subset, remove from rest, recur
+ RecSubsets(soFar + rest[0],rest.substr(1));
+ //don't add to substr, remove from rest, recur
+ RecSubsets(soFar, rest.substr(1));
+ }
+}
+
+
+void ListSubsets(string str)
+{
+ RecSubsets("",str);
+}
+
+```
+
+代码非常容易理解
+
+
+比较一下:两个都是有关选择,permutation是每次选哪一个char,而subsets是选择这个char 是否in.
+
+两个recursion tree都是有branching 和 depth的, depth都是n,每次选一个,知道n个选完.
+
+branching是how many recusive calls 每次made,subset每次都是两个,in/out,而permutation则是n,n-1.......grows very quickly.
+
+因为permutation是n!,subsets是2^n,跟树对应。这些都是比较intractable的问题,并不是因为recursion,而是问题本身的复杂度。
+
+
+这两个问题都是exhaustive的,然而,我们会更多碰到一些问题,有着
+
+similar exhaustive structure,但是遇到'satisfactory' outcome就会stop的 -> 也就是backtracking了.
+
+##BackTracking
+
+
+
+### pseudocode
+
+把问题转成decision problem,然后开始make choice.
+
+```
+bool Solve(configuration conf)
+{
+ if (no more choices) // BASE CASE
+ return (conf is goal state);
+
+ for (all available choices){
+ try one choice c;
+ // sove from here, it works out. you're done.
+ if (Solve(conf with choice c made)) return true;
+ unmake choice c;
+ }
+ return false; //tried all choices, no soln found
+}
+```
+
+
+###IsAnagram
+
+
+```
+bool IsAnagram(string soFar, string rest, Lexicon & lex)
+{
+ if(rest == ""){
+ if(lex.contains(soFar)){
+ cout << soFar << endl;
+ return true;
+ }
+ } else {
+ for(int i = 0; i < rest.length() ; i++ ){
+ string next = soFar + rest[i];
+ string remaining = rest.substr(0,i) + rest.substr(i+1);
+ if(IsAnagram(next, remaining, lex)) return true;
+ }
+ }
+ return false;
+}
+```
+
+
+### 8 Queens
+
+
+```
+
+bool Solve(Grid &board, int col)
+{
+ if(col > = board.numCols()) return true;
+
+ for(int rowToTry = 0; rowToTry < board.numRows(); rowToTry++){
+ if (IsSafe(board,rowToTry, col)){
+ PlaceQueen(board,rowToTry,col);
+ if (Solve(board,col+1)) return true;
+ RemoveQueen(board,rowToTry, col);
+ }
+ }
+ return false;
+}
+
+```
+
diff --git "a/docs/Leetcode_Solutions/Python/Summary/backtracking\346\200\235\350\267\257.md" "b/docs/Leetcode_Solutions/Python/Summary/backtracking\346\200\235\350\267\257.md"
new file mode 100644
index 000000000..dbb7e8cf1
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/backtracking\346\200\235\350\267\257.md"
@@ -0,0 +1,295 @@
+## backtracking 全集
+
+### 回溯是啥
+用爬山来比喻回溯,好比从山脚下找一条爬上山顶的路,起初有好几条道可走,当选择一条道走到某处时,又有几条岔道可供选择,只能选择其中一条道往前走,若能这样子顺利爬上山顶则罢了,否则走到一条绝路上时,只好返回到最近的一个路口,重新选择另一条没走过的道往前走。如果该路口的所有路都走不通,只得从该路口继续回返。照此规则走下去,要么找到一条到达山顶的路,要么最终试过所有可能的道,无法到达山顶。
+回溯是一种穷举,但与brute force有一些区别,回溯带了两点脑子的,并不多,brute force一点也没带。
+第一点脑子是回溯知道回头;相反如果是brute force,发现走不通立刻跳下山摔死,换第二条命从头换一条路走。
+第二点脑子是回溯知道剪枝;如果有一条岔路上放了一坨屎,那这条路我们不走,就可以少走很多不必要走的路。
+
+还有一些爱混淆的概念:递归,回溯,DFS。
+回溯是一种找路方法,搜索的时候走不通就回头换路接着走,直到走通了或者发现此山根本不通。
+DFS是一种开路策略,就是一条道先走到头,再往回走一步换一条路走到头,这也是回溯用到的策略。在树和图上回溯时人们叫它DFS。
+递归是一种行为,回溯和递归如出一辙,都是一言不合就回到来时的路,所以一般回溯用递归实现;当然也可以不用,用栈。
+以下以回溯统称,因为这个词听上去很文雅。
+
+### 识别回溯
+判断回溯很简单,拿到一个问题,你感觉如果不穷举一下就没法知道答案,那就可以开始回溯了。
+一般回溯的问题有三种:
+
+1. Find a path to success 有没有解
+2. Find all paths to success 求所有解
+ - 2.1 求所有解的个数,
+ - 2.2 求所有解的具体信息
+3. Find the best path to success 求最优解
+
+理解回溯:给一堆选择, 必须从里面选一个. 选完之后我又有了新的一组选择. ```This procedure is repeated over and over until you reach a final state. If you made a good sequence of choices, your final state is a goal state; if you didn't, it isn't.```
+
+回溯可以抽象为一棵树,我们的目标可以是找这个树有没有good leaf,也可以是问有多少个good leaf,也可以是找这些good leaf都在哪,也可以问哪个good leaf最好,分别对应上面所说回溯的问题分类。
+good leaf都在leaf上。good leaf是我们的goal state,leaf node是final state,是解空间的边界。
+
+对于第一类问题(问有没有解),基本都是长着个样子的,理解了它,其他类别迎刃而解:
+```java
+boolean solve(Node n) {
+ if n is a leaf node {
+ if the leaf is a goal node, return true
+ else return false
+ } else {
+ for each child c of n {
+ if solve(c) succeeds, return true
+ }
+ return false
+ }
+}
+```
+请读以下这段话以加深理解:
+```Notice that the algorithm is expressed as a boolean function. This is essential to understanding the algorithm. If solve(n) is true, that means node n is part of a solution--that is, node n is one of the nodes on a path from the root to some goal node. We say that n is solvable. If solve(n) is false, then there is no path that includes n to any goal node.```
+
+还不懂的话请通读全文吧:[Backtracking - David Matuszek](https://www.cis.upenn.edu/~matuszek/cit594-2012/Pages/backtracking.html)
+
+关于回溯的三种问题,模板略有不同,
+第一种,返回值是true/false。
+第二种,求个数,设全局counter,返回值是void;求所有解信息,设result,返回值void。
+第三种,设个全局变量best,返回值是void。
+
+第一种:
+```java
+boolean solve(Node n) {
+ if n is a leaf node {
+ if the leaf is a goal node, return true
+ else return false
+ } else {
+ for each child c of n {
+ if solve(c) succeeds, return true
+ }
+ return false
+ }
+}
+```
+第二种:
+```java
+void solve(Node n) {
+ if n is a leaf node {
+ if the leaf is a goal node, count++, return;
+ else return
+ } else {
+ for each child c of n {
+ solve(c)
+ }
+ }
+}
+```
+第三种:
+```java
+void solve(Node n) {
+ if n is a leaf node {
+ if the leaf is a goal node, update best result, return;
+ else return
+ } else {
+ for each child c of n {
+ solve(c)
+ }
+ }
+}
+```
+题目
+
+八皇后 N-Queens
+
+问题
+
+1. 给个n,问有没有解;
+2. 给个n,有几种解;(Leetcode N-Queens II)
+3. 给个n,给出所有解;(Leetcode N-Queens I)
+
+解答
+
+1.有没有解
+
+怎么做:一行一行的放queen,每行尝试n个可能,有一个可达,返回true;都不可达,返回false.
+
+边界条件leaf:放完第n行 或者 该放第n+1行(出界,返回)
+
+目标条件goal:n行放满且isValid,即目标一定在leaf上
+
+helper函数:
+boolean solve(int i, int[][] matrix)
+在进来的一瞬间,满足property:第i行还没有被放置,前i-1行放置完毕且valid
+solve要在给定的matrix上试图给第i行每个位置放queen。
+```java
+public static boolean solve1(int i, List matrix, int n) {
+ if (i == n) {
+ if (isValid(matrix))
+ return true;
+ return false;
+ } else {
+ for (int j = 0; j < n; j++) {
+ matrix.add(j);
+ if (isValid(matrix)) { //剪枝
+ if (solve1(i + 1, matrix, n))
+ return true;
+ }
+ matrix.remove(matrix.size() - 1);
+ }
+ return false;
+ }
+}
+```
+2.求解的个数
+
+怎么做:一行一行的放queen,每行尝试n个可能。这回因为要找所有,返回值就没有了意义,用void即可。在搜索时,如果有一个可达,仍要继续尝试;每个子选项都试完了,返回.
+
+边界条件leaf:放完第n行 或者 该放第n+1行(出界,返回)
+
+目标条件goal:n行放满且isValid,即目标一定在leaf上
+
+helper函数:
+void solve(int i, int[][] matrix)
+在进来的一瞬间,满足property:第i行还没有被放置,前i-1行放置完毕且valid
+solve要在给定的matrix上试图给第i行每个位置放queen。
+这里为了记录解的个数,设置一个全局变量(static)int是比较efficient的做法。
+```java
+public static void solve2(int i, List matrix, int n) {
+ if (i == n) {
+ if (isValid(matrix))
+ count++;
+ return;
+ } else {
+ for (int j = 0; j < n; j++) {
+ matrix.add(j);
+ if (isValid(matrix)) { //剪枝
+ solve2(i + 1, matrix, n);
+ }
+ matrix.remove(matrix.size() - 1);
+ }
+ }
+}
+```
+3.求所有解的具体信息
+
+怎么做:一行一行的放queen,每行尝试n个可能。返回值同样用void即可。在搜索时,如果有一个可达,仍要继续尝试;每个子选项都试完了,返回.
+
+边界条件leaf:放完第n行 或者 该放第n+1行(出界,返回)
+
+目标条件goal:n行放满且isValid,即目标一定在leaf上
+
+helper函数:
+void solve(int i, int[][] matrix)
+在进来的一瞬间,满足property:第i行还没有被放置,前i-1行放置完毕且valid
+solve要在给定的matrix上试图给第i行每个位置放queen。
+这里为了记录解的具体情况,设置一个全局变量(static)集合是比较efficient的做法。
+当然也可以把结果集合作为参数传来传去。
+```java
+public static void solve3(int i, List matrix, int n) {
+ if (i == n) {
+ if (isValid(matrix))
+ result.add(new ArrayList(matrix));
+ return;
+ } else {
+ for (int j = 0; j < n; j++) {
+ matrix.add(j);
+ if (isValid(matrix)) { //剪枝
+ solve3(i + 1, matrix, n);
+ }
+ matrix.remove(matrix.size() - 1);
+ }
+ }
+}
+```
+优化
+
+上面的例子用了省空间的方法。
+由于每行只能放一个,一共n行的话,用一个大小为n的数组,数组的第i个元素表示第i行放在了第几列上。
+
+Utility(给一个list判断他的最后一行是否和前面冲突):
+```java
+public static boolean isValid(List list){
+ int row = list.size() - 1;
+ int col = list.get(row);
+ for (int i = 0; i <= row - 1; i++) {
+ int row1 = i;
+ int col1 = list.get(i);
+ if (col == col1)
+ return false;
+ if (row1 - row == col1 - col)
+ return false;
+ if (row1 - row == col - col1)
+ return false;
+ }
+ return true;
+
+}
+```
+
+参考[Backtracking回溯法(又称DFS,递归)全解](https://segmentfault.com/a/1190000006121957)
+以及 [Python Patterns - Implementing Graphs](https://www.python.org/doc/essays/graphs/)
+
+
+
+## 以Generate Parentheses为例,backtrack的题到底该怎么去思考?
+
+
+所谓Backtracking都是这样的思路:在当前局面下,你有若干种选择。那么尝试每一种选择。如果已经发现某种选择肯定不行(因为违反了某些限定条件),就返回;如果某种选择试到最后发现是正确解,就将其加入解集
+
+所以你思考递归题时,只要明确三点就行:选择 (Options),限制 (Restraints),结束条件 (Termination)。即“ORT原则”(这个是我自己编的)
+
+
+
+
+对于这道题,在任何时刻,你都有两种选择:
+1. 加左括号。
+2. 加右括号。
+
+同时有以下限制:
+1. 如果左括号已经用完了,则不能再加左括号了。
+2. 如果已经出现的右括号和左括号一样多,则不能再加右括号了。因为那样的话新加入的右括号一定无法匹配。
+
+结束条件是:
+左右括号都已经用完。
+
+结束后的正确性:
+左右括号用完以后,一定是正确解。因为1. 左右括号一样多,2. 每个右括号都一定有与之配对的左括号。因此一旦结束就可以加入解集(有时也可能出现结束以后不一定是正确解的情况,这时要多一步判断)。
+
+递归函数传入参数:
+限制和结束条件中有“用完”和“一样多”字样,因此你需要知道左右括号的数目。
+当然你还需要知道当前局面sublist和解集res。
+
+因此,把上面的思路拼起来就是代码:
+
+ if (左右括号都已用完) {
+ 加入解集,返回
+ }
+ //否则开始试各种选择
+ if (还有左括号可以用) {
+ 加一个左括号,继续递归
+ }
+ if (右括号小于左括号) {
+ 加一个右括号,继续递归
+ }
+
+
+
+你帖的那段代码逻辑中加了一条限制:“3. 是否还有右括号剩余。如有才加右括号”。这是合理的。不过对于这道题,如果满足限制1、2时,3一定自动满足,所以可以不判断3。
+
+这题其实是最好的backtracking初学练习之一,因为ORT三者都非常简单明显。你不妨按上述思路再梳理一遍,还有问题的话再说。
+
+
+
+以上文字来自 1point3arces的牛人解答
+
+
+
+Backtracking 伪码
+
+
+```
+Pick a starting point.
+while(Problem is not solved)
+ For each path from the starting point.
+ check if selected path is safe, if yes select it
+ and make recursive call to rest of the problem
+ If recursive calls returns true, then return true.
+ else undo the current move and return false.
+ End For
+ If none of the move works out, return false, NO SOLUTON.
+
+```
diff --git "a/docs/Leetcode_Solutions/Python/Summary/delete_node_in_a_linked_list\351\227\256\351\242\230.md" "b/docs/Leetcode_Solutions/Python/Summary/delete_node_in_a_linked_list\351\227\256\351\242\230.md"
new file mode 100644
index 000000000..e148bb218
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/delete_node_in_a_linked_list\351\227\256\351\242\230.md"
@@ -0,0 +1,69 @@
+##Delete Node in a Linked List问题
+
+
+This is a LeetCode question, I knew its solution, but wondering about why my code not work.
+
+
+>Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
+
+>Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function
+
+
+At first glance, my intution is delete like an array:
+
+shift all the node values one front, then delete the tail, here's my implementation and test case:
+
+
+
+ class ListNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+
+ node1 = ListNode(1)
+ node2 = ListNode(2)
+ node3 = ListNode(3)
+ node4 = ListNode(4)
+ node5 = ListNode(5)
+
+ node1.next = node2
+ node2.next = node3
+ node3.next = node4
+ node4.next = node5
+
+
+
+ def deleteNode(node):
+ """
+ :type node: ListNode
+ :rtype: void Do not return anything, modify node in-place instead.
+ """
+ while node.next:
+ node.val = node.next.val
+ node = node.next
+ node = None
+
+
+ deleteNode(node4)
+
+But After deletion, it has two 5 value nodes, the tail was still kept, can anyone please explain to me what's wrong here?
+
+ deleteNode(node4)
+
+ node1.val
+ Out[162]: 1
+
+ node1.next.val
+ Out[163]: 2
+
+ node1.next.next.val
+ Out[164]: 3
+
+ node1.next.next.next.val
+ Out[165]: 5
+
+ node1.next.next.next.next.val
+ Out[166]: 5
+
+
+Really appreciate any help.
\ No newline at end of file
diff --git a/docs/Leetcode_Solutions/Python/Summary/python_base.md b/docs/Leetcode_Solutions/Python/Summary/python_base.md
new file mode 100644
index 000000000..718e2edbb
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/Summary/python_base.md
@@ -0,0 +1,1338 @@
+```python
+# _*_ coding: utf-8 _*_
+
+"""类型和运算----类型和运算----类型和运算----类型和运算----类型和运算----类型和运算----类型和运算----类型和运算----类型和运算----类型和运算----类型和运算"""
+
+#-- 寻求帮助:
+ dir(obj) # 简单的列出对象obj所包含的方法名称,返回一个字符串列表
+ help(obj.func) # 查询obj.func的具体介绍和用法
+
+#-- 测试类型的三种方法,推荐第三种
+ if type(L) == type([]):
+ print("L is list")
+ if type(L) == list:
+ print("L is list")
+ if isinstance(L, list):
+ print("L is list")
+
+#-- Python数据类型:哈希类型、不可哈希类型
+ # 哈希类型,即在原地不能改变的变量类型,不可变类型。可利用hash函数查看其hash值,也可以作为字典的key
+ "数字类型:int, float, decimal.Decimal, fractions.Fraction, complex"
+ "字符串类型:str, bytes"
+ "元组:tuple"
+ "冻结集合:frozenset"
+ "布尔类型:True, False"
+ "None"
+ # 不可hash类型:原地可变类型:list、dict和set。它们不可以作为字典的key。
+
+#-- 数字常量
+ 1234, -1234, 0, 999999999 # 整数
+ 1.23, 1., 3.14e-10, 4E210, 4.0e+210 # 浮点数
+ 0o177, 0x9ff, 0X9FF, 0b101010 # 八进制、十六进制、二进制数字
+ 3+4j, 3.0+4.0j, 3J # 复数常量,也可以用complex(real, image)来创建
+ hex(I), oct(I), bin(I) # 将十进制数转化为十六进制、八进制、二进制表示的“字符串”
+ int(string, base) # 将字符串转化为整数,base为进制数
+ # 2.x中,有两种整数类型:一般整数(32位)和长整数(无穷精度)。可以用l或L结尾,迫使一般整数成为长整数
+ float('inf'), float('-inf'), float('nan') # 无穷大, 无穷小, 非数
+
+#-- 数字的表达式操作符
+ yield x # 生成器函数发送协议
+ lambda args: expression # 生成匿名函数
+ x if y else z # 三元选择表达式
+ x and y, x or y, not x # 逻辑与、逻辑或、逻辑非
+ x in y, x not in y # 成员对象测试
+ x is y, x is not y # 对象实体测试
+ xy, x>=y, x==y, x!=y # 大小比较,集合子集或超集值相等性操作符
+ 1 < a < 3 # Python中允许连续比较
+ x|y, x&y, x^y # 位或、位与、位异或
+ x<>y # 位操作:x左移、右移y位
+ +, -, *, /, //, %, ** # 真除法、floor除法:返回不大于真除法结果的整数值、取余、幂运算
+ -x, +x, ~x # 一元减法、识别、按位求补(取反)
+ x[i], x[i:j:k] # 索引、分片、调用
+ int(3.14), float(3) # 强制类型转换
+
+#-- 整数可以利用bit_length函数测试所占的位数
+ a = 1; a.bit_length() # 1
+ a = 1024; a.bit_length() # 11
+
+#-- repr和str显示格式的区别
+ """
+ repr格式:默认的交互模式回显,产生的结果看起来它们就像是代码。
+ str格式:打印语句,转化成一种对用户更加友好的格式。
+ """
+
+#-- 数字相关的模块
+ # math模块
+ # Decimal模块:小数模块
+ import decimal
+ from decimal import Decimal
+ Decimal("0.01") + Decimal("0.02") # 返回Decimal("0.03")
+ decimal.getcontext().prec = 4 # 设置全局精度为4 即小数点后边4位
+ # Fraction模块:分数模块
+ from fractions import Fraction
+ x = Fraction(4, 6) # 分数类型 4/6
+ x = Fraction("0.25") # 分数类型 1/4 接收字符串类型的参数
+
+#-- 集合set
+ """
+ set是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素。
+ set支持union(联合), intersection(交), difference(差)和symmetric difference(对称差集)等数学运算。
+ set支持x in set, len(set), for x in set。
+ set不记录元素位置或者插入点, 因此不支持indexing, slicing, 或其它类序列的操作
+ """
+ s = set([3,5,9,10]) # 创建一个数值集合,返回{3, 5, 9, 10}
+ t = set("Hello") # 创建一个唯一字符的集合返回{}
+ a = t | s; t.union(s) # t 和 s的并集
+ b = t & s; t.intersection(s) # t 和 s的交集
+ c = t – s; t.difference(s) # 求差集(项在t中, 但不在s中)
+ d = t ^ s; t.symmetric_difference(s) # 对称差集(项在t或s中, 但不会同时出现在二者中)
+ t.add('x'); t.remove('H') # 增加/删除一个item
+ s.update([10,37,42]) # 利用[......]更新s集合
+ x in s, x not in s # 集合中是否存在某个值
+ s.issubset(t); s <= t # 测试是否 s 中的每一个元素都在 t 中
+ s.issuperset(t); s >= t # 测试是否 t 中的每一个元素都在 s 中
+ s.copy();
+ s.discard(x); # 删除s中x
+ s.clear() # 清空s
+ {x**2 for x in [1, 2, 3, 4]} # 集合解析,结果:{16, 1, 4, 9}
+ {x for x in 'spam'} # 集合解析,结果:{'a', 'p', 's', 'm'}
+
+#-- 集合frozenset,不可变对象
+ """
+ set是可变对象,即不存在hash值,不能作为字典的键值。同样的还有list等(tuple是可以作为字典key的)
+ frozenset是不可变对象,即存在hash值,可作为字典的键值
+ frozenset对象没有add、remove等方法,但有union/intersection/difference等方法
+ """
+ a = set([1, 2, 3])
+ b = set()
+ b.add(a) # error: set是不可哈希类型
+ b.add(frozenset(a)) # ok,将set变为frozenset,可哈希
+
+#-- 布尔类型bool
+ type(True) # 返回
+ isinstance(False, int) # bool类型属于整型,所以返回True
+ True == 1; True is 1 # 输出(True, False)
+
+#-- 动态类型简介
+ """
+ 变量名通过引用,指向对象。
+ Python中的“类型”属于对象,而不是变量,每个对象都包含有头部信息,比如"类型标示符" "引用计数器"等
+ """
+ #共享引用及在原处修改:对于可变对象,要注意尽量不要共享引用!
+ #共享引用和相等测试:
+ L = [1], M = [1], L is M # 返回False
+ L = M = [1, 2, 3], L is M # 返回True,共享引用
+ #增强赋值和共享引用:普通+号会生成新的对象,而增强赋值+=会在原处修改
+ L = M = [1, 2]
+ L = L + [3, 4] # L = [1, 2, 3, 4], M = [1, 2]
+ L += [3, 4] # L = [1, 2, 3, 4], M = [1, 2, 3, 4]
+
+#-- 常见字符串常量和表达式
+ S = '' # 空字符串
+ S = "spam’s" # 双引号和单引号相同
+ S = "s\np\ta\x00m" # 转义字符
+ S = """spam""" # 三重引号字符串,一般用于函数说明
+ S = r'\temp' # Raw字符串,不会进行转义,抑制转义
+ S = b'Spam' # Python3中的字节字符串
+ S = u'spam' # Python2.6中的Unicode字符串
+ s1+s2, s1*3, s[i], s[i:j], len(s) # 字符串操作
+ 'a %s parrot' % 'kind' # 字符串格式化表达式
+ 'a {1} {0} parrot'.format('kind', 'red')# 字符串格式化方法
+ for x in s: print(x) # 字符串迭代,成员关系
+ [x*2 for x in s] # 字符串列表解析
+ ','.join(['a', 'b', 'c']) # 字符串输出,结果:a,b,c
+
+#-- 内置str处理函数:
+ str1 = "stringobject"
+ str1.upper(); str1.lower(); str1.swapcase(); str1.capitalize(); str1.title() # 全部大写,全部小写、大小写转换,首字母大写,每个单词的首字母都大写
+ str1.ljust(width) # 获取固定长度,左对齐,右边不够用空格补齐
+ str1.rjust(width) # 获取固定长度,右对齐,左边不够用空格补齐
+ str1.center(width) # 获取固定长度,中间对齐,两边不够用空格补齐
+ str1.zfill(width) # 获取固定长度,右对齐,左边不足用0补齐
+ str1.find('t',start,end) # 查找字符串,可以指定起始及结束位置搜索
+ str1.rfind('t') # 从右边开始查找字符串
+ str1.count('t') # 查找字符串出现的次数
+ #上面所有方法都可用index代替,不同的是使用index查找不到会抛异常,而find返回-1
+ str1.replace('old','new') # 替换函数,替换old为new,参数中可以指定maxReplaceTimes,即替换指定次数的old为new
+ str1.strip(); # 默认删除空白符
+ str1.strip('d'); # 删除str1字符串中开头、结尾处,位于 d 删除序列的字符
+ str1.lstrip();
+ str1.lstrip('d'); # 删除str1字符串中开头处,位于 d 删除序列的字符
+ str1.rstrip();
+ str1.rstrip('d') # 删除str1字符串中结尾处,位于 d 删除序列的字符
+ str1.startswith('start') # 是否以start开头
+ str1.endswith('end') # 是否以end结尾
+ str1.isalnum(); str1.isalpha(); str1.isdigit(); str1.islower(); str1.isupper() # 判断字符串是否全为字符、数字、小写、大写
+
+#-- 三重引号编写多行字符串块,并且在代码折行处嵌入换行字符\n
+ mantra = """hello world
+ hello python
+ hello my friend"""
+ # mantra为"""hello world \n hello python \n hello my friend"""
+
+#-- 索引和分片:
+ S[0], S[len(S)–1], S[-1] # 索引
+ S[1:3], S[1:], S[:-1], S[1:10:2] # 分片,第三个参数指定步长,如`S[1:10:2]`是从1位到10位没隔2位获取一个字符。
+
+#-- 字符串转换工具:
+ int('42'), str(42) # 返回(42, '42')
+ float('4.13'), str(4.13) # 返回(4.13, '4.13')
+ ord('s'), chr(115) # 返回(115, 's')
+ int('1001', 2) # 将字符串作为二进制数字,转化为数字,返回9
+ bin(13), oct(13), hex(13) # 将整数转化为二进制/八进制/十六进制字符串,返回('0b1101', '015', '0xd')
+
+#-- 另类字符串连接
+ name = "wang" "hong" # 单行,name = "wanghong"
+ name = "wang" \
+ "hong" # 多行,name = "wanghong"
+
+#-- Python中的字符串格式化实现1--字符串格式化表达式
+ """
+ 基于C语言的'print'模型,并且在大多数的现有的语言中使用。
+ 通用结构:%[(name)][flag][width].[precision]typecode
+ """
+ "this is %d %s bird" % (1, 'dead') # 一般的格式化表达式
+ "%s---%s---%s" % (42, 3.14, [1, 2, 3]) # 字符串输出:'42---3.14---[1, 2, 3]'
+ "%d...%6d...%-6d...%06d" % (1234, 1234, 1234, 1234) # 对齐方式及填充:"1234... 1234...1234 ...001234"
+ x = 1.23456789
+ "%e | %f | %g" % (x, x, x) # 对齐方式:"1.234568e+00 | 1.234568 | 1.23457"
+ "%6.2f*%-6.2f*%06.2f*%+6.2f" % (x, x, x, x) # 对齐方式:' 1.23*1.23 *001.23* +1.23'
+ "%(name1)d---%(name2)s" % {"name1":23, "name2":"value2"} # 基于字典的格式化表达式
+ "%(name)s is %(age)d" % vars() # vars()函数调用返回一个字典,包含了所有本函数调用时存在的变量
+
+#-- Python中的字符串格式化实现2--字符串格式化调用方法
+ # 普通调用
+ "{0}, {1} and {2}".format('spam', 'ham', 'eggs') # 基于位置的调用
+ "{motto} and {pork}".format(motto = 'spam', pork = 'ham') # 基于Key的调用
+ "{motto} and {0}".format('ham', motto = 'spam') # 混合调用
+ # 添加键 属性 偏移量 (import sys)
+ "my {1[spam]} runs {0.platform}".format(sys, {'spam':'laptop'}) # 基于位置的键和属性
+ "{config[spam]} {sys.platform}".format(sys = sys, config = {'spam':'laptop'}) # 基于Key的键和属性
+ "first = {0[0]}, second = {0[1]}".format(['A', 'B', 'C']) # 基于位置的偏移量
+ # 具体格式化
+ "{0:e}, {1:.3e}, {2:g}".format(3.14159, 3.14159, 3.14159) # 输出'3.141590e+00, 3.142e+00, 3.14159'
+ "{fieldname:format_spec}".format(......)
+ # 说明:
+ """
+ fieldname是指定参数的一个数字或关键字, 后边可跟可选的".name"或"[index]"成分引用
+ format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]
+ fill ::= #填充字符
+ align ::= "<" | ">" | "=" | "^" #对齐方式
+ sign ::= "+" | "-" | " " #符号说明
+ width ::= integer #字符串宽度
+ precision ::= integer #浮点数精度
+ type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
+ """
+ # 例子:
+ '={0:10} = {1:10}'.format('spam', 123.456) # 输出'=spam = 123.456'
+ '={0:>10}='.format('test') # 输出'= test='
+ '={0:<10}='.format('test') # 输出'=test ='
+ '={0:^10}='.format('test') # 输出'= test ='
+ '{0:X}, {1:o}, {2:b}'.format(255, 255, 255) # 输出'FF, 377, 11111111'
+ 'My name is {0:{1}}.'.format('Fred', 8) # 输出'My name is Fred .' 动态指定参数
+
+#-- 常用列表常量和操作
+ L = [[1, 2], 'string', {}] # 嵌套列表
+ L = list('spam') # 列表初始化
+ L = list(range(0, 4)) # 列表初始化
+ list(map(ord, 'spam')) # 列表解析
+ len(L) # 求列表长度
+ L.count(value) # 求列表中某个值的个数
+ L.append(obj) # 向列表的尾部添加数据,比如append(2),添加元素2
+ L.insert(index, obj) # 向列表的指定index位置添加数据,index及其之后的数据后移
+ L.extend(interable) # 通过添加iterable中的元素来扩展列表,比如extend([2]),添加元素2,注意和append的区别
+ L.index(value, [start, [stop]]) # 返回列表中值value的第一个索引
+ L.pop([index]) # 删除并返回index处的元素,默认为删除并返回最后一个元素
+ L.remove(value) # 删除列表中的value值,只删除第一次出现的value的值
+ L.reverse() # 反转列表
+ L.sort(cmp=None, key=None, reverse=False) # 排序列表
+ a = [1, 2, 3], b = a[10:] # 注意,这里不会引发IndexError异常,只会返回一个空的列表[]
+ a = [], a += [1] # 这里实在原有列表的基础上进行操作,即列表的id没有改变
+ a = [], a = a + [1] # 这里最后的a要构建一个新的列表,即a的id发生了变化
+
+#-- 用切片来删除序列的某一段
+ a = [1, 2, 3, 4, 5, 6, 7]
+ a[1:4] = [] # a = [1, 5, 6, 7]
+ a = [0, 1, 2, 3, 4, 5, 6, 7]
+ del a[::2] # 去除偶数项(偶数索引的),a = [1, 3, 5, 7]
+
+#-- 常用字典常量和操作
+ D = {}
+ D = {'spam':2, 'tol':{'ham':1}} # 嵌套字典
+ D = dict.fromkeys(['s', 'd'], 8) # {'s': 8, 'd': 8}
+ D = dict(name = 'tom', age = 12) # {'age': 12, 'name': 'tom'}
+ D = dict([('name', 'tom'), ('age', 12)]) # {'age': 12, 'name': 'tom'}
+ D = dict(zip(['name', 'age'], ['tom', 12])) # {'age': 12, 'name': 'tom'}
+ D.keys(); D.values(); D.items() # 字典键、值以及键值对
+ D.get(key, default) # get函数
+ D.update(D_other) # 合并字典,如果存在相同的键值,D_other的数据会覆盖掉D的数据
+ D.pop(key, [D]) # 删除字典中键值为key的项,返回键值为key的值,如果不存在,返回默认值D,否则异常
+ D.popitem() # pop字典中随机的一项(一个键值对)
+ D.setdefault(k[, d]) # 设置D中某一项的默认值。如果k存在,则返回D[k],否则设置D[k]=d,同时返回D[k]。
+ del D # 删除字典
+ del D['key'] # 删除字典的某一项
+ if key in D: if key not in D: # 测试字典键是否存在
+ # 字典注意事项:(1)对新索引赋值会添加一项(2)字典键不一定非得是字符串,也可以为任何的不可变对象
+ # 不可变对象:调用对象自身的任意方法,也不会改变该对象自身的内容,这些方法会创建新的对象并返回。
+ # 字符串、整数、tuple都是不可变对象,dict、set、list都是可变对象
+ D[(1,2,3)] = 2 # tuple作为字典的key
+
+#-- 字典解析
+ D = {k:8 for k in ['s', 'd']} # {'s': 8, 'd': 8}
+ D = {k:v for (k, v) in zip(['name', 'age'], ['tom', 12])} # {'age': 12, 'name': tom}
+
+#-- 字典的特殊方法__missing__:当查找找不到key时,会执行该方法
+ class Dict(dict):
+ def __missing__(self, key):
+ self[key] = []
+ return self[key]
+ dct = dict()
+ dct["foo"].append(1) # 这有点类似于collections.defalutdict
+ dct["foo"] # [1]
+
+#-- 元组和列表的唯一区别在于元组是不可变对象,列表是可变对象
+ a = [1, 2, 3] # a[1] = 0, OK
+ a = (1, 2, 3) # a[1] = 0, Error
+ a = ([1, 2]) # a[0][1] = 0, OK
+ a = [(1, 2)] # a[0][1] = 0, Error
+
+#-- 元组的特殊语法: 逗号和圆括号
+ D = (12) # 此时D为一个整数 即D = 12
+ D = (12, ) # 此时D为一个元组 即D = (12, )
+
+#-- 文件基本操作
+ output = open(r'C:\spam', 'w') # 打开输出文件,用于写
+ input = open('data', 'r') # 打开输入文件,用于读。打开的方式可以为'w', 'r', 'a', 'wb', 'rb', 'ab'等
+ fp.read([size]) # size为读取的长度,以byte为单位
+ fp.readline([size]) # 读一行,如果定义了size,有可能返回的只是一行的一部分
+ fp.readlines([size]) # 把文件每一行作为一个list的一个成员,并返回这个list。其实它的内部是通过循环调用readline()来实现的。如果提供size参数,size是表示读取内容的总长。
+ fp.readable() # 是否可读
+ fp.write(str) # 把str写到文件中,write()并不会在str后加上一个换行符
+ fp.writelines(seq) # 把seq的内容全部写到文件中(多行一次性写入)
+ fp.writeable() # 是否可写
+ fp.close() # 关闭文件。
+ fp.flush() # 把缓冲区的内容写入硬盘
+ fp.fileno() # 返回一个长整型的”文件标签“
+ fp.isatty() # 文件是否是一个终端设备文件(unix系统中的)
+ fp.tell() # 返回文件操作标记的当前位置,以文件的开头为原点
+ fp.next() # 返回下一行,并将文件操作标记位移到下一行。把一个file用于for … in file这样的语句时,就是调用next()函数来实现遍历的。
+ fp.seek(offset[,whence]) # 将文件打开操作标记移到offset的位置。whence为0表示从头开始计算,1表示以当前位置为原点计算。2表示以文件末尾为原点进行计算。
+ fp.seekable() # 是否可以seek
+ fp.truncate([size]) # 把文件裁成规定的大小,默认的是裁到当前文件操作标记的位置。
+ for line in open('data'):
+ print(line) # 使用for语句,比较适用于打开比较大的文件
+ with open('data') as file:
+ print(file.readline()) # 使用with语句,可以保证文件关闭
+ with open('data') as file:
+ lines = file.readlines() # 一次读入文件所有行,并关闭文件
+ open('f.txt', encoding = 'latin-1') # Python3.x Unicode文本文件
+ open('f.bin', 'rb') # Python3.x 二进制bytes文件
+ # 文件对象还有相应的属性:buffer closed encoding errors line_buffering name newlines等
+
+#-- 其他
+ # Python中的真假值含义:1. 数字如果非零,则为真,0为假。 2. 其他对象如果非空,则为真
+ # 通常意义下的类型分类:1. 数字、序列、映射。 2. 可变类型和不可变类型
+
+
+"""语法和语句----语法和语句----语法和语句----语法和语句----语法和语句----语法和语句----语法和语句----语法和语句----语法和语句----语法和语句----语法和语句"""
+
+#-- 赋值语句的形式
+ spam = 'spam' # 基本形式
+ spam, ham = 'spam', 'ham' # 元组赋值形式
+ [spam, ham] = ['s', 'h'] # 列表赋值形式
+ a, b, c, d = 'abcd' # 序列赋值形式
+ a, *b, c = 'spam' # 序列解包形式(Python3.x中才有)
+ spam = ham = 'no' # 多目标赋值运算,涉及到共享引用
+ spam += 42 # 增强赋值,涉及到共享引用
+
+#-- 序列赋值 序列解包
+ [a, b, c] = (1, 2, 3) # a = 1, b = 2, c = 3
+ a, b, c, d = "spam" # a = 's', b = 'p', c = 'a', d = 'm'
+ a, b, c = range(3) # a = 0, b = 1, c = 2
+ a, *b = [1, 2, 3, 4] # a = 1, b = [2, 3, 4]
+ *a, b = [1, 2, 3, 4] # a = [1, 2, 3], b = 4
+ a, *b, c = [1, 2, 3, 4] # a = 1, b = [2, 3], c = 4
+ # 带有*时 会优先匹配*之外的变量 如
+ a, *b, c = [1, 2] # a = 1, c = 2, b = []
+
+#-- print函数原型
+ print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
+ # 流的重定向
+ print('hello world') # 等于sys.stdout.write('hello world')
+ temp = sys.stdout # 原有流的保存
+ sys.stdout = open('log.log', 'a') # 流的重定向
+ print('hello world') # 写入到文件log.log
+ sys.stdout.close()
+ sys.stdout = temp # 原有流的复原
+
+#-- Python中and或or总是返回对象(左边的对象或右边的对象) 且具有短路求值的特性
+ 1 or 2 or 3 # 返回 1
+ 1 and 2 and 3 # 返回 3
+
+#-- if/else三元表达符(if语句在行内)
+ A = 1 if X else 2
+ A = 1 if X else (2 if Y else 3)
+ # 也可以使用and-or语句(一条语句实现多个if-else)
+ a = 6
+ result = (a > 20 and "big than 20" or a > 10 and "big than 10" or a > 5 and "big than 5") # 返回"big than 5"
+
+#-- Python的while语句或者for语句可以带else语句 当然也可以带continue/break/pass语句
+ while a > 1:
+ anything
+ else:
+ anything
+ # else语句会在循环结束后执行,除非在循环中执行了break,同样的还有for语句
+ for i in range(5):
+ anything
+ else:
+ anything
+
+#-- for循环的元组赋值
+ for (a, b) in [(1, 2), (3, 4)]: # 最简单的赋值
+ for ((a, b), c) in [((1, 2), 3), ((4, 5), 6)]: # 自动解包赋值
+ for ((a, b), c) in [((1, 2), 3), ("XY", 6)]: # 自动解包 a = X, b = Y, c = 6
+ for (a, *b) in [(1, 2, 3), (4, 5, 6)]: # 自动解包赋值
+
+#-- 列表解析语法
+ M = [[1,2,3], [4,5,6], [7,8,9]]
+ res = [sum(row) for row in M] # G = [6, 15, 24] 一般的列表解析 生成一个列表
+ res = [c * 2 for c in 'spam'] # ['ss', 'pp', 'aa', 'mm']
+ res = [a * b for a in [1, 2] for b in [4, 5]] # 多解析过程 返回[4, 5, 8, 10]
+ res = [a for a in [1, 2, 3] if a < 2] # 带判断条件的解析过程
+ res = [a if a > 0 else 0 for a in [-1, 0, 1]] # 带判断条件的高级解析过程
+ # 两个列表同时解析:使用zip函数
+ for teama, teamb in zip(["Packers", "49ers"], ["Ravens", "Patriots"]):
+ print(teama + " vs. " + teamb)
+ # 带索引的列表解析:使用enumerate函数
+ for index, team in enumerate(["Packers", "49ers", "Ravens", "Patriots"]):
+ print(index, team) # 输出0, Packers \n 1, 49ers \n ......
+
+#-- 生成器表达式
+ G = (sum(row) for row in M) # 使用小括号可以创建所需结果的生成器generator object
+ next(G), next(G), next(G) # 输出(6, 15, 24)
+ G = {sum(row) for row in M} # G = {6, 15, 24} 解析语法还可以生成集合和字典
+ G = {i:sum(M[i]) for i in range(3)} # G = {0: 6, 1: 15, 2: 24}
+
+#-- 文档字符串:出现在Module的开端以及其中函数或类的开端 使用三重引号字符串
+ """
+ module document
+ """
+ def func():
+ """
+ function document
+ """
+ print()
+ class Employee(object):
+ """
+ class document
+ """
+ print()
+ print(func.__doc__) # 输出函数文档字符串
+ print(Employee.__doc__) # 输出类的文档字符串
+
+#-- 命名惯例:
+ """
+ 以单一下划线开头的变量名(_X)不会被from module import*等语句导入
+ 前后有两个下划线的变量名(__X__)是系统定义的变量名,对解释器有特殊意义
+ 以两个下划线开头但不以下划线结尾的变量名(__X)是类的本地(私有)变量
+ """
+
+#-- 列表解析 in成员关系测试 map sorted zip enumerate内置函数等都使用了迭代协议
+ 'first line' in open('test.txt') # in测试 返回True或False
+ list(map(str.upper, open('t'))) # map内置函数
+ sorted(iter([2, 5, 8, 3, 1])) # sorted内置函数
+ list(zip([1, 2], [3, 4])) # zip内置函数 [(1, 3), (2, 4)]
+
+#-- del语句: 手动删除某个变量
+ del X
+
+#-- 获取列表的子表的方法:
+ x = [1,2,3,4,5,6]
+ x[:3] # 前3个[1,2,3]
+ x[1:5] # 中间4个[2,3,4,5]
+ x[-3:] # 最后3个[4,5,6]
+ x[::2] # 奇数项[1,3,5]
+ x[1::2] # 偶数项[2,4,6]
+
+#-- 手动迭代:iter和next
+ L = [1, 2]
+ I = iter(L) # I为L的迭代器
+ I.next() # 返回1
+ I.next() # 返回2
+ I.next() # Error:StopIteration
+
+#-- Python中的可迭代对象
+ """
+ 1.range迭代器
+ 2.map、zip和filter迭代器
+ 3.字典视图迭代器:D.keys()), D.items()等
+ 4.文件类型
+ """
+
+
+"""函数语法规则----函数语法规则----函数语法规则----函数语法规则----函数语法规则----函数语法规则----函数语法规则----函数语法规则----函数语法规则----函数语法规则"""
+
+#-- 函数相关的语句和表达式
+ myfunc('spam') # 函数调用
+ def myfunc(): # 函数定义
+ return None # 函数返回值
+ global a # 全局变量
+ nonlocal x # 在函数或其他作用域中使用外层(非全局)变量
+ yield x # 生成器函数返回
+ lambda # 匿名函数
+
+#-- Python函数变量名解析:LEGB原则,即:
+ """
+ local(functin) --> encloseing function locals --> global(module) --> build-in(python)
+ 说明:以下边的函数maker为例 则相对于action而言 X为Local N为Encloseing
+ """
+
+#-- 嵌套函数举例:工厂函数
+ def maker(N):
+ def action(X):
+ return X ** N
+ return action
+ f = maker(2) # pass 2 to N
+ f(3) # 9, pass 3 to X
+
+#-- 嵌套函数举例:lambda实例
+ def maker(N):
+ action = (lambda X: X**N)
+ return action
+ f = maker(2) # pass 2 to N
+ f(3) # 9, pass 3 to X
+
+#-- nonlocal和global语句的区别
+ # nonlocal应用于一个嵌套的函数的作用域中的一个名称 例如:
+ start = 100
+ def tester(start):
+ def nested(label):
+ nonlocal start # 指定start为tester函数内的local变量 而不是global变量start
+ print(label, start)
+ start += 3
+ return nested
+ # global为全局的变量 即def之外的变量
+ def tester(start):
+ def nested(label):
+ global start # 指定start为global变量start
+ print(label, start)
+ start += 3
+ return nested
+
+#-- 函数参数,不可变参数通过“值”传递,可变参数通过“引用”传递
+ def f(a, b, c): print(a, b, c)
+ f(1, 2, 3) # 参数位置匹配
+ f(1, c = 3, b = 2) # 参数关键字匹配
+ def f(a, b=1, c=2): print(a, b, c)
+ f(1) # 默认参数匹配
+ f(1, 2) # 默认参数匹配
+ f(a = 1, c = 3) # 关键字参数和默认参数的混合
+ # Keyword-Only参数:出现在*args之后 必须用关键字进行匹配
+ def keyOnly(a, *b, c): print('') # c就为keyword-only匹配 必须使用关键字c = value匹配
+ def keyOnly(a, *, b, c): ...... # b c为keyword-only匹配 必须使用关键字匹配
+ def keyOnly(a, *, b = 1): ...... # b有默认值 或者省略 或者使用关键字参数b = value
+
+#-- 可变参数匹配: * 和 **
+ def f(*args): print(args) # 在元组中收集不匹配的位置参数
+ f(1, 2, 3) # 输出(1, 2, 3)
+ def f(**args): print(args) # 在字典中收集不匹配的关键字参数
+ f(a = 1, b = 2) # 输出{'a':1, 'b':2}
+ def f(a, *b, **c): print(a, b, c) # 两者混合使用
+ f(1, 2, 3, x=4, y=5) # 输出1, (2, 3), {'x':4, 'y':5}
+
+#-- 函数调用时的参数解包: * 和 ** 分别解包元组和字典
+ func(1, *(2, 3)) <==> func(1, 2, 3)
+ func(1, **{'c':3, 'b':2}) <==> func(1, b = 2, c = 3)
+ func(1, *(2, 3), **{'c':3, 'b':2}) <==> func(1, 2, 3, b = 2, c = 3)
+
+#-- 函数属性:(自己定义的)函数可以添加属性
+ def func():.....
+ func.count = 1 # 自定义函数添加属性
+ print.count = 1 # Error 内置函数不可以添加属性
+
+#-- 函数注解: 编写在def头部行 主要用于说明参数范围、参数类型、返回值类型等
+ def func(a:'spam', b:(1, 10), c:float) -> int :
+ print(a, b, c)
+ func.__annotations__ # {'c':, 'b':(1, 10), 'a':'spam', 'return':}
+ # 编写注解的同时 还是可以使用函数默认值 并且注解的位置位于=号的前边
+ def func(a:'spam'='a', b:(1, 10)=2, c:float=3) -> int :
+ print(a, b, c)
+
+#-- 匿名函数:lambda
+ f = lambda x, y, z : x + y + z # 普通匿名函数,使用方法f(1, 2, 3)
+ f = lambda x = 1, y = 1: x + y # 带默认参数的lambda函数
+ def action(x): # 嵌套lambda函数
+ return (lambda y : x + y)
+ f = lambda: a if xxx() else b # 无参数的lambda函数,使用方法f()
+
+#-- lambda函数与map filter reduce函数的结合
+ list(map((lambda x: x + 1), [1, 2, 3])) # [2, 3, 4]
+ list(filter((lambda x: x > 0), range(-4, 5))) # [1, 2, 3, 4]
+ functools.reduce((lambda x, y: x + y), [1, 2, 3]) # 6
+ functools.reduce((lambda x, y: x * y), [2, 3, 4]) # 24
+
+#-- 生成器函数:yield VS return
+ def gensquare(N):
+ for i in range(N):
+ yield i** 2 # 状态挂起 可以恢复到此时的状态
+ for i in gensquare(5): # 使用方法
+ print(i, end = ' ') # [0, 1, 4, 9, 16]
+ x = gensquare(2) # x是一个生成对象
+ next(x) # 等同于x.__next__() 返回0
+ next(x) # 等同于x.__next__() 返回1
+ next(x) # 等同于x.__next__() 抛出异常StopIteration
+
+#-- 生成器表达式:小括号进行列表解析
+ G = (x ** 2 for x in range(3)) # 使用小括号可以创建所需结果的生成器generator object
+ next(G), next(G), next(G) # 和上述中的生成器函数的返回值一致
+ #(1)生成器(生成器函数/生成器表达式)是单个迭代对象
+ G = (x ** 2 for x in range(4))
+ I1 = iter(G) # 这里实际上iter(G) = G
+ next(I1) # 输出0
+ next(G) # 输出1
+ next(I1) # 输出4
+ #(2)生成器不保留迭代后的结果
+ gen = (i for i in range(4))
+ 2 in gen # 返回True
+ 3 in gen # 返回True
+ 1 in gen # 返回False,其实检测2的时候,1已经就不在生成器中了,即1已经被迭代过了,同理2、3也不在了
+
+#-- 本地变量是静态检测的
+ X = 22 # 全局变量X的声明和定义
+ def test():
+ print(X) # 如果没有下一语句 则该句合法 打印全局变量X
+ X = 88 # 这一语句使得上一语句非法 因为它使得X变成了本地变量 上一句变成了打印一个未定义的本地变量(局部变量)
+ if False: # 即使这样的语句 也会把print语句视为非法语句 因为:
+ X = 88 # Python会无视if语句而仍然声明了局部变量X
+ def test(): # 改进
+ global X # 声明变量X为全局变量
+ print(X) # 打印全局变量X
+ X = 88 # 改变全局变量X
+
+#-- 函数的默认值是在函数定义的时候实例化的 而不是在调用的时候 例子:
+ def foo(numbers=[]): # 这里的[]是可变的
+ numbers.append(9)
+ print(numbers)
+ foo() # first time, like before, [9]
+ foo() # second time, not like before, [9, 9]
+ foo() # third time, not like before too, [9, 9, 9]
+ # 改进:
+ def foo(numbers=None):
+ if numbers is None: numbers = []
+ numbers.append(9)
+ print(numbers)
+ # 另外一个例子 参数的默认值为不可变的:
+ def foo(count=0): # 这里的0是数字, 是不可变的
+ count += 1
+ print(count)
+ foo() # 输出1
+ foo() # 还是输出1
+ foo(3) # 输出4
+ foo() # 还是输出1
+
+
+"""函数例子----函数例子----函数例子----函数例子----函数例子----函数例子----函数例子----函数例子----函数例子----函数例子----函数例子----函数例子----函数例子"""
+
+ """数学运算类"""
+ abs(x) # 求绝对值,参数可以是整型,也可以是复数,若参数是复数,则返回复数的模
+ complex([real[, imag]]) # 创建一个复数
+ divmod(a, b) # 分别取商和余数,注意:整型、浮点型都可以
+ float([x]) # 将一个字符串或数转换为浮点数。如果无参数将返回0.0
+ int([x[, base]]) # 将一个字符串或浮点数转换为int类型,base表示进制
+ long([x[, base]]) # 将一个字符串或浮点数转换为long类型
+ pow(x, y) # 返回x的y次幂
+ range([start], stop[, step]) # 产生一个序列,默认从0开始
+ round(x[, n]) # 四舍五入
+ sum(iterable[, start]) # 对集合求和
+ oct(x) # 将一个数字转化为8进制字符串
+ hex(x) # 将一个数字转换为16进制字符串
+ chr(i) # 返回给定int类型对应的ASCII字符
+ unichr(i) # 返回给定int类型的unicode
+ ord(c) # 返回ASCII字符对应的整数
+ bin(x) # 将整数x转换为二进制字符串
+ bool([x]) # 将x转换为Boolean类型
+
+ """集合类操作"""
+ basestring() # str和unicode的超类,不能直接调用,可以用作isinstance判断
+ format(value [, format_spec]) # 格式化输出字符串,格式化的参数顺序从0开始,如“I am {0},I like {1}”
+ enumerate(sequence[, start=0]) # 返回一个可枚举的对象,注意它有第二个参数
+ iter(obj[, sentinel]) # 生成一个对象的迭代器,第二个参数表示分隔符
+ max(iterable[, args...][key]) # 返回集合中的最大值
+ min(iterable[, args...][key]) # 返回集合中的最小值
+ dict([arg]) # 创建数据字典
+ list([iterable]) # 将一个集合类转换为另外一个集合类
+ set() # set对象实例化
+ frozenset([iterable]) # 产生一个不可变的set
+ tuple([iterable]) # 生成一个tuple类型
+ str([object]) # 转换为string类型
+ sorted(iterable[, cmp[, key[, reverse]]]) # 集合排序
+ L = [('b',2),('a',1),('c',3),('d',4)]
+ sorted(L, key=lambda x: x[1]), reverse=True) # 使用Key参数和reverse参数
+ sorted(L, key=lambda x: (x[0], x[1])) # 使用key参数进行多条件排序,即如果x[0]相同,则比较x[1]
+
+ """逻辑判断"""
+ all(iterable) # 集合中的元素都为真的时候为真,特别的,若为空串返回为True
+ any(iterable) # 集合中的元素有一个为真的时候为真,特别的,若为空串返回为False
+ cmp(x, y) # 如果x < y ,返回负数;x == y, 返回0;x > y,返回正数
+
+ """IO操作"""
+ file(filename [, mode [, bufsize]]) # file类型的构造函数。
+ input([prompt]) # 获取用户输入,推荐使用raw_input,因为该函数将不会捕获用户的错误输入,意思是自行判断类型
+ # 在 Built-in Functions 里有一句话是这样写的:Consider using the raw_input() function for general input from users.
+ raw_input([prompt]) # 设置输入,输入都是作为字符串处理
+ open(name[, mode[, buffering]]) # 打开文件,与file有什么不同?推荐使用open
+
+ """其他"""
+ callable(object) # 检查对象object是否可调用
+ classmethod(func) # 用来说明这个func是个类方法
+ staticmethod(func) # 用来说明这个func为静态方法
+ dir([object]) # 不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。
+ help(obj) # 返回obj的帮助信息
+ eval(expression) # 计算表达式expression的值,并返回
+ exec(str) # 将str作为Python语句执行
+ execfile(filename) # 用法类似exec(),不同的是execfile的参数filename为文件名,而exec的参数为字符串。
+ filter(function, iterable) # 构造一个序列,等价于[item for item in iterable if function(item)],function返回值为True或False的函数
+ list(filter(bool, range(-3, 4)))# 返回[-3, -2, -1, 1, 2, 3], 没有0
+ hasattr(object, name) # 判断对象object是否包含名为name的特性
+ getattr(object, name [, defalut]) # 获取一个类的属性
+ setattr(object, name, value) # 设置属性值
+ delattr(object, name) # 删除object对象名为name的属性
+ globals() # 返回一个描述当前全局符号表的字典
+ hash(object) # 如果对象object为哈希表类型,返回对象object的哈希值
+ id(object) # 返回对象的唯一标识,一串数字
+ isinstance(object, classinfo) # 判断object是否是class的实例
+ isinstance(1, int) # 判断是不是int类型
+ isinstance(1, (int, float)) # isinstance的第二个参数接受一个元组类型
+ issubclass(class, classinfo) # 判断class是否为classinfo的子类
+ locals() # 返回当前的变量列表
+ map(function, iterable, ...) # 遍历每个元素,执行function操作
+ list(map(abs, range(-3, 4))) # 返回[3, 2, 1, 0, 1, 2, 3]
+ next(iterator[, default]) # 类似于iterator.next()
+ property([fget[, fset[, fdel[, doc]]]]) # 属性访问的包装类,设置后可以通过c.x=value等来访问setter和getter
+ reduce(function, iterable[, initializer]) # 合并操作,从第一个开始是前两个参数,然后是前两个的结果与第三个合并进行处理,以此类推
+ def add(x,y):return x + y
+ reduce(add, range(1, 11)) # 返回55 (注:1+2+3+4+5+6+7+8+9+10 = 55)
+ reduce(add, range(1, 11), 20) # 返回75
+ reload(module) # 重新加载模块
+ repr(object) # 将一个对象变幻为可打印的格式
+ slice(start, stop[, step]) # 产生分片对象
+ type(object) # 返回该object的类型
+ vars([object]) # 返回对象的变量名、变量值的字典
+ a = Class(); # Class为一个空类
+ a.name = 'qi', a.age = 9
+ vars(a) # {'name':'qi', 'age':9}
+ zip([iterable, ...]) # 返回对应数组
+ list(zip([1, 2, 3], [4, 5, 6])) # [(1, 4), (2, 5), (3, 6)]
+ a = [1, 2, 3], b = ["a", "b", "c"]
+ z = zip(a, b) # 压缩:[(1, "a"), (2, "b"), (3, "c")]
+ zip(*z) # 解压缩:[(1, 2, 3), ("a", "b", "c")]
+ unicode(string, encoding, errors) # 将字符串string转化为unicode形式,string为encoded string。
+
+
+"""模块Moudle----模块Moudle----模块Moudle----模块Moudle----模块Moudle----模块Moudle----模块Moudle----模块Moudle----模块Moudle----模块Moudle----模块Moudle"""
+
+#-- Python模块搜索路径:
+ """
+ (1)程序的主目录 (2)PYTHONPATH目录 (3)标准链接库目录 (4)任何.pth文件的内容
+ """
+
+#-- 查看全部的模块搜索路径
+ import sys
+ sys.path
+ sys.argv # 获得脚本的参数
+ sys.builtin_module_names # 查找内建模块
+ sys.platform # 返回当前平台 出现如: "win32" "linux" "darwin"等
+ sys.modules # 查找已导入的模块
+ sys.modules.keys()
+ sys.stdout # stdout 和 stderr 都是类文件对象,但是它们都是只写的。它们都没有 read 方法,只有 write 方法
+ sys.stdout.write("hello")
+ sys.stderr
+ sys.stdin
+
+#-- 模块的使用代码
+ import module1, module2 # 导入module1 使用module1.printer()
+ from module1 import printer # 导入module1中的printer变量 使用printer()
+ from module1 import * # 导入module1中的全部变量 使用不必添加module1前缀
+
+#-- 重载模块reload: 这是一个内置函数 而不是一条语句
+ from imp import reload
+ reload(module)
+
+#-- 模块的包导入:使用点号(.)而不是路径(dir1\dir2)进行导入
+ import dir1.dir2.mod # d导入包(目录)dir1中的包dir2中的mod模块 此时dir1必须在Python可搜索路径中
+ from dir1.dir2.mod import * # from语法的包导入
+
+#-- __init__.py包文件:每个导入的包中都应该包含这么一个文件
+ """
+ 该文件可以为空
+ 首次进行包导入时 该文件会自动执行
+ 高级功能:在该文件中使用__all__列表来定义包(目录)以from*的形式导入时 需要导入什么
+ """
+
+#-- 包相对导入:使用点号(.) 只能使用from语句
+ from . import spam # 导入当前目录下的spam模块(Python2: 当前目录下的模块, 直接导入即可)
+ from .spam import name # 导入当前目录下的spam模块的name属性(Python2: 当前目录下的模块, 直接导入即可,不用加.)
+ from .. import spam # 导入当前目录的父目录下的spam模块
+
+#-- 包相对导入与普通导入的区别
+ from string import * # 这里导入的string模块为sys.path路径上的 而不是本目录下的string模块(如果存在也不是)
+ from .string import * # 这里导入的string模块为本目录下的(不存在则导入失败) 而不是sys.path路径上的
+
+#-- 模块数据隐藏:最小化from*的破坏
+ _X # 变量名前加下划线可以防止from*导入时该变量名被复制出去
+ __all__ = ['x', 'x1', 'x2'] # 使用__all__列表指定from*时复制出去的变量名(变量名在列表中为字符串形式)
+
+#-- 可以使用__name__进行模块的单元测试:当模块为顶层执行文件时值为'__main__' 当模块被导入时为模块名
+ if __name__ == '__main__':
+ doSomething
+ # 模块属性中还有其他属性,例如:
+ __doc__ # 模块的说明文档
+ __file__ # 模块文件的文件名,包括全路径
+ __name__ # 主文件或者被导入文件
+ __package__ # 模块所在的包
+
+#-- import语句from语句的as扩展
+ import modulename as name
+ from modulename import attrname as name
+
+#-- 得到模块属性的几种方法 假设为了得到name属性的值
+ M.name
+ M.__dict__['name']
+ sys.modules['M'].name
+ getattr(M, 'name')
+
+
+"""类与面向对象----类与面向对象----类与面向对象----类与面向对象----类与面向对象----类与面向对象----类与面向对象----类与面向对象----类与面向对象----类与面向对象"""
+
+#-- 最普通的类
+ class C1(C2, C3):
+ spam = 42 # 数据属性
+ def __init__(self, name): # 函数属性:构造函数
+ self.name = name
+ def __del__(self): # 函数属性:析构函数
+ print("goodbey ", self.name)
+ I1 = C1('bob')
+
+#-- Python的类没有基于参数的函数重载
+ class FirstClass(object):
+ def test(self, string):
+ print(string)
+ def test(self): # 此时类中只有一个test函数 即后者test(self) 它覆盖掉前者带参数的test函数
+ print("hello world")
+
+#-- 子类扩展超类: 尽量调用超类的方法
+ class Manager(Person):
+ def giveRaise(self, percent, bonus = .10):
+ self.pay = int(self.pay*(1 + percent + bonus)) # 不好的方式 复制粘贴超类代码
+ Person.giveRaise(self, percent + bonus) # 好的方式 尽量调用超类方法
+
+#-- 类内省工具
+ bob = Person('bob')
+ bob.__class__ #
+ bob.__class__.__name__ # 'Person'
+ bob.__dict__ # {'pay':0, 'name':'bob', 'job':'Manager'}
+
+#-- 返回1中 数据属性spam是属于类 而不是对象
+ I1 = C1('bob'); I2 = C2('tom') # 此时I1和I2的spam都为42 但是都是返回的C1的spam属性
+ C1.spam = 24 # 此时I1和I2的spam都为24
+ I1.spam = 3 # 此时I1新增自有属性spam 值为3 I2和C1的spam还都为24
+
+#-- 类方法调用的两种方式
+ instance.method(arg...)
+ class.method(instance, arg...)
+
+#-- 抽象超类的实现方法
+ # (1)某个函数中调用未定义的函数 子类中定义该函数
+ def delegate(self):
+ self.action() # 本类中不定义action函数 所以使用delegate函数时就会出错
+ # (2)定义action函数 但是返回异常
+ def action(self):
+ raise NotImplementedError("action must be defined")
+ # (3)上述的两种方法还都可以定义实例对象 实际上可以利用@装饰器语法生成不能定义的抽象超类
+ from abc import ABCMeta, abstractmethod
+ class Super(metaclass = ABCMeta):
+ @abstractmethod
+ def action(self): pass
+ x = Super() # 返回 TypeError: Can't instantiate abstract class Super with abstract methods action
+
+#-- # OOP和继承: "is-a"的关系
+ class A(B):
+ pass
+ a = A()
+ isinstance(a, B) # 返回True, A是B的子类 a也是B的一种
+ # OOP和组合: "has-a"的关系
+ pass
+ # OOP和委托: "包装"对象 在Python中委托通常是以"__getattr__"钩子方法实现的, 这个方法会拦截对不存在属性的读取
+ # 包装类(或者称为代理类)可以使用__getattr__把任意读取转发给被包装的对象
+ class wrapper(object):
+ def __init__(self, object):
+ self.wrapped = object
+ def __getattr(self, attrname):
+ print('Trace: ', attrname)
+ return getattr(self.wrapped, attrname)
+ # 注:这里使用getattr(X, N)内置函数以变量名字符串N从包装对象X中取出属性 类似于X.__dict__[N]
+ x = wrapper([1, 2, 3])
+ x.append(4) # 返回 "Trace: append" [1, 2, 3, 4]
+ x = wrapper({'a':1, 'b':2})
+ list(x.keys()) # 返回 "Trace: keys" ['a', 'b']
+
+#-- 类的伪私有属性:使用__attr
+ class C1(object):
+ def __init__(self, name):
+ self.__name = name # 此时类的__name属性为伪私有属性 原理 它会自动变成self._C1__name = name
+ def __str__(self):
+ return 'self.name = %s' % self.__name
+ I = C1('tom')
+ print(I) # 返回 self.name = tom
+ I.__name = 'jeey' # 这里无法访问 __name为伪私有属性
+ I._C1__name = 'jeey' # 这里可以修改成功 self.name = jeey
+
+#-- 类方法是对象:无绑定类方法对象 / 绑定实例方法对象
+ class Spam(object):
+ def doit(self, message):
+ print(message)
+ def selfless(message)
+ print(message)
+ obj = Spam()
+ x = obj.doit # 类的绑定方法对象 实例 + 函数
+ x('hello world')
+ x = Spam.doit # 类的无绑定方法对象 类名 + 函数
+ x(obj, 'hello world')
+ x = Spam.selfless # 类的无绑定方法函数 在3.0之前无效
+ x('hello world')
+
+#-- 获取对象信息: 属性和方法
+ a = MyObject()
+ dir(a) # 使用dir函数
+ hasattr(a, 'x') # 测试是否有x属性或方法 即a.x是否已经存在
+ setattr(a, 'y', 19) # 设置属性或方法 等同于a.y = 19
+ getattr(a, 'z', 0) # 获取属性或方法 如果属性不存在 则返回默认值0
+ #这里有个小技巧,setattr可以设置一个不能访问到的属性,即只能用getattr获取
+ setattr(a, "can't touch", 100) # 这里的属性名带有空格,不能直接访问
+ getattr(a, "can't touch", 0) # 但是可以用getattr获取
+
+#-- 为类动态绑定属性或方法: MethodType方法
+ # 一般创建了一个class的实例后, 可以给该实例绑定任何属性和方法, 这就是动态语言的灵活性
+ class Student(object):
+ pass
+ s = Student()
+ s.name = 'Michael' # 动态给实例绑定一个属性
+ def set_age(self, age): # 定义一个函数作为实例方法
+ self.age = age
+ from types import MethodType
+ s.set_age = MethodType(set_age, s) # 给实例绑定一个方法 类的其他实例不受此影响
+ s.set_age(25) # 调用实例方法
+ Student.set_age = MethodType(set_age, Student) # 为类绑定一个方法 类的所有实例都拥有该方法
+
+
+"""类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题"""
+
+#-- 多重继承: "混合类", 搜索方式"从下到上 从左到右 广度优先"
+ class A(B, C):
+ pass
+
+#-- 类的继承和子类的初始化
+ # 1.子类定义了__init__方法时,若未显示调用基类__init__方法,python不会帮你调用。
+ # 2.子类未定义__init__方法时,python会自动帮你调用首个基类的__init__方法,注意是首个。
+ # 3.子类显示调用基类的初始化函数:
+ class FooParent(object):
+ def __init__(self, a):
+ self.parent = 'I\'m the Parent.'
+ print('Parent:a=' + str(a))
+ def bar(self, message):
+ print(message + ' from Parent')
+ class FooChild(FooParent):
+ def __init__(self, a):
+ FooParent.__init__(self, a)
+ print('Child:a=' + str(a))
+ def bar(self, message):
+ FooParent.bar(self, message)
+ print(message + ' from Child')
+ fooChild = FooChild(10)
+ fooChild.bar('HelloWorld')
+
+#-- #实例方法 / 静态方法 / 类方法
+ class Methods(object):
+ def imeth(self, x): print(self, x) # 实例方法:传入的是实例和数据,操作的是实例的属性
+ def smeth(x): print(x) # 静态方法:只传入数据 不传入实例,操作的是类的属性而不是实例的属性
+ def cmeth(cls, x): print(cls, x) # 类方法:传入的是类对象和数据
+ smeth = staticmethod(smeth) # 调用内置函数,也可以使用@staticmethod
+ cmeth = classmethod(cmeth) # 调用内置函数,也可以使用@classmethod
+ obj = Methods()
+ obj.imeth(1) # 实例方法调用 <__main__.Methods object...> 1
+ Methods.imeth(obj, 2) # <__main__.Methods object...> 2
+ Methods.smeth(3) # 静态方法调用 3
+ obj.smeth(4) # 这里可以使用实例进行调用
+ Methods.cmeth(5) # 类方法调用 5
+ obj.cmeth(6) # 6
+
+#-- 函数装饰器:是它后边的函数的运行时的声明 由@符号以及后边紧跟的"元函数"(metafunction)组成
+ @staticmethod
+ def smeth(x): print(x)
+ # 等同于:
+ def smeth(x): print(x)
+ smeth = staticmethod(smeth)
+ # 同理
+ @classmethod
+ def cmeth(cls, x): print(x)
+ # 等同于
+ def cmeth(cls, x): print(x)
+ cmeth = classmethod(cmeth)
+
+#-- 类修饰器:是它后边的类的运行时的声明 由@符号以及后边紧跟的"元函数"(metafunction)组成
+ def decorator(aClass):.....
+ @decorator
+ class C(object):....
+ # 等同于:
+ class C(object):....
+ C = decorator(C)
+
+#-- 限制class属性: __slots__属性
+ class Student(object):
+ __slots__ = ('name', 'age') # 限制Student及其实例只能拥有name和age属性
+ # __slots__属性只对当前类起作用, 对其子类不起作用
+ # __slots__属性能够节省内存
+ # __slots__属性可以为列表list,或者元组tuple
+
+#-- 类属性高级话题: @property
+ # 假设定义了一个类:C,该类必须继承自object类,有一私有变量_x
+ class C(object):
+ def __init__(self):
+ self.__x = None
+ # 第一种使用属性的方法
+ def getx(self):
+ return self.__x
+ def setx(self, value):
+ self.__x = value
+ def delx(self):
+ del self.__x
+ x = property(getx, setx, delx, '')
+ # property函数原型为property(fget=None,fset=None,fdel=None,doc=None)
+ # 使用
+ c = C()
+ c.x = 100 # 自动调用setx方法
+ y = c.x # 自动调用getx方法
+ del c.x # 自动调用delx方法
+ # 第二种方法使用属性的方法
+ @property
+ def x(self):
+ return self.__x
+ @x.setter
+ def x(self, value):
+ self.__x = value
+ @x.deleter
+ def x(self):
+ del self.__x
+ # 使用
+ c = C()
+ c.x = 100 # 自动调用setter方法
+ y = c.x # 自动调用x方法
+ del c.x # 自动调用deleter方法
+
+#-- 定制类: 重写类的方法
+ # (1)__str__方法、__repr__方法: 定制类的输出字符串
+ # (2)__iter__方法、next方法: 定制类的可迭代性
+ class Fib(object):
+ def __init__(self):
+ self.a, self.b = 0, 1 # 初始化两个计数器a,b
+ def __iter__(self):
+ return self # 实例本身就是迭代对象,故返回自己
+ def next(self):
+ self.a, self.b = self.b, self.a + self.b
+ if self.a > 100000: # 退出循环的条件
+ raise StopIteration()
+ return self.a # 返回下一个值
+ for n in Fib():
+ print(n) # 使用
+ # (3)__getitem__方法、__setitem__方法: 定制类的下标操作[] 或者切片操作slice
+ class Indexer(object):
+ def __init__(self):
+ self.data = {}
+ def __getitem__(self, n): # 定义getitem方法
+ print('getitem:', n)
+ return self.data[n]
+ def __setitem__(self, key, value): # 定义setitem方法
+ print('setitem:key = {0}, value = {1}'.format(key, value))
+ self.data[key] = value
+ test = Indexer()
+ test[0] = 1; test[3] = '3' # 调用setitem方法
+ print(test[0]) # 调用getitem方法
+ # (4)__getattr__方法: 定制类的属性操作
+ class Student(object):
+ def __getattr__(self, attr): # 定义当获取类的属性时的返回值
+ if attr=='age':
+ return 25 # 当获取age属性时返回25
+ raise AttributeError('object has no attribute: %s' % attr)
+ # 注意: 只有当属性不存在时 才会调用该方法 且该方法默认返回None 需要在函数最后引发异常
+ s = Student()
+ s.age # s中age属性不存在 故调用__getattr__方法 返回25
+ # (5)__call__方法: 定制类的'可调用'性
+ class Student(object):
+ def __call__(self): # 也可以带参数
+ print('Calling......')
+ s = Student()
+ s() # s变成了可调用的 也可以带参数
+ callable(s) # 测试s的可调用性 返回True
+ # (6)__len__方法:求类的长度
+ def __len__(self):
+ return len(self.data)
+
+#-- 动态创建类type()
+ # 一般创建类 需要在代码中提前定义
+ class Hello(object):
+ def hello(self, name='world'):
+ print('Hello, %s.' % name)
+ h = Hello()
+ h.hello() # Hello, world
+ type(Hello) # Hello是一个type类型 返回
+ type(h) # h是一个Hello类型 返回
+ # 动态类型语言中 类可以动态创建 type函数可用于创建新类型
+ def fn(self, name='world'): # 先定义函数
+ print('Hello, %s.' % name)
+ Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello类 type原型: type(name, bases, dict)
+ h = Hello() # 此时的h和上边的h一致
+
+
+"""异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关"""
+
+#-- #捕获异常:
+ try:
+ except: # 捕获所有的异常 等同于except Exception:
+ except name: # 捕获指定的异常
+ except name, value: # 捕获指定的异常和额外的数据(实例)
+ except (name1, name2):
+ except (name1, name2), value:
+ except name4 as X:
+ else: # 如果没有发生异常
+ finally: # 总会执行的部分
+ # 引发异常: raise子句(raise IndexError)
+ raise # raise instance of a class, raise IndexError()
+ raise # make and raise instance of a class, raise IndexError
+ raise # reraise the most recent exception
+
+#-- Python3.x中的异常链: raise exception from otherException
+ except Exception as X:
+ raise IndexError('Bad') from X
+
+#-- assert子句: assert ,
+ assert x < 0, 'x must be negative'
+
+#-- with/as环境管理器:作为常见的try/finally用法模式的替代方案
+ with expression [as variable], expression [as variable]:
+ # 例子:
+ with open('test.txt') as myfile:
+ for line in myfile: print(line)
+ # 等同于:
+ myfile = open('test.txt')
+ try:
+ for line in myfile: print(line)
+ finally:
+ myfile.close()
+
+#-- 用户自定义异常: class Bad(Exception):.....
+ """
+ Exception超类 / except基类即可捕获到其所有子类
+ Exception超类有默认的打印消息和状态 当然也可以定制打印显示:
+ """
+ class MyBad(Exception):
+ def __str__(self):
+ return '定制的打印消息'
+ try:
+ MyBad()
+ except MyBad as x:
+ print(x)
+
+#-- 用户定制异常数据
+ class FormatError(Exception):
+ def __init__(self, line ,file):
+ self.line = line
+ self.file = file
+ try:
+ raise FormatError(42, 'test.py')
+ except FormatError as X:
+ print('Error at ', X.file, X.line)
+ # 用户定制异常行为(方法):以记录日志为例
+ class FormatError(Exception):
+ logfile = 'formaterror.txt'
+ def __init__(self, line ,file):
+ self.line = line
+ self.file = file
+ def logger(self):
+ open(self.logfile, 'a').write('Error at ', self.file, self.line)
+ try:
+ raise FormatError(42, 'test.py')
+ except FormatError as X:
+ X.logger()
+
+#-- 关于sys.exc_info:允许一个异常处理器获取对最近引发的异常的访问
+ try:
+ ......
+ except:
+ # 此时sys.exc_info()返回一个元组(type, value, traceback)
+ # type:正在处理的异常的异常类型
+ # value:引发的异常的实例
+ # traceback:堆栈信息
+
+#-- 异常层次
+ BaseException
+ +-- SystemExit
+ +-- KeyboardInterrupt
+ +-- GeneratorExit
+ +-- Exception
+ +-- StopIteration
+ +-- ArithmeticError
+ +-- AssertionError
+ +-- AttributeError
+ +-- BufferError
+ +-- EOFError
+ +-- ImportError
+ +-- LookupError
+ +-- MemoryError
+ +-- NameError
+ +-- OSError
+ +-- ReferenceError
+ +-- RuntimeError
+ +-- SyntaxError
+ +-- SystemError
+ +-- TypeError
+ +-- ValueError
+ +-- Warning
+
+
+"""Unicode和字节字符串---Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串"""
+
+#-- Python的字符串类型
+ """Python2.x"""
+ # 1.str表示8位文本和二进制数据
+ # 2.unicode表示宽字符Unicode文本
+ """Python3.x"""
+ # 1.str表示Unicode文本(8位或者更宽)
+ # 2.bytes表示不可变的二进制数据
+ # 3.bytearray是一种可变的bytes类型
+
+#-- 字符编码方法
+ """ASCII""" # 一个字节,只包含英文字符,0到127,共128个字符,利用函数可以进行字符和数字的相互转换
+ ord('a') # 字符a的ASCII码为97,所以这里返回97
+ chr(97) # 和上边的过程相反,返回字符'a'
+ """Latin-1""" # 一个字节,包含特殊字符,0到255,共256个字符,相当于对ASCII码的扩展
+ chr(196) # 返回一个特殊字符:Ä
+ """Unicode""" # 宽字符,一个字符包含多个字节,一般用于亚洲的字符集,比如中文有好几万字
+ """UTF-8""" # 可变字节数,小于128的字符表示为单个字节,128到0X7FF之间的代码转换为两个字节,0X7FF以上的代码转换为3或4个字节
+ # 注意:可以看出来,ASCII码是Latin-1和UTF-8的一个子集
+ # 注意:utf-8是unicode的一种实现方式,unicode、gbk、gb2312是编码字符集
+
+#-- 查看Python中的字符串编码名称,查看系统的编码
+ import encodings
+ help(encoding)
+ import sys
+ sys.platform # 'win64'
+ sys.getdefaultencoding() # 'utf-8'
+ sys.getdefaultencoding() # 返回当前系统平台的编码类型
+ sys.getsizeof(object) # 返回object占有的bytes的大小
+
+#-- 源文件字符集编码声明: 添加注释来指定想要的编码形式 从而改变默认值 注释必须出现在脚本的第一行或者第二行
+ """说明:其实这里只会检查#和coding:utf-8,其余的字符都是为了美观加上的"""
+ # _*_ coding: utf-8 _*_
+ # coding = utf-8
+
+#-- #编码: 字符串 --> 原始字节 #解码: 原始字节 --> 字符串
+
+#-- Python3.x中的字符串应用
+ s = '...' # 构建一个str对象,不可变对象
+ b = b'...' # 构建一个bytes对象,不可变对象
+ s[0], b[0] # 返回('.', 113)
+ s[1:], b[1:] # 返回('..', b'..')
+ B = B"""
+ xxxx
+ yyyy
+ """
+ # B = b'\nxxxx\nyyyy\n'
+ # 编码,将str字符串转化为其raw bytes形式:
+ str.encode(encoding = 'utf-8', errors = 'strict')
+ bytes(str, encoding)
+ # 编码例子:
+ S = 'egg'
+ S.encode() # b'egg'
+ bytes(S, encoding = 'ascii') # b'egg'
+ # 解码,将raw bytes字符串转化为str形式:
+ bytes.decode(encoding = 'utf-8', errors = 'strict')
+ str(bytes_or_buffer[, encoding[, errors]])
+ # 解码例子:
+ B = b'spam'
+ B.decode() # 'spam'
+ str(B) # "b'spam'",不带编码的str调用,结果为打印该bytes对象
+ str(B, encoding = 'ascii')# 'spam',带编码的str调用,结果为转化该bytes对象
+
+#-- Python2.x的编码问题
+ u = u'汉'
+ print repr(u) # u'\xba\xba'
+ s = u.encode('UTF-8')
+ print repr(s) # '\xc2\xba\xc2\xba'
+ u2 = s.decode('UTF-8')
+ print repr(u2) # u'\xba\xba'
+ # 对unicode进行解码是错误的
+ s2 = u.decode('UTF-8') # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
+ # 同样,对str进行编码也是错误的
+ u2 = s.encode('UTF-8') # UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)
+
+#-- bytes对象
+ B = b'abc'
+ B = bytes('abc', 'ascii')
+ B = bytes([97, 98, 99])
+ B = 'abc'.encode()
+ # bytes对象的方法调用基本和str类型一致 但:B[0]返回的是ASCII码值97, 而不是b'a'
+
+#-- #文本文件: 根据Unicode编码来解释文件内容,要么是平台的默认编码,要么是指定的编码类型
+ # 二进制文件:表示字节值的整数的一个序列 open('bin.txt', 'rb')
+
+#-- Unicode文件
+ s = 'A\xc4B\xe8C' # s = 'A?BèC' len(s) = 5
+ #手动编码
+ l = s.encode('latin-1') # l = b'A\xc4B\xe8C' len(l) = 5
+ u = s.encode('utf-8') # u = b'A\xc3\x84B\xc3\xa8C' len(u) = 7
+ #文件输出编码
+ open('latindata', 'w', encoding = 'latin-1').write(s)
+ l = open('latindata', 'rb').read() # l = b'A\xc4B\xe8C' len(l) = 5
+ open('uft8data', 'w', encoding = 'utf-8').write(s)
+ u = open('uft8data', 'rb').read() # u = b'A\xc3\x84B\xc3\xa8C' len(u) = 7
+ #文件输入编码
+ s = open('latindata', 'r', encoding = 'latin-1').read() # s = 'A?BèC' len(s) = 5
+ s = open('latindata', 'rb').read().decode('latin-1') # s = 'A?BèC' len(s) = 5
+ s = open('utf8data', 'r', encoding = 'utf-8').read() # s = 'A?BèC' len(s) = 5
+ s = open('utf8data', 'rb').read().decode('utf-8') # s = 'A?BèC' len(s) = 5
+
+
+"""其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他"""
+
+#-- Python实现任意深度的赋值 例如a[0] = 'value1'; a[1][2] = 'value2'; a[3][4][5] = 'value3'
+ class MyDict(dict):
+ def __setitem__(self, key, value): # 该函数不做任何改动 这里只是为了输出
+ print('setitem:', key, value, self)
+ super().__setitem__(key, value)
+ def __getitem__(self, item): # 主要技巧在该函数
+ print('getitem:', item, self) # 输出信息
+ # 基本思路: a[1][2]赋值时 需要先取出a[1] 然后给a[1]的[2]赋值
+ if item not in self: # 如果a[1]不存在 则需要新建一个dict 并使得a[1] = dict
+ temp = MyDict() # 新建的dict: temp
+ super().__setitem__(item, temp) # 赋值a[1] = temp
+ return temp # 返回temp 使得temp[2] = value有效
+ return super().__getitem__(item) # 如果a[1]存在 则直接返回a[1]
+ # 例子:
+ test = MyDict()
+ test[0] = 'test'
+ print(test[0])
+ test[1][2] = 'test1'
+ print(test[1][2])
+ test[1][3] = 'test2'
+ print(test[1][3])
+
+#-- Python中的多维数组
+ lists = [0] * 3 # 扩展list,结果为[0, 0, 0]
+ lists = [[]] * 3 # 多维数组,结果为[[], [], []],但有问题,往下看
+ lists[0].append(3) # 期望看到的结果[[3], [], []],实际结果[[3], [3], [3]],原因:list*n操作,是浅拷贝,如何避免?往下看
+ lists = [[] for i in range(3)] # 多维数组,结果为[[], [], []]
+ lists[0].append(3) # 结果为[[3], [], []]
+ lists[1].append(6) # 结果为[[3], [6], []]
+ lists[2].append(9) # 结果为[[3], [6], [9]]
+ lists = [[[] for j in range(4)] for i in range(3)] # 3行4列,且每一个元素为[]
+```
diff --git "a/docs/Leetcode_Solutions/Python/Summary/python\347\232\204\345\220\204\347\247\215pass.md" "b/docs/Leetcode_Solutions/Python/Summary/python\347\232\204\345\220\204\347\247\215pass.md"
new file mode 100644
index 000000000..c1ac085a8
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/python\347\232\204\345\220\204\347\247\215pass.md"
@@ -0,0 +1,123 @@
+#Python的各种Pass
+
+感觉最近对于pass by reference 和 pass by value又有了一点/一些认识
+
+
+1. python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于通过“传值'来传递对象。
+2. 当人们复制列表或字典时,就复制了对象列表的引用同,如果改变引用的值,则修改了原始的参数。
+3. 为了简化内存管理,Python通过引用计数机制实现自动垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。
+
+
+##### Linked List的例子
+
+
+
+```
+class ListNode(object):
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+
+node1 = ListNode(1)
+node2 = ListNode(2)
+node3 = ListNode(3)
+node4 = ListNode(4)
+node5 = ListNode(5)
+
+node1.next = node2
+node2.next = node3
+node3.next = node4
+node4.next = node5
+
+```
+
+
+
+来改变head
+
+```
+def testWithPointers1(head):
+ head.next = None
+```
+
+
+
+运行 testWithPointers1(node1)
+
+然后node1.next 为None了
+
+// 可以理解,因为传进去的是head这个可变对象。
+
+
+
+```
+def testWithPointers2(head):
+ cur = head
+ cur.next = None
+```
+
+
+
+运行 testWithPointers2(node1)
+// node1.next 同样为None了
+
+Python的object,list都是pass by reference,所以是改变的
+
+看另外一个例子:
+
+```
+def printLinkedList(head):
+ while head:
+ print(head)
+ head = head.next
+```
+
+
+输出
+
+```
+ printLinkedList(head)
+
+<__main__.ListNode object at 0x1044c0e10>
+
+1
+
+<__main__.ListNode object at 0x1044c0fd0>
+
+2
+
+<__main__.ListNode object at 0x1044c0c88>
+
+3
+
+<__main__.ListNode object at 0x1044c0be0>
+
+4
+
+<__main__.ListNode object at 0x1044c0780>
+
+5
+
+head
+
+Out[39]: <__main__.ListNode at 0x1044c0e10>
+
+```
+
+其实这里的head为什么没有改变有点疑惑
+
+
+
+##### String看一下
+
+
+ a = "abc"
+
+ def changeA(s):
+ s = ""
+ changeA(a)
+
+
+a 并不会改变,依旧为'abc'
+
+
\ No newline at end of file
diff --git a/docs/Leetcode_Solutions/Python/Summary/slide_windows_template.md b/docs/Leetcode_Solutions/Python/Summary/slide_windows_template.md
new file mode 100644
index 000000000..919d1c0f9
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/Summary/slide_windows_template.md
@@ -0,0 +1,185 @@
+能用此模板解决的题目目前有如下:
+[leetcode 003](https://github.com/Lisanaaa/thinking_in_lc/blob/master/003._longest_substring_without_repeating_characters.md),
+[leetcode 030](https://github.com/Lisanaaa/thinking_in_lc/edit/master/30._Substring_with_Concatenation_of_All_Words.md),
+[leetcode 076](https://github.com/Lisanaaa/thinking_in_lc/blob/master/076._Minimum_Window_Substring.md),
+[leetcode 159](https://github.com/Lisanaaa/thinking_in_lc/blob/master/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md),
+[leetcode 438](https://github.com/Lisanaaa/thinking_in_lc/blob/master/438._Find_All_Anagrams_in_a_String.md)
+
+
+
+带注释python版本
+```python
+class Solution(object):
+ def slideWindowTemplateByLisanaaa(self, s, t):
+ """
+ :type s: str
+ :type t: str
+ :rtype: 具体题目具体分析
+ """
+ # init a collection or int value to save the result according the question.
+ res = []
+ if len(t) > len(s):
+ return res
+
+ # create a hashmap to save the Characters of the target substring.
+ # (K, V) = (Character, Frequence of the Characters)
+ maps = collections.Counter(t)
+
+ # maintain a counter to check whether match the target string.
+ # must be the map size, NOT the string size because the char may be duplicate.
+ counter = len(maps.keys())
+
+ # Two Pointers: begin - left pointer of the window; end - right pointer of the window
+ begin, end = 0, 0
+
+ # the length of the substring which match the target string.
+ length = sys.maxint
+
+ # loop at the begining of the source string
+ while end < len(s):
+ if s[end] in maps:
+ maps[s[end]] -= 1 # plus or minus one
+ if maps[s[end]] == 0:
+ counter -= 1 # modify the counter according the requirement(different condition).
+ end += 1
+
+ # increase begin pointer to make it invalid/valid again
+ while counter == 0: # counter condition. different question may have different condition
+ if s[begin] in maps:
+ maps[s[begin]] += 1 # plus or minus one
+ if maps[s[begin]] > 0:
+ counter += 1 # modify the counter according the requirement(different condition).
+ begin += 1
+
+ '''
+ type your code here according to the question
+ 1. save / update(min/max) the result if find a target
+ 2. result: collections or int value
+ '''
+ return res
+```
+
+无注释python版本:
+```python
+class Solution(object):
+ def slideWindowTemplateByLisanaaa(self, s, t):
+ res = []
+ if len(t) > len(s):
+ return res
+ maps = collections.Counter(t)
+ counter = len(maps.keys())
+ begin, end = 0, 0
+ length = sys.maxint
+ while end < len(s):
+ if s[end] in maps:
+ maps[s[end]] -= 1
+ if maps[s[end]] == 0:
+ counter -= 1
+ end += 1
+ while counter == 0:
+ if s[begin] in maps:
+ maps[s[begin]] += 1
+ if maps[s[begin]] > 0:
+ counter += 1
+ begin += 1
+
+ '''
+ 1. save / update(min/max) the result if find a target
+ 2. result: collections or int value
+ '''
+ return res
+```
+带注释java版本
+```java
+public class Solution {
+ public List slidingWindowTemplateByHarryChaoyangHe(String s, String t) {
+ //init a collection or int value to save the result according the question.
+ List result = new LinkedList<>();
+ if(t.length()> s.length()) return result;
+
+ //create a hashmap to save the Characters of the target substring.
+ //(K, V) = (Character, Frequence of the Characters)
+ Map map = new HashMap<>();
+ for(char c : t.toCharArray()){
+ map.put(c, map.getOrDefault(c, 0) + 1);
+ }
+ //maintain a counter to check whether match the target string.
+ int counter = map.size();//must be the map size, NOT the string size because the char may be duplicate.
+
+ //Two Pointers: begin - left pointer of the window; end - right pointer of the window
+ int begin = 0, end = 0;
+
+ //the length of the substring which match the target string.
+ int len = Integer.MAX_VALUE;
+
+ //loop at the begining of the source string
+ while(end < s.length()){
+
+ char c = s.charAt(end);//get a character
+
+ if( map.containsKey(c) ){
+ map.put(c, map.get(c)-1);// plus or minus one
+ if(map.get(c) == 0) counter--;//modify the counter according the requirement(different condition).
+ }
+ end++;
+
+ //increase begin pointer to make it invalid/valid again
+ while(counter == 0 /* counter condition. different question may have different condition */){
+
+ char tempc = s.charAt(begin);//***be careful here: choose the char at begin pointer, NOT the end pointer
+ if(map.containsKey(tempc)){
+ map.put(tempc, map.get(tempc) + 1);//plus or minus one
+ if(map.get(tempc) > 0) counter++;//modify the counter according the requirement(different condition).
+ }
+
+ /* save / update(min/max) the result if find a target*/
+ // result collections or result int value
+
+ begin++;
+ }
+ }
+ return result;
+ }
+}
+```
+
+无注释java版本:
+```java
+public class Solution {
+ public List slidingWindowTemplateByHarryChaoyangHe(String s, String t) {
+ List result = new LinkedList<>();
+ if(t.length()> s.length()) return result;
+ Map map = new HashMap<>();
+ for(char c : t.toCharArray()){
+ map.put(c, map.getOrDefault(c, 0) + 1);
+ }
+ int counter = map.size();
+ int begin = 0, end = 0;
+ int len = Integer.MAX_VALUE;
+ while(end < s.length()){
+ char c = s.charAt(end);
+ if( map.containsKey(c) ){
+ map.put(c, map.get(c)-1);
+ if(map.get(c) == 0) counter--;
+ }
+ end++;
+ while(counter == 0){
+ char tempc = s.charAt(begin);
+ if(map.containsKey(tempc)){
+ map.put(tempc, map.get(tempc) + 1);
+ if(map.get(tempc) > 0) counter++;
+ }
+
+ /*
+ save / update(min/max) the result if find a target
+ result collections or result int value
+ */
+
+ begin++;
+ }
+ }
+ return result;
+ }
+}
+```
+
diff --git a/docs/Leetcode_Solutions/Python/Summary/union_find.md b/docs/Leetcode_Solutions/Python/Summary/union_find.md
new file mode 100644
index 000000000..5e32d3089
--- /dev/null
+++ b/docs/Leetcode_Solutions/Python/Summary/union_find.md
@@ -0,0 +1,281 @@
+## 并查集(参考leetcode323题)
+
+### 应用场景:
+
+动态联通性
+
+- 网络连接判断:
+如果每个pair中的两个整数用来表示这两个节点是需要连通的,那么为所有的pairs建立了动态连通图后,就能够尽可能少的减少布线的需要,
+因为已经连通的两个节点会被直接忽略掉。例如[1,2]代表节点1和节点2是联通的,如果再次出现[2,1]我们就不需要再连接他们了,因为已经连接过一次了。
+
+- 变量名等同性(类似于指针的概念):
+在程序中,可以声明多个引用来指向同一对象,这个时候就可以通过为程序中声明的引用和实际对象建立动态连通图来判断哪些引用实际上是指向同一对象。
+
+### 对问题建模:
+
+在对问题进行建模的时候,我们应该尽量想清楚需要解决的问题是什么。因为模型中选择的数据结构和算法显然会根据问题的不同而不同,
+就动态连通性这个场景而言,我们需要解决的问题可能是:
+
+1. 给出两个节点,判断它们是否连通,如果连通,不需要给出具体的路径
+2. 给出两个节点,判断它们是否连通,如果连通,需要给出具体的路径
+
+就上面两种问题而言,虽然只有是否能够给出具体路径的区别,但是这个区别导致了选择算法的不同
+
+### 建模思路:
+
+最简单而直观的假设是,对于连通的所有节点,我们可以认为它们属于一个组,因此不连通的节点必然就属于不同的组。
+随着Pair的输入,我们需要首先判断输入的两个节点是否连通。如何判断呢?按照上面的假设,我们可以通过判断它们属于的组,然后看看这两个组是否相同。
+如果相同,那么这两个节点连通,反之不连通。为简单起见,我们将所有的节点以整数表示,即对N个节点使用0到N-1的整数表示。
+而在处理输入的Pair之前,每个节点必然都是孤立的,即他们分属于不同的组,可以使用数组来表示这一层关系。
+数组的index是节点的整数表示,而相应的值就是该节点的组号了。该数组可以初始化为:```uf = [i for i in range(n)]```
+
+初始化完毕之后,对该动态连通图有几种可能的操作:
+
+1. 查询节点属于的组
+
+数组对应位置的值即为组号
+
+2. 判断两个节点是否属于同一个组
+
+分别得到两个节点的组号,然后判断组号是否相等
+
+3. 连接两个节点,使之属于同一个组
+
+分别得到两个节点的组号,组号相同时操作结束,不同时,将其中的一个节点的组号换成另一个节点的组号
+
+4. 获取组的数目
+
+初始化为节点的数目,然后每次成功连接两个节点之后,递减1
+
+### API:
+
+我们可以设置对应的API
+```python
+def uf(n) # 初始化uf数组和组数目
+def union(x, y) # 连接两个节点
+def find(x) # 判断节点所属于的组
+def connected(x, y) # 判断两个节点是否联通
+def count() # 返回所有组的数目
+```
+
+注意其中使用整数来表示节点,如果需要使用其他的数据类型表示节点,比如使用字符串,那么可以用哈希表来进行映射,即将String映射成这里需要的Integer类型。
+
+分析以上的API,方法connected和union都依赖于find,connected对两个参数调用两次find方法,而union在真正执行union之前也需要判断是否连通,
+这又是两次调用find方法。因此我们需要把find方法的实现设计的尽可能的高效。所以就有了下面的Quick-Find实现。
+
+### Quick-Find实现
+
+```
+class Solution(object):
+ uf = [] # access to component id (site indexed)
+ count = 0 # number of components
+
+ def uf(self, n): # 初始化uf数组和组数目
+ self.count = n
+ self.uf = [i for i in range(n)]
+
+ def find(self, x): # 判断节点所属于的组
+ return uf[x]
+
+ def union(self, x, y): # 连接两个节点
+ x_root = find(x)
+ y_root = find(y)
+ if x_root == y_root:
+ return
+ for i in range(len(self.uf)):
+ if uf[i] == x_root:
+ uf[i] = y_root
+ count -= 1
+
+ def connected(self, x, y): # 判断两个节点是否联通
+ return find(x) == find(y)
+
+ def count(self): # 返回所有组的数目
+ return count
+```
+
+上述代码的find方法十分高效,因为仅仅需要一次数组读取操作就能够找到该节点的组号。
+但是问题随之而来,对于需要添加新路径的情况,就涉及到对于组号的修改,因为并不能确定哪些节点的组号需要被修改,
+因此就必须对整个数组进行遍历,找到需要修改的节点,逐一修改,这一下每次添加新路径带来的复杂度就是线性关系了,
+如果要添加的新路径的数量是M,节点数量是N,那么最后的时间复杂度就是MN,显然是一个平方阶的复杂度,对于大规模的数据而言,平方阶的算法是存在问题的,
+这种情况下,每次添加新路径就是“牵一发而动全身”,想要解决这个问题,关键就是要提高union方法的效率,让它不再需要遍历整个数组。
+
+
+### Quick-Union 算法:
+
+考虑一下,为什么以上的解法会造成“牵一发而动全身”?因为每个节点所属的组号都是单独记录,各自为政的,没有将它们以更好的方式组织起来,
+当涉及到修改的时候,除了逐一通知、修改,别无他法。所以现在的问题就变成了,如何将节点以更好的方式组织起来,组织的方式有很多种,
+但是最直观的还是将组号相同的节点组织在一起,想想所学的数据结构,什么样子的数据结构能够将一些节点给组织起来?
+常见的就是链表,图,树,什么的了。但是哪种结构对于查找和修改的效率最高?毫无疑问是树,因此考虑如何将节点和组的关系以树的形式表现出来。
+
+如果不改变底层数据结构,即不改变使用数组的表示方法的话。可以采用parent-link的方式将节点组织起来,
+举例而言,uf[p]的值就是p节点的父节点的序号,如果p是树根的话,uf[p]的值就是p,因此最后经过若干次查找,一个节点总是能够找到它的根节点,
+即满足uf[root] = root的节点也就是组的根节点了,然后就可以使用根节点的序号来表示组号。所以在处理一个pair的时候,
+将首先找到pair中每一个节点的组号(即它们所在树的根节点的序号),如果属于不同的组的话,就将其中一个根节点的父节点设置为另外一个根节点,
+相当于将一颗独立的树编程另一颗独立的树的子树。直观的过程如下图所示。但是这个时候又引入了问题。
+
+树这种数据结构容易出现极端情况,因为在建树的过程中,树的最终形态严重依赖于输入数据本身的性质,比如数据是否排序,是否随机分布等等。
+比如在输入数据是有序的情况下,构造的BST会退化成一个链表。在我们这个问题中,也是会出现的极端情况的。
+
+```
+class Solution(object):
+ uf = [] # access to component id (site indexed)
+ count = 0 # number of components
+
+ def uf(self, n): # 初始化uf数组和组数目
+ self.count = n
+ self.uf = [i for i in range(n)]
+
+ def find(self, x): # 判断节点所属于的组
+ # if uf[x] != x: ## 这种方式也可以,但是递归次数多了容易出问题
+ # uf[x] = find(uf[x])
+ while x != uf[x]:
+ x = uf[x]
+ return uf[x]
+
+ def union(self, x, y): # 连接两个节点
+ x_root = find(x)
+ y_root = find(y)
+ uf[x_root] = y_root
+ count -= 1
+
+ def connected(self, x, y): # 判断两个节点是否联通
+ return find(x) == find(y)
+
+ def count(self): # 返回所有组的数目
+ return count
+```
+
+为了克服这个问题,BST可以演变成为红黑树或者AVL树等等。
+
+然而,在我们考虑的这个应用场景中,每对节点之间是不具备可比性的。因此需要想其它的办法。在没有什么思路的时候,多看看相应的代码可能会有一些启发,
+考虑一下Quick-Union算法中的union方法实现:
+
+```
+def union(self, x, y): # 连接两个节点
+ x_root = find(x)
+ y_root = find(y)
+ uf[x_root] = y_root
+ count -= 1
+```
+
+上面 id[pRoot] = qRoot 这行代码看上去似乎不太对劲。因为这也属于一种“硬编码”,这样实现是基于一个约定,即p所在的树总是会被作为q所在树的子树,
+从而实现两颗独立的树的融合。那么这样的约定是不是总是合理的呢?显然不是,比如p所在的树的规模比q所在的树的规模大的多时,
+p和q结合之后形成的树就是十分不和谐的一头轻一头重的”畸形树“了。
+
+所以我们应该考虑树的大小,然后再来决定到底是调用 uf[x_root] = y_root 或者是 uf[y_root] = x_root
+
+即总是size小的树作为子树和size大的树进行合并。这样就能够尽量的保持整棵树的平衡。
+
+所以现在的问题就变成了:树的大小该如何确定?
+
+我们回到最初的情形,即每个节点最一开始都是属于一个独立的组,通过下面的代码进行初始化:
+```
+tree_size = [1 for i in range(n)]
+```
+
+然后:
+
+```
+def union(self, x, y): # 连接两个节点
+ x_root = find(x)
+ y_root = find(y)
+ if tree_size[x_root] <= tree_size[y_root]:
+ uf[x_root] = y_root
+ tree_size[y_root] += tree_size[x_root]
+ else:
+ uf[y_root] = x_root
+ tree_size[x_root] += tree_size[y_root]
+ count -= 1
+```
+
+可以发现,通过tree_size数组决定如何对两棵树进行合并之后,最后得到的树的高度大幅度减小了。这是十分有意义的。
+因为在Quick-Union算法中的任何操作,都不可避免的需要调用find方法,而该方法的执行效率依赖于树的高度。树的高度减小了,
+find方法的效率就增加了,从而也就增加了整个Quick-Union算法的效率。
+
+上面的论证其实还可以给我们一些启示,即对于Quick-Union算法而言,节点组织的理想情况应该是一颗十分扁平的树,所有的孩子节点应该都在height为1的地方,
+即所有的孩子都直接连接到根节点。这样的组织结构能够保证find操作的最高效率。
+
+那么如何构造这种理想结构呢?
+
+在find方法的执行过程中,不是需要进行一个while循环找到根节点嘛?如果保存所有路过的中间节点到一个数组中,然后在while循环结束之后,
+将这些中间节点的父节点指向根节点,不就行了么?但是这个方法也有问题,因为find操作的频繁性,会造成频繁生成中间节点数组,
+相应的分配销毁的时间自然就上升了。那么有没有更好的方法呢?还是有的,即将节点的父节点指向该节点的爷爷节点,这一点很巧妙,
+十分方便且有效,相当于在寻找根节点的同时,对路径进行了压缩,使整个树结构扁平化。相应的实现如下,实际上只需要添加一行代码:
+
+```
+def find(self, x): # 判断节点所属于的组
+ while x != uf[x]:
+ uf[x] = uf[uf[x]]
+ x = uf[x]
+ return uf[x]
+```
+综上,我决定以后解决问题的时候用这个模版就行了:
+
+```python
+class UnionFind(object):
+ uf = [] # access to component id (site indexed)
+ count = 0 # number of components
+
+ def uf(self, n): # 初始化uf数组和组数目
+ self.count = n
+ self.uf = [i for i in range(n)]
+
+ def find(self, x): # 判断节点所属于的组
+ while x != self.uf[x]:
+ self.uf[x] = self.uf[self.uf[x]]
+ x = self.uf[x]
+ return self.uf[x]
+
+ def union(self, x, y): # 连接两个节点
+ x_root = self.find(x)
+ y_root = self.find(y)
+ self.uf[x_root] = y_root
+ self.count -= 1
+
+ def connected(self, x, y): # 判断两个节点是否联通
+ return self.find(x) == self.find(y)
+
+ def count(self): # 返回所有组的数目
+ return self.count
+```
+### 时间复杂度分析
+- find()操作的时间复杂度最坏情况下为O(N)
+- union()操作的时间复杂度最坏情况下为O(1)
+
+Quick union的表现将随着我们不断调用union()构建联通集而变差。因为代表这个联通集的树越来越高,调用find()的开销也就越来越大。
+
+至此,动态连通性相关的Union-Find算法基本上就介绍完了,从容易想到的Quick-Find到相对复杂但是更加高效的Quick-Union,然后到对Quick-Union的几项改进,
+让我们的算法的效率不断的提高。
+
+这几种算法的时间复杂度如下所示:
+
+
+对大规模数据进行处理,使用平方阶的算法是不合适的,比如简单直观的Quick-Find算法,通过发现问题的更多特点,找到合适的数据结构,然后有针对性的进行改进,
+得到了Quick-Union算法及其多种改进算法,最终使得算法的复杂度降低到了近乎线性复杂度。
+
+如果需要的功能不仅仅是检测两个节点是否连通,还需要在连通时得到具体的路径,那么就需要用到别的算法了,比如DFS或者BFS。
+
+并查集的应用,可以参考另外一篇文章[并查集应用举例](https://blog.csdn.net/dm_vincent/article/details/7769159)
+
+## References
+
+1. [并查集(Union-Find)算法介绍](https://blog.csdn.net/dm_vincent/article/details/7655764)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\200\344\272\233\346\223\215\344\275\234.md" "b/docs/Leetcode_Solutions/Python/Summary/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\200\344\272\233\346\223\215\344\275\234.md"
new file mode 100644
index 000000000..54d08ab00
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\200\344\272\233\346\223\215\344\275\234.md"
@@ -0,0 +1,245 @@
+### 1. 二叉搜索树(BSTree)的概念
+
+二叉搜索树又被称为二叉排序树,那么它本身也是一棵二叉树,那么满足以下性质的二叉树就是二叉搜索树,如图:
+
+- 若左子树不为空,则左子树上所有节点的值都小于根节点的值;
+- 若它的右子树不为空,则它的右子树上所有节点的值都大于根节点的值;
+- 它的左右子树也要分别是二叉搜索树。
+
+### 2. 二叉搜索树的插入
+
+- 如果插入值已经存在,则不插,return False
+- 如果not root,则返回TreeNode(val)
+- 根据与root.val的比较,在左右子树中进行递归操作
+
+代码中保证插入的值不存在,也是[leetcode第701题](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/701._Insert_into_a_Binary_Search_Tree.md)中所gurantee的
+```python
+# 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 insertIntoBST(self, root, val):
+ """
+ :type root: TreeNode
+ :type val: int
+ :rtype: TreeNode
+ """
+ if not root:
+ return TreeNode(val)
+ if val < root.val:
+ root.left = self.insertIntoBST(root.left, val)
+ if val > root.val:
+ root.right = self.insertIntoBST(root.right, val)
+ return root
+```
+
+### 3. 二叉搜索树的搜索
+
+* 搜索节点
+```java
+public TreeNode search(int key) {
+ TreeNode pNode = root;
+ while (pNode != null) {
+ if (key == pNode.key) {
+ return pNode;
+ } else if (key > pNode.key) {
+ pNode = pNode.rchild;
+ } else if (key < pNode.key) {
+ pNode = pNode.lchild;
+ }
+ }
+ return null;// 如果没有搜索到结果那么就只能返回空值了
+}
+```
+
+* 获取最小节点
+
+```java
+public TreeNode minElemNode(TreeNode node) throws Exception {
+ if (node == null) {
+ throw new Exception("此树为空树!");
+ }
+ TreeNode pNode = node;
+ while (pNode.lchild != null) {
+ pNode = pNode.lchild;
+ }
+ return pNode;
+}
+```
+
+* 获取最大节点
+
+```java
+public TreeNode maxElemNode(TreeNode node) throws Exception {
+ if (node == null) {
+ throw new Exception("此树为空树!");
+ }
+ TreeNode pNode = node;
+ while (pNode.rchild != null) {
+ pNode = pNode.rchild;
+ }
+ return pNode;
+}
+```
+
+* 获取给定节点在中序遍历下的后续第一个节点(即找到该节点的右子树中的最左孩子)
+
+```java
+public TreeNode successor(TreeNode node) throws Exception {
+ if (node == null) {
+ throw new Exception("此树为空树!");
+ }
+ // 分两种情况考虑,此节点是否有右子树
+ // 当这个节点有右子树的情况下,那么右子树的最小关键字节点就是这个节点的后续节点
+ if (node.rchild != null) {
+ return minElemNode(node.rchild);
+ }
+
+ // 当这个节点没有右子树的情况下,即 node.rchild == null
+ // 如果这个节点是它父节点的左子树的话,那么就说明这个父节点就是后续节点了
+ TreeNode parentNode = node.parent;
+ while (parentNode != null && parentNode.rchild == node) {
+ node = parentNode;
+ parentNode = parentNode.parent;
+ }
+ return parentNode;
+}
+```
+
+
+* 获取给定节点在中序遍历下的前趋结点
+
+```java
+public TreeNode precessor(TreeNode node) throws Exception {
+ // 查找前趋节点也是分两种情况考虑
+ // 如果这个节点存在左子树,那么这个左子树的最大关键字就是这个节点的前趋节点
+ if (node.lchild != null) {
+ return maxElemNode(node.lchild);
+ }
+ // 如果这个节点不存在左子树,那么这个节点的父节点
+ TreeNode parentNode = node.parent;
+ while (parentNode != null && parentNode.lchild == node) {
+ node = parentNode;
+ parentNode = parentNode.lchild;
+ }
+ return parentNode;
+}
+```
+
+
+
+### 4. 二叉搜索树的删除
+
+- 要删除的节点不存在,return False
+- 要删除的节点没有子节点,直接删
+- 要删除的节点只有一个子节点(即只有一个左子节点或者一个右子节点),让被删除节点的父亲节点指向其子节点即可
+- 要删除的节点target有两个子节点(即左右均存在),则首先找到该节点的右子树中的最左孩子(也就是右子树中序遍历的第一个节点,分两种情况),
+然后将两者互换,再删除target即可
+
+```java
+ // 从二叉树当中删除指定的节点
+ public void delete(int key) throws Exception {
+ TreeNode pNode = search(key);
+ if (pNode == null) {
+ throw new Exception("此树中不存在要删除的这个节点!");
+ }
+
+ delete(pNode);
+ }
+
+ private void delete(TreeNode pNode) throws Exception {
+ // 第一种情况:删除没有子节点的节点
+ if (pNode.lchild == null && pNode.rchild == null) {
+ if (pNode == root) {// 如果是根节点,那么就删除整棵树
+ root = null;
+ } else if (pNode == pNode.parent.lchild) {
+ // 如果这个节点是父节点的左节点,则将父节点的左节点设为空
+ pNode.parent.lchild = null;
+ } else if (pNode == pNode.parent.rchild) {
+ // 如果这个节点是父节点的右节点,则将父节点的右节点设为空
+ pNode.parent.rchild = null;
+ }
+ }
+
+ // 第二种情况: (删除有一个子节点的节点)
+ // 如果要删除的节点只有右节点
+ if (pNode.lchild == null && pNode.rchild != null) {
+ if (pNode == root) {
+ root = pNode.rchild;
+ } else if (pNode == pNode.parent.lchild) {
+ pNode.parent.lchild = pNode.rchild;
+ pNode.rchild.parent = pNode.parent;
+ } else if (pNode == pNode.parent.rchild) {
+ pNode.parent.rchild = pNode.rchild;
+ pNode.rchild.parent = pNode.parent;
+ }
+ }
+ // 如果要删除的节点只有左节点
+ if (pNode.lchild != null && pNode.rchild == null) {
+ if (pNode == root) {
+ root = pNode.lchild;
+ } else if (pNode == pNode.parent.lchild) {
+ pNode.parent.lchild = pNode.lchild;
+ pNode.lchild.parent = pNode.parent;
+ } else if (pNode == pNode.parent.rchild) {
+ pNode.parent.rchild = pNode.lchild;
+ pNode.lchild.parent = pNode.parent;
+ }
+ }
+
+ // 第三种情况: (删除有两个子节点的节点,即左右子节点都非空)
+
+ // 方法是用要删除的节点的后续节点代替要删除的节点,并且删除后续节点(删除后续节点的时候需要递归操作)
+ // 解析:这里要用到的最多也就会发生两次,即后续节点不会再继续递归的删除下一个后续节点了,
+ // 因为,要删除的节点的后续节点肯定是:要删除的那个节点的右子树的最小关键字,而这个最小关键字肯定不会有左节点;
+ // 所以,在删除后续节点的时候肯定不会用到(两个节点都非空的判断 ),如有有子节点,肯定就是有一个右节点。
+ if (pNode.lchild != null && pNode.rchild != null) {
+ // 先找出后续节点
+ TreeNode successorNode = successor(pNode);
+ if (pNode == root) {
+ root.key = successorNode.key;
+ } else {
+ pNode.key = successorNode.key;// 赋值,将后续节点的值赋给要删除的那个节点
+ }
+ delete(successorNode);// 递归的删除后续节点
+ }
+ }
+```
+
+
+### 5. 二叉搜索树的遍历
+
+前序遍历:[leetcode第144题](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/144._binary_tree_preorder_traversal.md)
+
+中序遍历:[leetcode第94题](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/094._binary_tree_inorder_traversal.md)
+
+后序遍历:[leetcode第145题](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/145._binary_tree_postorder_traversal.md)
+
+
+层次遍历:[leetcode第102题](https://github.com/apachecn/LeetCode/blob/master/docs/Leetcode_Solutions/102._binary_tree_level_order_traversal.md)
+
+## References
+
+[数据结构与算法之二叉搜索树插入、查询与删除](https://blog.csdn.net/chenliguan/article/details/52956546)
+
+[二叉搜索树的插入与删除图解](http://www.cnblogs.com/MrListening/p/5782752.html)
+
+[二叉树算法删除代码实现](https://blog.csdn.net/tayanxunhua/article/details/11100113)
+
+[二叉树的Java实现及特点总结](http://www.cnblogs.com/lzq198754/p/5857597.html)
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\344\275\215\350\277\220\347\256\227.md" "b/docs/Leetcode_Solutions/Python/Summary/\344\275\215\350\277\220\347\256\227.md"
new file mode 100644
index 000000000..aeaa44c4d
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\344\275\215\350\277\220\347\256\227.md"
@@ -0,0 +1,38 @@
+### 位运算
+
+位运算包括: 加 减 乘 取反 and 异或
+
+- 0110 + 0110 = 0110 * 2 ,也就是0110左移1位
+
+- 0011 * 0100 0100 = 4, 一个数乘以 2^n 即是将这个数左移n
+
+- a ^(~a) = 0
+
+- x & (~0 << n ) 这样来看,0取反全部为1,然后将其右移n位,后面的全是0,x & (~0 <>:右移
+
+
+
+Bit Facts and Tricks
+
+```
+x ^ 0s = x x & 0s = 0 x | 0s = x
+x ^ 1s = ~x x & 1s = x x | 1s = 1s
+x ^ x = 0 x & x = x x | x = x
+```
+
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\345\205\250\346\216\222\345\210\227\347\256\227\346\263\225.md" "b/docs/Leetcode_Solutions/Python/Summary/\345\205\250\346\216\222\345\210\227\347\256\227\346\263\225.md"
new file mode 100644
index 000000000..767617664
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\345\205\250\346\216\222\345\210\227\347\256\227\346\263\225.md"
@@ -0,0 +1,194 @@
+### 全排列算法
+
+
+#### 46. Permutations
+
+
+Given a collection of distinct numbers, return all possible permutations.
+
+For example,
+[1,2,3] have the following permutations:
+
+ [
+ [1,2,3],
+ [1,3,2],
+ [2,1,3],
+ [2,3,1],
+ [3,1,2],
+ [3,2,1]
+ ]
+
+
+#####从空开始加
+
+先跳离开这道题,来看类似的'ABC',我们要求它的全排列
+
+
+```
+def recPermute(sofar, rest):
+ if rest == '':
+ print sofar
+ else:
+ for i in range(len(rest)):
+ nxt = sofar + rest[i]
+ remaining = rest[:i] + rest[i+1:]
+ recPermute(nxt, remaining)
+
+// "wrapper" function
+def listPermute(s):
+ recPermute('',s)
+```
+
+会正确输出`ABC ACB BAC BCA CAB CBA`,题目依靠的是每次我们从余下的字母中选一个,如果画图则会是这样:
+
+
+```
+ A B C
+ B C A C A B
+ C B C A B A
+```
+
+时间复杂度应该是O(n!)
+
+- n choose 1
+- n-1 choose 1
+- ...
+
+
+
+#####另一种市面上常见思路是交换:
+
+思路是这样的,同样看上面的图:
+
+- n个元素的全排列 = (n-1)个元素的全排列 + 另一个元素作为前缀
+- 如果只有一个元素,那么这个元素本身就是它的全排列
+- 不断将每个元素放作第一个元素,然后将这个元素作为前缀,并将其余元素继续全排列,等到出口,出口出去后还需要还原数组
+
+
+这个用数组来测试更容易写代码和直观:
+
+
+```
+def recPermute(nums,begin):
+ n = len(nums)
+ if begin == n:
+ print nums,
+
+ for i in range(begin,n):
+ nums[begin], nums[i] = nums[i],nums[begin]
+ recPermute(nums,begin+1)
+ nums[begin],nums[i] = nums[i],nums[begin]
+
+recPermute(['A','B','C'],0)
+
+```
+
+这样的写法更容易理解:
+
+
+```python
+class Solution:
+ # @param num, a list of integer
+ # @return a list of lists of integers
+ def permute(self, num):
+ if len(num) == 0: return []
+ if len(num) == 1: return [num]
+ res = []
+ for i in range(len(num)):
+ x = num[i]
+ xs = num[:i] + num[i+1:]
+ for j in self.permute(xs):
+ res.append([x] + j)
+ return res
+```
+
+每次用一个没有用过的头元素,然后加上全排列产生的结果.
+
+如果分析复杂度,应该也是O(n!)
+
+
+#### 47. Permutations II
+
+
+最简单的想法:
+
+- 排序
+- 如果碰到重复的就继续处理下一个
+
+```
+class Solution(object):
+ def permuteUnique(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: List[List[int]]
+ """
+ if len(nums) == 0: return []
+ if len(nums) == 1: return [nums]
+ res = []
+ nums.sort()
+ for i in range(len(nums)):
+ if i > 0 and nums[i] == nums[i-1]: continue
+ for j in self.permuteUnique(nums[:i] + nums[i+1:]):
+ res.append([nums[i]] + j)
+ return res
+
+```
+
+
+
+
+#### 31. Next Permutation
+
+实际上这个题目也就是Generation in lexicographic order,
+
+wikipedia 和 [这里](https://www.nayuki.io/page/next-lexicographical-permutation-algorithm) 有很好,很精妙的算法,也有点two pointer的意思
+
+
+```
+1. Find the highest index i such that s[i] < s[i+1]. If no such index exists, the permutation is the last permutation.
+2. Find the highest index j > i such that s[j] > s[i]. Such a j must exist, since i+1 is such an index.
+3. Swap s[i] with s[j].
+4. Reverse the order of all of the elements after index i till the last element.
+```
+
+
+看例子:
+
+125430
+
+
+- 从末尾开始,找到decreasing subsequence,5430,因为来调5330无论怎么调,都不可能有比它更小的,数也被自然的分成两部分(1,2) 和 (5,4,3,0)
+- 下一步是找这个sequence里面第一个比前面部分,比2大的,3,也很容易理解,因为下一个必定是(1,3)打头
+- 交换 3和2 ,变成 (1,3,5,4,2,0),再把后面的部分reverse,得到后面部分可得到的最小的
+
+这个时候,得到下一个sequence 130245
+
+
+
+```
+class Solution(object):
+ def nextPermutation(self, nums):
+ """
+ :type nums: List[int]
+ :rtype: void Do not return anything, modify nums in-place instead.
+ """
+ m, n = 0, 0
+ for i in range(len(nums) - 2, 0 , -1):
+ if nums[i] < nums[i+1]:
+ m = i
+ break
+
+ for i in range(len(nums) - 1, 0 , -1):
+ if nums[i] > nums[m]:
+ n = i
+ break
+
+ if m < n :
+ nums[m], nums[n] = nums[n], nums[m]
+ nums[m+1:] = nums[len(nums):m:-1]
+ else:
+ nums = nums.reverse()
+```
+
+
+所以可以用这个next permutation来解46/47也可以,然后我兴奋了一下,这个算法很快的!然后我又冷静了,因为permutation的个数是O(n!)个啊|||,所以也不可能有啥大的提升吧
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\345\205\253\346\216\222\345\272\217.md" "b/docs/Leetcode_Solutions/Python/Summary/\345\205\253\346\216\222\345\272\217.md"
new file mode 100644
index 000000000..83b327202
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\345\205\253\346\216\222\345\272\217.md"
@@ -0,0 +1,386 @@
+## 前言
+八大排序,三大查找是《数据结构》当中非常基础的知识点,在这里为了复习顺带总结了一下常见的八种排序算法。
+常见的八大排序算法,他们之间关系如下:
+
+
+
+他们的性能比较:
+
+
+
+### 直接插入排序 (Insertion sort)
+
+
+
+直接插入排序的核心思想就是:将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换,直到全部元素都比较过。
+因此,从上面的描述中我们可以发现,直接插入排序可以用两个循环完成:
+
+1. 第一层循环:遍历待比较的所有数组元素
+2. 第二层循环:将本轮选择的元素(selected)与已经排好序的元素(ordered)相比较。
+ - 如果```selected > ordered```,那么将二者交换
+
+```python
+#直接插入排序
+def insert_sort(L):
+ #遍历数组中的所有元素,其中0号索引元素默认已排序,因此从1开始
+ for x in range(1,len(L)):
+ #将该元素与已排序好的前序数组依次比较,如果该元素小,则交换
+ #range(x-1,-1,-1):从x-1倒序循环到0
+ for i in range(x-1,-1,-1):
+ #判断:如果符合条件则交换
+ if L[i] > L[i+1]:
+ L[i], L[i+1] = L[i+1], L[i]
+```
+### 希尔排序 (Shell sort)
+
+
+
+希尔排序的算法思想:将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。
+同样的:从上面的描述中我们可以发现:希尔排序的总体实现应该由三个循环完成:
+
+1. 第一层循环:将gap依次折半,对序列进行分组,直到gap=1
+2. 第二、三层循环:也即直接插入排序所需要的两次循环。具体描述见上。
+
+```python
+#希尔排序
+def insert_shell(L):
+ #初始化gap值,此处利用序列长度的一半为其赋值
+ gap = int(len(L)/2)
+ #第一层循环:依次改变gap值对列表进行分组
+ while (gap >= 1):
+ #下面:利用直接插入排序的思想对分组数据进行排序
+ #range(gap,len(L)):从gap开始
+ for x in range(gap,len(L)):
+ #range(x-gap,-1,-gap):从x-gap开始与选定元素开始倒序比较,每个比较元素之间间隔gap
+ for i in range(x-gap,-1,-gap):
+ #如果该组当中两个元素满足交换条件,则进行交换
+ if L[i] > L[i+gap]:
+ L[i], L[i+gap] = L[i+gap], L[i]
+ #while循环条件折半
+ gap = int((gap/2))
+```
+
+### 简单选择排序 (Selection sort)
+
+
+
+简单选择排序的基本思想:比较+交换。
+
+1. 从待排序序列中,找到关键字最小的元素;
+2. 如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;
+3. 从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束。
+因此我们可以发现,简单选择排序也是通过两层循环实现。
+ - 第一层循环:依次遍历序列当中的每一个元素
+ - 第二层循环:将遍历得到的当前元素依次与余下的元素进行比较,符合最小元素的条件,则交换。
+
+```python
+# 简单选择排序
+def select_sort(L):
+#依次遍历序列中的每一个元素
+ for x in range(0,len(L)):
+#将当前位置的元素定义此轮循环当中的最小值
+ minimum = L[x]
+#将该元素与剩下的元素依次比较寻找最小元素
+ for i in range(x+1,len(L)):
+ if L[i] < minimum:
+ L[i], minimum = minimum, L[i]
+#将比较后得到的真正的最小值赋值给当前位置
+ L[x] = minimum
+```
+
+### 堆排序 (Heap sort)
+
+#### 堆的概念
+
+堆:本质是一种数组对象。特别重要的一点性质:任意的叶子节点小于(或大于)它所有的父节点。对此,又分为大顶堆和小顶堆,大顶堆要求节点的元素都要大于其孩子,小顶堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求。
+利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。下面,我们通过大顶堆来实现。
+
+基本思想:
+堆排序可以按照以下步骤来完成:
+
+1. 首先将序列构建称为大顶堆;
+
+(这样满足了大顶堆那条性质:位于根节点的元素一定是当前序列的最大值)
+
+
+
+2. 取出当前大顶堆的根节点,将其与序列末尾元素进行交换;
+
+(此时:序列末尾的元素为已排序的最大值;由于交换了元素,当前位于根节点的堆并不一定满足大顶堆的性质)
+
+3. 对交换后的n-1个序列元素进行调整,使其满足大顶堆的性质;
+
+
+
+4. 重复2.3步骤,直至堆中只有1个元素为止
+
+```python
+#-------------------------堆排序--------------------------------
+#**********获取左右叶子节点**********
+def LEFT(i):
+ return 2*i + 1
+def RIGHT(i):
+ return 2*i + 2
+#********** 调整大顶堆 **********
+#L:待调整序列 length: 序列长度 i:需要调整的结点
+def adjust_max_heap(L, length, i):
+#定义一个int值保存当前序列最大值的下标
+ largest = i
+#获得序列左右叶子节点的下标
+ left, right = LEFT(i), RIGHT(i)
+#当左叶子节点的下标小于序列长度 并且 左叶子节点的值大于父节点时,将左叶子节点的下标赋值给largest
+ if (left < length) and (L[left] > L[i]):
+ largest = left
+#当右叶子节点的下标小于序列长度 并且 右叶子节点的值大于父节点时,将右叶子节点的下标值赋值给largest
+ if (right < length) and (L[right] > L[largest]):
+ largest = right
+#如果largest不等于i 说明当前的父节点不是最大值,需要交换值
+ if (largest != i):
+ L[i], L[largest] = L[largest], L[i]
+ # 执行递归操作:两个任务:1 寻找最大值的下标;2.最大值与父节点交换
+ adjust_max_heap(L, length, largest)
+#********** 建立大顶堆 **********
+def build_max_heap(L):
+ length = len(L)
+ for x in range(int((length-1)/2), -1, -1):
+ adjust_max_heap(L, length, x)
+#********** 堆排序 **********
+def heap_sort(L):
+#先建立大顶堆,保证最大值位于根节点;并且父节点的值大于叶子结点
+ build_max_heap(L)
+#i:当前堆中序列的长度.初始化为序列的长度
+ i = len(L)
+#执行循环:1. 每次取出堆顶元素置于序列的最后(len-1,len-2,len-3...)
+# 2. 调整堆,使其继续满足大顶堆的性质,注意实时修改堆中序列的长度
+ while (i > 0):
+ L[i-1], L[0] = L[0], L[i-1]
+#堆中序列长度减1
+ i -= 1
+#调整大顶堆
+ adjust_max_heap(L, i, 0)
+```
+### 冒泡排序 (Bubble sort)
+
+
+
+冒泡排序思路比较简单:
+
+1. 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
+( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;)
+2. 对序列当中剩下的n-1个元素再次执行步骤1。
+3. 对于长度为n的序列,一共需要执行n-1轮比较
+(利用while循环可以减少执行次数)
+
+```python
+#冒泡排序
+def bubble_sort(L):
+ length = len(L)
+#序列长度为length,需要执行length-1轮交换
+ for x in range(1, length):
+#对于每一轮交换,都将序列当中的左右元素进行比较
+#每轮交换当中,由于序列最后的元素一定是最大的,因此每轮循环到序列未排序的位置即可
+ for i in range(0, length-x):
+ if L[i] > L[i+1]:
+ L[i], L[i+1] = L[i+1], L[i]
+```
+
+### 快速排序 (Quick sort)
+
+
+
+快速排序的基本思想:挖坑填数+分治法
+
+1. 从序列当中选择一个基准数(pivot)
+在这里我们选择序列当中第一个数作为基准数
+2. 将序列当中的所有数依次遍历,比基准数大的位于其右侧,比基准数小的位于其左侧
+3. 重复步骤1.2,直到所有子集当中只有一个元素为止。
+
+用伪代码描述如下:
+- i =L; j = R; 将基准数挖出形成第一个坑a[i]。
+- j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。
+- i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。
+- 再重复执行2,3二步,直到i==j,将基准数填入a[i]中
+
+```python
+#快速排序
+#L:待排序的序列;start排序的开始index,end序列末尾的index
+#对于长度为length的序列:start = 0;end = length-1
+def quick_sort(L, start, end):
+ if start < end:
+ i, j, pivot = start, end, L[start]
+ while i < j:
+#从右开始向左寻找第一个小于pivot的值
+ while (i < j) and (L[j] >= pivot):
+ j -= 1
+#将小于pivot的值移到左边
+ if (i < j):
+ L[i] = L[j]
+ i += 1
+#从左开始向右寻找第一个大于pivot的值
+ while (i < j) and (L[i] <= pivot):
+ i += 1
+#将大于pivot的值移到右边
+ if (i < j):
+ L[j] = L[i]
+ j -= 1
+#循环结束后,说明 i=j,此时左边的值全都小于pivot,右边的值全都大于pivot
+#pivot的位置移动正确,那么此时只需对左右两侧的序列调用此函数进一步排序即可
+#递归调用函数:依次对左侧序列:从0 ~ i-1//右侧序列:从i+1 ~ end
+ L[i] = pivot
+#左侧序列继续排序
+ quick_sort(L, start, i-1)
+#右侧序列继续排序
+ quick_sort(L, i+1, end)
+```
+
+### 归并排序 (Merge sort)
+
+
+
+1. 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个典型的应用。它的基本操作是:将已有的子序列合并,达到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
+2. 归并排序其实要做两件事:
+ - 分解----将序列每次折半拆分
+ - 合并----将划分后的序列段两两排序合并
+因此,归并排序实际上就是两个操作,拆分+合并
+3. 如何合并?
+ - L[first...mid]为第一段,L[mid+1...last]为第二段,并且两端已经有序,现在我们要将两端合成达到L[first...last]并且也有序。
+ - 首先依次从第一段与第二段中取出元素比较,将较小的元素赋值给temp[]
+ - 重复执行上一步,当某一段赋值结束,则将另一段剩下的元素赋值给temp[]
+ - 此时将temp[]中的元素复制给L[],则得到的L[first...last]有序
+4. 如何分解?
+ - 在这里,我们采用递归的方法,首先将待排序列分成A,B两组;
+ - 然后重复对A、B序列分组;
+ - 直到分组后组内只有一个元素,此时我们认为组内所有元素有序,则分组结束。
+
+```python
+# 归并排序
+#这是合并的函数
+# 将序列L[first...mid]与序列L[mid+1...last]进行合并
+def mergearray(L, first, mid, last, temp):
+#对i,j,k分别进行赋值
+ i, j, k = first, mid+1, 0
+#当左右两边都有数时进行比较,取较小的数
+ while (i <= mid) and (j <= last):
+ if L[i] <= L[j]:
+ temp[k] = L[i]
+ i += 1
+ k += 1
+ else:
+ temp[k] = L[j]
+ j += 1
+ k += 1
+#如果左边序列还有数
+ while (i <= mid):
+ temp[k] = L[i]
+ i += 1
+ k += 1
+#如果右边序列还有数
+ while (j <= last):
+ temp[k] = L[j]
+ j += 1
+ k += 1
+#将temp当中该段有序元素赋值给L待排序列使之部分有序
+ for x in range(0, k):
+ L[first+x] = temp[x]
+# 这是分组的函数
+def merge_sort(L, first, last, temp):
+ if first < last:
+ mid = int(((first + last) / 2))
+#使左边序列有序
+ merge_sort(L, first, mid, temp)
+#使右边序列有序
+ merge_sort(L, mid+1, last, temp)
+#将两个有序序列合并
+ mergearray(L, first, mid, last, temp)
+# 归并排序的函数
+def merge_sort_array(L):
+#声明一个长度为len(L)的空列表
+ temp = len(L)*[None]
+#调用归并排序
+ merge_sort(L, 0, len(L)-1, temp)
+```
+
+### 基数排序 (Radix sort)
+
+
+
+1. 基数排序:通过序列中各个元素的值,对排序的N个元素进行若干趟的“分配”与“收集”来实现排序。
+ - 分配:我们将L[i]中的元素取出,首先确定其个位上的数字,根据该数字分配到与之序号相同的桶中
+ - 收集:当序列中所有的元素都分配到对应的桶中,再按照顺序依次将桶中的元素收集形成新的一个待排序列L[ ]
+ - 对新形成的序列L[]重复执行分配和收集元素中的十位、百位...直到分配完该序列中的最高位,则排序结束
+2. 根据上述“基数排序”的展示,我们可以清楚的看到整个实现的过程
+
+```python
+#************************基数排序****************************
+#确定排序的次数
+#排序的顺序跟序列中最大数的位数相关
+def radix_sort_nums(L):
+ maxNum = L[0]
+#寻找序列中的最大数
+ for x in L:
+ if maxNum < x:
+ maxNum = x
+#确定序列中的最大元素的位数
+ times = 0
+ while (maxNum > 0):
+ maxNum = int((maxNum/10))
+ times += 1
+ return times
+#找到num从低到高第pos位的数据
+def get_num_pos(num, pos):
+ return (int((num/(10**(pos-1))))) % 10
+#基数排序
+def radix_sort(L):
+ count = 10 * [None] #存放各个桶的数据统计个数
+ bucket = len(L) * [None] #暂时存放排序结果
+#从低位到高位依次执行循环
+ for pos in range(1, radix_sort_nums(L)+1):
+ #置空各个桶的数据统计
+ for x in range(0, 10):
+ count[x] = 0
+ #统计当前该位(个位,十位,百位....)的元素数目
+ for x in range(0, len(L)):
+ #统计各个桶将要装进去的元素个数
+ j = get_num_pos(int(L[x]), pos)
+ count[j] += 1
+ #count[i]表示第i个桶的右边界索引
+ for x in range(1,10):
+ count[x] += count[x-1]
+ #将数据依次装入桶中
+ for x in range(len(L)-1, -1, -1):
+ #求出元素第K位的数字
+ j = get_num_pos(L[x], pos)
+ #放入对应的桶中,count[j]-1是第j个桶的右边界索引
+ bucket[count[j]-1] = L[x]
+ #对应桶的装入数据索引-1
+ count[j] -= 1
+ # 将已分配好的桶中数据再倒出来,此时已是对应当前位数有序的表
+ for x in range(0, len(L)):
+ L[x] = bucket[x]
+```
+
+## 运行时间实测
+
+10w数据
+```
+直接插入排序:1233.581131
+希尔排序:1409.8012320000003
+简单选择排序:466.66974500000015
+堆排序:1.2036720000000969
+冒泡排序:751.274449
+#****************************************************
+快速排序:1.0000003385357559e-06
+#快速排序有误:实际上并未执行
+#RecursionError: maximum recursion depth exceeded in comparison
+#****************************************************
+归并排序:0.8262230000000272
+基数排序:1.1162899999999354
+```
+从运行结果上来看,堆排序、归并排序、基数排序真的快。
+对于快速排序迭代深度超过的问题,可以将考虑将快排通过非递归的方式进行实现。
+
+## Resources
+
+1. [算法导论》笔记汇总](http://mindlee.com/2011/08/21/study-notes-directory/)
+2. [八大排序算法的 Python 实现](http://python.jobbole.com/82270/)
+3. [数据结构常见的八大排序算法(详细整理)](https://www.jianshu.com/p/7d037c332a9d)
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\345\255\220\351\233\206\345\220\210\351\227\256\351\242\230.md" "b/docs/Leetcode_Solutions/Python/Summary/\345\255\220\351\233\206\345\220\210\351\227\256\351\242\230.md"
new file mode 100644
index 000000000..0d4afa96a
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\345\255\220\351\233\206\345\220\210\351\227\256\351\242\230.md"
@@ -0,0 +1,114 @@
+###子集合问题
+
+####78. Subsets
+
+子集合是全排列的好朋友,也是combination组合的好朋友,排列·组合·子集,他们三个都是好朋友.
+
+
+#####从空开始加
+
+同样先来看'ABC'
+
+```
+def recsubsets(sofar, rest):
+ if rest == '':
+ print sofar,
+ else:
+ recsubsets(sofar, rest[1:])
+ recsubsets(sofar + rest[0], rest[1:])
+
+def listsubsets(s):
+ recsubsets('',s)
+
+
+listsubsets('ABC')
+```
+
+##### 市面流行思路
+
+市面上流行的思路:
+
+- [[],[1]] 是 [1] 的子集合
+- [[],[1],[2],[1,2]] 是 [1,2] 的子集合,实际上就是1的子集合们加了一个2
+
+
+所以用python写起来也很简单/精美
+
+```
+def subsets(nums):
+ """
+ :type nums: List[int]
+ :rtype: List[List[int]]
+ """
+ results = [[]]
+ for num in nums:
+ results.extend([result + [num] for result in results])
+ return results
+```
+我在这里犯过错,所以这一句
+
+`results.extend([result + [num] for result in results])` 实际上等于:
+
+
+```
+tmp = []
+for result in results:
+ tmp.append(result + [num])
+results.extend(tmp)
+```
+
+
+
+
+
+#### 90. Subsets II
+
+
+要去重了,比如如果有 [1,2,2],那么解答为:
+
+
+ [
+ [2],
+ [1],
+ [1,2,2],
+ [2,2],
+ [1,2],
+ []
+ ]
+
+
+现在来观察规律,与之前有不同之处是我们需要一个位置来mark,因为不再需要往之前出现过的地方再加了,看这个:
+
+
+```
+[[],[1]] 是 [1] 的子集合
+[[],[1],[2],[1,2]] 是 [1,2] 的子集合,实际上就是1的子集合们加了一个2
+新来的2不能再从头开始加了,它需要从[ .., [2],[1,2] ]加 才是合理的
+```
+
+所以看到非常精妙的代码
+
+
+```
+def subsets(nums):
+ """
+ :type nums: List[int]
+ :rtype: List[List[int]]
+ """
+ nums.sort()
+ result = [[]]
+ temp_size = 0
+
+ for i in range(len(nums)):
+ start = temp_size if i >= 1 and nums[i] == nums[i-1] else 0
+ temp_size = len(result)
+ #print start,temp_size,result
+ for j in range(start, temp_size):
+ result.append(result[j] + [nums[i]])
+ print result
+
+subsets([1,2,2])
+```
+
+这里这个start是来记录了之前一次数组的长度,temp_size记住目前数组的长度,然后用这个来达到去重的目的,非常聪明
+
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\346\200\273\347\273\223.md" "b/docs/Leetcode_Solutions/Python/Summary/\346\200\273\347\273\223.md"
new file mode 100644
index 000000000..99fcba752
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\346\200\273\347\273\223.md"
@@ -0,0 +1,120 @@
+# 1
+```solution```下自定义函数```func(self, fargs, *args, **kwargs)```, 调用时使用```self.func()```的格式
+
+# 2
+```not fargs``` 和 ```fargs == None```不一样,前者```fargs```可能为[], '', 0, etc
+
+# 3
+递归问题
+Any problem can be solved using dp. Solving using a greedy strategy is harder though, since you need to prove that greedy will work for that problem. There are some tell-tale signs of a problem where greedy may be applicable, but isn’t immediately apparent. Example:
+
+- Choice of an element depends only on its immediate neighbours (wiggle sort).
+- Answer is monotonically non-decreasing or non-increasing (sorting). This is also applicable for LIS for example.
+- Anything that requires lexicographically largest or smallest of something.
+- Anything where processing the input in sorted order will help.
+- Anything where processing the input in forward or reverse (as given) will help.
+- Anything which requires you to track the minimum or maximum of something (think of sliding window problems).
+
+There’s matroid theory which deal with greedy algorithms, but I don’t really understand it. If someone does, I’ll be super grateful to them to explain it to me in simple language!
+
+In general, try to see if for a problem, the solution doesn’t depend on a lot of history about the solution itself, but the next part of the solution is somewhat independent from the rest of the solution. These are all indicative of the fact that a greedy strategy could be applicable.
+
+# 4
+[Counter.elements()](https://docs.python.org/2/library/collections.html)
+
+# 5
+测试案例写法
+
+```python
+import unittest
+class Solution(object):
+ def isMatch(self, s, p):
+ """
+ :type s: str
+ :type p: str
+ :rtype: bool
+ """
+ m, n = len(s), len(p)
+ dp = [ [0 for i in range(n+1)] for j in range(m+1)]
+
+ dp[0][0] = 1
+
+ # init the first line
+ for i in range(2,n+1):
+ if p[i-1] == '*':
+ dp[0][i] = dp[0][i-2]
+
+ for i in range(1,m+1):
+ for j in range(1,n+1):
+ if p[j-1] == '*':
+ if p[j-2] != s[i-1] and p[j-2] != '.':
+ dp[i][j] = dp[i][j-2]
+ elif p[j-2] == s[i-1] or p[j-2] == '.':
+ dp[i][j] = dp[i-1][j] or dp[i][j-2]
+
+ elif s[i-1] == p[j-1] or p[j-1] == '.':
+ dp[i][j] = dp[i-1][j-1]
+
+ return dp[m][n] == 1
+
+
+class TestSolution(unittest.TestCase):
+ def test_none_0(self):
+ s = ""
+ p = ""
+ self.assertTrue(Solution().isMatch(s, p))
+
+ def test_none_1(self):
+ s = ""
+ p = "a"
+ self.assertFalse(Solution().isMatch(s, p))
+
+ def test_no_symbol_equal(self):
+ s = "abcd"
+ p = "abcd"
+ self.assertTrue(Solution().isMatch(s, p))
+
+ def test_no_symbol_not_equal_0(self):
+ s = "abcd"
+ p = "efgh"
+ self.assertFalse(Solution().isMatch(s, p))
+
+ def test_no_symbol_not_equal_1(self):
+ s = "ab"
+ p = "abb"
+ self.assertFalse(Solution().isMatch(s, p))
+
+ def test_symbol_0(self):
+ s = ""
+ p = "a*"
+ self.assertTrue(Solution().isMatch(s, p))
+
+ def test_symbol_1(self):
+ s = "a"
+ p = "ab*"
+ self.assertTrue(Solution().isMatch(s, p))
+
+ def test_symbol_2(self):
+ # E.g.
+ # s a b b
+ # p 1 0 0 0
+ # a 0 1 0 0
+ # b 0 0 1 0
+ # * 0 1 1 1
+ s = "abb"
+ p = "ab*"
+ self.assertTrue(Solution().isMatch(s, p))
+
+
+if __name__ == "__main__":
+ unittest.main()
+
+
+
+输出:
+........
+
+Ran 8 tests in 0.001s
+
+OK
+```
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\346\226\220\346\263\242\351\202\243\345\245\221\347\232\204DP\346\200\235\350\200\203.md" "b/docs/Leetcode_Solutions/Python/Summary/\346\226\220\346\263\242\351\202\243\345\245\221\347\232\204DP\346\200\235\350\200\203.md"
new file mode 100644
index 000000000..84ce8bbbf
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\346\226\220\346\263\242\351\202\243\345\245\221\347\232\204DP\346\200\235\350\200\203.md"
@@ -0,0 +1,42 @@
+Fibonacci 的DP版本
+
+对于DP的不同理解造成不同的写法
+Memoization will usually add on your time-complexity to your space-complexity (e.g. with tabulation you have more liberty to throw away calculations, like using tabulation with Fib lets you use O(1) space, but memoization with Fib uses O(N) stack space).
+详看
+
+[Dynamic programming and memoization: bottom-up vs top-down approaches](https://awjin.me/algos-js/dp/tab-memo.html)
+
+[Tabulation vs Memoizatation](http://www.geeksforgeeks.org/tabulation-vs-memoizatation/)
+- top-down(memorize)
+
+```
+def memorize_fib(n): # n为第几个Fibonacci数
+ memo = {1:1, 2:1}
+ if n in memo:
+ return memo[n]
+ else:
+ memo[n] = memorize_fib(n-1) + memorize_fib(n-2)
+ return memo[n]
+
+print(memorize_fib(4)) # 输出3
+```
+
+
+
+- bottom up(tabulation)
+
+```
+def tabulation_fib(n): # n为第几个Fibonacci数
+ fib = [1, 1, 2]
+ if n < 4:
+ return fib[n-1]
+ for k in range(3, n+1):
+ fib[2] = fib[0] + fib[1]
+ fib[0], fib[1] = fib[1], fib[2]
+ return fib[2]
+
+print(tabulation_fib(4)) # 输出3
+```
+
+
+这里memo用dict,用array也一样。当然用bottom up还有一点,可以只存每次最后两个数,可以save space.,这样就只用到constant space.
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\347\203\231\345\215\260\344\277\256\347\202\274\345\244\247\346\263\225.md" "b/docs/Leetcode_Solutions/Python/Summary/\347\203\231\345\215\260\344\277\256\347\202\274\345\244\247\346\263\225.md"
new file mode 100644
index 000000000..1765d341f
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\347\203\231\345\215\260\344\277\256\347\202\274\345\244\247\346\263\225.md"
@@ -0,0 +1,12 @@
+## 战略思想
+
+先要了解敌方的战略
+
+```
+自我介绍5分钟,闲聊20分钟,再给你半道题目,要求你15分钟内想出最优解
+且代码实现 bug free并完成test cases,没完成超时,完成不符合题意
+```
+
+## 应对方法
+
+没辙,🤷♂️
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\347\273\204\345\220\210\351\227\256\351\242\230.md" "b/docs/Leetcode_Solutions/Python/Summary/\347\273\204\345\220\210\351\227\256\351\242\230.md"
new file mode 100644
index 000000000..33f295e82
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\347\273\204\345\220\210\351\227\256\351\242\230.md"
@@ -0,0 +1,84 @@
+### 组合问题
+
+
+#### 77.Combinations
+
+
+##### 会超时的recursion
+
+
+
+```
+class Solution(object):
+ def combine(self, n, k):
+ """
+ :type n: int
+ :type k: int
+ :rtype: List[List[int]]
+ """
+ ans = []
+ self.dfs(n, k, 1, [], ans)
+ return ans
+
+ def dfs(self, n, k ,start, lst, ans):
+ if k == 0 :
+ ans.append(lst)
+ return
+ for i in range(start, n+1):
+ self.dfs(n, k - 1, i + 1,lst +[i], ans)
+```
+
+理解方式
+
+```
+
+ 1 2 3
+ 12 13 14 23 24 34
+```
+
+可以参照这里
+
+
+
+
+
+##### 市面上流行解法
+
+递归的思想: n选k
+
+- 如果 k==n ,则全选。
+- n > k 又可以分成两类:
+ - 选了n, 则在余下的n-1中选k-1
+ - 没有选n, 则在余下的n-1中选k
+
+注意一下会有两个base case,因为k在不断减小和n在不断减小,所以写起来可以这样:
+
+
+```
+def combine(n,k):
+ if k == 1:
+ return [[i+1] for i in range(n)]
+ if n == k:
+ return [range(1, k+1)]
+ # choose n , not choose n
+ return [r + [n] for r in combine(n-1,k-1)] + combine(n-1,k)
+
+
+print combine(20,16)
+```
+
+
+#### 39. Combination Sum
+
+
+使用正常递归思路
+
+
+#### 40. Combination Sum II
+
+重复做跳过处理
+
+#### 216. Combination Sum III
+
+
+#### 377. Combination Sum IV
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\347\274\226\347\250\213\346\200\235\350\267\257\346\200\273\347\273\223.md" "b/docs/Leetcode_Solutions/Python/Summary/\347\274\226\347\250\213\346\200\235\350\267\257\346\200\273\347\273\223.md"
new file mode 100644
index 000000000..53cde29b2
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\347\274\226\347\250\213\346\200\235\350\267\257\346\200\273\347\273\223.md"
@@ -0,0 +1,20 @@
+## 1. OJ 基本条件
+达尔大佬对刷leetcode和刷笔试题有几个建议:
+
+1. 一般oj是有要求时间的,一般是1秒。后台判题系统都是单核单线程跑,机器性能不会太好。1秒能运行的基本操作个数的量级是10^6-10^7,
+个别代码能跑到10^8,但很少见。这种情况下,看数据范围是可以大致了解到这个题目需要什么样子的时间复杂度。
+比如说,n<=1000的数据范围,o(n^3)的代码就不要写了,浪费时间而已。写代码之前得先计算自己代码的复杂度,预估自己代码跑的速度,再动手。
+2. 基本操作指的是逻辑和加减法,乘法比加减法慢得多,但在大复杂度的前提下,这种复杂度是可以忽略的。比如说,在一个算法o(n^3)中,
+代码中一个两层嵌套循环o(n^2)就显得没什么优化意义了。优化代码主要优化算法复杂度,而那些,要不要用位运算代替除法啊,
+或者两个一层循环要不要合并成一个一层循环啊,没有意义,不要纠结,同级复杂度,才有优化意义
+3. 高级编程语言每个api都有自己的复杂度,在没有了解复杂度之前不建议使用那些api,最好自己实现,比如哈希表啊,堆啊,
+什么语言都有实现,熟悉之前还是乖乖自己实现的好
+4. 注意精度误差。。。比如开方,如果开方开的是一个整数,结果也是整数,最好写个二分,或者写个牛顿迭代求零点,
+不要用内置函数sqrt,求出来是个浮点数,会有误差
+
+
+## 2. 判断环
+- 看到链表中的环就想到快慢指针
+- 看到图中的环就想到并查集,wisdompeak大佬说:用union find确实是判断图是否成环的一个很好的手段。但是它更常用在无向图。
+对于有向图,用并查集需要非常小心。这里的edge都是有向的,我觉得无脑用并查集会有风险。
+我的总结是:union find唯一能用在有向图的地方,就是只有我们试图保证这张图是树的时候。
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\351\200\222\345\275\222_recursion.md" "b/docs/Leetcode_Solutions/Python/Summary/\351\200\222\345\275\222_recursion.md"
new file mode 100644
index 000000000..413872965
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\351\200\222\345\275\222_recursion.md"
@@ -0,0 +1,39 @@
+#递归 Recursion
+
+### 递归
+
+递归绝对是一个非常重要的概念。比如安利? 不断的delegate,本来想要完成1000个人的销售,找10个人,每人完成100人的,这10个人每人再去找10个人,每人完成10人的销售,这样就完成了1000人的销售(不懂安利是否这样,拿来举例)。
+
+
+递归之所以重要,这里面存在的概念太多了,首先上面这个例子里面就有divide and conquer的意思,把task divide小,然后来解决它。
+
+
+同样有趣的例子 → 吃完一个bowl of chips:
+
+- for loop,知道多少薯片,然后从0开始吃到最后
+- while, while 碗里还有薯片,就吃
+- 递归,吃一片,然后继续吃剩下的 N - 1 片,直到碗里的薯片数量只剩下0片了
+
+
+典型的例子:
+
+- pow(x,n)
+- isPalindrome
+- TowerofHanoi
+- binarySearch
+
+
+
+### 链表, 树, 图
+
+链表(linked list) 是数据结构的基础,而链表本身就是具有递归特性的,看C++中对于linked list node的定义, next指向本身这样的结构,就是再这个node定义还未完成之时,我们已经指向自己。
+
+
+```
+struct node{
+ int data;
+ node* next;
+};
+```
+
+binary tree定义就是靠递归来实现的。
diff --git "a/docs/Leetcode_Solutions/Python/Summary/\351\235\242\350\257\225\347\241\256\350\256\244\351\242\230\347\233\256\347\273\206\350\212\202\351\227\256\351\242\230.md" "b/docs/Leetcode_Solutions/Python/Summary/\351\235\242\350\257\225\347\241\256\350\256\244\351\242\230\347\233\256\347\273\206\350\212\202\351\227\256\351\242\230.md"
new file mode 100644
index 000000000..90a8924a2
--- /dev/null
+++ "b/docs/Leetcode_Solutions/Python/Summary/\351\235\242\350\257\225\347\241\256\350\256\244\351\242\230\347\233\256\347\273\206\350\212\202\351\227\256\351\242\230.md"
@@ -0,0 +1,3 @@
+1. The length of the given array is positive and will not exceed 20?
+2. The sum of elements in the given array will not exceed 1000?
+3. The output answer is guaranteed to be fitted in a 32-bit integer?
diff --git a/docs/Leetcode_Solutions/ipynb/001._two_sum.ipynb b/docs/Leetcode_Solutions/ipynb/001._two_sum.ipynb
new file mode 100644
index 000000000..c1fc51bf0
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/001._two_sum.ipynb
@@ -0,0 +1,251 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 1. Two Sum 两数之和\n",
+ "\n",
+ "## 题目:\n",
+ "\n",
+ " - https://leetcode.com/problems/two-sum/\n",
+ " - https://leetcode-cn.com/problems/two-sum/description/\n",
+ "\n",
+ "```\n",
+ "给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。\n",
+ "\n",
+ "你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。\n",
+ "\n",
+ "> 示例:\n",
+ "\n",
+ "给定 nums = [2, 7, 11, 15], target = 9\n",
+ "\n",
+ "因为 nums[0] + nums[1] = 2 + 7 = 9\n",
+ "所以返回 [0, 1]\n",
+ "```\n",
+ "\n",
+ "## 难度:Easy\n",
+ "\n",
+ "这个题目略微有点简单,我们只要注意的是,同样的元素不能被重复利用两次。\n",
+ "\n",
+ "还有就是思考,是不是我们可以使用一次循环就能够找到这两个数呢?\n",
+ "\n",
+ "接下来我们看一下如何解决这个问题。\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 简单判断一下,是否两个数都在 list 中,以及判断两个数不是重复利用一个元素即可。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[1, 2]\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def twoSum(self, nums, target):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :type target: int\n",
+ " :rtype: List[int]\n",
+ " \"\"\"\n",
+ " # 循环名为 nums 的 list\n",
+ " for num_one in nums:\n",
+ " # 判断 target 减去 num_one 是否仍在我们的 nums list 中,另一个条件是这两个数不是同一个元素\n",
+ " if target - num_one in nums and num_one is not target-num_one:\n",
+ " # 返回两个数对应的 index\n",
+ " return [nums.index(num_one), nums.index(target - num_one)]\n",
+ " \n",
+ "nums = [4, 3, 5, 15]\n",
+ "target = 8\n",
+ "s = Solution()\n",
+ "print(s.twoSum(nums, target))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ " - 其实我们上一个解决方案已经是弄的一个 for 循环了,这次我们换一个思路。\n",
+ " - 可以用 $O(n^2)$ 的循环(lookup)\n",
+ " - 其实也可以牺牲空间换取时间,异常聪明的 AC 解法\n",
+ " \n",
+ "```\n",
+ " 2 7 11 15\n",
+ " 不存在 存在之中 \n",
+ "lookup {2:0} [0, 1]\n",
+ "```\n",
+ "大体思路如下:\n",
+ "\n",
+ " - 建立字典 lookup 存放第一个数字,并存放该数字的 index\n",
+ " - 判断 lookup 中是否存在: target - 当前数字, 则表面 当前值和 lookup中的值加和为 target\n",
+ " - 如果存在,则返回: target - 当前数字 的 index 和 当前值的 index"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[1, 2]\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def twoSum(self, nums, target):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :type target: int\n",
+ " :rtype: List[int]\n",
+ " \"\"\"\n",
+ " # 创建 lookup 字典\n",
+ " lookup = {}\n",
+ " # 使用 enumerate 语法,返回的是每一个元素及其对应的 index\n",
+ " for i, num in enumerate(nums):\n",
+ " if target - num in lookup:\n",
+ " return [lookup[target - num],i]\n",
+ " lookup[num] = i\n",
+ " return []\n",
+ " \n",
+ "nums = [4, 3, 5, 15]\n",
+ "target = 8\n",
+ "s = Solution()\n",
+ "print(s.twoSum(nums, target))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 3\n",
+ "\n",
+ " - 对于 dict ,也就是其他语言的 map,判断一个元素在不在容器中,list 要遍历,而 set 和 dict 直接根据哈希算出,不需要遍历\n",
+ " - 我们可以仿照上面的代码,但是换个简单的写法。\n",
+ " - 对于字典的这种方式,如果我们只是判断 i 以及 target - i 是不是相等,这样是错误的,如果两个元素相同,但是不是同一个元素,那就会出错了。\n",
+ " \n",
+ "比如,我们先看一下错误的版本:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "None\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def twoSum(self, nums, target):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :type target: int\n",
+ " :rtype: List[int]\n",
+ " \"\"\"\n",
+ " dict1 = {}\n",
+ " for k, i in enumerate(nums):\n",
+ " dict1[i] = k\n",
+ " if target - i in dict1 and i is not target - i:\n",
+ " return [dict1[target - i], dict1[i]]\n",
+ "\n",
+ "nums = [3, 3]\n",
+ "target = 6\n",
+ "s = Solution()\n",
+ "print(s.twoSum(nums, target))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "上面的代码是存在问题的,对于相同的元素 [3, 3], target =6, 就得到了 None ,按理说,应该得到 [0, 1] 的。所以,这地方的判断是错误的。\n",
+ "\n",
+ " - 对于字典的那种方式,就只能索引为 key,数据为value,只是这样一来,判断在或者不在,还是多了一层循环\n",
+ " \n",
+ "下面的版本是正确的版本:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[0, 1]\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def twoSum(self, nums, target):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :type target: int\n",
+ " :rtype: List[int]\n",
+ " \"\"\"\n",
+ " for k, i in enumerate(nums):\n",
+ " if target - i in nums[k + 1:]:\n",
+ " return [k, nums[k + 1:].index(target - i) + k + 1]\n",
+ "\n",
+ "nums = [3, 3]\n",
+ "target = 6\n",
+ "s = Solution()\n",
+ "print(s.twoSum(nums, target)) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 小结\n",
+ "\n",
+ "应该还有更加好的解法,大佬们积极贡献自己的解法哈。一起为好的工作,好的未来,加油。"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/002._add_two_numbers.ipynb b/docs/Leetcode_Solutions/ipynb/002._add_two_numbers.ipynb
new file mode 100644
index 000000000..7971d4200
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/002._add_two_numbers.ipynb
@@ -0,0 +1,245 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 2.Add Two Numbers\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容:\n",
+ "\n",
+ "> 原题链接:\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/add-two-numbers/description/\n",
+ " - 英文:https://leetcode.com/problems/add-two-numbers/\n",
+ "\n",
+ "> 内容描述:\n",
+ "\n",
+ "给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。\n",
+ "\n",
+ "你可以假设除了数字 0 之外,这两个数字都不会以零开头。\n",
+ "\n",
+ "示例:\n",
+ "```\n",
+ "输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)\n",
+ "输出:7 -> 0 -> 8\n",
+ "原因:342 + 465 = 807\n",
+ "```\n",
+ "\n",
+ "## 解法方案\n",
+ "\n",
+ "由于两数相加可能会出现进位,所以加法我们谁都会算,但是要着重注意的一点是,要考虑上一位的进位,并且传递给下一位计算时的进位。\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "我们先构建一个空的头结点不动,然后尾结点从头结点开始向后不断生成新的结点。遍历两个链表的公共部分,每次相加相应位数字和进位,分配到结果的链表中。公共部分遍历完后再确定长的链表剩余的部分,同样的方式遍历完。\n",
+ "\n",
+ " - 需要注意的是遍历时每次都要更新进位,不断计算和时有没有发生进位,以防止之前数据的污染。\n",
+ " - 对于 python 来说,需要新的变量做游标来遍历两个链表,不能直接用形参,否则我们会修改原链表。\n",
+ " - 注意最后可能的进位。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "7\n",
+ "0\n",
+ "8\n",
+ "None\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Definition for singly-linked list.\n",
+ "class ListNode:\n",
+ " def __init__(self, x):\n",
+ " self.val = x\n",
+ " self.next = None\n",
+ "\n",
+ "class Solution: \n",
+ " def addTwoNumbers(self, l1, l2):\n",
+ " \"\"\"\n",
+ " :type l1: ListNode\n",
+ " :type l2: ListNode\n",
+ " :rtype: ListNode\n",
+ " \"\"\"\n",
+ " # 用 p1, p2 赋值为 l1 和 l2 ,以防止我们的操作改变原链表\n",
+ " p1, p2 = l1, l2\n",
+ " # 创建一个空链表用来返回结果,分别有头结点和尾结点\n",
+ " head = ListNode(0)\n",
+ " tail = head\n",
+ " # carry 表示进位值\n",
+ " carry = 0\n",
+ " # 处理两个链表的公共部分,也就是两个链表都不为空的部分\n",
+ " while p1 and p2:\n",
+ " # 计算当前位相加的和\n",
+ " num = p1.val + p2.val + carry\n",
+ " # 大于 9 ,应该向前进一位\n",
+ " if num > 9:\n",
+ " num -= 10\n",
+ " carry = 1\n",
+ " else:\n",
+ " carry = 0\n",
+ " # 添加结点\n",
+ " tail.next = ListNode(num)\n",
+ " # 尾结点向后移动\n",
+ " tail = tail.next\n",
+ " # 移动两条链表的公共部分\n",
+ " p1 = p1.next\n",
+ " p2 = p2.next\n",
+ " # 取长链表剩余的部分,也就是未参与上面计算的部分\n",
+ " if p2:\n",
+ " # 如果 p2 较长,将 p2 剩余的部分赋值给 p1 ,我们只需要处理 p1 就行了\n",
+ " p1 = p2\n",
+ " # 接下来,处理长链表剩余分部分\n",
+ " while p1:\n",
+ " # 最近的一位,我们要考虑一下,是否有进位\n",
+ " num = p1.val + carry\n",
+ " if num > 9:\n",
+ " num -= 10\n",
+ " carry = 1\n",
+ " else:\n",
+ " carry = 0\n",
+ " # 添加结点\n",
+ " tail.next = ListNode(num)\n",
+ " tail = tail.next\n",
+ " \n",
+ " # 移动我们处理的链表\n",
+ " p1 = p1.next\n",
+ " # 如果最后仍然有进位,我们需要再分配一个结点\n",
+ " if carry:\n",
+ " # 创建一个 val 为 1 的 ListNode 结点,然后将 tail 向后移动一位\n",
+ " tail.next = ListNode(1)\n",
+ " tail = tail.next\n",
+ " # 将所有的加和及进位都处理完成了,现在我们将链表收尾\n",
+ " tail.next = None\n",
+ " # 将 链表的头结点返回\n",
+ " return head.next # 去除掉我们初始化为 0 的头结点\n",
+ "\n",
+ "la = ListNode(2)\n",
+ "la.next = ListNode(4)\n",
+ "la.next.next = ListNode(3)\n",
+ "\n",
+ "lb = ListNode(5)\n",
+ "lb.next = ListNode(6)\n",
+ "lb.next.next = ListNode(4)\n",
+ "\n",
+ "s = Solution()\n",
+ "ss = s.addTwoNumbers(la, lb)\n",
+ "print(ss.val)\n",
+ "print(ss.next.val)\n",
+ "print(ss.next.next.val)\n",
+ "print(ss.next.next.next) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "因此,这个地方我们可以考虑使用递归来求解,具体可以分为以下情况:\n",
+ "\n",
+ " - 当两个链表均不为空时,计算两个节点值与上一位进位的和 sum,取 sum 的个位数构建新的节点,更新进位为 sum 的十位数,令本节点的 next 指针指向下一位求和返回的节点。\n",
+ " - 当两个链表其中一个为空时,计算不为空的节点值与上一位进位的和 sum,更新进位为 sum 的十位数。若进位不为 0 ,取 sum 的个位数构建新节点,令本节点的 next 指针指向下一位求和返回的节点,注意只传递不为空的链表;若进位为 0,则直接更新不为空节点的值为 sum,此时此链表之后的所有高位值都不会更新,因此返回此节点。\n",
+ " - 若两个链表都为空,判断进位是否为 0。若进位为 0,直接返回 NULL;否则构建值为进位值的新节点,并返回此节点。\n",
+ " \n",
+ "> 思路 2\n",
+ "\n",
+ " - 跟 plus One ,add Binary 玩的同一个花样,但是相对上个思路来说,更加简单和简洁。\n",
+ " - 使用递归调用简化算法"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "7\n",
+ "0\n",
+ "8\n",
+ "None\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Definition for singly-linked list.\n",
+ "class ListNode:\n",
+ " def __init__(self, x):\n",
+ " self.val = x\n",
+ " self.next = None\n",
+ "\n",
+ "class Solution(object):\n",
+ " def addTwoNumbers(self, l1, l2):\n",
+ " \"\"\"\n",
+ " :type l1: ListNode\n",
+ " :type l2: ListNode\n",
+ " :rtype: ListNode\n",
+ " \"\"\"\n",
+ " # 特殊情况\n",
+ " if l1 == None:\n",
+ " return l2\n",
+ " if l2 == None:\n",
+ " return l1\n",
+ " # 如果 相加 小于 10 ,不需要进位\n",
+ " if l1.val + l2.val < 10:\n",
+ " l3 = ListNode(l1.val + l2.val)\n",
+ " l3.next = self.addTwoNumbers(l1.next, l2.next)\n",
+ " # 相加大于等于 10,需要进位\n",
+ " elif l1.val + l2.val >= 10:\n",
+ " l3 = ListNode(l1.val + l2.val - 10)\n",
+ " tmp = ListNode(1)\n",
+ " tmp.next = None\n",
+ " # 递归调用\n",
+ " l3.next = self.addTwoNumbers(l1.next, self.addTwoNumbers(l2.next ,tmp))\n",
+ " return l3\n",
+ " \n",
+ "la = ListNode(2)\n",
+ "la.next = ListNode(4)\n",
+ "la.next.next = ListNode(3)\n",
+ "\n",
+ "lb = ListNode(5)\n",
+ "lb.next = ListNode(6)\n",
+ "lb.next.next = ListNode(4)\n",
+ "\n",
+ "s = Solution()\n",
+ "ss = s.addTwoNumbers(la, lb)\n",
+ "print(ss.val)\n",
+ "print(ss.next.val)\n",
+ "print(ss.next.next.val)\n",
+ "print(ss.next.next.next)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/005._longest_palindromic_substring.ipynb b/docs/Leetcode_Solutions/ipynb/005._longest_palindromic_substring.ipynb
new file mode 100644
index 000000000..f0a71c9d4
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/005._longest_palindromic_substring.ipynb
@@ -0,0 +1,388 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 005. Longest Palindromic Substring 最长回文子串\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/longest-palindromic-substring/description/\n",
+ " - 英文:https://leetcode.com/problems/longest-palindromic-substring/\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: \"babad\"\n",
+ "输出: \"bab\"\n",
+ "注意: \"aba\"也是一个有效答案。\n",
+ "\n",
+ "示例 2:\n",
+ "输入: \"cbbd\"\n",
+ "输出: \"bb\"\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "如果一个字符串从左向右写和从右向左写是一样的,这样我们就把它叫做回文字符串。如 aba 或者 abba。\n",
+ "\n",
+ "首先想到的是一个最笨的方法,就是依次把每一个字符当做回文字符串的中间的那个字符,向两边扩展,找到以该字符为中间字符的回文串的最大长度。但是这需要将回文串长度是奇偶的情况分开来讨论。然后接下来要注意的关键是对边界的把握,确保下标不要越界。当子串已经包含首字符或最后一个字符且此时还是回文串的时候,下标分别会向两边多移一位,需要补回来。\n",
+ "\n",
+ "以 abba 这样一个字符串为例来看,abba 中,一共有偶数个字,第 1 位=倒数第 1 位,第 2 位=倒数第 2 位......第 N 位=倒数第 N 位\n",
+ "\n",
+ "以 aba 这样一个字符串为例来看,aba 中,一共有奇数个字符,排除掉正中间的那个字符后,第 1 位=倒数第 1 位......第 N 位=倒数第 N 位\n",
+ "\n",
+ "所以,假设找到一个长度为 len1 的子串后,我们接下去测试它是否满足,第 1 位=倒数第 1 位,第 2 位=倒数第 2 位......第 N 位=倒数第 N 位,也就是说,去测试从头尾到中点,字符是否逐一对应相等。如果一直进行了 [length/2] 次后,对应字符都相等,即满足第 i 位=倒数第 i 位。那么这个子串必然是palindromic string。并且,很容易知道,无论这个字符串长度为奇数还是偶数,都是 palindromic string,因为奇数位数的字符串相当于满足,第中间位=第中间位。\n",
+ "\n",
+ "于是,现在问题转化为能不能找到一个子串,满足,第 1 位=倒数第 1 位(下文叫做候选子串)。如果有,就对剩下的字符做进一步的检查。\n",
+ "\n",
+ "我们看一下下面的代码:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cbc\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def longestPalindrome(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: str\n",
+ " \"\"\"\n",
+ " if not s:\n",
+ " return\n",
+ " n = len(s)\n",
+ " if n == 1:\n",
+ " return s\n",
+ " # Left index of the target substring\n",
+ " l = 0\n",
+ " # Right index of the target substring\n",
+ " r = 0\n",
+ " # Length of the longest palindromic substring for now \n",
+ " m = 0\n",
+ " # Length of the current substring\n",
+ " c = 0\n",
+ " # Whether the substring contains the first character or last character\n",
+ " # and is palindromic\n",
+ " b = True\n",
+ " # i 设置的是字符串的一个字符\n",
+ " for i in range(0, n):\n",
+ " # 奇数情况\n",
+ " # j 设置的是字符串的 i 字符的左右两边的 j 个字符是不是属于回文串,n-i 限制的是不能超出字符串末尾,i+1 限制的是不能越过字符串的开头\n",
+ " for j in range(0, min(n - i, i + 1)):\n",
+ " # 如果 以 i 字符为中央字符的情况,向两边扩展,不相等的话,代表不是回文串,停止继续比较\n",
+ " if (s[i - j] != s[i + j]):\n",
+ " b = False\n",
+ " break\n",
+ " else:\n",
+ " # 如果以 i 字符为中心字符向左右扩展 j 个字符是回文串,那么现在回文串的长度设置为 c\n",
+ " c = 2 * j + 1\n",
+ " # 判断 c 与 m 的大小,m 记录的是我们目前为止最长的回文串的长度,如果 c > m,那我们最长回文子串设置为 c ,否则仍然是原来的 m\n",
+ " if (c > m):\n",
+ " # 设置新的回文子串的左 index,b 是 True 就是等于 1,b 是 False 等于 0\n",
+ " l = i - j + 1 - b\n",
+ " # 设置新的回文子串的右 index\n",
+ " r = i + j + b\n",
+ " # 将新的最长回文子串赋值给 m\n",
+ " m = c\n",
+ " b = True\n",
+ " # 偶数情况\n",
+ " # i+1 限制的是不超越字符串的开头,n-i-1 限制的是不超过字符串末尾\n",
+ " for j in range(0, min(n - i - 1, i + 1)):\n",
+ " # 偶数情况下,对应位置上是够相等,相等则是回文串,不相等就不是回文串\n",
+ " if (s[i - j] != s[i + j + 1]):\n",
+ " b = False\n",
+ " break\n",
+ " else:\n",
+ " c = 2 * j + 2\n",
+ " if (c > m):\n",
+ " l = i - j + 1 - b\n",
+ " r = i + j + 1 + b\n",
+ " m = c\n",
+ " b = True\n",
+ " # 将最终的回文串返回\n",
+ " return s[l:r]\n",
+ " \n",
+ "s = Solution()\n",
+ "nums = \"acbcd\"\n",
+ "print(s.longestPalindrome(nums))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "上面是我们的一个参考版本,算是思路很清晰的。下面这个是 Lisanaaa 大佬根据上面版本进行修改的完成版本,总体思路是相同的,大家可以参考下。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cbc\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def longestPalindrome(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: str\n",
+ " \"\"\"\n",
+ " n = len(s)\n",
+ "\n",
+ " m,l,r = 0,0,0\n",
+ "\n",
+ " for i in range(n):\n",
+ " # odd case\n",
+ " for j in range(min(i+1,n-i)):\n",
+ " if s[i-j] != s[i+j]:\n",
+ " break\n",
+ " if 2*j + 1 > m :\n",
+ " m = 2 * j + 1\n",
+ " l = i-j\n",
+ " r = i+j\n",
+ "\n",
+ "\n",
+ " if i+1 < n and s[i] == s[i+1]:\n",
+ " for j in range(min(i+1,n-i-1)):\n",
+ " if s[i-j] != s[i+j+1]:\n",
+ " break\n",
+ " if 2 * j + 2 > m :\n",
+ " m = 2*j +2\n",
+ " l = i-j\n",
+ " r = i+j+1\n",
+ "\n",
+ "\n",
+ " return s[l:r+1]\n",
+ " \n",
+ "s = Solution()\n",
+ "nums = \"acbcd\"\n",
+ "print(s.longestPalindrome(nums))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ "很明显的一个动态规划思路。\n",
+ "\n",
+ " - 这个问题可以联想我们之前做的动态规划的问题,也就是 72 题,思想是一样的,但是相对于我们的 72 题来说,已经是相当简单了。\n",
+ " - 一个比较好的想法是 s 和 reverse(s) 共有的最长的 substring 就是 longest palindromic substring,这样我们就把问题转化为求 Longest common substring 问题了。\n",
+ " - 我们来看一下下面的代码,你就懂得了。\n",
+ " - 如果还是看不懂,那就去看看我们 72 题的讲解,已经很清楚了。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cbc\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution2(object):\n",
+ " def longestPalindrome(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: str\n",
+ " \"\"\"\n",
+ " def lcs(s1, s2):\n",
+ " m = [[0] * (1 + len(s2)) for i in range(1 + len(s1))]\n",
+ " longest, x_longest = 0, 0\n",
+ " for x in range(1, 1 + len(s1)):\n",
+ " for y in range(1, 1 + len(s2)):\n",
+ " if s1[x - 1] == s2[y - 1]:\n",
+ " m[x][y] = m[x - 1][y - 1] + 1\n",
+ " if m[x][y] > longest:\n",
+ " longest = m[x][y]\n",
+ " x_longest = x\n",
+ " else:\n",
+ " m[x][y] = 0\n",
+ " return s1[x_longest - longest: x_longest]\n",
+ "\n",
+ " return lcs(s, s[::-1])\n",
+ " \n",
+ "s_2 = Solution2()\n",
+ "nums = \"acbcd\"\n",
+ "print(s_2.longestPalindrome(nums))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "典型的动态规划问题。\n",
+ "\n",
+ "伪码如下:\n",
+ "\n",
+ "LCSuff(S1...p, T1...q) = LCS(S1...p1, T1...q-1) if S[p] = T[q] else 0\n",
+ "\n",
+ "代码可以参考:\n",
+ "\n",
+ "https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Longest_common_substring#Python_2\n",
+ "\n",
+ "**但是我们上面的动态规划问题,仍然出现了超时的情况。**\n",
+ "\n",
+ "因为我们以为这样s[::-1]已经很快了.\n",
+ "\n",
+ "**特别注意:**\n",
+ "\n",
+ "这个方法是buggy的,看字符串 abcxgcba ,它 reverse 之后是 abcgxcba ,它们有公共字符串,但是这里面没有回文,修复方式是:\n",
+ "\n",
+ "we check if the substring’s indices are the same as the reversed substring’s original indices. If it is, then we attempt to update the longest palindrome found so far; if not, we skip this and find the next candidate.\n",
+ "\n",
+ "我觉得的修复方式这样么:\n",
+ "\n",
+ "```\n",
+ "原本 翻转\n",
+ "ABXYBA ABYXBA\n",
+ "\n",
+ "求出来的substring indices是 0:2 但是这个s1[0:2] 和 s2[0:2]一样,所以不行\n",
+ "同理common substring indices还是s[4:6] 和s2[4:6]一样,不行\n",
+ "\n",
+ "而比如ABAD和 DABA\n",
+ "\n",
+ "substring indice 一个是0:3, 一个是1:4,这样就没问题\n",
+ "```\n",
+ "\n",
+ "> 思路 3\n",
+ "\n",
+ "[Manacher算法,我私下叫马拉车算法,哈哈](https://www.felix021.com/blog/read.php?2040)\n",
+ "\n",
+ "Manacher 算法增加两个辅助变量 id 和 mx ,其中 id 表示最大回文子串中心的位置,mx 则为 id+P[id] ,也就是最大回文子串的边界。得到一个很重要的结论:\n",
+ "\n",
+ " - 如果 mx > i,那么 P[i] >= Min(P[2 * id - i], mx - i) . 为什么这样说呢,下面解释\n",
+ "\n",
+ "下面,令 j = 2 * id - i ,也就是说 j 是 i 关于 id 的对称点。\n",
+ "\n",
+ " - 当 mx - i > P[j] 的时候,以 S[j] 为中心的回文子串包含在以 S[id] 为中心的回文子串中,由于 i 和 j 对称,以 S[i] 为中心的回文子串必然包含在以 S[id] 为中心的回文子串中,所以必有 P[i] = P[j] ; \n",
+ "\n",
+ " - 当 P[j] >= mx - i 的时候,以 S[j] 为中心的回文子串不一定完全包含于以 S[id] 为中心的回文子串中,但是基于对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以 S[i] 为中心的回文子串,其向右至少会扩张到 mx 的位置,也就是说 P[i] >= mx - i。至于 mx 之后的部分是否对称,再具体匹配。 所以 P[i] >= Min(P[2 * id - i], mx - i),因为以 j 为中心的绘回文子串的左边界可能会比 mx 关于 id 的对称点要大,此时只能证明 P[i]=P[2 * id - i]\n",
+ "\n",
+ " - 此外,对于 mx <= i 的情况,因为无法对 P[i] 做更多的假设,只能让 P[i] = 1,然后再去匹配。\n",
+ "\n",
+ "在下面的程序中我的 P 数组保存的是,以当前字符为回文子串中心时,该回文子串的长度(不包含当前字符自身)\n",
+ "\n",
+ "简单地用一个小例子来解释:原字符串为 'qacbcaw' ,一眼就可以看出来最大回文子串是 'acbca' , 下面是我做的图,累 shi 了!\n",
+ "\n",
+ "\n",
+ "\n",
+ "所以最终代码中的 max_i 就是字符 'b' 所对应的 index8 ,start 的值就是 (max_i - P[max_i] - 1) / 2 = 1 ,最终输出结果为 s[1:6] ,即‘acbca’"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cbc\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution3(object):\n",
+ " def longestPalindrome(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: str\n",
+ " \"\"\"\n",
+ " def preProcess(s):\n",
+ " if not s:\n",
+ " return ['^', '&']\n",
+ " T = ['^']\n",
+ " for i in s:\n",
+ " T += ['#', i]\n",
+ " T += ['#', '$']\n",
+ " return T\n",
+ " T = preProcess(s)\n",
+ " P = [0] * len(T)\n",
+ " id, mx = 0, 0\n",
+ " for i in range(1, len(T)-1):\n",
+ " j = 2 * id - i\n",
+ " if mx > i:\n",
+ " P[i] = min(P[j], mx-i)\n",
+ " else:\n",
+ " P[i]= 0\n",
+ " while T[i+P[i]+1] == T[i-P[i]-1]:\n",
+ " P[i] += 1\n",
+ " if i + P[i] > mx:\n",
+ " id, mx = i, i + P[i]\n",
+ " max_i = P.index(max(P)) #保存的是当前最大回文子串中心位置的index\n",
+ " start = int((max_i - P[max_i] - 1) / 2)\n",
+ " res = s[start: start + P[max_i]]\n",
+ " return res\n",
+ " \n",
+ "s_3 = Solution3()\n",
+ "nums = \"acbcd\"\n",
+ "print(s_3.longestPalindrome(nums)) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "run code的时候结果会跟expected不一样,但是该input确实2个结果都可以,所以放心地submit吧 还可以转到647题去看一看,也可以用这个算法解"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/007._Reverse_Integer.ipynb b/docs/Leetcode_Solutions/ipynb/007._Reverse_Integer.ipynb
new file mode 100644
index 000000000..d471473d6
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/007._Reverse_Integer.ipynb
@@ -0,0 +1,168 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 7. Reverse Integer 反转整数\n",
+ "\n",
+ "### 难度:Easy\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/reverse-integer/description/\n",
+ " - 英文:https://leetcode.com/problems/Reverse-Integer\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个 32 位有符号整数,将整数中的数字进行反转。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: 123\n",
+ "输出: 321\n",
+ "\n",
+ "示例 2:\n",
+ "输入: -123\n",
+ "输出: -321\n",
+ "\n",
+ "示例 3:\n",
+ "输入: 120\n",
+ "输出: 21\n",
+ "\n",
+ "注意:\n",
+ "假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。根据这个假设,如果反转后的整数溢出,则返回 0。\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - x > 0, flag = 1; x < 0, flag = -1\n",
+ " - 将 x 转成字符串 s = str(abs(x)),然后再反转字符串 s1 = s[::-1]\n",
+ " - 字符串再转为整数:x1 = int(s1) * flag\n",
+ " - 判断是否溢出,将数据返回"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "21\n",
+ "-654\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def reverse(self, x):\n",
+ " \"\"\"\n",
+ " :type x: int\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " # 如果是负数,我们需要注意转化为绝对值\n",
+ " flag = 1\n",
+ " x_1 = 0\n",
+ " if x < 0:\n",
+ " flag = -1\n",
+ " x = int(str(abs(x))[::-1])\n",
+ " x_1 = x * flag\n",
+ " else:\n",
+ " flag = 1\n",
+ " x = int(str(x)[::-1])\n",
+ " x_1 = x * flag\n",
+ " if x_1 > 2**31-1 or x_1 < -2**31:\n",
+ " return 0\n",
+ " else:\n",
+ " return x_1\n",
+ "\n",
+ "s = Solution()\n",
+ "x = 120\n",
+ "y = -456\n",
+ "print(s.reverse(x))\n",
+ "print(s.reverse(y))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ " - 按照低位摘除,在按高位加上去其实就可以了\n",
+ " - 利用循环,每次将最后一位取出来(求余),然后将原来的数据除以 10 ,取整,这样就可以每次都得到个位数\n",
+ " - 按照取第二步,反向操作,取出来一个最后的个位数,然后乘以 10 ,再加上每一次得到的个位数,就实现了反转\n",
+ " - 注意一个点,python 中对一个数求余时,结果与 求余 的符号相同,比如 5 % 2 = 1, 5 % (-2) = -1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "21\n",
+ "-654\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def reverse(self, x):\n",
+ " \"\"\"\n",
+ " :type x: int\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " num = 0\n",
+ " flag = 1\n",
+ " if x > 0:\n",
+ " flag = 1\n",
+ " else:\n",
+ " flag = -1\n",
+ " while x != 0:\n",
+ " num = num * 10 + x % (10 * flag)\n",
+ " x = int(x / 10)\n",
+ " if num > 2**31-1 or num < -2**31:\n",
+ " return 0\n",
+ " else:\n",
+ " return num\n",
+ "s = Solution()\n",
+ "x = 120\n",
+ "y = -456\n",
+ "print(s.reverse(x))\n",
+ "print(s.reverse(y))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/009._Palindrome_Number.ipynb b/docs/Leetcode_Solutions/ipynb/009._Palindrome_Number.ipynb
new file mode 100644
index 000000000..4a643d0f0
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/009._Palindrome_Number.ipynb
@@ -0,0 +1,165 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 9.Palindrome Number 回文数\n",
+ "\n",
+ "### 难度:Easy\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/palindrome-number/description\n",
+ " - 英文:https://leetcode.com/problems/palindrome-number\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。\n",
+ "\n",
+ "示例 1:\n",
+ "\n",
+ "输入: 121\n",
+ "输出: true\n",
+ "\n",
+ "示例 2:\n",
+ "\n",
+ "输入: -121\n",
+ "输出: false\n",
+ "解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。\n",
+ "\n",
+ "示例 3:\n",
+ "\n",
+ "输入: 10\n",
+ "输出: false\n",
+ "解释: 从右向左读, 为 01 。因此它不是一个回文数。\n",
+ "\n",
+ "进阶:\n",
+ "\n",
+ "你能不将整数转为字符串来解决这个问题吗?\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 首先负数肯定不是回文数\n",
+ " - 通过字符串进行反转,再转化为数字,对比数字是否相等就行"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def isPalindrome(self, x):\n",
+ " \"\"\"\n",
+ " :type x: int\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " # 如果是负数,肯定不是回文数,排除掉\n",
+ " if x < 0:\n",
+ " return False\n",
+ " # 我们将 数字转为 str ,然后反转,再转化为 int,比较,相等的话,就是回文数,不相等的话,就不是回文数\n",
+ " elif x != int(str(x)[::-1]):\n",
+ " return False\n",
+ " else:\n",
+ " return True\n",
+ " \n",
+ "s = Solution()\n",
+ "x = 2345\n",
+ "y = 121\n",
+ "print(s.isPalindrome(x))\n",
+ "print(s.isPalindrome(y))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ " - 负数一定不是回文数\n",
+ " - 如果一个数字是正数,并且能被我 0 整除那它肯定也不是 palidrome\n",
+ " - 这样我们就降低了复杂度"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def isPalindrome(self, x):\n",
+ " \"\"\"\n",
+ " :type x: int\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " # 处理特殊情况:\n",
+ " # 1、负数一定不是回文数\n",
+ " # 2、如果数字的最后一位是 0, 为了让数字是回文数字,则第一位数字也应该是 0,只有 0 满足这种情况\n",
+ " if x < 0 or (x % 10 == 0 and x is not 0):\n",
+ " return False\n",
+ " revertNumber = 0\n",
+ " while x > revertNumber:\n",
+ " revertNumber = revertNumber * 10 + x % 10\n",
+ " x /= 10\n",
+ " # 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。\n",
+ " # 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,\n",
+ " # 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。\n",
+ " return x == revertNumber or x == revertNumber/10\n",
+ "\n",
+ "s = Solution()\n",
+ "x = 2345\n",
+ "y = 121\n",
+ "print(s.isPalindrome(x))\n",
+ "print(s.isPalindrome(y))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/010._regular_expression_matching.ipynb b/docs/Leetcode_Solutions/ipynb/010._regular_expression_matching.ipynb
new file mode 100644
index 000000000..8a6af2b6e
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/010._regular_expression_matching.ipynb
@@ -0,0 +1,311 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 010. Regular Expression Matching 正则表达式匹配\n",
+ "\n",
+ "### 难度:Hard\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/two-sum/description\n",
+ " - 英文:https://leetcode.com/problems/two-sum\n",
+ "\n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。\n",
+ "\n",
+ "'.' 匹配任意单个字符。\n",
+ "'*' 匹配零个或多个前面的元素。\n",
+ "匹配应该覆盖整个字符串 (s) ,而不是部分字符串。\n",
+ "\n",
+ "说明:\n",
+ " - s 可能为空,且只包含从 a-z 的小写字母。\n",
+ " - p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。\n",
+ "\n",
+ "示例 1:\n",
+ "输入:\n",
+ "s = \"aa\"\n",
+ "p = \"a\"\n",
+ "输出: false\n",
+ "解释: \"a\" 无法匹配 \"aa\" 整个字符串。\n",
+ "\n",
+ "示例 2:\n",
+ "输入:\n",
+ "s = \"aa\"\n",
+ "p = \"a*\"\n",
+ "输出: true\n",
+ "解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 \"aa\"。\n",
+ "\n",
+ "示例 3:\n",
+ "输入:\n",
+ "s = \"ab\"\n",
+ "p = \".*\"\n",
+ "输出: true\n",
+ "解释: \".*\" 表示可匹配零个或多个('*')任意字符('.')。\n",
+ "\n",
+ "示例 4:\n",
+ "输入:\n",
+ "s = \"aab\"\n",
+ "p = \"c*a*b\"\n",
+ "输出: true\n",
+ "解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 \"aab\"。\n",
+ "\n",
+ "示例 5:\n",
+ "输入:\n",
+ "s = \"mississippi\"\n",
+ "p = \"mis*is*p*.\"\n",
+ "输出: false\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "暴力法。Lisanaaa 大佬想出来的,不得不赞一个,哈哈哈。之前想暴力法,把脑袋想爆掉了都没想全各种情况。那么,看看他是怎么解的吧。\n",
+ "\n",
+ "\".\" 很容易处理。难点就在 \"*\" 身上, \"*\" 是不会单独的,它一定是和前面的 一个字母或者 \".\" 配成一对 出现的。看成一对后是这样子的 \"X*\" ,它的性质是:要么匹配 0 个,要么匹配连续的 \"X\" 。所以尝试暴力法的时候一个 trick 是从后往前匹配。\n",
+ "\n",
+ "暴力解法也是可以 AC 的。\n",
+ "\n",
+ "下面这样来分情况:\n",
+ "\n",
+ " - 如果 s[i] = p[j] 或者 p[j]= . : 往前匹配一位\n",
+ " - 如果 p[j] = ' * ' , 检查一下,如果这个时候 p[j-1] = . 或者 p[j-1] = s[i] ,那么就往前匹配,如果这样能匹配过,就 return True , 否者我们忽略 'X* ' ,这里注意里面的递推关系。\n",
+ " - 再处理一下边界情况:\n",
+ " - s 已经匹配完了, 如果此时 p 还有,那么如果剩下的是 X* 这种可以过,所以需要检查一下\n",
+ " - p 匹配完毕,如果 s 还有没有匹配的话,那么就 return False"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def isMatch(self, s, p):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type p: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " def helper(s, i, p, j):\n",
+ " if j == -1:\n",
+ " return i == -1\n",
+ " if i == -1:\n",
+ " if p[j] != '*':\n",
+ " return False\n",
+ " return helper(s, i, p, j-2)\n",
+ " if p[j] == '*':\n",
+ " if p[j-1] == '.' or p[j-1] == s[i]:\n",
+ " if helper(s, i-1, p, j):\n",
+ " return True\n",
+ " return helper(s, i, p, j-2)\n",
+ " if p[j] == '.' or p[j] == s[i]:\n",
+ " return helper(s, i-1, p, j-1)\n",
+ " return False\n",
+ "\n",
+ " return helper(s, len(s)-1, p, len(p)-1)\n",
+ " \n",
+ "s = 'abc'\n",
+ "p = 'a*abc'\n",
+ "ss = Solution()\n",
+ "print(ss.isMatch(s, p))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ "动态规划 解法。\n",
+ "\n",
+ "dp 优化,感觉和 edit distance 很像。DP优化待代码化,感觉学DP的一个重点除了递归学好以外,另一点是一定要会画表格。\n",
+ "\n",
+ "画一个表格来看一下状况\n",
+ "\n",
+ "```\n",
+ "\t\t\tc\t*\ta\t*\tb\n",
+ "\t\t0\t1\t2\t3\t4\t5\n",
+ "\t0\t1\t0\t1\t0\t1\t0\t\t\n",
+ "a\t1\t0\t0\t0\t1\t1\t0\t\t\t\t\t\n",
+ "a\t2\t0\t0\t0\t0\t1\t0\t\t\t\t\t\n",
+ "b\t3\t0\t0\t0\t0\t0\t1\t\t\t\n",
+ "```\n",
+ "\n",
+ "这里有几个取巧/容易出问题的敌方,这里画的表用的是1-based string。一上来,做的事包括:\n",
+ "\n",
+ " - 初始化,空字符匹配:dp[0][0] =1\n",
+ " - 第一行, c * 可以匹配空字符, c * a * 可以匹配空字符, p[j-1] != s[i] ,匹配空字符\n",
+ " - 然后进入第二行再来看,实际上我们可以看到,如果没有碰到 * 匹配还是很朴素的,但是碰到 * :\n",
+ " - 1 这个匹配可以从左侧传来,dp[i][j] = dp[i][j-1] ,that is 匹配 1 个\n",
+ " - 1 也可以有上方传来,这种情况是 p[j-1] = s[i] ,匹配多个 dp[i][j] = dp[i-1][j]\n",
+ " - 1 这个匹配也可以从间隔一个的左侧传来,that is 也可以有个性的匹配 0 个,如同匹配空字符一样 dp[i][j] = dp[i][j-2] ,但是注意匹配 0 个实际上有两种状况,如果 p[j-1]!=s[i] ,强制匹配 0 个,即使 p[j-1] == s[i] ,我们也可以傲娇的用它来匹配 0 个。\n",
+ " \n",
+ "再代码化一点:\n",
+ "\n",
+ " - s[i] == p[j] 或者 p[j] == '.' : dp[i][j] = dp[i-1][j-1]\n",
+ " - p[j] == '*' : 然后分几种情况\n",
+ " - p[j-1] != s[i] : dp[i][j] = dp[i][j-2] 匹配 0 个的状况\n",
+ " - p[j-1] == s[i] or p[i-1] == '.':\n",
+ " - dp[i][j] = dp[i-1][j] 匹配多个 s[i]\n",
+ " - dp[i][j] = dp[i][j-2] 匹配 0 个\n",
+ "\n",
+ "AC 代码,注意一下,因为上表为了表达方便,用的是 1-based string 系统,实际写代码的时候我们心里还是清楚这个 string 还是从 0 开始的,不过也可以尝试往前面添东西来方便。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def isMatch(self, s, p):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type p: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " m, n = len(s), len(p)\n",
+ " dp = [ [0 for i in range(n+1)] for j in range(m+1)]\n",
+ "\n",
+ " dp[0][0] = 1\n",
+ "\n",
+ " # init the first line\n",
+ " for i in range(2,n+1):\n",
+ " if p[i-1] == '*':\n",
+ " dp[0][i] = dp[0][i-2]\n",
+ "\n",
+ " for i in range(1,m+1):\n",
+ " for j in range(1,n+1):\n",
+ " if p[j-1] == '*':\n",
+ " if p[j-2] != s[i-1] and p[j-2] != '.':\n",
+ " dp[i][j] = dp[i][j-2]\n",
+ " elif p[j-2] == s[i-1] or p[j-2] == '.':\n",
+ " dp[i][j] = dp[i-1][j] or dp[i][j-2]\n",
+ "\n",
+ " elif s[i-1] == p[j-1] or p[j-1] == '.':\n",
+ " dp[i][j] = dp[i-1][j-1]\n",
+ "\n",
+ " return dp[m][n] == 1 \n",
+ " \n",
+ "s = 'abc'\n",
+ "p = 'a*abc'\n",
+ "ss = Solution()\n",
+ "print(ss.isMatch(s, p))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "我做的动态规划和上面大体思路是类似的。\n",
+ "\n",
+ "直接说动态转移方程组了,我们首先定义一些变量方便解释,被匹配串为s,模式串为p。状态转移数组 dp[i][j]表示利用 p 的前 j 个字符匹配 s 的前 i 个字符的匹配结果(成功为 true,失败为 false)。\n",
+ "\n",
+ " - **s[i] == p[j] || p[j] == '.'** ,那么 dp[i][j] = dp[i-1][j-1] ,也就是既然 s 串的第 i 个字符能和 p 串的第 j 个字符匹配,那么如果 s 串的前 i-1 个字符和 p 串的前 j-1 个字符能匹配则 s 串的前 i 个和 p 串的前 j 个则能匹配,反之不能。\n",
+ " - **p[j] == '*'** :分情况讨论。\n",
+ " - **s[i] != p[j-1] && p[j-1] != '.'** ,那么 dp[i][j] = dp[i][j-2] ,也就是 * 号前面的那个字符在匹配的过程当中一个都不使用。\n",
+ " - **else,那么dp[i][j] = dp[i-1][j] || dp[i][j-1] || dp[i][j-2]**,也就是说要么使用 '*' 号进行匹配( dp[i-1][j] ),要么只使用 '*' 号前面的那个字符匹配,不使用 '*' 匹配( dp[i][j-1] ),要么 '*' 号前面的那个字符在匹配的过程当中一个都不使用( dp[i][j-2] ),只要有一个是 true 则能够匹配。\n",
+ " \n",
+ "最后考虑一下边界条件。一开始 i 是从 1 到 len(s) ,j 是 1 到 len(p) 。首先一来就能想到 dp[0][0] 是true,其他都是 false。但是这个边界条件是不够的。比如 isMatch(\"aab\", \"c * a * b\") ,dp[1][3] 应该是从 dp[0][2] 转移过来的,所以需要更多的边界条件,也就是一开始的 * 是能匹配空字符串的。所以我把 i 改到了从 0 开始,并且第二条也添加了 i=0,dp[i][j] = dp[i][j-2] 。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def isMatch(self, s, p):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type p: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " dp = []\n",
+ " dp = [[False for i in range(len(p)+1)] for j in range(len(s)+1)]\n",
+ " dp[0][0] = True\n",
+ "# print(dp)\n",
+ " for i in range(len(s)+1):\n",
+ " for j in range(1, len(p)+1):\n",
+ " if i > 0 and (s[i-1] == p[j-1] or p[j-1] == '.'):\n",
+ "# print(\"1111111\",i)\n",
+ "# print(\"2222222\",j)\n",
+ " dp[i][j] = dp[i-1][j-1]\n",
+ "# print(\"3333333\",dp[i-1][j-1])\n",
+ " if p[j-1] == '*':\n",
+ " if i == 0 or (s[i-1] != p[j-2] and p[j-2] != '.'):\n",
+ "# print(\"4444444\",i)\n",
+ "# print(\"5555555\",j)\n",
+ " dp[i][j] = dp[i][j-2]\n",
+ "# print(\"6666666\",dp[i][j-2])\n",
+ " else:\n",
+ " dp[i][j] = dp[i-1][j] or dp[i][j-1] or dp[i][j-2]\n",
+ "# print(\"7777777\",i)\n",
+ "# print(\"8888888\",j)\n",
+ "# print(dp) \n",
+ " return dp[len(s)][len(p)]\n",
+ " \n",
+ "s = 'aa'\n",
+ "p = 'a*'\n",
+ "ss = Solution()\n",
+ "print(ss.isMatch(s, p))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/013._Roman_to_Integer.ipynb b/docs/Leetcode_Solutions/ipynb/013._Roman_to_Integer.ipynb
new file mode 100644
index 000000000..8ac444f28
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/013._Roman_to_Integer.ipynb
@@ -0,0 +1,197 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 013.Roman to Integer\n",
+ "\n",
+ "### 难度:Easy\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 英文:https://leetcode.com/problems/roman-to-integer/\n",
+ " - 中文:https://leetcode-cn.com/problems/roman-to-integer/description/\n",
+ "\n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "罗马数字包含以下七种字符:I, V, X, L,C,D 和 M。\n",
+ "\n",
+ "字符 数值\n",
+ "I 1\n",
+ "V 5\n",
+ "X 10\n",
+ "L 50\n",
+ "C 100\n",
+ "D 500\n",
+ "M 1000\n",
+ "\n",
+ "例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。\n",
+ "\n",
+ "通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:\n",
+ "\n",
+ "I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。\n",
+ "X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 \n",
+ "C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。\n",
+ "\n",
+ "给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: \"III\"\n",
+ "输出: 3\n",
+ "\n",
+ "示例 2:\n",
+ "输入: \"IV\"\n",
+ "输出: 4\n",
+ "\n",
+ "示例 3:\n",
+ "输入: \"IX\"\n",
+ "输出: 9\n",
+ "\n",
+ "示例 4:\n",
+ "输入: \"LVIII\"\n",
+ "输出: 58\n",
+ "解释: C = 100, L = 50, XXX = 30, III = 3.\n",
+ "\n",
+ "示例 5:\n",
+ "输入: \"MCMXCIV\"\n",
+ "输出: 1994\n",
+ "解释: M = 1000, CM = 900, XC = 90, IV = 4.\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 从前向后依次扫描,用一个临时变量记录当前数字。\n",
+ " - 如果没有出现题目中出现的特殊情况,那我们就可以一直一个一个加下去,这样就能得到正确结果。\n",
+ " - 特殊情况出现的时候,后一位数字比前一位数字大,而正常情况正好是相反的(后一位数字一定比前一位小),后一位减去前一位即可得到这两位得到的数值,但是要注意一点,我们在这之前已经将前一位进行加和了一次,所以这时候,我们要减去 2 次前一位数字。\n",
+ " - 其他地方没有太难的部分,以下是 AC 代码。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1994\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def romanToInt(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " lookup = {\n",
+ " 'M': 1000,\n",
+ " 'D': 500,\n",
+ " 'C': 100,\n",
+ " 'L': 50,\n",
+ " 'X': 10,\n",
+ " 'V': 5,\n",
+ " 'I': 1\n",
+ " }\n",
+ " res = 0\n",
+ " for i in range(len(s)):\n",
+ " if i > 0 and lookup[s[i]] > lookup[s[i-1]]:\n",
+ " res = res + lookup[s[i]] - 2 * lookup[s[i-1]]\n",
+ " else:\n",
+ " res += lookup[s[i]]\n",
+ " return res\n",
+ " \n",
+ "s = Solution()\n",
+ "string = \"MCMXCIV\"\n",
+ "print(s.romanToInt(string))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "可以修改一下的地方,我们可以将从字典中取数的逻辑封装到一个函数中,这样也比较优雅。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1994\n"
+ ]
+ }
+ ],
+ "source": [
+ "def getNum(x):\n",
+ " return {\"I\":1,\n",
+ " \"V\":5,\n",
+ " \"X\":10,\n",
+ " \"L\":50,\n",
+ " \"C\":100,\n",
+ " \"D\":500,\n",
+ " \"M\":1000}.get(x)\n",
+ "\n",
+ "class Solution: \n",
+ " def romanToInt(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " Num = {\n",
+ " 'M': 1000,\n",
+ " 'D': 500,\n",
+ " 'C': 100,\n",
+ " 'L': 50,\n",
+ " 'X': 10,\n",
+ " 'V': 5,\n",
+ " 'I': 1\n",
+ " }\n",
+ " result = 0\n",
+ " for i in range(len(s)):\n",
+ " if i > 0 and Num[s[i]] > Num[s[i-1]]:\n",
+ " result = result + Num[s[i]] - 2 * Num[s[i-1]]\n",
+ " else:\n",
+ " result += Num[s[i]]\n",
+ " return result\n",
+ " \n",
+ "s = Solution()\n",
+ "string = \"MCMXCIV\"\n",
+ "print(s.romanToInt(string))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/020._valid_parentheses.ipynb b/docs/Leetcode_Solutions/ipynb/020._valid_parentheses.ipynb
new file mode 100644
index 000000000..f665733dc
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/020._valid_parentheses.ipynb
@@ -0,0 +1,302 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 20. Valid Parentheses 有效的括号\n",
+ "\n",
+ "### 难度:Easy\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/valid-parentheses/description\n",
+ " - 英文:https://leetcode.com/problems/valid-parentheses\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。\n",
+ "\n",
+ "有效字符串需满足:\n",
+ "\n",
+ "1、左括号必须用相同类型的右括号闭合。\n",
+ "2、左括号必须以正确的顺序闭合。\n",
+ "\n",
+ "注意空字符串可被认为是有效字符串。\n",
+ "\n",
+ "示例1:\n",
+ "输入: \"()\"\n",
+ "输出: true\n",
+ "\n",
+ "示例2:\n",
+ "输入: \"()[]{}\"\n",
+ "输出: true\n",
+ "\n",
+ "示例3:\n",
+ "输入: \"(]\"\n",
+ "输出: false\n",
+ "\n",
+ "示例4:\n",
+ "输入: \"([)]\"\n",
+ "输出: false\n",
+ "\n",
+ "示例5:\n",
+ "输入: \"{[]}\"\n",
+ "输出: true\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "我们只需要匹配三种情况: \"(\" -> \")\", \"[\" -> \"]\", \"{\" -> \"}\".\n",
+ "\n",
+ "但是这里最重要的思想是 栈 。一遇到左括号就入栈,右括号出栈,这样来寻找对应。\n",
+ "\n",
+ "需要检查几件事:\n",
+ "\n",
+ " - 出现右括号时 stack 里是否还有符号(无论左右)\n",
+ " - 出 stack 时是否对应\n",
+ " - 最终 stack 是否为空"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def isValid(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " LEFT = {'(', '[', '{'} # 左括号\n",
+ " RIGHT = {')', ']', '}'} # 右括号\n",
+ " stack = [] # 创建一个栈\n",
+ " for brackets in s: # 迭代传过来的所有字符串\n",
+ " if brackets in LEFT: # 如果当前字符在左括号内\n",
+ " stack.append(brackets) # 把当前左括号入栈\n",
+ " elif brackets in RIGHT: # 如果是右括号\n",
+ " if not stack or not 1 <= ord(brackets) - ord(stack[-1]) <= 2:\n",
+ " # 如果当前栈为空,()]\n",
+ " # 如果右括号减去左括号的值不是小于等于2大于等于1\n",
+ " return False # 返回False\n",
+ " stack.pop() # 删除左括号\n",
+ " return not stack # 如果栈内没有值则返回True,否则返回False\n",
+ " \n",
+ "s = Solution()\n",
+ "print(s.isValid(\"([[])[]{}\"))\n",
+ "print(s.isValid(\"([])[]{}\"))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "与 思路 1 相同,但是更加容易理解的版本:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def isValid(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " leftP = '([{'\n",
+ " rightP = ')]}'\n",
+ " stack = []\n",
+ " for char in s:\n",
+ " if char in leftP:\n",
+ " stack.append(char)\n",
+ " if char in rightP:\n",
+ " if not stack:\n",
+ " return False\n",
+ " tmp = stack.pop()\n",
+ " if char == ')' and tmp != '(':\n",
+ " return False\n",
+ " if char == ']' and tmp != '[':\n",
+ " return False \n",
+ " if char == '}' and tmp != '{':\n",
+ " return False\n",
+ " return stack == []\n",
+ " \n",
+ "s = Solution()\n",
+ "print(s.isValid(\"([[])[]{}\"))\n",
+ "print(s.isValid(\"([])[]{}\"))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ " - 扩展性和可理解性更强\n",
+ " - 使用字典类型来存储对应关系"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def isValid(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " if len(s) % 2 == 1:\n",
+ " return False\n",
+ "\n",
+ " index = 0\n",
+ " stack = [i for i in s]\n",
+ " map1 = {\"(\": \")\", \"[\": \"]\", \"{\": \"}\"}\n",
+ "\n",
+ " while len(stack) > 0:\n",
+ " # 判断索引是否超过边界\n",
+ " if index >= len(stack)-1:\n",
+ " return False\n",
+ " \n",
+ " b = stack[index]\n",
+ " e = stack[index+1]\n",
+ "\n",
+ " if b not in map1.keys():\n",
+ " return False\n",
+ " elif e in map1.keys():\n",
+ " index += 1\n",
+ " elif map1[b] == e:\n",
+ " stack.pop(index+1)\n",
+ " stack.pop(index)\n",
+ " index = 0 if index-1<0 else index-1\n",
+ " else:\n",
+ " return False\n",
+ "\n",
+ " return stack == []\n",
+ " \n",
+ "s = Solution()\n",
+ "print(s.isValid(\"([[])[]{}\"))\n",
+ "print(s.isValid(\"([])[]{}\"))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 3\n",
+ "\n",
+ " - 括号匹配,我们可以换用另一种方式\n",
+ " - 首先,不管它是否符合第一个符号是左括号的要求,我们先把它放到list 中,作为栈,然后一个一个遍历,符合配对顺序就弹出,最终只需要判断是否栈为空就可以了"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "l_d = {\n",
+ " '{': -3,\n",
+ " '(': -2,\n",
+ " '[': -1,\n",
+ " ']': 1,\n",
+ " ')': 2,\n",
+ " '}': 3,\n",
+ "}\n",
+ " \n",
+ "class Solution:\n",
+ " def isValid(self, s):\n",
+ " l_s = []\n",
+ " for c_r in s:\n",
+ " if len(l_s) == 0:\n",
+ " l_s.append(c_r)\n",
+ " continue\n",
+ "\n",
+ " c_l = l_s[-1]\n",
+ "\n",
+ " if l_d[c_l] + l_d[c_r] == 0 and l_d[c_l] < 0:\n",
+ " l_s.pop()\n",
+ " else:\n",
+ " l_s.append(c_r)\n",
+ "\n",
+ " if len(l_s) == 0:\n",
+ " return True\n",
+ " else:\n",
+ " return False\n",
+ " \n",
+ "s = Solution()\n",
+ "print(s.isValid(\"([[])[]{}\"))\n",
+ "print(s.isValid(\"([])[]{}\"))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/032._longest_valid_parentheses.ipynb b/docs/Leetcode_Solutions/ipynb/032._longest_valid_parentheses.ipynb
new file mode 100644
index 000000000..56e88640c
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/032._longest_valid_parentheses.ipynb
@@ -0,0 +1,180 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "collapsed": true
+ },
+ "source": [
+ "# 032.longest-valid-parentheses 最长有效括号\n",
+ "\n",
+ "### 难度:Easy\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/longest-valid-parentheses/description\n",
+ " - 英文:https://leetcode.com/problems/longest-valid-parentheses\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: \"(()\"\n",
+ "输出: 2\n",
+ "解释: 最长有效括号子串为 \"()\"\n",
+ "\n",
+ "示例 2:\n",
+ "输入: \")()())\"\n",
+ "输出: 4\n",
+ "解释: 最长有效括号子串为 \"()()\"\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "**注:** 千万注意,这个题上来就坑了一下,题目没有说清楚一种情况,比如 (()) ,这种情况,有效括号子串是 4 ,而不是错误的。\n",
+ "\n",
+ "实际上,在看到这个最长有效括号的题目的时候,我就想到了之前我们做的一个题目。LeetCode 20 题,它的解法是如何使用堆栈判断括号序列是否可以成功配对。我们仍然可以将堆栈的思想延续到这里。\n",
+ "\n",
+ "每当遇到一个左括号或者是无法成对的右括号,就将它压入栈中,可以成对的括号则从栈中 pop 出。这样栈中剩下的就是无法成对的括号的下标。这时我们可以判断这些下标间的距离来获得最大的成对括号长度。 **在这里,我们需要先遍历一遍字符串,再遍历一下非空的堆栈。一定要注意,这里我们遍历的非空的栈存储的是没有匹配上的括号下标,匹配上的我们都已经做了pop 处理。**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "6\n",
+ "4\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def longestValidParentheses(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " # 创建一个 stack ,用来做 栈 的操作\n",
+ " stack = []\n",
+ " # 第一次遍历 s 字符串\n",
+ " for i in range(len(s)):\n",
+ " # 如果当前循环到的 字符 是 右括号,那就要 检查一下栈内是否有与之匹配的 左括号\n",
+ " if s[i] == ')':\n",
+ " # stack 如果不为空,并且 stack 的栈顶元素存储的下标在 s 字符串中是 左括号\n",
+ " if stack and s[stack[-1]] == '(':\n",
+ " # 将栈顶元素 pop 出来,与当前的 右括号 配对\n",
+ " stack.pop()\n",
+ " # 直接 continue\n",
+ " continue\n",
+ " stack.append(i)\n",
+ " # 设置 最大长度\n",
+ " max_length = 0\n",
+ " # 设置为当前字符串 s 的长度\n",
+ " next_index = len(s)\n",
+ " # 遍历 非空的栈\n",
+ " while stack:\n",
+ " # 当前的栈顶存储的 s 的下标\n",
+ " cur_index = stack.pop()\n",
+ " # 计算下一个有效的最长括号长度\n",
+ " cur_length = next_index - cur_index - 1\n",
+ " # 将之与 之前存储的 max_length 比较,留下较大值\n",
+ " max_length = max(cur_length, max_length)\n",
+ " # 下一个的有效括号的右索引赋值,接着进入下一次循环,一直到 stack 为空\n",
+ " next_index = cur_index\n",
+ " # 遍历到最后的时候,肯定 next_index 即是有效符号的长度,与 max_length 做比较,取较大值\n",
+ " return max(next_index, max_length)\n",
+ " \n",
+ " \n",
+ "s = Solution()\n",
+ "print(s.longestValidParentheses(\"()(())\"))\n",
+ "print(s.longestValidParentheses(\"()()(()\"))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ "使用动态规划(dynamic programming)思想来做这个问题。\n",
+ "\n",
+ "下面是 片刻 大佬想出来的,我感觉思想真的超棒。参考链接:http://www.cnblogs.com/George1994/p/7531574.html\n",
+ "\n",
+ "1. 用一个 dp 数组来存放以每个 index 为结尾的最长有效括号子串长度,例如:dp[3] = 2 代表以 index 为 3 结尾的最长有效括号子串长度为 2\n",
+ "2. 很明显,dp[i] 和 dp[i-1] 之间是有关系的。\n",
+ " - 当 dp[i] 所在的索引 i 在字符串 s 中代表的字符是 \"(\" 时,也就是 s[i] == '(' ,很显然,此时的 dp[i] 与之前的一个关系是 dp[i] = dp[i-1] + 0,也就是不用处理。\n",
+ " - 当 dp[i] 所在的索引 i 在字符串 s 中代表的字符是 \")\" 时,也就是 s[i] == ')' 时,如果在 dp[i-1] 的所表示的最长有效括号子串之前还有一个 '(' 与 s[i] 对应,那么 dp[i] = dp[i-1] + 2,并且还可以继续往前追溯(如果前面还能连接起来的话)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "6\n",
+ "4\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def longestValidParentheses(self, s):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " if len(s) == 0:\n",
+ " return 0\n",
+ " dp = [0 for i in range(len(s))]\n",
+ " for i in range(1, len(s)):\n",
+ " if s[i] == ')':\n",
+ " left = i - 1 - dp[i-1]\n",
+ " if left >= 0 and s[left] == '(':\n",
+ " dp[i] = dp[i-1] + 2\n",
+ " if left > 0: # 这个是判断 left 前面是否能与后面继续连起来\n",
+ " dp[i] += dp[left-1]\n",
+ " return max(dp)\n",
+ "\n",
+ "s = Solution()\n",
+ "print(s.longestValidParentheses(\"()(())\"))\n",
+ "print(s.longestValidParentheses(\"()()(()\"))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/053._maximum_subarray.ipynb b/docs/Leetcode_Solutions/ipynb/053._maximum_subarray.ipynb
new file mode 100644
index 000000000..1bbb8ab21
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/053._maximum_subarray.ipynb
@@ -0,0 +1,275 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 53. Maximum Subarray 最大子序和\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/maximum-subarray/description/\n",
+ " - 英文:https://leetcode.com/problems/maximum-subarray/\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。\n",
+ "\n",
+ "示例:\n",
+ "\n",
+ "输入: [-2,1,-3,4,-1,2,1,-5,4],\n",
+ "输出: 6\n",
+ "解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。\n",
+ "\n",
+ "进阶:\n",
+ "如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 可以用 O(N^2) 循环\n",
+ " - 从i开始,计算i到n,存比较大的sum\n",
+ " - 会超时,不会 AC"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "6\n",
+ "1\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def maxSubArray(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " # 设置为无穷小\n",
+ " ans = float('-inf')\n",
+ " # 这个循环控制子串的元素个数\n",
+ " for i in range(1, len(nums)):\n",
+ " # 这个循环控制子串从原始串的哪个位置开始计算\n",
+ " for j in range(len(nums)-i):\n",
+ " big = 0\n",
+ " big = sum(nums[j : j+i])\n",
+ " if big > ans:\n",
+ " ans = big\n",
+ " return ans\n",
+ "\n",
+ "s = Solution()\n",
+ "nums_1 = [-2,1,-3,4,-1,2,1,-5,4]\n",
+ "nums_2 = [1, -1]\n",
+ "print(s.maxSubArray(nums_1))\n",
+ "print(s.maxSubArray(nums_2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ " - 使用动态规划\n",
+ " - ms(i) = max(ms[i-1] + a[i], a[i])\n",
+ " - 我们只需要知道,计算到 i 处的最大值的两种可能,一个是加上 a[i],另一个是从 a[i] 开始重新计算子串。\n",
+ " - 比较 ms[i-1]+a[i] 与 a[i] 的值的大小关系,如果前者小于后者,就说明,前面的子串的最大的和是负数,我们可以抛弃掉,而从 a[i] 处开始起头重新计算子串;如果前者大于后者,说明,前面的子串的最大的和是正数,我们可以加上 a[i] 继续计算。\n",
+ " - 可以 AC"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "6\n",
+ "1\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def maxSubArray(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " n = len(nums)\n",
+ " maxSum = [nums[0] for i in range(n)]\n",
+ " for i in range(1,n):\n",
+ " \tmaxSum[i] = max(maxSum[i-1] + nums[i], nums[i])\n",
+ " return max(maxSum)\n",
+ " \n",
+ "s = Solution()\n",
+ "nums_1 = [-2,1,-3,4,-1,2,1,-5,4]\n",
+ "nums_2 = [1, -1]\n",
+ "print(s.maxSubArray(nums_1))\n",
+ "print(s.maxSubArray(nums_2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 3\n",
+ "\n",
+ "Kadane’s Algorithm wikipedia可以查到,然后一般的是负的可以还回0,这里需要稍作修改,参考:\n",
+ "http://algorithms.tutorialhorizon.com/kadanes-algorithm-maximum-subarray-problem/\n",
+ "\n",
+ "```\n",
+ "start:\n",
+ " max_so_far = a[0]\n",
+ " max_ending_here = a[0]\n",
+ "\n",
+ "loop i= 1 to n\n",
+ " (i) max_end_here = Max(arrA[i], max_end_here+a[i]);\n",
+ " (ii) max_so_far = Max(max_so_far,max_end_here);\n",
+ "\n",
+ "return max_so_far\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "AC 代码如下:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "6\n",
+ "1\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def maxSubArray(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " n = len(nums)\n",
+ " maxSum , maxEnd = nums[0], nums[0]\n",
+ " \n",
+ " for i in range(1,n):\n",
+ " maxEnd = max(nums[i],maxEnd + nums[i])\n",
+ " maxSum = max(maxEnd,maxSum)\n",
+ " return maxSum\n",
+ " \n",
+ "s = Solution()\n",
+ "nums_1 = [-2,1,-3,4,-1,2,1,-5,4]\n",
+ "nums_2 = [1, -1]\n",
+ "print(s.maxSubArray(nums_1))\n",
+ "print(s.maxSubArray(nums_2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 4\n",
+ "\n",
+ "参见clrs 第71页,用divide and conquer,有伪码\n",
+ "\n",
+ "最大的 subarray sum 有三个可能,左半段或者右半段,或者跨越左右半段,\n",
+ "\n",
+ "速度比较慢,AC代码,复杂度O(NlogN)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "class Solution(object):\n",
+ " def maxSubArray(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " def find_max_crossing_subarray(nums, low, mid, high):\n",
+ " left_sum = float('-inf')\n",
+ " sum = 0\n",
+ " for i in xrange(mid,low-1,-1):\n",
+ " sum = sum + nums[i]\n",
+ " if sum > left_sum:\n",
+ " left_sum = sum\n",
+ "\n",
+ " right_sum = float('-inf')\n",
+ " sum = 0\n",
+ " for j in range(mid+1,high+1):\n",
+ " sum = sum + nums[j]\n",
+ " if sum > right_sum:\n",
+ " right_sum = sum\n",
+ "\n",
+ " return left_sum + right_sum\n",
+ "\n",
+ " def find_max_subarray(nums,low,high):\n",
+ " if low == high: \n",
+ " return nums[low]\n",
+ " else:\n",
+ " mid = (low + high) / 2\n",
+ " left_sum = find_max_subarray(nums, low, mid)\n",
+ " right_sum = find_max_subarray(nums,mid+1,high)\n",
+ " cross_sum = find_max_crossing_subarray(nums,low,mid,high)\n",
+ " # print left_sum, right_sum, cross_sum\n",
+ " # print mid, low, high\n",
+ " return max(left_sum, right_sum, cross_sum)\n",
+ "\n",
+ " return find_max_subarray(nums, 0, len(nums)-1)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/062._unique_paths.ipynb b/docs/Leetcode_Solutions/ipynb/062._unique_paths.ipynb
new file mode 100644
index 000000000..372560e09
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/062._unique_paths.ipynb
@@ -0,0 +1,167 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 062.unique_paths 不同路径\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/unique-paths/description\n",
+ " - 英文:https://leetcode.com/problems/unique-paths\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。\n",
+ "\n",
+ "机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。\n",
+ "\n",
+ "问总共有多少条不同的路径?\n",
+ "\n",
+ "说明:m 和 n 的值均不超过 100。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: m = 3, n = 2\n",
+ "输出: 3\n",
+ "解释:\n",
+ "从左上角开始,总共有 3 条路径可以到达右下角。\n",
+ "1. 向右 -> 向右 -> 向下\n",
+ "2. 向右 -> 向下 -> 向右\n",
+ "3. 向下 -> 向右 -> 向右\n",
+ "\n",
+ "示例 2:\n",
+ "输入: m = 7, n = 3\n",
+ "输出: 28\n",
+ "\n",
+ "例如,下图是一个3 x 7 的网格。有多少可能的路径?\n",
+ "```\n",
+ "\n",
+ "\n",
+ "\n",
+ "## 解决方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "数学思路。\n",
+ "\n",
+ "本质上,这道题就是排列组合,一共走 m + n - 步,其中 m - 1 步是向右边走,所以不就是从 m + n - 2 中选择 m-1 个的问题,阶乘问题,so easy !妈妈再也不用担心我的学习!!!这个方法 beats 99.97% 。\n",
+ "\n",
+ "补充一下,math 模块中自带 factorial 函数,只要 import math 之后调用即可。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "28.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def uniquePaths(self, m, n):\n",
+ " \"\"\"\n",
+ " :type m: int\n",
+ " :type n: int\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " def factorial(num):\n",
+ " res = 1\n",
+ " for i in range(1, num+1):\n",
+ " res *= i\n",
+ " return res\n",
+ " return factorial(m+n-2)/factorial(n-1)/factorial(m-1)\n",
+ " \n",
+ "s = Solution()\n",
+ "print(s.uniquePaths(7,3))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "collapsed": true
+ },
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ "片刻大佬 想到的这个思想,真的棒!\n",
+ "\n",
+ "| | | |\n",
+ "| - | - | - |\n",
+ "| 1 | 1 | 1 |\n",
+ "| 1 | 2 | 3 |\n",
+ "| 1 | 3 | 6 |\n",
+ "| 1 | 4 | 10 |\n",
+ "| 1 | 5 | 15 |\n",
+ "| 1 | 6 | 21 |\n",
+ "| 1 | 7 | 28 |"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "28\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def uniquePaths(self, m, n):\n",
+ " \"\"\"\n",
+ " :type m: int\n",
+ " :type n: int\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " if m < 1 or n < 1:\n",
+ " return 0\n",
+ " dp = [0] *n\n",
+ " dp[0] = 1 \n",
+ " for i in range(0,m):\n",
+ " for j in range(1,n):\n",
+ " dp[j] += dp[j-1]\n",
+ " return dp[n-1]\n",
+ " \n",
+ "s = Solution()\n",
+ "print(s.uniquePaths(7,3))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/064._minimum_path_sum.ipynb b/docs/Leetcode_Solutions/ipynb/064._minimum_path_sum.ipynb
new file mode 100644
index 000000000..2844c4953
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/064._minimum_path_sum.ipynb
@@ -0,0 +1,160 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 064. Minimum Path Sum 最小路径和\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/minimum-path-sum/description\n",
+ " - 英文:https://leetcode.com/problems/minimum-path-sum\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。\n",
+ "\n",
+ "说明:每次只能向下或者向右移动一步。\n",
+ "\n",
+ "示例:\n",
+ "\n",
+ "输入:\n",
+ "[\n",
+ " [1,3,1],\n",
+ " [1,5,1],\n",
+ " [4,2,1]\n",
+ "]\n",
+ "输出: 7\n",
+ "解释: 因为路径 1→3→1→1→1 的总和最小。\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "使用 动态规划 ,我们考虑到,一个位于 [i][j] 位置的格子,到达它的路径只有 2 条:1 条是从上到下到达这个格子([i-1][j] -> [i][j]),另一条是从左到右到达这个格子([i][j-1] -> [i][j])。我们只需要关注这两条路径中,哪条路径的路径和最小就好了。 另外可以参考 072.编辑距离 。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "7\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def minPathSum(self, grid):\n",
+ " \"\"\"\n",
+ " :type grid: List[List[int]]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " m = len(grid)\n",
+ " n = len(grid[0])\n",
+ " dp = grid.copy()\n",
+ " for i in range(1, n):\n",
+ " dp[0][i] = dp[0][i-1] + grid[0][i]\n",
+ " for i in range(1, m):\n",
+ " dp[i][0] = dp[i-1][0] + grid[i][0]\n",
+ " for i in range(1, m):\n",
+ " for j in range(1, n):\n",
+ " dp[i][j] = min(dp[i][j-1] + grid[i][j], dp[i-1][j] + grid[i][j])\n",
+ " return dp[m-1][n-1]\n",
+ " \n",
+ "s = Solution()\n",
+ "grid = [\n",
+ " [1,3,1],\n",
+ " [1,5,1],\n",
+ " [4,2,1]\n",
+ "]\n",
+ "print(s.minPathSum(grid))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "上面的版本是我最初写成的,后来听大佬们说,尽量减少 for 循环的个数。改成下面的最终版本,已经 AC 。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "7\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def minPathSum(self, grid):\n",
+ " \"\"\"\n",
+ " :type grid: List[List[int]]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " if not grid or len(grid) == 0:\n",
+ " return 0\n",
+ " row = len(grid)\n",
+ " col = len(grid[0]) if row else 0\n",
+ " dp = [[0 for j in range(col)] for i in range(row)]\n",
+ " for i in range(row):\n",
+ " for j in range(col):\n",
+ " if i > 0 and j > 0:\n",
+ " dp[i][j] = min(dp[i-1][j]+grid[i][j], dp[i][j-1]+grid[i][j])\n",
+ " elif i > 0 and j == 0:\n",
+ " dp[i][j] = sum([grid[k][0] for k in range(i+1)])\n",
+ " elif i == 0 and j > 0:\n",
+ " dp[i][j] = sum([grid[0][k] for k in range(j+1)])\n",
+ " else:\n",
+ " dp[i][j] = grid[0][0]\n",
+ " return dp[-1][-1]\n",
+ " \n",
+ "s = Solution()\n",
+ "grid = [\n",
+ " [1,3,1],\n",
+ " [1,5,1],\n",
+ " [4,2,1]\n",
+ "]\n",
+ "print(s.minPathSum(grid))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/072._edit_distance.ipynb b/docs/Leetcode_Solutions/ipynb/072._edit_distance.ipynb
new file mode 100644
index 000000000..9c8a9d1c8
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/072._edit_distance.ipynb
@@ -0,0 +1,211 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 072. Edit Distance 编辑距离\n",
+ "\n",
+ "### 难度:Hard\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/edit-distance/description/\n",
+ " - 英文:https://leetcode.com/problems/edit-distance/\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。\n",
+ "\n",
+ "你可以对一个单词进行如下三种操作:\n",
+ "\n",
+ "插入一个字符\n",
+ "删除一个字符\n",
+ "替换一个字符\n",
+ "\n",
+ "示例 1:\n",
+ "输入: word1 = \"horse\", word2 = \"ros\"\n",
+ "输出: 3\n",
+ "解释: \n",
+ "horse -> rorse (将 'h' 替换为 'r')\n",
+ "rorse -> rose (删除 'r')\n",
+ "rose -> ros (删除 'e')\n",
+ "\n",
+ "示例 2:\n",
+ "输入: word1 = \"intention\", word2 = \"execution\"\n",
+ "输出: 5\n",
+ "解释: \n",
+ "intention -> inention (删除 't')\n",
+ "inention -> enention (将 'i' 替换为 'e')\n",
+ "enention -> exention (将 'n' 替换为 'x')\n",
+ "exention -> exection (将 'n' 替换为 'c')\n",
+ "exection -> execution (插入 'u')\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "这个题目是动态规划的典型例题,在 wikipedia 中是有相应页面介绍的。\n",
+ "\n",
+ " - https://en.wikipedia.org/wiki/Edit_distance#Common_algorithm\n",
+ " - https://en.wikipedia.org/wiki/Levenshtein_distance\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 使用动态规划\n",
+ "\n",
+ "下面我们说说,这个题的思路。具体来描述一下。\n",
+ "\n",
+ "要始终明确一点, dp[i][j] 的含义是使得 word1 的前 i 字符子串与 word2 的前 j 字符子串相等所需要的操作数,这也是为什么我们需要在初始化 dp 矩阵时需要行列数均加上 1 。\n",
+ "\n",
+ "我们创建一个 dp[][] 二维数组,表示从 word1 的前 i 个字符(下标为:0~ i-1)到 word2 的前 j 个字符(下标为:0~j-1)的编辑过程中,需要的最少步数,那么:\n",
+ "\n",
+ "如果 $word1[i] = word2[j]$ 则 $dp[i][j] = dp[i-1][j-1]$\n",
+ "\n",
+ "如果 $word1[i] != word2[j]$ 则 $dp[i][j] = min ( dp[i-1][j] , dp[i][j-1], dp[i-1][j-1] ) + 1$\n",
+ "\n",
+ "下面就是我们对上述动态规划过程的解释:\n",
+ "\n",
+ "第一个条件比较容易理解,就是说 word1 的下标为 i 的字符 和 word2 的下标为 j 的字符相同,那么这个位置的字符我们不需要进行操作,所以我们只需要关注 word1 和 word2 去除掉相应位置的字符之后的子串的结果即可。\n",
+ "\n",
+ "我们下面对第二个条件的三种情况进行重点讲解:\n",
+ "\n",
+ "假设 word1 的前 i+1 (下标为 0~i)的子串为 \"abcde\"\n",
+ "假设 word2 的前 j+1 (下标为 0~j)的子串为 \"abcddgf\"\n",
+ "现在 word1[i] != word2[j],也就是 'e' != 'f'\n",
+ "\n",
+ "那么我们接下来应该怎么做呢?\n",
+ "\n",
+ "我们会发现,我们做的三种解释实际上就是把我们题中写到的三种操作模拟在最后一步实现。每种操作都是额外加一的操作。\n",
+ "\n",
+ "简单说,就是这样:\n",
+ " - 1.delete:dp[i-1][j] + 1 —— 保留了从 word1[0~i-1] 转变到 word2[0~j] 的最优操作次数,因为我们的 word1 的 0~i-1 已经能够转变到 word2 了,所以我们就直接把 word1 中的最后一个字符删除掉就行了。所以就需要额外进行一个 删除 操作。\n",
+ " - 2.insert:dp[i][j-1] + 1 —— 保留了从 word1[0~i] 转变到 word2[0~j-1] 的最优操作次数,因为我们的 word1 的 0~i 只能转变到 word2 的倒数第二位,所以我们就直接在 word1 的末尾添加一个与 word2 的最后一个字符相同的字符就可以了。所以就需要额外进行一个 插入 操作。\n",
+ " - 3.replace:dp[i-1][j-1] + 1 —— 保留了从 word1[0~i-1] 转变到 word2[0~j-1] 的最优操作次数,因为我们的 word1 的 0~i-1 只能转变到 word2 的倒数第二位,而 word1 的最后一位与 word2 的最后一位是不同的,所以现在的情况只需要额外的一个 替换 操作即可。\n",
+ "\n",
+ "\n",
+ "无论我们选取上面 3 中操作的哪种操作,我们选其中最小的值就可以了。\n",
+ "\n",
+ "参考链接:http://www.cnblogs.com/pandora/archive/2009/12/20/levenshtein_distance.html\n",
+ "\n",
+ "下面我们看一下代码:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "3\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def minDistance(self, word1, word2):\n",
+ " \"\"\"\n",
+ " :type word1: str\n",
+ " :type word2: str\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " # 初始化一个 len(word1)+1 * len(word2)+1 的矩阵\n",
+ " matrix = [[i+j for j in range(len(word2) + 1)] for i in range(len(word1) + 1)]\n",
+ " # 辅助理解,matrix 矩阵的样子\n",
+ " # print(matrix)\n",
+ " for i in range(1, len(word1)+1):\n",
+ " for j in range(1,len(word2)+1):\n",
+ " if word1[i-1] == word2[j-1]:\n",
+ " d = 0\n",
+ " else:\n",
+ " d = 1\n",
+ " matrix[i][j] = min(matrix[i-1][j]+1, matrix[i][j-1]+1, matrix[i-1][j-1]+d)\n",
+ "\n",
+ " return matrix[len(word1)][len(word2)]\n",
+ " \n",
+ "s = Solution()\n",
+ "word1 = 'horse'\n",
+ "word2 = 'ros'\n",
+ "print(s.minDistance(word1, word2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "上面代码的 matrix 矩阵生成,可能会让大家产生理解误差,我在这个地方的理解也是通过大佬问,我才知道具体是怎么回事的。\n",
+ "\n",
+ "下面我们把它打印一下。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "matrix([[0, 1, 2, 3],\n",
+ " [1, 2, 3, 4],\n",
+ " [2, 3, 4, 5],\n",
+ " [3, 4, 5, 6],\n",
+ " [4, 5, 6, 7],\n",
+ " [5, 6, 7, 8]])"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "juzhen = [[i+j for j in range(len(word2) + 1)] for i in range(len(word1) + 1)]\n",
+ "juzhen = np.mat(juzhen)\n",
+ "juzhen"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "以 numpy 的样子打印出来,看这样子比较清晰。各行各列对应比较整齐。\n",
+ "\n",
+ "我要说明的是:\n",
+ "\n",
+ " - 这个 matrix 的 第 1 行(下标为0的行)的 [0, 1, 2, 3] 这个维度的意思,对应的是 dp[i][j] 。也就是说,word1 取前 i 个字符,然后编辑成 word2 时所需要转换的最少步数。因为这里 i = 0,也就是 word1 取 0 个字符,而 j 我们取 0 - 3 个字符的时候,我们从 word1 变换到 word2 的时候所需要经过的最小步数。本质上,就是在 **空的** word1 上进行对应插入 word2 对应的字符就可以变换到 word2 。word2 取几个字符,我们的最小变换次数就是几。也就对应这个维度上的数字。\n",
+ "\n",
+ " - 另一个维度上,matrix 的第 1 列(下标为 0 的列),对应的是 [0, 1, 2, 3, 4, 5] 也是对应的 dp[i][j]。只不过我们这里调换了顺序,i 现在不为 0 了,而是 j 为 0 。也就是 word1 取 0~ i 个字符的时候,变换到 word2 的最小步骤数。实际上 word2 是空的,也就是说,我们 word1 有几个字符,我们对应删除几个字符就可以得到 word2 。这就对应着我们的这个列维度上的数字。\n",
+ " \n",
+ " - 其他维度,i 和 j 都不为 0 的部分,我们的初始化的数字是没有意义的。我们在迭代过程中会全部都更改一遍。"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/139._word_break.ipynb b/docs/Leetcode_Solutions/ipynb/139._word_break.ipynb
new file mode 100644
index 000000000..ffbac6d1d
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/139._word_break.ipynb
@@ -0,0 +1,222 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Word Break 单词拆分\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/word-break/description/\n",
+ " - 英文:https://leetcode.com/problems/word-break/\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。\n",
+ "\n",
+ "说明:\n",
+ "\n",
+ "1、拆分时可以重复使用字典中的单词。\n",
+ "2、你可以假设字典中没有重复的单词。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: s = \"leetcode\", wordDict = [\"leet\", \"code\"]\n",
+ "输出: true\n",
+ "解释: 返回 true 因为 \"leetcode\" 可以被拆分成 \"leet code\"。\n",
+ "\n",
+ "示例 2:\n",
+ "输入: s = \"applepenapple\", wordDict = [\"apple\", \"pen\"]\n",
+ "输出: true\n",
+ "解释: 返回 true 因为 \"applepenapple\" 可以被拆分成 \"apple pen apple\"。\n",
+ " 注意你可以重复使用字典中的单词。\n",
+ "\n",
+ "示例 3:\n",
+ "输入: s = \"catsandog\", wordDict = [\"cats\", \"dog\", \"sand\", \"and\", \"cat\"]\n",
+ "输出: false\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 字符串 S ,它的长度为 N ,如果 S 能够被 字典集合(dict)中的单词拼接而成,那么所要满足的条件为:\n",
+ " - F(0, N) = F(0, i) && F(i, j) && F(j, N)\n",
+ " - 这样,如果我们想知道某个子串是否可由 Dict 中的几个单词拼接而成就可以用这样的方式得到结果(满足条件为True,不满足条件为 False)存入到一个 boolean 数组的对应位置上,这样,最后 boolean 数组的最后一位就是 F(0, N) 的值,为 True 表示这个字符串 S 可以由 Dict 中的单词拼接,否则是不行的。\n",
+ " - AC 代码如下"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution:\n",
+ " def wordBreak(self, s, wordDict):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type wordDict: List[str]\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " # 参数校验\n",
+ " if s is None or len(s) < 1 or wordDict is None or len(wordDict) < 1:\n",
+ " return False\n",
+ " # 标记是否匹配,match[i] 表示 [0, i-1] 都匹配\n",
+ " length = len(s)\n",
+ " match = [False for i in range(length + 1)]\n",
+ " match[0] = True\n",
+ " \n",
+ " for i in range(1, length +1):\n",
+ " for j in range(i):\n",
+ " if match[j] and s[j:i] in wordDict:\n",
+ " match[i] = True\n",
+ " break\n",
+ " return match[length]\n",
+ "\n",
+ "\n",
+ "sss = Solution()\n",
+ "s = \"leetcode\"\n",
+ "wordDict = [\"leet\", \"code\"]\n",
+ "print(sss.wordBreak(s, wordDict))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "collapsed": true
+ },
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ " - **ok[i] 表示 s[:i] 是不是存在于我们的字典中。**\n",
+ " - 原理类似于我们上面的 思路 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def wordBreak(self, s, wordDict):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type wordDict: List[str]\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " ok = [True]\n",
+ " for i in range(1, len(s)+1):\n",
+ " ok += [any(ok[j] and s[j:i] in wordDict for j in range(i))]\n",
+ " return ok[-1]\n",
+ " \n",
+ "sss = Solution()\n",
+ "s = \"leetcode\"\n",
+ "wordDict = [\"leet\", \"code\"]\n",
+ "print(sss.wordBreak(s, wordDict))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "但是往list里面加数据的方法有快有慢,下面是对比:\n",
+ "\n",
+ "```python\n",
+ ">>> from timeit import timeit\n",
+ ">>> timeit('x.append(1)', 'x = []', number=10000000)\n",
+ "1.9880003412529277\n",
+ ">>> timeit('x += 1,', 'x = []', number=10000000)\n",
+ "1.2676891852971721\n",
+ ">>> timeit('x += [1]', 'x = []', number=10000000)\n",
+ "3.361207239950204\n",
+ "```\n",
+ "\n",
+ "因此我们可以将代码直接换成下面的格式:\n",
+ "\n",
+ "```python\n",
+ "ok += any(ok[j] and s[j:i] in wordDict for j in range(i)) # 会报错\n",
+ "```\n",
+ "\n",
+ "但是这样会报错,TypeError: 'bool' object is not iterable,因此bool类型数据不能这样加,别的可以(list类型本身当然要注意哈)\n",
+ "\n",
+ "因此在这个例子中我们这样:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def wordBreak(self, s, wordDict):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type wordDict: List[str]\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " ok = [True]\n",
+ " for i in range(1, len(s)+1):\n",
+ " ok += any(ok[j] and s[j:i] in wordDict for j in range(i)),\n",
+ " return ok[-1]\n",
+ " \n",
+ "sss = Solution()\n",
+ "s = \"leetcode\"\n",
+ "wordDict = [\"leet\", \"code\"]\n",
+ "print(sss.wordBreak(s, wordDict))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/179._Largest_Number.ipynb b/docs/Leetcode_Solutions/ipynb/179._Largest_Number.ipynb
new file mode 100644
index 000000000..9ce763484
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/179._Largest_Number.ipynb
@@ -0,0 +1,186 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 179.Largest Number 最大数\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/largest-number/description/\n",
+ " - 英文:https://leetcode.com/problems/largest-number/\n",
+ "\n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: [10,2]\n",
+ "输出: 210\n",
+ "\n",
+ "示例 2:\n",
+ "输入: [3,30,34,5,9]\n",
+ "输出: 9534330\n",
+ "说明: 输出结果可能非常大,所以你需要返回一个字符串而不是整数。\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 先排序,后合并,若最后为空字符串,则返回 '0'\n",
+ "\n",
+ "其中的排序思想是字符串的经典比较:\n",
+ "\n",
+ "【注】:在 Python3 中没有了 cmp,只有 key,我们可以使用 functools.cmp_to_key 去修饰一下。\n",
+ "\n",
+ "cmp 函数比较两个对象,如 (x, y),若 x > y,则返回 1,if x == y,return 0,如果 x < y,则返回 -1 。\n",
+ "\n",
+ "下面这个是 python2 的解决方案,可以 AC ,但是在我们的 Python3 中就会报如下错误"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "TypeError",
+ "evalue": "'cmp' is an invalid keyword argument for this function",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[0ms\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mSolution\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mnums\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 13\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlargestNumber\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnums\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[1;32m\u001b[0m in \u001b[0;36mlargestNumber\u001b[1;34m(self, nums)\u001b[0m\n\u001b[0;32m 6\u001b[0m \"\"\"\n\u001b[0;32m 7\u001b[0m \u001b[0mnums\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mstr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnum\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mnum\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mnums\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m \u001b[0mnums\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msort\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcmp\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mcmp\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 9\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[1;34m''\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnum\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlstrip\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'0'\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;34m''\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnum\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlstrip\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'0'\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32melse\u001b[0m \u001b[1;34m'0'\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;31mTypeError\u001b[0m: 'cmp' is an invalid keyword argument for this function"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def largestNumber(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: str\n",
+ " \"\"\"\n",
+ " nums = [str(num) for num in nums]\n",
+ " nums.sort(cmp=lambda x, y: cmp(y+x, x+y))\n",
+ " return ''.join(num).lstrip('0') if ''.join(num).lstrip('0') else '0'\n",
+ " \n",
+ "s = Solution()\n",
+ "nums = [10, 2]\n",
+ "print(s.largestNumber(nums))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "或者更简单的写法,可以写成下面这样(Python2适用,python3 会报错):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "TypeError",
+ "evalue": "'cmp' is an invalid keyword argument for this function",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[0ms\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mSolution\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mnums\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 13\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlargestNumber\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnums\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[1;32m\u001b[0m in \u001b[0;36mlargestNumber\u001b[1;34m(self, nums)\u001b[0m\n\u001b[0;32m 6\u001b[0m \"\"\"\n\u001b[0;32m 7\u001b[0m \u001b[0mnums\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mstr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnum\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mnum\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mnums\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m \u001b[0mnums\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msort\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcmp\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mcmp\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 9\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[1;34m''\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnum\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlstrip\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'0'\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mor\u001b[0m \u001b[1;34m'0'\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;31mTypeError\u001b[0m: 'cmp' is an invalid keyword argument for this function"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def largestNumber(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: str\n",
+ " \"\"\"\n",
+ " nums = [str(num) for num in nums]\n",
+ " nums.sort(cmp=lambda x, y: cmp(y+x, x+y))\n",
+ " return ''.join(num).lstrip('0') or '0'\n",
+ " \n",
+ "s = Solution()\n",
+ "nums = [10, 2]\n",
+ "print(s.largestNumber(nums))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "下面这个解法就是我们在 Python3 中的解法"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "210\n"
+ ]
+ }
+ ],
+ "source": [
+ "from functools import cmp_to_key\n",
+ "\n",
+ "# 比较函数\n",
+ "def compare(a, b):\n",
+ " return int(b + a) - int(a + b)\n",
+ "\n",
+ "class Solution(object):\n",
+ " def largestNumber(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: str\n",
+ " \"\"\"\n",
+ " nums = sorted([str(x) for x in nums], key=cmp_to_key(compare))\n",
+ " return str(int(''.join(nums)))\n",
+ " \n",
+ "s = Solution()\n",
+ "nums = [10, 2]\n",
+ "print(s.largestNumber(nums))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/242._valid_anagram.ipynb b/docs/Leetcode_Solutions/ipynb/242._valid_anagram.ipynb
new file mode 100644
index 000000000..26218f62d
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/242._valid_anagram.ipynb
@@ -0,0 +1,189 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 242. Valid Anagram 有效的字母异位词\n",
+ "\n",
+ "### 难度:Easy\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/valid-anagram/description/\n",
+ " - 英文:https://leetcode.com/problems/valid-anagram/\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: s = \"anagram\", t = \"nagaram\"\n",
+ "输出: true\n",
+ "\n",
+ "示例 2:\n",
+ "输入: s = \"rat\", t = \"car\"\n",
+ "输出: false\n",
+ "\n",
+ "说明:\n",
+ "你可以假设字符串只包含小写字母。\n",
+ "\n",
+ "进阶:\n",
+ "如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ " - 一行瞬秒!\n",
+ " - 适用 collections.Counter() 方法"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "import collections\n",
+ "\n",
+ "class Solution(object):\n",
+ " def isAnagram(self, s, t):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type t: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " return collections.Counter(s) == collections.Counter(t)\n",
+ " \n",
+ "s = \"anagram\"\n",
+ "t = \"nagaram\"\n",
+ "ss = Solution()\n",
+ "print(ss.isAnagram(s, t))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "collapsed": true
+ },
+ "source": [
+ "> 思路 2\n",
+ "\n",
+ " - 同样是一行瞬秒!\n",
+ " - 适用 sorted() 函数"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def isAnagram(self, s, t):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type t: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " return sorted(s) == sorted(t)\n",
+ "s = \"anagram\"\n",
+ "t = \"nagaram\"\n",
+ "ss = Solution()\n",
+ "print(ss.isAnagram(s, t))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 3\n",
+ "\n",
+ " - 用字数统计,因为只可能是 26 个字母"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def isAnagram(self, s, t):\n",
+ " \"\"\"\n",
+ " :type s: str\n",
+ " :type t: str\n",
+ " :rtype: bool\n",
+ " \"\"\"\n",
+ " if len(s) != len(t):\n",
+ " return False\n",
+ " \n",
+ " charCnt = [0] * 26\n",
+ " \n",
+ " for i in range(len(s)):\n",
+ " charCnt[ord(s[i]) - 97] += 1\n",
+ " charCnt[ord(t[i]) - 97] -= 1 \n",
+ " \n",
+ " for cnt in charCnt:\n",
+ " if cnt != 0:\n",
+ " return False\n",
+ " return True\n",
+ " \n",
+ "s = \"anagram\"\n",
+ "t = \"nagaram\"\n",
+ "ss = Solution()\n",
+ "print(ss.isAnagram(s, t))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/Leetcode_Solutions/ipynb/287._Find_the_Duplicate_Number.ipynb b/docs/Leetcode_Solutions/ipynb/287._Find_the_Duplicate_Number.ipynb
new file mode 100644
index 000000000..62e7895dc
--- /dev/null
+++ b/docs/Leetcode_Solutions/ipynb/287._Find_the_Duplicate_Number.ipynb
@@ -0,0 +1,244 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 287.Find the Duplicate Number 找到重复的数\n",
+ "\n",
+ "### 难度:Medium\n",
+ "\n",
+ "## 刷题内容\n",
+ "\n",
+ "> 原题链接\n",
+ "\n",
+ " - 中文:https://leetcode-cn.com/problems/find-the-duplicate-number/description/\n",
+ " - 英文:https://leetcode.com/problems/find-the-duplicate-number\n",
+ " \n",
+ "> 内容描述\n",
+ "\n",
+ "```\n",
+ "给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。\n",
+ "\n",
+ "示例 1:\n",
+ "输入: [1,3,4,2,2]\n",
+ "输出: 2\n",
+ "\n",
+ "示例 2:\n",
+ "输入: [3,1,3,4,2]\n",
+ "输出: 3\n",
+ "\n",
+ "说明:\n",
+ "不能更改原数组(假设数组是只读的)。\n",
+ "只能使用额外的 O(1) 的空间。\n",
+ "时间复杂度小于 O(n2) 。\n",
+ "数组中只有一个重复的数字,但它可能不止重复出现一次。\n",
+ "```\n",
+ "\n",
+ "## 解题方案\n",
+ "\n",
+ "> 思路 1\n",
+ "\n",
+ "实际上,我们在阅读完题目的时候,直观感觉,题目不是很难。但是,在我们看到下面的说明,也就是对我们题目的限制条件的时候,会猛然发现,题目的难度瞬间提升了好多倍。\n",
+ "\n",
+ "下面我列出咱们需要注意的点:\n",
+ " - 包含 n+1 个整数的数组\n",
+ " - 数组中的数字都在 1 到 n 之间(包括 1 和 n ,但是可以不连续,比如 [1,4,4,3,4])\n",
+ " - 重复的数字,可以重复很多次,并不限于重复 1 次,2次,3次..\n",
+ " - 不能更改原数组(这条是最要命的,原本我的想法是,我们可以排序完成之后,再进行二分查找法,碍于这个规定,无法进行)\n",
+ " - 只能用额外的 O(1) 的空间。(O(1) 空间的意思是不会因数组的长度改变而改变,对应本题就是不管我们的数组多长,我们能用的额外控制只能是 m 这个m 是一个确定的数,不会随着 n 的改变而改变。)\n",
+ " - 时间的复杂度小于 $O(n^2)$\n",
+ " \n",
+ "注意的点差不多就是上面所说的了。\n",
+ "\n",
+ "```\n",
+ "这个思路我们使用 二分查找(binary search)+ 鸽笼原理(Pigeonhole Principle)\n",
+ "参考维基百科关于鸽笼原理的词条链接:https://en.wikipedia.org/wiki/Pigeonhole_principle\n",
+ "\n",
+ "\"不允许修改数组\" 与 \"常数空间复杂度\" 这两个限制条件意味着:禁止排序,并且不能使用 Map 等数据结构\n",
+ "\n",
+ "小于 O(n^2) 的运行时间复杂度可以联想到使用二分将其中的一个 n 化简为 log n\n",
+ "可以参考 LeetCode Discuss:https://leetcode.com/discuss/60830/python-solution-explanation-without-changing-input-array\n",
+ "\n",
+ "二分枚举答案范围,使用鸽笼原理进行检验\n",
+ "\n",
+ "根据鸽笼原理,给定 n+1 个范围为 [1, n]的整数,其中一定存在数字出现至少两次。\n",
+ "假设枚举的数字为 n / 2 :\n",
+ "遍历数组,若数组中不大于 n / 2 的数字个数超过 n / 2 ,则可以确定 [1, n/2] 范围内一定有解,否则可以确定解落在 (n/2, n]范围内。\n",
+ "```\n",
+ "\n",
+ "也可以这样分析一下:\n",
+ "```\n",
+ "\n",
+ "如果n 是5,那么就会有1 2 3 4 5 一共5个数字的可能,而array size 是6,那么其中一个数字肯定会至少出现两次。\n",
+ "\n",
+ "如果没有重复的数字,小于等于1的数字 出现的次数 等于 1;\n",
+ "\n",
+ "小于等于2的数字 出现的次数 等于 2;\n",
+ "\n",
+ "... 同理3;4;5。\n",
+ "\n",
+ "如果有重复的数字,如果重复的是1,那么 小于等于1的数字 出现的次数 肯定大于1;\n",
+ "\n",
+ "基于这个理论,我们可以在1 2 3 4 5 选出一个 mid, 遍历array来count 小于等于mid 的数字个数 小于等于 它自己mid 还是 大于 mid?\n",
+ "\n",
+ "如果count 小于等于mid, 说明 1 到 mid 这些数字 没有重复项, 重复项在 右半边 mid 到n, 所以缩小到右半边继续搜索;\n",
+ "\n",
+ "如果count 大于mid, 说明 1 到 mid 这些数字中 有重复项,缩小到 左半边继续搜索。\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "3\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def findDuplicate(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " low, high = 1, len(nums) - 1\n",
+ " while low <= high:\n",
+ " mid = (low + high) >> 1\n",
+ " cnt = sum(x <= mid for x in nums)\n",
+ " if cnt > mid:\n",
+ " high = mid - 1\n",
+ " else:\n",
+ " low = mid + 1\n",
+ " return low\n",
+ " \n",
+ "s = Solution()\n",
+ "nums = [1,2,3,3]\n",
+ "print(s.findDuplicate(nums))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "思路 1 的解法是时间复杂度为 $O(nlogn)$ 的解法,思路 2 则是时间复杂度为 $O(n)$ ,但是相对来说,是投机取巧了些。\n",
+ "> 思路 2\n",
+ "\n",
+ "一次遍历统计,另一次遍历输出即可。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "3\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def findDuplicate(self, nums):\n",
+ " \"\"\"\n",
+ " :type nums: List[int]\n",
+ " :rtype: int\n",
+ " \"\"\"\n",
+ " dic = dict()\n",
+ " for n in nums:\n",
+ " dic[n] = dic.get(n, 0) + 1\n",
+ " if dic[n] >= 2:\n",
+ " return n\n",
+ "\n",
+ "s = Solution()\n",
+ "nums = [1,2,3,3]\n",
+ "print(s.findDuplicate(nums))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> 思路 3 \n",
+ "\n",
+ "思路 3 则是更加完整的 $O(n)$ 的解法,现在我还没有完全搞懂,我先写在下面吧,大佬们可以提前学习了解。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "3\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Solution(object):\n",
+ " def findDuplicate(self, nums):\n",
+ " # The \"tortoise and hare\" step. We start at the end of the array and try\n",
+ " # to find an intersection point in the cycle.\n",
+ " slow = 0\n",
+ " fast = 0\n",
+ " \n",
+ " # Keep advancing 'slow' by one step and 'fast' by two steps until they\n",
+ " # meet inside the loop.\n",
+ " while True:\n",
+ " slow = nums[slow]\n",
+ " fast = nums[nums[fast]]\n",
+ " \n",
+ " if slow == fast:\n",
+ " break\n",
+ " \n",
+ " # Start up another pointer from the end of the array and march it forward\n",
+ " # until it hits the pointer inside the array.\n",
+ " finder = 0\n",
+ " while True:\n",
+ " slow = nums[slow]\n",
+ " finder = nums[finder]\n",
+ " \n",
+ " # If the two hit, the intersection index is the duplicate element.\n",
+ " if slow == finder:\n",
+ " return slow\n",
+ " \n",
+ "s = Solution()\n",
+ "nums = [1,2,3,3]\n",
+ "print(s.findDuplicate(nums))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/jianzhioffer/java/03_01_DuplicationInArray.md b/docs/jianzhioffer/java/03_01_DuplicationInArray.md
deleted file mode 100644
index e8094f1de..000000000
--- a/docs/jianzhioffer/java/03_01_DuplicationInArray.md
+++ /dev/null
@@ -1,72 +0,0 @@
-## 找出数组中重复的数字
-
-### 题目描述
-在一个长度为 `n` 的数组里的所有数字都在 `0` 到 `n-1` 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为 `7` 的数组 `{2, 3, 1, 0, 2, 5, 3}`,那么对应的输出是重复的数字 `2` 或者 `3`。
-
-
-### 解法
-#### 解法一
-排序后,顺序扫描,判断是否有重复,时间复杂度为 `O(n²)`。
-
-#### 解法二
-利用哈希表,遍历数组,如果哈希表中没有该元素,则存入哈希表中,否则返回重复的元素。时间复杂度为 `O(n)`,空间复杂度为 `O(n)`。
-
-#### 解法三
-长度为 `n`,元素的数值范围也为 `n`,如果没有重复元素,那么数组每个下标对应的值与下标相等。
-
-从头到尾遍历数组,当扫描到下标 `i` 的数字 `nums[i]`:
-- 如果等于 `i`,继续向下扫描;
-- 如果不等于 `i`,拿它与第 `nums[i]` 个数进行比较,如果相等,说明有重复值,返回 `nums[i]`。如果不相等,就把第 `i` 个数 和第 `nums[i]` 个数交换。重复这个比较交换的过程。
-
-此算法时间复杂度为 `O(n)`,因为每个元素最多只要两次交换,就能确定位置。空间复杂度为 `O(1)`。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/10/27
- */
-
-public class Solution {
- /**
- * 查找数组中的重复元素
- * @param numbers 数组
- * @param length 数组长度
- * @param duplication duplication[0]存储重复元素
- * @return boolean
- */
- public boolean duplicate(int[] numbers, int length, int[] duplication) {
- if (numbers == null || length < 1) {
- return false;
- }
- for (int e : numbers) {
- if (e >= length) {
- return false;
- }
- }
-
- for (int i = 0; i < length; ++i) {
- while (numbers[i] != i) {
- if (numbers[i] == numbers[numbers[i]]) {
- duplication[0] = numbers[i];
- return true;
- }
- swap(numbers, i, numbers[i]);
- }
- }
-
- return false;
- }
-
- private void swap(int[] numbers, int i, int j) {
- int t = numbers[i];
- numbers[i] = numbers[j];
- numbers[j] = t;
- }
-}
-```
-
-### 测试用例
-1. 长度为 n 的数组中包含一个或多个重复的数字;
-2. 数组中不包含重复的数字;
-3. 无效测试输入用例(输入空指针;长度为 n 的数组中包含 0~n-1 之外的数字)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/03_02_DuplicationInArrayNoEdit.md b/docs/jianzhioffer/java/03_02_DuplicationInArrayNoEdit.md
deleted file mode 100644
index 5fdac9cdc..000000000
--- a/docs/jianzhioffer/java/03_02_DuplicationInArrayNoEdit.md
+++ /dev/null
@@ -1,86 +0,0 @@
-## 不修改数组找出重复的数字
-
-### 题目描述
-在一个长度为 `n+1` 的数组里的所有数字都在 `1` 到 `n` 的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为 `8` 的数组 `{2, 3, 5, 4, 3, 2, 6, 7}`,那么对应的输出是重复的数字 `2` 或者 `3`。
-
-
-### 解法
-#### 解法一
-创建长度为 `n+1` 的辅助数组,把原数组的元素复制到辅助数组中。如果原数组被复制的数是 `m`,则放到辅助数组第 `m` 个位置。这样很容易找出重复元素。空间复杂度为 `O(n)`。
-
-#### 解法二
-数组元素的取值范围是 `[1, n]`,对该范围对半划分,分成 `[1, middle]`, `[middle+1, n]`。计算数组中有多少个(count)元素落在 `[1, middle]` 区间内,如果 count 大于 middle-1+1,那么说明这个范围内有重复元素,否则在另一个范围内。继续对这个范围对半划分,继续统计区间内元素数量。
-
-时间复杂度 `O(n * log n)`,空间复杂度 `O(1)`。
-
-注意,此方法无法找出所有重复的元素。
-
-```java
-/**
- * @author bingo
- * @since 2018/10/27
- */
-
-public class Solution {
- /**
- * 不修改数组查找重复的元素,没有则返回-1
- * @param numbers 数组
- * @return 重复的元素
- */
- public int getDuplication(int[] numbers) {
- if (numbers == null || numbers.length < 1) {
- return -1;
- }
-
- int start = 1;
- int end = numbers.length - 1;
- while (end >= start) {
- int middle = start + ((end - start) >> 1);
-
- // 调用 log n 次
- int count = countRange(numbers, start, middle);
- if (start == end) {
- if (count > 1) {
- return start;
- }
- break;
- } else {
- // 无法找出所有重复的数
- if (count > (middle - start) + 1) {
- end = middle;
- } else {
- start = middle + 1;
- }
- }
- }
- return -1;
- }
-
-
- /**
- * 计算整个数组中有多少个数的取值在[start, end] 之间
- * 时间复杂度 O(n)
- * @param numbers 数组
- * @param start 左边界
- * @param end 右边界
- * @return 数量
- */
- private int countRange(int[] numbers, int start, int end) {
- if (numbers == null) {
- return 0;
- }
- int count = 0;
- for(int e : numbers) {
- if (e >= start && e <= end) {
- ++count;
- }
- }
- return count;
- }
-}
-```
-
-### 测试用例
-1. 长度为 n 的数组中包含一个或多个重复的数字;
-2. 数组中不包含重复的数字;
-3. 无效测试输入用例(输入空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/04_FindInPartiallySortedMatrix.md b/docs/jianzhioffer/java/04_FindInPartiallySortedMatrix.md
deleted file mode 100644
index 70ab58be7..000000000
--- a/docs/jianzhioffer/java/04_FindInPartiallySortedMatrix.md
+++ /dev/null
@@ -1,57 +0,0 @@
-## 二维数组中的查找
-
-### 题目描述
-在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
-
-
-### 解法
-从二维数组的右上方开始查找:
-- 若元素值等于 `target`,返回 `true`;
-- 若元素值大于 `target`,砍掉这一列,即 `--j`;
-- 若元素值小于 `target`,砍掉这一行,即 `++i`。
-
-也可以从二维数组的左下方开始查找,以下代码使用左下方作为查找的起点。
-
-注意,不能选择左上方或者右下方的数字,因为这样无法缩小查找的范围。
-
-```java
-/**
- * @author bingo
- * @since 2018/10/27
- */
-
-public class Solution {
- /**
- * 二维数组中的查找
- * @param target 目标值
- * @param array 二维数组
- * @return boolean
- */
- public boolean find(int target, int[][] array) {
- if (array == null) {
- return false;
- }
- int rows = array.length;
- int columns = array[0].length;
-
- int i = rows - 1;
- int j = 0;
- while (i >= 0 && j < columns) {
- if (array[i][j] == target) {
- return true;
- }
- if (array[i][j] < target) {
- ++j;
- } else {
- --i;
- }
- }
- return false;
- }
-}
-```
-
-### 测试用例
-1. 二维数组中包含查找的数字(查找的数字是数组中的最大值和最小值;查找的数字介于数组中的最大值和最小值之间);
-2. 二维数组中没有查找的数字(查找的数字大于/小于数组中的最大值;查找的数字在数组的最大值和最小值之间但数组中没有这个数字);
-3. 特殊输入测试(输入空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/05_ReplaceSpaces.md b/docs/jianzhioffer/java/05_ReplaceSpaces.md
deleted file mode 100644
index eb3e00d3b..000000000
--- a/docs/jianzhioffer/java/05_ReplaceSpaces.md
+++ /dev/null
@@ -1,98 +0,0 @@
-## 替换空格
-
-### 题目描述
-请实现一个函数,将一个字符串中的每个空格替换成 `%20`。例如,当字符串为 `We Are Happy`,则经过替换之后的字符串为 `We%20Are%20Happy`。
-
-
-### 解法
-#### 解法一
-创建 `StringBuilder`,遍历原字符串,遇到非空格,直接 append 到 `StringBuilder` 中,遇到空格则将 `%20` append 到 `StringBuilder` 中。
-```java
-/**
- * @author bingo
- * @since 2018/10/27
- */
-
-public class Solution {
- /**
- * 将字符串中的所有空格替换为%20
- * @param str 字符串
- * @return 替换后的字符串
- */
- public String replaceSpace(StringBuffer str) {
- if (str == null || str.length() == 0) {
- return str.toString();
- }
- StringBuilder sb = new StringBuilder();
- int len = str.length();
- for (int i = 0; i < len; ++i) {
- char ch = str.charAt(i);
- sb.append(ch == ' ' ? "%20" : ch);
- }
-
- return sb.toString();
- }
-}
-```
-
-#### 解法二【推荐】
-先遍历原字符串,遇到空格,则在原字符串末尾 `append` 任意两个字符,如两个空格。
-
-用指针 `p` 指向原字符串末尾,`q` 指向现字符串末尾,`p`, `q` 从后往前遍历,当 `p` 遇到空格,`q` 位置依次要 `append` '02%',若不是空格,直接 `append` `p` 指向的字符。
-
-> 🤔思路扩展:
-在合并两个数组(包括字符串)时,如果从前往后复制每个数字(或字符)需要重复移动数字(或字符)多次,那么我们可以考虑从后往前复制,这样就能减少移动的次数,从而提高效率。
-
-```java
-/**
- * @author bingo
- * @since 2018/10/27
- */
-
-public class Solution {
- /**
- * 将字符串中的所有空格替换为%20
- * @param str 字符串
- * @return 替换后的字符串
- */
- public String replaceSpace(StringBuffer str) {
- if (str == null || str.length() == 0) {
- return str.toString();
- }
-
- int len = str.length();
- for (int i = 0; i < len; ++i) {
- if (str.charAt(i) == ' ') {
- // append 两个空格
- str.append(" ");
- }
- }
-
- // p 指向原字符串末尾
- int p = len - 1;
-
- // q 指向现字符串末尾
- int q = str.length() - 1;
-
- while (p >= 0) {
- char ch = str.charAt(p--);
- if (ch == ' ') {
- str.setCharAt(q--, '0');
- str.setCharAt(q--, '2');
- str.setCharAt(q--, '%');
- } else {
- str.setCharAt(q--, ch);
- }
- }
-
- return str.toString();
-
- }
-}
-```
-
-
-### 测试用例
-1. 输入的字符串包含空格(空格位于字符串的最前面/最后面/中间;字符串有多个连续的空格);
-2. 输入的字符串中没有空格;
-3. 特殊输入测试(字符串是一个空指针;字符串是一个空字符串;字符串只有一个空格字符;字符串中有多个连续空格)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/06_PrintListInReversedOrder.md b/docs/jianzhioffer/java/06_PrintListInReversedOrder.md
deleted file mode 100644
index 60e99a538..000000000
--- a/docs/jianzhioffer/java/06_PrintListInReversedOrder.md
+++ /dev/null
@@ -1,110 +0,0 @@
-## 从尾到头打印链表
-
-### 题目描述
-输入一个链表,按链表值从尾到头的顺序返回一个 `ArrayList`。
-
-
-### 解法
-#### 解法一【推荐】
-遍历链表,每个链表结点值 `push` 进栈,最后将栈中元素依次 `pop` 到 `list` 中。
-```java
-/**
-* public class ListNode {
-* int val;
-* ListNode next = null;
-*
-* ListNode(int val) {
-* this.val = val;
-* }
-* }
-*
-*/
-import java.util.ArrayList;
-import java.util.Stack;
-
-/**
- * @author bingo
- * @since 2018/10/28
- */
-public class Solution {
- /**
- * 从尾到头打印链表
- * @param listNode 链表头节点
- * @return list
- */
- public ArrayList printListFromTailToHead(ListNode listNode) {
- ArrayList res = new ArrayList<>();
- if (listNode == null) {
- return res;
- }
- Stack stack = new Stack<>();
- while (listNode != null) {
- stack.push(listNode.val);
- listNode = listNode.next;
- }
- while (!stack.isEmpty()) {
- res.add(stack.pop());
- }
-
- return res;
- }
-}
-```
-
-#### 解法二【不推荐】
-利用递归方式:
-- 若不是链表尾结点,继续递归;
-- 若是,添加到 `list` 中。
-
-这种方式不推荐,当递归层数过多时,容易发生 `Stack Overflow`。
-
-```java
-/**
-* public class ListNode {
-* int val;
-* ListNode next = null;
-*
-* ListNode(int val) {
-* this.val = val;
-* }
-* }
-*
-*/
-import java.util.ArrayList;
-import java.util.Stack;
-
-/**
- * @author bingo
- * @since 2018/10/28
- */
-public class Solution {
- /**
- * 从尾到头打印链表
- * @param listNode 链表头结点
- * @return list
- */
- public ArrayList printListFromTailToHead(ListNode listNode) {
- ArrayList res = new ArrayList<>();
- if (listNode == null) {
- return res;
- }
-
- addElement(listNode, res);
- return res;
-
- }
-
- private void addElement(ListNode listNode, ArrayList res) {
- if (listNode.next != null) {
- // 递归调用
- addElement(listNode.next, res);
- }
- res.add(listNode.val);
- }
-}
-```
-
-
-### 测试用例
-1. 功能测试(输入的链表有多个结点;输入的链表只有一个结点);
-2. 特殊输入测试(输入的链表结点指针为空)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/07_ConstructBinaryTree.md b/docs/jianzhioffer/java/07_ConstructBinaryTree.md
deleted file mode 100644
index f8c824a2e..000000000
--- a/docs/jianzhioffer/java/07_ConstructBinaryTree.md
+++ /dev/null
@@ -1,82 +0,0 @@
-## 重建二叉树
-
-### 题目描述
-输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 `{1,2,4,7,3,5,6,8}` 和中序遍历序列 `{4,7,2,1,5,3,8,6}`,则重建二叉树并返回。
-
-
-### 解法
-在二叉树的前序遍历序列中,第一个数字总是根结点的值。在中序遍历序列中,根结点的值在序列的中间,左子树的结点位于根结点左侧,而右子树的结点位于根结点值的右侧。
-
-遍历中序序列,找到根结点,递归构建左子树与右子树。
-
-注意添加特殊情况的 `if` 判断。
-
-```java
-/**
- * Definition for binary tree
- * public class TreeNode {
- * int val;
- * TreeNode left;
- * TreeNode right;
- * TreeNode(int x) { val = x; }
- * }
- */
-
-/**
- * @author bingo
- * @since 2018/10/28
- */
-
-public class Solution {
- /**
- * 重建二叉树
- *
- * @param pre 先序序列
- * @param in 中序序列
- * @return 二叉树根结点
- */
- public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
- if (pre == null || in == null || pre.length != in.length) {
- return null;
- }
- int n = pre.length;
- return constructBinaryTree(pre, 0, n - 1, in, 0, n - 1);
- }
-
- private TreeNode constructBinaryTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) {
- TreeNode node = new TreeNode(pre[startPre]);
- if (startPre == endPre) {
- if (startIn == endIn) {
- return node;
- }
- throw new IllegalArgumentException("Invalid input!");
- }
-
- int inOrder = startIn;
- while (in[inOrder] != pre[startPre]) {
- ++inOrder;
- if (inOrder > endIn) {
- new IllegalArgumentException("Invalid input!");
- }
- }
- int len = inOrder - startIn;
- if (len > 0) {
- // 递归构建左子树
- node.left = constructBinaryTree(pre, startPre + 1, startPre + len, in, startIn, inOrder - 1);
- }
-
- if (inOrder < endIn) {
- // 递归构建右子树
- node.right = constructBinaryTree(pre, startPre + len + 1, endPre, in, inOrder + 1, endIn);
- }
- return node;
-
- }
-}
-```
-
-
-### 测试用例
-1. 普通二叉树(完全二叉树;不完全二叉树);
-2. 特殊二叉树(所有结点都没有左/右子结点;只有一个结点的二叉树);
-3. 特殊输入测试(二叉树根结点为空;输入的前序序列和中序序列不匹配)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/08_NextNodeInBinaryTrees.md b/docs/jianzhioffer/java/08_NextNodeInBinaryTrees.md
deleted file mode 100644
index e16037ce7..000000000
--- a/docs/jianzhioffer/java/08_NextNodeInBinaryTrees.md
+++ /dev/null
@@ -1,74 +0,0 @@
-## 二叉树的下一个结点
-
-### 题目描述
-给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
-
-
-### 解法
-对于结点 `pNode`:
-- 如果它有右子树,则**右子树的最左结点**就是它的下一个结点;
-- 如果它没有右子树,判断它与父结点 `pNode.next` 的位置情况:
- - 如果它是父结点的左孩子,那么父结点 `pNode.next` 就是它的下一个结点;
- - 如果它是父结点的右孩子,一直向上寻找,直到找到某个结点,它是它父结点的左孩子,那么该父结点就是 `pNode` 的下一个结点。
-
-```java
-/*
-public class TreeLinkNode {
- int val;
- TreeLinkNode left = null;
- TreeLinkNode right = null;
- TreeLinkNode next = null;
-
- TreeLinkNode(int val) {
- this.val = val;
- }
-}
-*/
-
-/**
- * @author bingo
- * @since 2018/10/28
- */
-
-public class Solution {
- /**
- * 获取中序遍历结点的下一个结点
- * @param pNode 某个结点
- * @return pNode的下一个结点
- */
- public TreeLinkNode GetNext(TreeLinkNode pNode) {
- if (pNode == null) {
- return null;
- }
-
- if (pNode.right != null) {
- TreeLinkNode t = pNode.right;
- while (t.left != null) {
- t = t.left;
- }
- return t;
- }
-
- // 须保证 pNode.next 不为空,否则会出现 NPE
- if (pNode.next != null && pNode.next.left == pNode) {
- return pNode.next;
- }
-
- while (pNode.next != null) {
- if (pNode.next.left == pNode) {
- return pNode.next;
- }
- pNode = pNode.next;
- }
-
- return null;
-
- }
-}
-```
-
-
-### 测试用例
-1. 普通二叉树(完全二叉树;不完全二叉树);
-2. 特殊二叉树(所有结点都没有左/右子结点;只有一个结点的二叉树;二叉树的根结点为空);
-3. 不同位置的结点的下一个结点(下一个结点为当前结点的右子结点、右子树的最左子结点、父结点、跨层的父结点等;当前结点没有下一个结点)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/09_01_QueueWithTwoStacks.md b/docs/jianzhioffer/java/09_01_QueueWithTwoStacks.md
deleted file mode 100644
index 9dc32d0d2..000000000
--- a/docs/jianzhioffer/java/09_01_QueueWithTwoStacks.md
+++ /dev/null
@@ -1,47 +0,0 @@
-## 用两个栈实现队列
-
-### 题目描述
-用两个栈来实现一个队列,完成队列的 `Push` 和 `Pop` 操作。 队列中的元素为 `int` 类型。
-
-
-### 解法
-`Push` 操作,每次都存入 `stack1`;
-`Pop` 操作,每次从 `stack2` 取:
-- `stack2` 栈不为空时,不能将 `stack1` 元素倒入;
-- `stack2` 栈为空时,需要一次将 `stack1` 元素全部倒入。
-
-```java
-import java.util.Stack;
-
-/**
- * @author bingo
- * @since 2018/10/28
- */
-
-public class Solution {
- Stack stack1 = new Stack();
- Stack stack2 = new Stack();
-
- public void push(int node) {
- stack1.push(node);
- }
-
- public int pop() {
- if (stack2.isEmpty()) {
- if (stack1.isEmpty()) {
- return -1;
- }
- while (!stack1.isEmpty()) {
- stack2.push(stack1.pop());
- }
- }
- return stack2.pop();
- }
-}
-```
-
-
-### 测试用例
-1. 往空的队列里添加、删除元素;
-2. 往非空的队列添加、删除元素;
-3. 连续删除元素直至队列为空。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/09_02_StackWithTwoQueues.md b/docs/jianzhioffer/java/09_02_StackWithTwoQueues.md
deleted file mode 100644
index 823b8fa29..000000000
--- a/docs/jianzhioffer/java/09_02_StackWithTwoQueues.md
+++ /dev/null
@@ -1,55 +0,0 @@
-## 用两个队列实现栈
-
-### 题目描述
-用两个队列来实现一个栈,完成栈的 `Push` 和 `Pop` 操作。 栈中的元素为 `int` 类型。
-
-
-### 解法
-`Push` 操作,每次都存入 `queue1`;
-`Pop` 操作,每次从 `queue1` 取:
-- 将 `queue1` 中的元素依次倒入 `queue2`,直到 `queue1` 剩下一个元素,这个元素就是要 `pop` 出去的;
-- 将 `queue1` 与 `queue2` 进行交换,这样保证每次都从 `queue1` 中存取元素,`queue2` 只起到辅助暂存的作用。
-
-```java
-import java.util.LinkedList;
-import java.util.Queue;
-
-/**
- * @author bingo
- * @since 2018/10/29
- */
-
-public class Solution {
-
- private Queue queue1 = new LinkedList<>();
- private Queue queue2 = new LinkedList<>();
-
- public void push(int node) {
- queue1.offer(node);
- }
-
- public int pop() {
- if (queue1.isEmpty()) {
- throw new RuntimeException("Empty stack!");
- }
-
- while (queue1.size() > 1) {
- queue2.offer(queue1.poll());
- }
-
- int val = queue1.poll();
-
- Queue t = queue1;
- queue1 = queue2;
- queue2 = t;
- return val;
-
- }
-}
-```
-
-
-### 测试用例
-1. 往空的栈里添加、删除元素;
-2. 往非空的栈添加、删除元素;
-3. 连续删除元素直至栈为空。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/10_01_Fibonacci.md b/docs/jianzhioffer/java/10_01_Fibonacci.md
deleted file mode 100644
index 31ac8b0ec..000000000
--- a/docs/jianzhioffer/java/10_01_Fibonacci.md
+++ /dev/null
@@ -1,79 +0,0 @@
-## 斐波那契数列
-
-### 题目描述
-大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第 `n` 项(从 `0` 开始,第 `0` 项为 `0`)。`n<=39`
-
-
-### 解法
-#### 解法一
-采用递归方式,简洁明了,但效率很低,存在大量的重复计算。
-```
- f(10)
- / \
- f(9) f(8)
- / \ / \
- f(8) f(7) f(7) f(6)
- / \ / \
- f(7) f(6) f(6) f(5)
-```
-
-```java
-
-/**
- * @author bingo
- * @since 2018/10/29
- */
-
-public class Solution {
- /**
- * 求斐波那契数列的第n项,n从0开始
- * @param n 第n项
- * @return 第n项的值
- */
- public int Fibonacci(int n) {
- if (n < 2) {
- return n;
- }
- // 递归调用
- return Fibonacci(n - 1) + Fibonacci(n - 2);
- }
-}
-```
-
-#### 解法二
-从下往上计算,递推,时间复杂度 `O(n)`。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/10/29
- */
-
-public class Solution {
- /**
- * 求斐波那契数列的第n项,n从0开始
- * @param n 第n项
- * @return 第n项的值
- */
- public int Fibonacci(int n) {
- if (n < 2) {
- return n;
- }
- int[] res = new int[n + 1];
- res[0] = 0;
- res[1] = 1;
- for (int i = 2; i <= n; ++i) {
- res[i] = res[i - 1] + res[i - 2];
- }
- return res[n];
-
- }
-}
-```
-
-
-### 测试用例
-1. 功能测试(如输入 3、5、10 等);
-2. 边界值测试(如输入 0、1、2);
-3. 性能测试(输入较大的数字,如 40、50、100 等)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/10_02_JumpFloor.md b/docs/jianzhioffer/java/10_02_JumpFloor.md
deleted file mode 100644
index 268b7c8af..000000000
--- a/docs/jianzhioffer/java/10_02_JumpFloor.md
+++ /dev/null
@@ -1,42 +0,0 @@
-## 跳台阶
-
-### 题目描述
-一只青蛙一次可以跳上`1`级台阶,也可以跳上`2`级。求该青蛙跳上一个`n`级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
-
-### 解法
-跳上 `n` 级台阶,可以从 `n-1` 级跳 `1` 级上去,也可以从 `n-2` 级跳 `2` 级上去。所以
-```
-f(n) = f(n-1) + f(n-2)
-```
-
-```java
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-public class Solution {
- /**
- * 青蛙跳台阶
- * @param target 跳上的那一级台阶
- * @return 多少种跳法
- */
- public int JumpFloor(int target) {
- if (target < 3) {
- return target;
- }
- int[] res = new int[target + 1];
- res[1] = 1;
- res[2] = 2;
- for (int i = 3; i <= target; ++i) {
- res[i] = res[i - 1] + res[i - 2];
- }
- return res[target];
- }
-}
-```
-
-### 测试用例
-1. 功能测试(如输入 3、5、10 等);
-2. 边界值测试(如输入 0、1、2);
-3. 性能测试(输入较大的数字,如 40、50、100 等)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/10_03_JumpFloorII.md b/docs/jianzhioffer/java/10_03_JumpFloorII.md
deleted file mode 100644
index 91f3ac3ea..000000000
--- a/docs/jianzhioffer/java/10_03_JumpFloorII.md
+++ /dev/null
@@ -1,48 +0,0 @@
-## 变态跳台阶
-
-### 题目描述
-一只青蛙一次可以跳上`1`级台阶,也可以跳上`2`级……它也可以跳上`n`级。求该青蛙跳上一个`n`级的台阶总共有多少种跳法。
-
-### 解法
-跳上 `n-1` 级台阶,可以从 `n-2` 级跳 `1` 级上去,也可以从 `n-3` 级跳 `2` 级上去...也可以从 `0` 级跳上去。那么
-```
-f(n-1) = f(0) + f(1) + ... + f(n-2) ①
-```
-
-跳上 `n` 级台阶,可以从 `n-1` 级跳 `1` 级上去,也可以从 `n-2` 级跳 `2` 级上去...也可以从 `0` 级跳上去。那么
-```
-f(n) = f(0) + f(1) + ... + f(n-2) + f(n-1) ②
-
-②-①:
-f(n) - f(n-1) = f(n-1)
-f(n) = 2f(n-1)
-```
-
-所以 f(n) 是一个等比数列:
-```
-f(n) = 2^(n-1)
-```
-
-
-```java
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-public class Solution {
- /**
- * 青蛙跳台阶II
- * @param target 跳上的那一级台阶
- * @return 多少种跳法
- */
- public int JumpFloorII(int target) {
- return (int) Math.pow(2, target - 1);
- }
-}
-```
-
-### 测试用例
-1. 功能测试(如输入 3、5、10 等);
-2. 边界值测试(如输入 0、1、2);
-3. 性能测试(输入较大的数字,如 40、50、100 等)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/10_04_RectCover.md b/docs/jianzhioffer/java/10_04_RectCover.md
deleted file mode 100644
index 07ddc850c..000000000
--- a/docs/jianzhioffer/java/10_04_RectCover.md
+++ /dev/null
@@ -1,73 +0,0 @@
-## 矩形覆盖
-
-### 题目描述
-我们可以用`2*1`的小矩形横着或者竖着去覆盖更大的矩形。请问用`n`个`2*1`的小矩形无重叠地覆盖一个`2*n`的大矩形,总共有多少种方法?
-
-### 解法
-覆盖 `2*n` 的矩形:
-- 可以先覆盖 `2*n-1` 的矩形,再覆盖一个 `2*1` 的矩形;
-- 也可以先覆盖 `2*(n-2)` 的矩形,再覆盖两个 `1*2` 的矩形。
-
-#### 解法一:利用数组存放结果
-```java
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-public class Solution {
- /**
- * 矩形覆盖
- * @param target 2*target大小的矩形
- * @return 多少种覆盖方法
- */
- public int RectCover(int target) {
- if (target < 3) {
- return target;
- }
- int[] res = new int[target + 1];
- res[1] = 1;
- res[2] = 2;
- for (int i = 3; i <= target; ++i) {
- res[i] = res[i - 1] + res[i - 2];
- }
- return res[target];
- }
-}
-```
-
-#### 解法二:直接用变量存储结果
-```java
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-public class Solution {
- /**
- * 矩形覆盖
- * @param target 2*target大小的矩形
- * @return 多少种覆盖方法
- */
- public int RectCover(int target) {
- if (target < 3) {
- return target;
- }
- int res1 = 1;
- int res2 = 2;
- int res = 0;
- for (int i = 3; i <= target; ++i) {
- res = res1 + res2;
- res1 = res2;
- res2 = res;
- }
- return res;
- }
-}
-```
-
-
-### 测试用例
-1. 功能测试(如输入 3、5、10 等);
-2. 边界值测试(如输入 0、1、2);
-3. 性能测试(输入较大的数字,如 40、50、100 等)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/11_MinNumberInRotatedArray.md b/docs/jianzhioffer/java/11_MinNumberInRotatedArray.md
deleted file mode 100644
index e8fcdad00..000000000
--- a/docs/jianzhioffer/java/11_MinNumberInRotatedArray.md
+++ /dev/null
@@ -1,119 +0,0 @@
-## 旋转数组的最小数字
-
-### 题目描述
-把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组 `{3,4,5,1,2}` 为 `{1,2,3,4,5}` 的一个旋转,该数组的最小值为 `1`。
-
-**NOTE:**给出的所有元素都大于 `0`,若数组大小为 `0`,请返回 `0`。
-
-
-### 解法
-#### 解法一
-直接遍历数组找最小值,时间复杂度 `O(n)`,不推荐。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/10/30
- */
-
-public class Solution {
- /**
- * 获取旋转数组的最小元素
- * @param array 旋转数组
- * @return 数组中的最小值
- */
- public int minNumberInRotateArray(int[] array) {
- if (array == null || array.length == 0) {
- return 0;
- }
-
- int n = array.length;
- if (n == 1 || array[0] < array[n - 1]) {
- return array[0];
- }
-
- int min = array[0];
- for (int i = 1; i < n; ++i) {
- min = array[i] < min ? array[i] : min;
- }
-
- return min;
- }
-
-}
-```
-
-#### 解法二
-利用指针 `p`,`q` 指向数组的首尾,如果 `array[p] < array[q]`,说明数组是递增数组,直接返回 `array[p]`。否则进行如下讨论。
-
-计算中间指针 `mid`:
-- 如果此时 `array[p]`, `array[q]`, `array[mid]` 两两相等,此时无法采用二分方式,只能通过遍历区间 `[p,q]` 获取最小值;
-- 如果此时 `p`,`q` 相邻,说明此时 `q` 指向的元素是最小值,返回 `array[q]`;
-- 如果此时 `array[mid] >= array[p]`,说明 `mid` 位于左边的递增数组中,最小值在右边,因此,把 `p` 指向 `mid`,此时保持了 `p` 指向左边递增子数组;
-- 如果此时 `array[mid] <= array[q]`,说明 `mid` 位于右边的递增数组中,最小值在左边,因此,把 `q` 指向 `mid`,此时保持了 `q` 指向右边递增子数组。
-
-```java
-
-
-/**
- * @author bingo
- * @since 2018/10/30
- */
-
-public class Solution {
- /**
- * 获取旋转数组的最小元素
- * @param array 旋转数组
- * @return 数组中的最小值
- */
- public int minNumberInRotateArray(int[] array) {
- if (array == null || array.length == 0) {
- return 0;
- }
-
- int p = 0;
- // mid初始为p,为了兼容当数组是递增数组(即不满足 array[p] >= array[q])时,返回 array[p]
- int mid = p;
- int q = array.length - 1;
- while (array[p] >= array[q]) {
- if (q - p == 1) {
- // 当p,q相邻时(距离为1),那么q指向的元素就是最小值
- mid = q;
- break;
- }
- mid = p + ((q - p) >> 1);
-
- // 当p,q,mid指向的值相等时,此时只能通过遍历查找最小值
- if (array[p] == array[q] && array[mid] == array[p]) {
- mid = getMinIndex(array, p, q);
- break;
- }
-
- if (array[mid] >= array[p]) {
- p = mid;
- } else if (array[mid] <= array[q]) {
- q = mid;
- }
- }
-
- return array[mid];
-
-
- }
-
- private int getMinIndex(int[] array, int p, int q) {
- int minIndex = p;
- for (int i = p + 1; i <= q; ++i) {
- minIndex = array[i] < array[minIndex] ? i : minIndex;
- }
- return minIndex;
- }
-}
-```
-
-
-### 测试用例
-1. 功能测试(输入的数组是升序排序数组的一个旋转,数组中有重复数字或者没有重复数字);
-2. 边界值测试(输入的数组是一个升序排序的数组,只包含一个数字的数组);
-3. 特殊输入测试(输入空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/12_StringPathInMatrix.md b/docs/jianzhioffer/java/12_StringPathInMatrix.md
deleted file mode 100644
index 9a87e9e3e..000000000
--- a/docs/jianzhioffer/java/12_StringPathInMatrix.md
+++ /dev/null
@@ -1,66 +0,0 @@
-## 矩阵中的路径
-
-### 题目描述
-请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 `a b c e s f c s a d e e` 这样的 `3 X 4` 矩阵中包含一条字符串`"bcced"`的路径,但是矩阵中不包含`"abcb"`路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
-
-### 解法
-回溯法。首先,任选一个格子作为路径起点。假设格子对应的字符为 ch,并且对应路径上的第 i 个字符。若相等,到相邻格子寻找路径上的第 i+1 个字符。重复这一过程。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
- /**
- * 判断矩阵中是否包含某条路径
- * @param matrix 矩阵
- * @param rows 行数
- * @param cols 列数
- * @param str 路径
- * @return bool
- */
- public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
- if (matrix == null || rows < 1 || cols < 1 || str == null) {
- return false;
- }
- boolean[] visited = new boolean[matrix.length];
- int pathLength = 0;
- for (int i = 0; i < rows; ++i) {
- for (int j = 0; j < cols; ++j) {
- if (hasPath(matrix, rows, cols, str, i, j, pathLength, visited)) {
- return true;
- }
- }
- }
- return false;
- }
-
- private boolean hasPath(char[] matrix, int rows, int cols, char[] str, int i, int j, int pathLength, boolean[] visited) {
- if (pathLength == str.length) {
- return true;
- }
- boolean hasPath = false;
- if (i >= 0 && i < rows && j >= 0 && j < cols && matrix[i * cols + j] == str[pathLength] && !visited[i * cols + j]) {
- ++pathLength;
- visited[i * cols + j] = true;
- hasPath = hasPath(matrix, rows, cols, str, i - 1, j, pathLength, visited)
- || hasPath(matrix, rows, cols, str, i + 1, j, pathLength, visited)
- || hasPath(matrix, rows, cols, str, i, j - 1, pathLength, visited)
- || hasPath(matrix, rows, cols, str, i, j + 1, pathLength, visited);
- if (!hasPath) {
- --pathLength;
- visited[i * cols + j] = false;
- }
- }
- return hasPath;
- }
-}
-
-```
-
-### 测试用例
-1. 功能测试(在多行多列的矩阵中存在或者不存在路径);
-2. 边界值测试(矩阵只有一行或者一列;矩阵和路径中的所有字母都是相同的);
-3. 特殊输入测试(输入空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/13_RobotMove.md b/docs/jianzhioffer/java/13_RobotMove.md
deleted file mode 100644
index 7a4e8d5ed..000000000
--- a/docs/jianzhioffer/java/13_RobotMove.md
+++ /dev/null
@@ -1,66 +0,0 @@
-## 机器人的移动范围
-
-### 题目描述
-地上有一个`m`行和`n`列的方格。一个机器人从坐标`0,0`的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于`k`的格子。 例如,当`k`为`18`时,机器人能够进入方格`(35,37)`,因为`3+5+3+7 = 18`。但是,它不能进入方格`(35,38)`,因为`3+5+3+8 = 19`。请问该机器人能够达到多少个格子?
-
-### 解法
-从坐标(0, 0) 开始移动,当它准备进入坐标(i, j),判断是否能进入,如果能,再判断它能否进入 4 个相邻的格子 (i-1, j), (i+1, j), (i, j-1), (i, j+1)。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
- /**
- * 计算能到达的格子数
- * @param threshold 限定的数字
- * @param rows 行数
- * @param cols 列数
- * @return 格子数
- */
- public int movingCount(int threshold, int rows, int cols) {
- if (threshold < 0 || rows < 1 || cols < 1) {
- return 0;
- }
- boolean[] visited = new boolean[rows * cols];
- return getCount(threshold, 0, 0, rows, cols, visited);
- }
-
- private int getCount(int threshold, int i, int j, int rows, int cols, boolean[] visited) {
- if (check(threshold, i, j, rows, cols, visited)) {
- visited[i * cols + j] = true;
- return 1
- + getCount(threshold, i - 1, j, rows, cols, visited)
- + getCount(threshold, i + 1, j, rows, cols, visited)
- + getCount(threshold, i, j - 1, rows, cols, visited)
- + getCount(threshold, i, j + 1, rows, cols, visited);
- }
- return 0;
- }
-
- private boolean check(int threshold, int i, int j, int rows, int cols, boolean[] visited) {
- return i >= 0
- && i < rows
- && j >= 0
- && j < cols
- && !visited[i * cols + j]
- && getDigitSum(i) + getDigitSum(j) <= threshold;
- }
-
- private int getDigitSum(int i) {
- int res = 0;
- while (i > 0) {
- res += i % 10;
- i /= 10;
- }
- return res;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(方格为多行多列;k 为正数);
-2. 边界值测试(方格只有一行或者一列;k = 0);
-3. 特殊输入测试(k < 0)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/14_CuttingRope.md b/docs/jianzhioffer/java/14_CuttingRope.md
deleted file mode 100644
index c120a5b78..000000000
--- a/docs/jianzhioffer/java/14_CuttingRope.md
+++ /dev/null
@@ -1,102 +0,0 @@
-## 剪绳子
-
-### 题目描述
-给你一根长度为`n`绳子,请把绳子剪成`m`段(`m`、`n`都是整数,`n>1`并且`m≥1`)。每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]*k[1]*…*k[m]可能的最大乘积是多少?例如当绳子的长度是 8 时,我们把它剪成长度分别为 `2、3、3` 的三段,此时得到最大的乘积`18`。
-
-### 解法
-#### 解法一:动态规划法
-时间复杂度`O(n²)`,空间复杂度`O(n)`。
-
-- 长度为 2,只可能剪成长度为 1 的两段,因此 f(2)=1
-- 长度为 3,剪成长度分别为 1 和 2 的两段,乘积比较大,因此 f(3) = 2
-- 长度为 n,在剪第一刀的时候,有 n-1 种可能的选择,剪出来的绳子又可以继续剪,可以看出,原问题可以划分为子问题,子问题又有重复子问题。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
-
- /**
- * 剪绳子求最大乘积
- * @param length 绳子长度
- * @return 乘积最大值
- */
- public int maxProductAfterCutting(int length) {
- if (length < 2) {
- return 0;
- }
- if (length < 4) {
- return length - 1;
- }
-
- // res[i] 表示当长度为i时的最大乘积
- int[] res = new int[length + 1];
- res[1] = 1;
- res[2] = 2;
- res[3] = 3;
- // 从长度为4开始计算
- for (int i = 4; i <= length; ++i) {
- int max = 0;
- for (int j = 1; j <= i / 2; ++j) {
- max = Math.max(max, res[j] * res[i - j]);
- }
- res[i] = max;
- }
-
- return res[length];
-
- }
-}
-
-```
-
-#### 贪心算法
-时间复杂度`O(1)`,空间复杂度`O(1)`。
-
-贪心策略:
-- 当 n>=5 时,尽可能多地剪长度为 3 的绳子
-- 当剩下的绳子长度为 4 时,就把绳子剪成两段长度为 2 的绳子。
-
-**证明:**
-- 当 n>=5 时,可以证明 2(n-2)>n,并且 3(n-3)>n。也就是说,当绳子剩下长度大于或者等于 5 的时候,可以把它剪成长度为 3 或者 2 的绳子段。
-- 当 n>=5 时,3(n-3)>=2(n-2),因此,应该尽可能多地剪长度为 3 的绳子段。
-- 当 n=4 时,剪成两根长度为 2 的绳子,其实没必要剪,只是题目的要求是至少要剪一刀。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
-
- /**
- * 剪绳子求最大乘积
- * @param length 绳子长度
- * @return 乘积最大值
- */
- public int maxProductAfterCutting(int length) {
- if (length < 2) {
- return 0;
- }
- if (length < 4) {
- return length - 1;
- }
-
- int timesOf3 = length / 3;
- if (length % 3 == 1) {
- --timesOf3;
- }
- int timesOf2 = (length - timesOf3 * 3) >> 1;
- return (int) (Math.pow(3, timesOf3) * Math.pow(2, timesOf2));
- }
-}
-
-```
-
-### 测试用例
-1. 功能测试(绳子的初始长度大于 5);
-2. 边界值测试(绳子的初始长度分别为 0、1、2、3、4)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/15_NumberOf1InBinary.md b/docs/jianzhioffer/java/15_NumberOf1InBinary.md
deleted file mode 100644
index 23bf9351a..000000000
--- a/docs/jianzhioffer/java/15_NumberOf1InBinary.md
+++ /dev/null
@@ -1,73 +0,0 @@
-## 二进制中 1 的个数
-
-### 题目描述
-输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
-
-### 解法
-#### 解法一
-利用整数 1,依次左移每次与 n 进行与运算,若结果不为0,说明这一位上数字为 1,++cnt。
-
-此解法 i 需要左移 32 次。
-
-不要用 n 去右移并与 1 进行与运算,因为n 可能为负数,右移时会陷入死循环。
-
-```java
-public class Solution {
- public int NumberOf1(int n) {
- int cnt = 0;
- int i = 1;
- while (i != 0) {
- if ((n & i) != 0) {
- ++cnt;
- }
- i <<= 1;
- }
- return cnt;
- }
-}
-```
-
-#### 解法二(推荐)
-- 运算 (n - 1) & n,直至 n 为 0。运算的次数即为 n 的二进制中 1 的个数。
-
-因为 n-1 会将 n 的最右边一位 1 改为 0,如果右边还有 0,则所有 0 都会变成 1。结果与 n 进行与运算,会去除掉最右边的一个1。
-
-举个栗子:
-```
-若 n = 1100,
-n - 1 = 1011
-n & (n - 1) = 1000
-
-即:把最右边的 1 变成了 0。
-```
-
-> 把一个整数减去 1 之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的 1 变成 0。很多二进制的问题都可以用这种思路解决。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
- /**
- * 计算整数的二进制表示里1的个数
- * @param n 整数
- * @return 1的个数
- */
- public int NumberOf1(int n) {
- int cnt = 0;
- while (n != 0) {
- n = (n - 1 ) & n;
- ++cnt;
- }
- return cnt;
- }
-}
-
-```
-
-### 测试用例
-1. 正数(包括边界值 1、0x7FFFFFFF);
-2. 负数(包括边界值 0x80000000、0xFFFFFFFF);
-3. 0。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/16_Power.md b/docs/jianzhioffer/java/16_Power.md
deleted file mode 100644
index f1bbc09c8..000000000
--- a/docs/jianzhioffer/java/16_Power.md
+++ /dev/null
@@ -1,36 +0,0 @@
-## 数值的整数次方
-
-### 题目描述
-给定一个 `double` 类型的浮点数 `base` 和 `int` 类型的整数 `exponent`。求 `base`的 `exponent` 次方。
-
-### 解法
-注意判断值数是否小于 0。另外 0 的 0 次方没有意义,也需要考虑一下,看具体题目要求。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
- /**
- * 计算数值的整数次方
- * @param base 底数
- * @param exponent 指数
- * @return 数值的整数次方
- */
- public double Power(double base, int exponent) {
- double result = 1.0;
- int n = Math.abs(exponent);
- for (int i = 0; i < n; ++i) {
- result *= base;
- }
-
- return exponent < 0 ? 1.0 / result : result;
- }
-}
-
-```
-
-### 测试用例
-1. 把底数和指数分别设为正数、负数和零。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/17_Print1ToMaxOfNDigits.md b/docs/jianzhioffer/java/17_Print1ToMaxOfNDigits.md
deleted file mode 100644
index 86b8e8fa3..000000000
--- a/docs/jianzhioffer/java/17_Print1ToMaxOfNDigits.md
+++ /dev/null
@@ -1,90 +0,0 @@
-## 打印从 1 到最大的 n 位数
-
-### 题目描述
-输入数字 `n`,按顺序打印出从 `1` 最大的 `n` 位十进制数。比如输入 `3`,则打印出 `1、2、3` 一直到最大的 3 位数即 999。
-
-### 解法
-此题需要注意 n 位数构成的数字可能超出最大的 int 或者 long long 能表示的范围。因此,采用字符数组来存储数字。
-
-关键是:
-- 对字符数组表示的数进行递增操作
-- 输出数字(0开头的需要把0去除)
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
-
- /**
- * 打印从1到最大的n位数
- * @param n n位
- */
- public void print1ToMaxOfNDigits(int n) {
- if (n < 1) {
- return;
- }
-
- char[] chars = new char[n];
- for (int i = 0; i < n; ++i) {
- chars[i] = '0';
- }
-
- while (!increment(chars)) {
- printNumber(chars);
- }
- }
-
- /**
- * 打印数字(去除前面的0)
- * @param chars 数字数组
- */
- private void printNumber(char[] chars) {
- int index = 0;
- int n = chars.length;
- for (char ch : chars) {
- if (ch != '0') {
- break;
- }
- ++index;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = index; i < n; ++i) {
- sb.append(chars[i]);
- }
- System.out.println(sb.toString());
- }
-
- /**
- * 数字加1
- * @param chars 数字数组
- * @return 是否溢出
- */
- private boolean increment(char[] chars) {
- boolean flag = false;
- int n = chars.length;
- int carry = 1;
- for (int i = n - 1; i >= 0; --i) {
-
- int num = chars[i] - '0' + carry;
- if (num > 9) {
- if (i == 0) {
- flag = true;
- break;
- }
- chars[i] = '0';
- } else {
- ++chars[i];
- break;
- }
- }
- return flag;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入 1、2、3......);
-2. 特殊输入测试(输入 -1、0)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/18_01_DeleteNodeInList.md b/docs/jianzhioffer/java/18_01_DeleteNodeInList.md
deleted file mode 100644
index fdebe01dc..000000000
--- a/docs/jianzhioffer/java/18_01_DeleteNodeInList.md
+++ /dev/null
@@ -1,59 +0,0 @@
-## 在O(1)时间内删除链表节点
-
-### 题目描述
-给定单向链表的头指针和一个节点指针,定义一个函数在 O(1) 时间内删除该节点。
-
-### 解法
-判断要删除的节点是否是尾节点,若是,直接删除;若不是,把要删除节点的下一个节点赋给要删除的节点即可。
-
-### ```进行n次操作,平均时间复杂度为:( (n-1) * O(1) + O(n) ) / n = O(1),所以符合题目上说的O(1)```
-
-```java
-/**
- * @author bingo
- * @since 2018/11/20
- */
-
-public class Solution {
-
- class ListNode {
- int val;
- ListNode next;
- }
-
- /**
- * 删除链表的节点
- * @param head 链表头节点
- * @param tobeDelete 要删除的节点
- */
- public ListNode deleteNode(ListNode head, ListNode tobeDelete) {
- if (head == null || tobeDelete == null) {
- return head;
- }
-
- // 删除的不是尾节点
- if (tobeDelete.next != null) {
- tobeDelete.val = tobeDelete.next.val;
- tobeDelete.next = tobeDelete.next.next;
- }
- // 链表中仅有一个节点
- else if (head == tobeDelete) {
- head = null;
- }
- // 删除的是尾节点
- else {
- ListNode ptr = head;
- while (ptr.next != tobeDelete) {
- ptr = ptr.next;
- }
- ptr.next = null;
- }
-
- return head;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(从有多个节点的链表的中间/头部/尾部删除一个节点;从只有一个节点的链表中删除唯一的节点);
-2. 特殊输入测试(指向链表头节点的为空指针;指向要删除节点的为空指针)。
diff --git a/docs/jianzhioffer/java/18_02_DeleteDuplicatedNode.md b/docs/jianzhioffer/java/18_02_DeleteDuplicatedNode.md
deleted file mode 100644
index 054e6e341..000000000
--- a/docs/jianzhioffer/java/18_02_DeleteDuplicatedNode.md
+++ /dev/null
@@ -1,94 +0,0 @@
-## 删除链表中重复的节点
-
-### 题目描述
-在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表`1->2->3->3->4->4->5` 处理后为 `1->2->5`。
-
-### 解法
-#### 解法一:递归
-
-```java
-/**
- * @author bingo
- * @since 2018/11/21
- */
-
-/*
- public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}
-*/
-public class Solution {
- /**
- * 删除链表重复的节点
- * @param pHead 链表头节点
- * @return 删除节点后的链表
- */
- public ListNode deleteDuplication(ListNode pHead) {
- if (pHead == null || pHead.next == null) {
- return pHead;
- }
-
- if (pHead.val == pHead.next.val) {
- if (pHead.next.next == null) {
- return null;
- }
- if (pHead.next.next.val == pHead.val) {
- return deleteDuplication(pHead.next);
- }
- return deleteDuplication(pHead.next.next);
- }
- pHead.next = deleteDuplication(pHead.next);
- return pHead;
- }
-}
-```
-
-#### 解法二
-```java
-/*
- public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}
-*/
-public class Solution {
- public ListNode deleteDuplication(ListNode pHead) {
- if (pHead == null || pHead.next == null) {
- return pHead;
- }
-
- ListNode pre = null;
- ListNode cur = pHead;
- while (cur != null) {
- if (cur.next != null && cur.next.val == cur.val) {
- int val = cur.val;
- while (cur.next != null && cur.next.val == val) {
- cur = cur.next;
- }
- if (pre == null) {
- pHead = cur.next;
- } else {
- pre.next = cur.next;
- }
- } else {
- pre = cur;
- }
- cur = cur.next;
- }
- return pHead;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(重复的节点位于链表的头部/中间/尾部;链表中没有重复的节点);
-2. 特殊输入测试(指向链表头节点的为空指针;链表中所有节点都是重复的)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/19_RegularExpressionsMatching.md b/docs/jianzhioffer/java/19_RegularExpressionsMatching.md
deleted file mode 100644
index 5cd4833bb..000000000
--- a/docs/jianzhioffer/java/19_RegularExpressionsMatching.md
+++ /dev/null
@@ -1,68 +0,0 @@
-## 正则表达式匹配
-
-### 题目描述
-请实现一个函数用来匹配包括`.`和`*`的正则表达式。模式中的字符`.`表示任意一个字符,而`*`表示它前面的字符可以出现任意次(包含`0`次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串`aaa`与模式`a.a`和`ab*ac*a`匹配,但是与`aa.a`和`ab*a`均不匹配。
-
-### 解法
-判断模式中第二个字符是否是 `*`:
-- 若是,看如果模式串第一个字符与字符串第一个字符是否匹配:
- - 1. 若不匹配,在模式串上向右移动两个字符`j+2`,相当于 a* 被忽略
- - 2. 若匹配,字符串后移`i+1`。此时模式串可以移动两个字符`j+2`,也可以不移动`j`。
-- 若不是,看当前字符与模式串的当前字符是否匹配,即 str[i] == pattern[j] || pattern[j] == '.':
- - 1. 若匹配,则字符串与模式串都向右移动一位,`i+1`,`j+1`。
- - 2. 若不匹配,返回 fasle。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/21
- */
-
-public class Solution {
- /**
- * 判断字符串是否与模式串匹配
- * @param str 字符串
- * @param pattern 模式串
- * @return 是否匹配
- */
- public boolean match(char[] str, char[] pattern) {
- if (str == null || pattern == null) {
- return false;
- }
- return match(str, 0, str.length, pattern, 0, pattern.length);
- }
-
- private boolean match(char[] str, int i, int len1,
- char[] pattern, int j, int len2) {
- if (i == len1 && j == len2) {
- return true;
- }
-
- // "",".*"
- if (i != len1 && j == len2) {
- return false;
- }
-
- if (j + 1 < len2 && pattern[j + 1] == '*') {
- if (i < len1 && (str[i] == pattern[j] || pattern[j] == '.')) {
- return match(str, i, len1, pattern, j + 2, len2)
- || match(str, i + 1, len1, pattern, j, len2)
- || match(str, i + 1, len1, pattern,j + 2, len2);
- }
-
- // "",".*"
- return match(str, i, len1, pattern, j + 2, len2);
-
- }
- if (i < len1 && (str[i] == pattern[j] || pattern[j] == '.')) {
- return match(str, i + 1, len1, pattern, j + 1, len2);
- }
- return false;
-
- }
-}
-```
-
-### 测试用例
-1. 功能测试(模式字符串里包含普通字符、`.`、`*`;模式字符串和输入字符串匹配/不匹配);
-2. 特殊输入测试(输入字符串和模式字符串是空指针、空字符串)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/20_NumericStrings.md b/docs/jianzhioffer/java/20_NumericStrings.md
deleted file mode 100644
index 55fa620c8..000000000
--- a/docs/jianzhioffer/java/20_NumericStrings.md
+++ /dev/null
@@ -1,115 +0,0 @@
-## 表示数值的字符串
-
-### 题目描述
-请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
-
-### 解法
-
-#### 解法一
-
-利用正则表达式匹配即可。
-```
-[] : 字符集合
-() : 分组
-? : 重复 0 ~ 1
-+ : 重复 1 ~ n
-* : 重复 0 ~ n
-. : 任意字符
-\\. : 转义后的 .
-\\d : 数字
-```
-
-```java
-/**
- * @author bingo
- * @since 2018/11/21
- */
-
-public class Solution {
- /**
- * 判断是否是数字
- * @param str
- * @return
- */
- public boolean isNumeric(char[] str) {
- return str != null
- && str.length != 0
- && new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?");
- }
-}
-```
-
-#### 解法二【剑指offer解法】
-
-表示数值的字符串遵循模式`A[.[B]][e|EC]`或者`.B[e|EC]`,其中A为数值的整数部分,B紧跟小数点为数值的小数部分,C紧跟着e或者E为数值的指数部分。上述A和C都有可能以 `+` 或者 `-` 开头的0~9的数位串,B也是0~9的数位串,但前面不能有正负号。
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2018/12/29
- * @description
- */
-public class Solution {
-
- private int index = 0;
-
- /**
- * 判断是否是数值
- * @param str
- * @return
- */
- public boolean isNumeric(char[] str) {
- if (str == null || str.length < 1) {
- return false;
- }
-
- // 判断是否存在整数
- boolean flag = scanInteger(str);
-
- // 小数部分
- if (index < str.length && str[index] == '.') {
- index++;
- // 小数部分可以有整数或者没有整数
- // 所以使用 ||
- flag = scanUnsignedInteger(str) || flag;
- }
-
- if (index < str.length && (str[index] == 'e' || str[index] == 'E')) {
- index++;
- // e或E前面必须有数字
- // e或者E后面必须有整数
- // 所以使用 &&
- flag = scanInteger(str) && flag;
- }
-
- return flag && index == str.length;
-
- }
-
- private boolean scanInteger(char[] str) {
- // 去除符号
- while (index < str.length && (str[index] == '+' || str[index] == '-')) {
- index++;
- }
-
- return scanUnsignedInteger(str);
- }
-
- private boolean scanUnsignedInteger(char[] str) {
- int start = index;
- while (index < str.length && str[index] >= '0' && str[index] <= '9') {
- index++;
- }
- // 判断是否存在整数
- return index > start;
- }
-}
-```
-
-
-
-### 测试用例
-
-1. 功能测试(正数或者负数;包含或者不包含整数部分的数值;包含或者不包含效数部分的值;包含或者不包含指数部分的值;各种不能表达有效数值的字符串);
-2. 特殊输入测试(输入字符串和模式字符串是空指针、空字符串)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/21_ReorderArray.md b/docs/jianzhioffer/java/21_ReorderArray.md
deleted file mode 100644
index a4730a321..000000000
--- a/docs/jianzhioffer/java/21_ReorderArray.md
+++ /dev/null
@@ -1,68 +0,0 @@
-## 调整数组顺序使奇数位于偶数前面
-
-### 题目描述
-输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
-
-### 解法
-#### 解法一
-计算出奇数的个数,就很容易写出来了。
-
-```java
-import java.util.Arrays;
-
-/**
- * @author bingo
- * @since 2018/11/21
- */
-
-public class Solution {
- /**
- * 调整数组元素顺序,使得奇数元素位于偶数元素前面,且保证奇数和奇数,偶数和偶数之间的相对位置不变。
- * @param array 数组
- */
- public void reOrderArray(int [] array) {
- if (array == null || array.length < 2) {
- return;
- }
-
- int numsOfOdd = 0;
- for (int val : array) {
- if (val % 2 == 1) {
- ++numsOfOdd;
- }
- }
- int[] bak = Arrays.copyOf(array, array.length);
- int i = 0, j = numsOfOdd;
- for (int val : bak) {
- if (val % 2 == 1) {
- array[i++] = val;
- } else {
- array[j++] = val;
- }
- }
- }
-
-}
-```
-
-#### 解法二
-```java
-import java.util.Arrays;
-
-public class Solution {
- public void reOrderArray(int [] array) {
- if (array == null || array.length < 2) {
- return;
- }
- Integer[] bak = new Integer[array.length];
- Arrays.setAll(bak, i -> array[i]);
- Arrays.sort(bak, (x, y) -> (y & 1) - (x & 1));
- Arrays.setAll(array, i -> bak[i]);
- }
-
-}
-```
-
-### 测试用例
-1. 功能测试(输入数组中的奇数、偶数交替出现;输入的数组中所有偶数都出现在奇数的前面;输入的数组中所有偶数都出现在奇数的前面;输入的数组中所有奇数都出现在偶数的前面);
-2. 特殊输入测试(输入空指针;输入的数组只包含一个数字)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/22_KthNodeFromEnd.md b/docs/jianzhioffer/java/22_KthNodeFromEnd.md
deleted file mode 100644
index 2e54c99e4..000000000
--- a/docs/jianzhioffer/java/22_KthNodeFromEnd.md
+++ /dev/null
@@ -1,61 +0,0 @@
-## 链表中倒数第k个结点
-
-### 题目描述
-输入一个链表,输出该链表中倒数第k个结点。
-
-### 解法
-pre 指针走 `k-1` 步。之后 cur 指针指向 phead,然后两个指针同时走,直至 pre 指针到达尾结点。
-
-> 当用一个指针遍历链表不能解决问题的时候,可以尝试用两个指针来遍历链表。可以让其中一个指针遍历的速度快一些。
-
-此题需要考虑一些特殊情况。比如 k 的值小于 0 或者大于链表长度。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/21
- */
-
-/*
-public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}*/
-public class Solution {
- /**
- * 找出链表倒数第k个节点,k从1开始
- * @param head 链表头部
- * @param k 第k个节点
- * @return 倒数第k个节点
- */
- public ListNode FindKthToTail(ListNode head,int k) {
- if (head == null || k < 1) {
- return null;
- }
-
- ListNode pre = head;
- for (int i = 0; i < k - 1; ++i) {
- if (pre.next != null) {
- pre = pre.next;
- } else {
- return null;
- }
- }
-
- ListNode cur = head;
- while (pre.next != null) {
- pre = pre.next;
- cur = cur.next;
- }
- return cur;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(第 k 个节点在链表的中间/头部/尾部);
-2. 特殊输入测试(输入空指针;链表的节点总数小于 k;k=0)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/23_EntryNodeInListLoop.md b/docs/jianzhioffer/java/23_EntryNodeInListLoop.md
deleted file mode 100644
index 262cd9f58..000000000
--- a/docs/jianzhioffer/java/23_EntryNodeInListLoop.md
+++ /dev/null
@@ -1,83 +0,0 @@
-## 链表中环的入口结点
-
-### 题目描述
-给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出`null`。
-
-### 解法
-- 先利用快慢指针。若能相遇,说明存在环,且相遇点一定是在环上;若没有相遇,说明不存在环,返回 `null`。
-- 固定当前相遇点,用一个指针继续走,同时累积结点数。计算出环的结点个数 `cnt`。
-- 指针 p1 先走 `cnt` 步,p2 指向链表头部,之后 `p1`,`p2` 同时走,相遇时,相遇点一定是在环的入口处。因为 `p1` 比 `p2` 多走了环的一圈。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-/*
- public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}
-*/
-public class Solution {
-
- /**
- * 求链表环的入口,若没有环,返回null
- * @param pHead 链表头
- * @return 环的入口点
- */
- public ListNode EntryNodeOfLoop(ListNode pHead) {
- if (pHead == null || pHead.next == null) {
- return null;
- }
- ListNode fast = pHead;
- ListNode slow = pHead;
- boolean flag = false;
- while (fast != null && fast.next != null) {
- slow = slow.next;
- fast = fast.next.next;
- if (fast == slow) {
- flag = true;
- break;
- }
- }
-
- // 快指针与慢指针没有相遇,说明无环,返回 null
- if (!flag) {
- return null;
- }
-
- ListNode cur = slow.next;
- // 求出环中结点个数
- int cnt = 1;
- while (cur != slow) {
- cur = cur.next;
- ++cnt;
- }
-
- // 指针p1先走cnt步
- ListNode p1 = pHead;
- for (int i = 0; i < cnt; ++i) {
- p1 = p1.next;
- }
-
- // p2指向链表头,然后p1/p2同时走,首次相遇的地方就是环的入口
- ListNode p2 = pHead;
- while (p1 != p2) {
- p1 = p1.next;
- p2 = p2.next;
- }
- return p1;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(链表中包含/不包含环;链表中有多个或者只有一个节点);
-2. 特殊输入测试(链表头节点为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/24_ReverseList.md b/docs/jianzhioffer/java/24_ReverseList.md
deleted file mode 100644
index 118d65874..000000000
--- a/docs/jianzhioffer/java/24_ReverseList.md
+++ /dev/null
@@ -1,94 +0,0 @@
-## 反转链表
-
-### 题目描述
-输入一个链表,反转链表后,输出新链表的表头。
-
-### 解法
-#### 解法一
-利用头插法解决。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-/*
-public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}*/
-public class Solution {
- /**
- * 反转链表
- * @param head 链表头部
- * @return 反转后的链表
- */
- public ListNode ReverseList(ListNode head) {
- if (head == null || head.next == null) {
- return head;
- }
-
- ListNode dummy = new ListNode(-1);
- dummy.next = null;
- ListNode p1 = head;
- ListNode p2 = p1.next;
- while (p1 != null) {
- p1.next = dummy.next;
- dummy.next = p1;
- p1 = p2;
- if (p1 == null) {
- break;
- }
- p2 = p1.next;
- }
-
- return dummy.next;
- }
-}
-```
-
-#### 解法二:递归
-
-```java
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-
-/*
-public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}*/
-public class Solution {
- public ListNode ReverseList(ListNode head) {
- if (head == null || head.next == null) {
- return head;
- }
-
- ListNode next = ReverseList(head.next);
- ListNode cur = next;
- while (cur.next != null) {
- cur = cur.next;
- }
- cur.next = head;
- head.next = null;
- return next;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(链表中有多个结点/只有一个节点);
-2. 特殊输入测试(链表头节点为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/25_MergeSortedLists.md b/docs/jianzhioffer/java/25_MergeSortedLists.md
deleted file mode 100644
index 9bcc3c7b0..000000000
--- a/docs/jianzhioffer/java/25_MergeSortedLists.md
+++ /dev/null
@@ -1,112 +0,0 @@
-## 合并两个排序的链表
-
-### 题目描述
-输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
-
-### 解法
-#### 解法一
-同时遍历两链表进行 `merge`。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-/*
-public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}*/
-public class Solution {
- /**
- * 合并两个排序链表
- * @param list1 链表1
- * @param list2 链表2
- * @return 合并后的单调不递减链表
- */
- public ListNode Merge(ListNode list1, ListNode list2) {
- if (list1 == null) {
- return list2;
- }
- if (list2 == null) {
- return list1;
- }
-
- ListNode dummy = new ListNode(-1);
- ListNode cur = dummy;
- ListNode p1 = list1;
- ListNode p2 = list2;
- while (p1 != null && p2 != null) {
- if (p1.val < p2.val) {
- ListNode t = p1.next;
- cur.next = p1;
- p1.next = null;
- p1 = t;
- } else {
- ListNode t = p2.next;
- cur.next = p2;
- p2.next = null;
- p2 = t;
- }
- cur = cur.next;
- }
-
- cur.next = p1 == null ? p2 : p1;
- return dummy.next;
-
- }
-}
-```
-
-#### 解法二:递归
-```java
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-/*
-public class ListNode {
- int val;
- ListNode next = null;
-
- ListNode(int val) {
- this.val = val;
- }
-}*/
-public class Solution {
- /**
- * 合并两个排序链表
- * @param list1 链表1
- * @param list2 链表2
- * @return 合并后的单调不递减链表
- */
- public ListNode Merge(ListNode list1, ListNode list2) {
- if (list1 == null) {
- return list2;
- }
- if (list2 == null) {
- return list1;
- }
-
- if (list1.val < list2.val) {
- list1.next = Merge(list1.next, list2);
- return list1;
- }
-
- list2.next = Merge(list1, list2.next);
- return list2;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的两个链表有多个节点;节点的值互不相同或者存在值相等的多个节点);
-2. 特殊输入测试(两个链表的一个或者两个头节点为空指针;两个链表中只有一个节点)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/26_SubstructureInTree.md b/docs/jianzhioffer/java/26_SubstructureInTree.md
deleted file mode 100644
index 24b852e96..000000000
--- a/docs/jianzhioffer/java/26_SubstructureInTree.md
+++ /dev/null
@@ -1,69 +0,0 @@
-## 树的子结构
-
-### 题目描述
-输入两棵二叉树`A`,`B`,判断`B`是不是`A`的子结构。(ps:我们约定空树不是任意一个树的子结构)
-
-### 解法
-递归方式遍历:
-
-- 在树A中找到和树B的根结点值一样的结点R
-- 判断树A以R为根结点的子树是否包含与树B一样的结构
-
-这道题的time complexity应该为O(n * m),其中n为root1的节点数,m为root2的节点数。
-
-```java
-/**
-public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-}
-*/
-
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/01/01
- * @description
- */
-public class Solution {
-
- public boolean HasSubtree(TreeNode root1, TreeNode root2) {
-
- if (root1 == null || root2 == null) {
- return false;
- }
-
- return isSame(root1, root2) ||
- HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
- }
-
- private boolean isSame(TreeNode root1, TreeNode root2) {
-
- if (root2 == null) {
- return true;
- }
-
- // 在root2,root1遍历完成后,仍未找到符合的结构,返回false
- if (root1 == null) {
- return false;
- }
-
- if (root1.val != root2.val) {
- return false;
- }
-
- return isSame(root1.left, root2.left) && isSame(root1.right, root2.right);
- }
-
-}
-```
-
-### 测试用例
-1. 功能测试(树A和树B都是普通的二叉树;树B是/不是树A的子结构);
-2. 特殊输入测试(两棵二叉树的一个或者两个根结点为空指针,二叉树的所有结点都没有左/右子树)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/27_MirrorOfBinaryTree.md b/docs/jianzhioffer/java/27_MirrorOfBinaryTree.md
deleted file mode 100644
index 8e036d5c2..000000000
--- a/docs/jianzhioffer/java/27_MirrorOfBinaryTree.md
+++ /dev/null
@@ -1,70 +0,0 @@
-## 二叉树的镜像
-
-### 题目描述
-操作给定的二叉树,将其变换为源二叉树的镜像。
-
-```
-源二叉树
- 8
- / \
- 6 10
- / \ / \
- 5 7 9 11
-
-镜像二叉树
- 8
- / \
- 10 6
- / \ / \
- 11 9 7 5
-```
-
-### 解法
-将根结点的左右孩子互换,之后递归左右孩子。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-/*
- public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-
- }
- */
-public class Solution {
- /**
- * 将二叉树转换为它的镜像
- * @param root 二叉树的根结点
- */
- public void Mirror(TreeNode root) {
- if (root == null || !hasChild(root)) {
- return;
- }
-
- TreeNode t = root.left;
- root.left = root.right;
- root.right = t;
- Mirror(root.left);
- Mirror(root.right);
- }
-
- private boolean hasChild(TreeNode root) {
- return root.left != null || root.right != null;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(普通的二叉树;二叉树的所有结点都没有左/右子树;只有一个结点的二叉树);
-2. 特殊输入测试(二叉树的根结点为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/28_SymmetricalBinaryTree.md b/docs/jianzhioffer/java/28_SymmetricalBinaryTree.md
deleted file mode 100644
index 6b13edefe..000000000
--- a/docs/jianzhioffer/java/28_SymmetricalBinaryTree.md
+++ /dev/null
@@ -1,58 +0,0 @@
-## 对称的二叉树
-
-### 题目描述
-请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
-
-### 解法
-比较二叉树的前序遍历序列和对称前序遍历序列是否一样,若是,说明是对称的。
-
-```java
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-/*
-public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-
-}
-*/
-public class Solution {
- /**
- * 判断是否是对称二叉树
- * @param pRoot 二叉树的根结点
- * @return 是否为对称二叉树
- */
- boolean isSymmetrical(TreeNode pRoot) {
- return isSymmetrical(pRoot, pRoot);
- }
-
- private boolean isSymmetrical(TreeNode pRoot1, TreeNode pRoot2) {
- if (pRoot1 == null && pRoot2 == null) {
- return true;
- }
- if (pRoot1 == null || pRoot2 == null) {
- return false;
- }
- if (pRoot1.val != pRoot2.val) {
- return false;
- }
-
- return isSymmetrical(pRoot1.left, pRoot2.right) && isSymmetrical(pRoot1.right, pRoot2.left);
-
- }
-}
-```
-
-### 测试用例
-1. 功能测试(对称的二叉树;因结构而不对称的二叉树;结构对称但节点的值不对称的二叉树);
-2. 特殊输入测试(二叉树的根结点为空指针;只有一个节点的二叉树;所有节点的值都相同的二叉树)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/29_PrintMatrix.md b/docs/jianzhioffer/java/29_PrintMatrix.md
deleted file mode 100644
index e47e18c89..000000000
--- a/docs/jianzhioffer/java/29_PrintMatrix.md
+++ /dev/null
@@ -1,103 +0,0 @@
-## 顺时针打印矩阵
-
-### 题目描述
-输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下 `4 X 4` 矩阵:
-```
-1 2 3 4
-5 6 7 8
-9 10 11 12
-13 14 15 16
-```
-
-则依次打印出数字:
-```
-1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
-```
-### 解法
-剑指offer上的思路有点复杂,需要考虑坐标变换太多,考虑用另一种思路来解决。
-
-在矩阵中,使用左上角坐标(tR,tC)和右下角的坐标(dR,dC)就可以表示一个矩阵。比如题目中的矩阵,当(tR,tC) = (0,0)和(dR,dC) = (3,3)时,表示的子矩阵就是整个矩阵:
-
-```java
-1 2 3 4
-5 8
-9 12
-13 14 15 16
-```
-
-当外层循环遍历后,可以令tR和tC加1,dR和dC减1,执行内层循环。当左上角的坐标跑到右下角坐标的右方或者下方,则整个过程就终止。
-
-```java
-/**
- * @author mcrwayfun
- * @version 1.0
- * @description
- * @date Created in 2019/1/2
- */
-public class Solution {
- /**
- * 转圈打印矩阵
- * @param matrix 矩阵
- * @return 存放结果的list
- */
- public ArrayList printMatrix(int[][] matrix) {
- ArrayList reList = new ArrayList<>();
- if (matrix == null) {
- return reList;
- }
-
- int tR = 0;
- int tC = 0;
- int dR = matrix.length - 1;
- int dC = matrix[0].length - 1;
-
- while (tR <= dR && tC <= dC) {
- printMatrix(matrix, tR++, tC++, dR--, dC--, reList);
- }
-
- return reList;
- }
-
- public void printMatrix(int[][] matrix, int tR, int tC, int dR, int dC, ArrayList reList) {
- // 只有一行
- if (tR == dR) {
- for (int i = tC; i <= dC; i++) {
- reList.add(matrix[tR][i]);
- }
- }
- // 只有一列
- else if (tC == dC) {
- for (int i = tR; i <= dR; i++) {
- reList.add(matrix[i][tC]);
- }
- } else {
- int curR = tR;
- int curC = tC;
- // 从左到右
- while (curC != dC) {
- reList.add(matrix[tR][curC]);
- curC++;
- }
- // 从上到下
- while (curR != dR) {
- reList.add(matrix[curR][dC]);
- curR++;
- }
- // 从右到左
- while (curC != tC) {
- reList.add(matrix[dR][curC]);
- curC--;
- }
- // 从下到上
- while (curR != tR) {
- reList.add(matrix[curR][tC]);
- curR--;
- }
- }
-
- }
-}
-```
-
-### 测试用例
-1. 数组中有多行多列;数组中只有一行;数组中只有一列;数组中只有一行一列。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/30_MinInStack.md b/docs/jianzhioffer/java/30_MinInStack.md
deleted file mode 100644
index 38353b273..000000000
--- a/docs/jianzhioffer/java/30_MinInStack.md
+++ /dev/null
@@ -1,63 +0,0 @@
-## 包含min函数的栈
-
-### 题目描述
-定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为`O(1)`)。
-
-### 解法
-定义两个`stack`。
-
-压栈时,先将元素`node`压入`stack1`。然后判断`stack2`的情况:
-- `stack2`栈为空或者栈顶元素大于`node`,则将`node`压入`stack2`中。
-- `stack2`栈不为空且栈定元素小于`node`,则重复压入栈顶元素。
-
-获取最小元素时,从`stack2`中获取栈顶元素即可。
-
-```java
-import java.util.Stack;
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-
-public class Solution {
-
- private Stack stack1 = new Stack<>();
- private Stack stack2 = new Stack<>();
-
- /**
- * 压栈
- * @param node 待压入的元素
- */
- public void push(int node) {
- stack1.push(node);
- if (stack2.isEmpty() || stack2.peek() >= node) {
- stack2.push(node);
- } else {
- stack2.push(stack2.peek());
- }
- }
-
- public void pop() {
- stack1.pop();
- stack2.pop();
- }
-
- public int top() {
- return stack2.peek();
- }
-
- /**
- * O(1)获取栈中最小值
- * @return 最小值
- */
- public int min() {
- return stack2.peek();
- }
-}
-```
-
-### 测试用例
-1. 新压入栈的数字比之前的最小值大/小。
-2. 弹出栈的数字是/不是最小元素。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/31_StackPushPopOrder.md b/docs/jianzhioffer/java/31_StackPushPopOrder.md
deleted file mode 100644
index 3b2a5e590..000000000
--- a/docs/jianzhioffer/java/31_StackPushPopOrder.md
+++ /dev/null
@@ -1,58 +0,0 @@
-## 栈的压入、弹出序列
-
-### 题目描述
-输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列`1,2,3,4,5`是某栈的压入顺序,序列`4,5,3,2,1`是该压栈序列对应的一个弹出序列,但`4,3,5,1,2`就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
-
-### 解法
-判断下一个要弹出的元素:
-- 如果刚好是栈顶元素,直接弹出。
-- 如果不在栈顶,则把压栈序列中还没有入栈的数字压入栈,直到待弹出的数字压入栈顶。
-- 如果所有数字都压入栈顶后依然没有后找到下一个弹出的数字,则不可能是弹出序列。
-
-```java
-import java.util.Stack;
-
-/**
- * @author bingo
- * @since 2018/11/22
- */
-
-
-public class Solution {
- /**
- * 判断是否是弹出序列
- * @param pushA 压栈序列
- * @param popA 弹栈序列
- * @return 是否是弹出序列
- */
- public boolean IsPopOrder(int[] pushA,int[] popA) {
- if (pushA == null || popA == null || pushA.length != popA.length) {
- return false;
- }
-
- Stack stack = new Stack<>();
- int i = 0;
- int n = pushA.length;
- boolean flag = false;
- for (int val : popA) {
- while (stack.isEmpty() || stack.peek() != val) {
- if (i >= n) {
- flag = true;
- break;
- }
- stack.push(pushA[i++]);
- }
- if (flag) {
- break;
- }
- stack.pop();
- }
-
- return stack.isEmpty();
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的两个数组含有多个数字或者只有一个数字:第二个数组是/不是第一个数组表示的压入序列对应的栈的弹出序列);
-2. 特殊输入测试(输入两个空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/32_01_PrintTreeFromTopToBottom.md b/docs/jianzhioffer/java/32_01_PrintTreeFromTopToBottom.md
deleted file mode 100644
index c93a997e5..000000000
--- a/docs/jianzhioffer/java/32_01_PrintTreeFromTopToBottom.md
+++ /dev/null
@@ -1,64 +0,0 @@
-## 不分行从上到下打印二叉树
-
-### 题目描述
-从上往下打印出二叉树的每个节点,同层节点从左至右打印。
-
-### 解法
-先将根节点进入队列。
-
-队头元素出队,将值存入 list,判断该元素是否有左/右子树,有的话依次进入队列中。队列为空时结束。
-
-```java
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Queue;
-
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-/**
- public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-
- }
- */
-public class Solution {
- /**
- * 从上到下打印二叉树
- * @param root 二叉树根节点
- * @return 结果list
- */
- public ArrayList PrintFromTopToBottom(TreeNode root) {
- ArrayList list = new ArrayList<>();
- if (root == null) {
- return list;
- }
- Queue queue = new LinkedList<>();
- queue.offer(root);
- while (!queue.isEmpty()) {
- TreeNode node = queue.poll();
- if (node.left != null) {
- queue.offer(node.left);
- }
- if (node.right != null) {
- queue.offer(node.right);
- }
- list.add(node.val);
- }
- return list;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(完全二叉树;所有节点只有左/右子树);
-2. 特殊输入测试(二叉树根节点为空指针;只有一个节点的二叉树)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/32_02_PrintTreesInLines.md b/docs/jianzhioffer/java/32_02_PrintTreesInLines.md
deleted file mode 100644
index 4904948ff..000000000
--- a/docs/jianzhioffer/java/32_02_PrintTreesInLines.md
+++ /dev/null
@@ -1,73 +0,0 @@
-## 把二叉树打印成多行
-
-### 题目描述
-从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
-
-### 解法
-与上一题类似,只不过需要用变量记录每一层要打印多少个节点。
-
-```java
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Queue;
-
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-/*
-public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-
-}
-*/
-public class Solution {
- /**
- * 把二叉树打印成多行
- * @param pRoot 二叉树根节点
- * @return 结果list
- */
- ArrayList > Print(TreeNode pRoot) {
- ArrayList> list = new ArrayList<>();
- if (pRoot == null) {
- return list;
- }
-
- Queue queue = new LinkedList<>();
- queue.offer(pRoot);
- int cnt = 1;
- while (cnt > 0) {
- int num = cnt;
- cnt = 0;
- ArrayList res = new ArrayList<>();
- for (int i = 0; i < num; ++i) {
- TreeNode node = queue.poll();
- if (node.left != null) {
- queue.offer(node.left);
- ++cnt;
- }
- if (node.right != null) {
- queue.offer(node.right);
- ++cnt;
- }
- res.add(node.val);
- }
- list.add(res);
- }
- return list;
- }
-
-}
-```
-
-### 测试用例
-1. 功能测试(完全二叉树;所有节点只有左/右子树);
-2. 特殊输入测试(二叉树根节点为空指针;只有一个节点的二叉树)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/32_03_PrintTreesInZigzag.md b/docs/jianzhioffer/java/32_03_PrintTreesInZigzag.md
deleted file mode 100644
index 538f10c0a..000000000
--- a/docs/jianzhioffer/java/32_03_PrintTreesInZigzag.md
+++ /dev/null
@@ -1,104 +0,0 @@
-## 按之字形打印二叉树
-
-### 题目描述
-请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
-
-如二叉树:
-```
- 1
- / \
- 2 3
- / \ / \
- 4 5 6 7
-```
-
-打印结果为:
-```
-1
-3 2
-4 5 6 7
-```
-
-### 解法
-对于上述二叉树:
-
-首先访问根结点,之后把2、3存入某结构。打印的时候,先打印3、2。这不就是栈?
-
-依次弹出栈元素,分别是3、2。弹出时需要把3、2的子结点存入结构。由于访问时顺序是`4 5 6 7`。所以也需要用栈来存放。而且,此时需要先存放右孩子,再存放左孩子。(奇数层/偶数层存放左右孩子的顺序不同)
-
-这里需要用两个栈来实现。如果只用一个栈,那么当弹出3、2 时,先将 3 的孩子节点压入栈。之后弹栈的时候不是先弹出 2,而是弹出了 3 的 孩子节点,就错了。
-
-
-```java
-import java.util.ArrayList;
-import java.util.Stack;
-
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-/*
-public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-
-}
-*/
-public class Solution {
- /**
- * 按之字形打印二叉树
- * @param pRoot 二叉树的根节点
- * @return 结果list
- */
- public ArrayList> Print(TreeNode pRoot) {
- ArrayList> res = new ArrayList<>();
- if (pRoot == null) {
- return res;
- }
- Stack stack1 = new Stack<>();
- Stack stack2 = new Stack<>();
- stack1.push(pRoot);
- int i = 1;
- Stack stack = stack1;
- while (!stack.isEmpty()) {
- ArrayList list = new ArrayList<>();
- while (!stack.isEmpty()) {
- TreeNode node = stack.pop();
- list.add(node.val);
- if (i % 2 == 1) {
- if (node.left != null) {
- stack2.push(node.left);
- }
- if (node.right != null) {
- stack2.push(node.right);
- }
- } else {
- if (node.right != null) {
- stack1.push(node.right);
- }
- if (node.left != null) {
- stack1.push(node.left);
- }
- }
- }
- res.add(list);
- ++i;
- stack = stack1.isEmpty() ? stack2 : stack1;
- }
-
- return res;
- }
-
-}
-```
-
-### 测试用例
-1. 功能测试(完全二叉树;所有节点只有左/右子树);
-2. 特殊输入测试(二叉树根节点为空指针;只有一个节点的二叉树)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/33_SquenceOfBST.md b/docs/jianzhioffer/java/33_SquenceOfBST.md
deleted file mode 100644
index 4d99624f8..000000000
--- a/docs/jianzhioffer/java/33_SquenceOfBST.md
+++ /dev/null
@@ -1,60 +0,0 @@
-## 二叉搜索树的后序遍历序列
-
-### 题目描述
-输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出`Yes`,否则输出`No`。假设输入的数组的任意两个数字都互不相同。
-
-### 解法
-序列的最后一个元素是二叉搜索树的根节点。
-
-在序列中从左到右找到根节点的左子树(比根节点小)、右子树(比根节点大)。
-- 如果右子树中出现比根节点小的元素,那么为 false。
-- 否则递归左右子树。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-public class Solution {
- /**
- * 判断数组是否是某个二叉搜索树的后序遍历序列
- *
- * @param sequence 数组
- * @return 是否属于某二叉搜索树的后序遍历序列
- */
- public boolean VerifySquenceOfBST(int[] sequence) {
- if (sequence == null || sequence.length < 1) {
- return false;
- }
- return verify(sequence, 0, sequence.length - 1);
- }
-
- private boolean verify(int[] sequence, int start, int end) {
- if (start >= end) {
- return true;
- }
- int val = sequence[end];
- int i = start;
- for (; i <= end; ++i) {
- if (sequence[i] >= val) {
- break;
- }
- }
-
- for (int j = i; j < end; ++j) {
- if (sequence[j] < val) {
- return false;
- }
- }
-
- return verify(sequence, start, i - 1) && verify(sequence, i, end - 1);
-
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的后序遍历序列对应一棵二叉树,包括完全二叉树、所有节点都没有左/右子树的二叉树、只有一个节点的二叉树;输入的后续遍历序列没有对应一棵二叉树);
-2. 特殊输入测试(后序遍历序列为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/34_PathInTree.md b/docs/jianzhioffer/java/34_PathInTree.md
deleted file mode 100644
index d4dfc62a6..000000000
--- a/docs/jianzhioffer/java/34_PathInTree.md
+++ /dev/null
@@ -1,64 +0,0 @@
-## 二叉树中和为某一值的路径
-
-### 题目描述
-输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的`list`中,数组长度大的数组靠前)
-
-### 解法
-
-```java
-import java.util.ArrayList;
-
-/**
- * @author bingo
- * @since 2018/11/23
- */
-
-/**
- public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-
- }
- */
-public class Solution {
-
- private ArrayList> res = new ArrayList<>();
-
- /**
- * 找出二叉树中和为某一值的路径(必须从根节点到叶节点)
- *
- * @param root 二叉树的根结点
- * @param target 目标值
- * @return 结果list
- */
- public ArrayList> FindPath(TreeNode root, int target) {
- findPath(root, target, new ArrayList<>());
- return res;
- }
-
- private void findPath(TreeNode root, int target, ArrayList list) {
- if (root == null) {
- return;
- }
- list.add(root.val);
- target -= root.val;
- if (target == 0 && root.left == null && root.right == null) {
- res.add(new ArrayList<>(list));
- } else {
- findPath(root.left, target, list);
- findPath(root.right, target, list);
- }
- list.remove(list.size() - 1);
- }
-}
-```
-
-### 测试用例
-1. 功能测试(二叉树中有一条、多条符合要求的路径;二叉树中没有符合要求的路径);
-2. 特殊输入测试(指向二叉树根节点的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/35_CopyComplexList.md b/docs/jianzhioffer/java/35_CopyComplexList.md
deleted file mode 100644
index 762e595c8..000000000
--- a/docs/jianzhioffer/java/35_CopyComplexList.md
+++ /dev/null
@@ -1,73 +0,0 @@
-## 复杂链表的复制
-
-### 题目描述
-输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的 `head`。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
-
-### 解法
-可以分为3步:
-
-1. 复制每个节点,并插入到被复制节点的后面。比如1->2->3 clone 1->1->2->2->3->3
-2. 复制随机节点。当遍历到的当前节点存在随机节点时,则其复制节点也应该存在随机节点。比如当前节点`cur.random != null`,则`RandomListNode clone = cur.next;clone.random = cur.random.next;`
-3. 分离两个链表。其中奇数链表为原链表,偶数链表为复制的链表
-
-这道题的time complexity为O(n)。
-
-```java
-/**
- * @author bingo
- * @since 2018/11/24
- */
-
-/*
-public class RandomListNode {
- int label;
- RandomListNode next = null;
- RandomListNode random = null;
-
- RandomListNode(int label) {
- this.label = label;
- }
-}
-*/
-public class Solution {
- /**
- * 复杂链表的复制
- * @param pHead 链表头结点
- * @return 复制的链表
- */
- public RandomListNode Clone(RandomListNode pHead) {
- if (pHead == null) {
- return null;
- }
- RandomListNode cur = pHead;
- while (cur != null) {
- RandomListNode node = new RandomListNode(cur.label);
- node.next = cur.next;
- cur.next = node;
- cur = node.next;
- }
-
- cur = pHead;
- while (cur != null) {
- RandomListNode clone = cur.next;
- if (cur.random != null) {
- clone.random = cur.random.next;
- }
- cur = clone.next;
- }
-
- cur = pHead;
- RandomListNode cloneHead = pHead.next;
- while (cur.next != null) {
- RandomListNode clone = cur.next;
- cur.next = clone.next;
- cur = clone;
- }
- return cloneHead;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(结点中的 random 指针指向结点自身;两个结点的 random 形成环状结构;链表中只有一个结点);
-2. 特殊输入测试(指向链表头结点的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/36_ConvertBinarySearchTree.md b/docs/jianzhioffer/java/36_ConvertBinarySearchTree.md
deleted file mode 100644
index d80076e29..000000000
--- a/docs/jianzhioffer/java/36_ConvertBinarySearchTree.md
+++ /dev/null
@@ -1,76 +0,0 @@
-## 二叉搜索树与双向链表
-
-### 题目描述
-输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
-
-### 解法
-由于是二叉搜索树,因此中序遍历的结果就是排序的。
-
-中序遍历利用栈来实现。遍历时,前一个结点的 right 指向后一个结点,后一个结点的 left 指向前一个结点。
-```java
-pre.right = cur
-cur.left = pre
-```
-
-```java
-import java.util.Stack;
-
-/**
- * @author bingo
- * @since 2018/11/24
- */
-
-/**
- public class TreeNode {
- int val = 0;
- TreeNode left = null;
- TreeNode right = null;
-
- public TreeNode(int val) {
- this.val = val;
-
- }
-
- }
- */
-public class Solution {
- /**
- * 将二叉搜索树转换为双向链表
- *
- * @param pRootOfTree
- * @return
- */
- public TreeNode Convert(TreeNode pRootOfTree) {
- if (pRootOfTree == null) {
- return null;
- }
- Stack stack = new Stack<>();
- TreeNode cur = pRootOfTree;
- TreeNode res = null;
- TreeNode pre = null;
- while (cur != null || !stack.isEmpty()) {
- if (cur != null) {
- stack.push(cur);
- cur = cur.left;
- } else {
- cur = stack.pop();
- if (pre == null) {
- pre = cur;
- res = pre;
- } else {
- pre.right = cur;
- cur.left = pre;
- pre = cur;
- }
- cur = cur.right;
-
- }
- }
- return res;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的二叉树是完全二叉树;所有结点都没有左/右子树;只有一个结点的二叉树);
-2. 特殊输入测试(指向二叉树根结点的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/37_SerializeBinaryTrees.md b/docs/jianzhioffer/java/37_SerializeBinaryTrees.md
deleted file mode 100644
index e9795c2f3..000000000
--- a/docs/jianzhioffer/java/37_SerializeBinaryTrees.md
+++ /dev/null
@@ -1,89 +0,0 @@
-## 序列化二叉树
-
-### 题目描述
-请实现两个函数,分别用来序列化和反序列化二叉树。使用前序遍历实现,空节点使用字符`#` 表示。
-
-比如有如下二叉树:
-
-```java
- 1
- 2 3
- 4 # 5 6
- # # # # # #
-```
-
-序列化的结果为 `1,2,4,#,#,#,3,5,#,#,6,#,#`
-
-反序列化的结果为上述二叉树
-
-### 解法
-使用前序遍历进行序列化和反序列化。对格式没有要求,只要序列化得到的结果,再反序列化后能与原树相同即可。
-```java
-/**
- * @author mcrwayfun
- * @version 1.0
- * @description
- * @date Created in 2019/1/12
- */
-public class Solution {
-
-
- public String Serialize(TreeNode root) {
-
- StringBuilder res = new StringBuilder();
- if (root == null) {
- return res.toString();
- }
-
- serializeHelper(root, res);
- // 移除最后一个的符号","
- res.deleteCharAt(res.lastIndexOf(","));
- return res.toString();
- }
-
- private void serializeHelper(TreeNode root, StringBuilder res) {
-
- if (root == null) {
- res.append("#");
- res.append(",");
- return;
- }
-
- res.append(root.val);
- res.append(",");
- serializeHelper(root.left, res);
- serializeHelper(root.right, res);
- }
-
- private int index = -1;
-
- public TreeNode Deserialize(String str) {
-
- if (str == null || str.length() == 0) {
- return null;
- }
-
- String[] treeNodeStr = str.split(",");
- return deserializeHelper(treeNodeStr);
- }
-
- private TreeNode deserializeHelper(String[] treeNodeStr) {
-
- index++;
- TreeNode node = null;
-
- // index不越界并且当前节点不为#
- if (index < treeNodeStr.length && !"#".equals(treeNodeStr[index])) {
- node = new TreeNode(Integer.valueOf(treeNodeStr[index]));
- node.left = deserializeHelper(treeNodeStr);
- node.right = deserializeHelper(treeNodeStr);
- }
-
- return node;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的二叉树是完全二叉树;所有节点都没有左/右子树的二叉树;只有一个节点的二叉树;所有节点的值都相同的二叉树);
-2. 特殊输入测试(指向二叉树根结点的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/38_StringPermutation.md b/docs/jianzhioffer/java/38_StringPermutation.md
deleted file mode 100644
index b603cb511..000000000
--- a/docs/jianzhioffer/java/38_StringPermutation.md
+++ /dev/null
@@ -1,74 +0,0 @@
-## 字符串的排列
-
-### 题目描述
-输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。(输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母)。ps:牛客上的测试用例对返回的list要排序。
-
-### 解法
-对整个字符串的排列可以看成两部分。第一步求所有可能出现在第一个位置的字符,即把第一个字符与后面所有非重复的字符进行交换。第二步固定第一个字符,求后面所有字符的排列;第二步中后面的所有字符又可以看成一个完整的字符,继续执行这两个步骤。
-
-注意存在重复值得情况,比如输入字符串bab,将首字符b作为固定字符串,对于将第2个下标的b换到首位仍然是bab,所有这种情况无需输出。
-
-**这道题的时间复杂度应该为O(n!)**
-
-```java
-/**
- * @author mcrwayfun
- * @version 1.0
- * @description
- * @date Created in 2019/1/14
- */
-public class Solution {
-
- public ArrayList Permutation(String str) {
-
- ArrayList reList = new ArrayList<>();
-
- if (str == null || str.length() == 0) {
- return reList;
- }
-
- char[] chars = str.toCharArray();
-
- // 递归输出字符串排列
- permutationHelper(chars, 0, reList);
- Collections.sort(reList);
- return reList;
- }
-
- private void permutationHelper(char[] chars, int index, ArrayList list) {
-
- if (index == chars.length - 1) {
- list.add(new String(chars));
- return;
- }
-
- Set set = new HashSet<>();
- // 确定交换的字符,包括自己[index,length-1]
- for (int i = index; i < chars.length; i++) {
-
- // 排除出现重复字符
- // hash表,查询花费O(1)
- if (!set.contains(chars[i])) {
- set.add(chars[i]);
- // 固定字符index
- swap(chars, i, index);
- // 递归固定剩余字符[index+1,length-1]
- permutationHelper(chars, index + 1, list);
- // 恢复原数组
- swap(chars, index, i);
- }
- }
- }
-
- private void swap(char[] chars, int x, int y) {
-
- char temp = chars[x];
- chars[x] = chars[y];
- chars[y] = temp;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的字符串有一个或多个字符);
-2. 特殊输入测试(输入的字符串为nullptr指针或者内容为空)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/39_MoreThanHalfNumber.md b/docs/jianzhioffer/java/39_MoreThanHalfNumber.md
deleted file mode 100644
index a256e5abe..000000000
--- a/docs/jianzhioffer/java/39_MoreThanHalfNumber.md
+++ /dev/null
@@ -1,162 +0,0 @@
-## 数组中出现次数超过一半的数字
-
-### 题目描述
-数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为 9 的数组 `{1,2,3,2,2,2,5,4,2}`。由于数字 2 在数组中出现了 5 次,超过数组长度的一半,因此输出 2。如果不存在则输出 0。
-
-### 解法
-#### 解法一
-利用快排中的 partition 思想。
-
-数组中有一个数字出现次数超过了数组长度的一半,那么排序后,数组中间的数字一定就是我们要找的数字。我们随机选一个数字,利用 partition() 函数,使得比选中数字小的数字都排在它左边,比选中数字大的数字都排在它的右边。
-
-判断选中数字的下标 `index`:
-
-- 如果 `index = n/2`,那么这个数字就是中位数。
-- 如果 `index > n/2`,那么接着在 index 的左边进行 partition。
-- 如果 `index < n/2`,则在 index 的右边继续进行 partition。
-
-**注意:**这种方法会修改输入的数组。时间复杂度为 `O(n)`。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/6
- */
-
-public class Solution {
- /**
- * 查找数组中出现次数超过一次的数字
- *
- * @param array 数组
- * @return 返回该数,不存在则返回0
- */
- public int MoreThanHalfNum_Solution(int[] array) {
- if (array == null || array.length == 0) {
- return 0;
- }
- int n = array.length;
- int start = 0, end = n - 1;
- int mid = n >> 1;
- int index = partition(array, start, end);
- while (index != mid) {
- if (index > mid) {
- end = index - 1;
- } else {
- start = index + 1;
- }
- index = partition(array, start, end);
- }
-
- return isMoreThanHalf(array, array[index]) ? array[index] : 0;
- }
-
- /**
- * 快排中的 partition 方法
- *
- * @param array 数组
- * @param start 开始位置
- * @param end 结束位置
- * @return
- */
- private int partition(int[] array, int start, int end) {
- int small = start - 1;
- for (int i = start; i < end; ++i) {
- if (array[i] < array[end]) {
- swap(array, i, ++small);
- }
- }
- ++small;
- swap(array, small, end);
- return small;
-
- }
-
- private void swap(int[] array, int i, int j) {
- int t = array[i];
- array[i] = array[j];
- array[j] = t;
- }
-
- /**
- * 判断val元素是否真的超过数组元素个数的一半
- *
- * @param array 数组
- * @param val 某元素
- * @return boolean
- */
- private boolean isMoreThanHalf(int[] array, int val) {
- int cnt = 0;
- for (int e : array) {
- if (e == val) {
- ++cnt;
- }
- }
-
- return cnt * 2 > array.length;
- }
-}
-```
-
-#### 解法二
-利用多数投票算法,从头到尾遍历数组,遇到两个不一样的数就把这两个数同时除去。除去的两个数可能都不是 majority,也可能一个是 majority 另一个不是,但是因为 majority 总数大于一半,所以这么删完最后剩下的肯定是 majority。
-
-此方法时间复杂度为 `O(n)`,且不会改变数组。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/6
- */
-
-public class Solution {
- /**
- * 查找数组中出现次数超过一次的数字
- *
- * @param array 数组
- * @return 返回该数,不存在则返回0
- */
- public int MoreThanHalfNum_Solution(int[] array) {
- if (array == null || array.length == 0) {
- return 0;
- }
-
- int res = array[0];
- int times = 1;
- for (int i = 1; i < array.length; ++i) {
- if (times == 0) {
- res = array[i];
- times = 1;
- } else if (array[i] == res) {
- ++times;
- } else {
- --times;
- }
- }
-
- return isMoreThanHalf(array, res) ? res : 0;
- }
-
-
- /**
- * 判断val元素是否真的超过数组元素个数的一半
- *
- * @param array 数组
- * @param val 某元素
- * @return boolean
- */
- private boolean isMoreThanHalf(int[] array, int val) {
- int cnt = 0;
- for (int e : array) {
- if (e == val) {
- ++cnt;
- }
- }
-
- return cnt * 2 > array.length;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的数组中存在/不存在一个出现次数超过数组长度一半的数字);
-2. 特殊输入测试(输入的数组只有一个数字;输入空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/40_KLeastNumbers.md b/docs/jianzhioffer/java/40_KLeastNumbers.md
deleted file mode 100644
index 645478a08..000000000
--- a/docs/jianzhioffer/java/40_KLeastNumbers.md
+++ /dev/null
@@ -1,132 +0,0 @@
-## 获取数组中最小的k个数
-
-### 题目描述
-输入 n 个整数,找出其中最小的 K 个数。例如输入 `4,5,1,6,2,7,3,8` 这 8 个数字,则最小的 4 个数字是 `1,2,3,4`。
-
-### 解法
-#### 解法一
-利用快排中的 partition 思想。
-
-数组中有一个数字出现次数超过了数组长度的一半,那么排序后,数组中间的数字一定就是我们要找的数字。我们随机选一个数字,利用 partition() 函数,使得比选中数字小的数字都排在它左边,比选中数字大的数字都排在它的右边。
-
-判断选中数字的下标 `index`:
-
-- 如果 `index = k-1`,结束循环,返回前 k 个数。
-- 如果 `index > k-1`,那么接着在 index 的左边进行 partition。
-- 如果 `index < k-1`,则在 index 的右边继续进行 partition。
-
-**注意**,这种方法会修改输入的数组。时间复杂度为 `O(n)`。
-
-```java
-import java.util.ArrayList;
-
-/**
- * @author bingo
- * @since 2018/12/6
- */
-
-public class Solution {
-
- /**
- * 获取数组中最小的k个数
- *
- * @param input 输入的数组
- * @param k 元素个数
- * @return 最小的k的数列表
- */
- public ArrayList GetLeastNumbers_Solution(int[] input, int k) {
- ArrayList res = new ArrayList<>();
- if (input == null || input.length == 0 || input.length < k || k < 1) {
- return res;
- }
- int n = input.length;
- int start = 0, end = n - 1;
- int index = partition(input, start, end);
- while (index != k - 1) {
- if (index > k - 1) {
- end = index - 1;
- } else {
- start = index + 1;
- }
- index = partition(input, start, end);
- }
- for (int i = 0; i < k; ++i) {
- res.add(input[i]);
- }
- return res;
- }
-
- private int partition(int[] input, int start, int end) {
- int index = start - 1;
- for (int i = start; i < end; ++i) {
- if (input[i] < input[end]) {
- swap(input, i, ++index);
- }
- }
- ++index;
- swap(input, index, end);
- return index;
- }
-
- private void swap(int[] array, int i, int j) {
- int t = array[i];
- array[i] = array[j];
- array[j] = t;
- }
-}
-```
-
-#### 解法二
-利用大根堆,存储最小的 k 个数,最后返回即可。
-
-此方法时间复杂度为 `O(nlogk)`。虽然慢一点,但是它不会改变输入的数组,并且它**适合海量数据的输入**。
-
-假设题目要求从海量的数据中找出最小的 k 个数,由于内存的大小是有限的,有可能不能把这些海量的数据一次性全部载入内存。这个时候,用这种方法是最合适的。就是说它适合 n 很大并且 k 较小的问题。
-
-```java
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.PriorityQueue;
-
-/**
- * @author bingo
- * @since 2018/12/6
- */
-
-public class Solution {
-
- /**
- * 获取数组中最小的k个数
- *
- * @param input 输入的数组
- * @param k 元素个数
- * @return 最小的k的数列表
- */
- public ArrayList GetLeastNumbers_Solution(int[] input, int k) {
- ArrayList res = new ArrayList<>();
- if (input == null || input.length == 0 || input.length < k || k < 1) {
- return res;
- }
-
- PriorityQueue maxHeap = new PriorityQueue<>(k, Comparator.reverseOrder());
- System.out.println(maxHeap.size());
- for (int e : input) {
- if (maxHeap.size() < k) {
- maxHeap.add(e);
- } else {
- if (maxHeap.peek() > e) {
- maxHeap.poll();
- maxHeap.add(e);
- }
-
- }
- }
- res.addAll(maxHeap);
- return res;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的数组中存在/不存在一个出现次数超过数组长度一半的数字);
-2. 特殊输入测试(输入的数组只有一个数字;输入空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/41_StreamMedian.md b/docs/jianzhioffer/java/41_StreamMedian.md
deleted file mode 100644
index f3e3ce8ed..000000000
--- a/docs/jianzhioffer/java/41_StreamMedian.md
+++ /dev/null
@@ -1,67 +0,0 @@
-## 数据流中的中位数
-
-### 题目描述
-如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用`Insert()`方法读取数据流,使用`GetMedian()`方法获取当前读取数据的中位数。
-
-### 解法
-利用大根堆存放较小的一半元素,小根堆存放较大的一半元素。维持大小堆的元素个数差不超过 1。
-
-
-```java
-import java.util.Comparator;
-import java.util.PriorityQueue;
-
-/**
- * @author bingo
- * @since 2018/12/7
- */
-
-public class Solution {
-
- private PriorityQueue minHeap = new PriorityQueue<>();
- private PriorityQueue maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
-
- /**
- * 插入一个数
- *
- * @param num 数
- */
- public void Insert(Integer num) {
-
- if (maxHeap.isEmpty() || num < maxHeap.peek()) {
- maxHeap.offer(num);
- if (maxHeap.size() - minHeap.size() > 1) {
- minHeap.offer(maxHeap.poll());
- }
-
- } else {
- minHeap.offer(num);
- if (minHeap.size() - maxHeap.size() > 1) {
- maxHeap.offer(minHeap.poll());
- }
- }
- }
-
- /**
- * 获取中位数
- *
- * @return 中位数
- */
- public Double GetMedian() {
- int size1 = maxHeap.size();
- int size2 = minHeap.size();
- if (size1 > size2) {
- return (double) maxHeap.peek();
- }
- if (size1 < size2) {
- return (double) minHeap.peek();
- }
-
- return (maxHeap.peek() + minHeap.peek()) / 2.0;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(从数据流中读出奇数/偶数个数字);
-2. 边界值测试(从数据流中读出 0/1/2 个数字)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/42_GreatestSumOfSubarrays.md b/docs/jianzhioffer/java/42_GreatestSumOfSubarrays.md
deleted file mode 100644
index e5a2d99c6..000000000
--- a/docs/jianzhioffer/java/42_GreatestSumOfSubarrays.md
+++ /dev/null
@@ -1,49 +0,0 @@
-## 连续子数组的最大和
-
-### 题目描述
-输入一个**非空**整型数组,数组里的数可能为正,也可能为负。
-数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。
-
-要求时间复杂度为`O(n)`。
-
-### 解法
-动态规划法。
-
-res[i] 表示以第 i 个数字结尾的子数组的最大和,那么求出 `max(res[i])` 即可。
-
-- `res[i] = array[i]`, if `res[i - 1] < 0`
-- `res[i] = res[i - 1] + array[i]`, if `res[i - 1] >= 0`
-
-```java
-
-/**
- * @author bingo
- * @since 2018/12/7
- */
-
-public class Solution {
- /**
- * 求连续子数组的最大和
- *
- * @param array 数组
- * @return 最大和
- */
- public int FindGreatestSumOfSubArray(int[] array) {
- int n = array.length;
- int[] res = new int[n];
- res[0] = array[0];
- int max = res[0];
- for (int i = 1; i < n; ++i) {
- res[i] = res[i - 1] > 0 ? res[i - 1] + array[i] : array[i];
- max = Math.max(max, res[i]);
- }
- return max;
- }
-}
-
-
-```
-
-### 测试用例
-1. 功能测试(输入的数组中有正数也有负数;输入的数组中全是正数;输入的数组中全是负数);
-2. 特殊输入测试(表示数组的指针位为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/43_NumberOf1.md b/docs/jianzhioffer/java/43_NumberOf1.md
deleted file mode 100644
index 27352aafc..000000000
--- a/docs/jianzhioffer/java/43_NumberOf1.md
+++ /dev/null
@@ -1,66 +0,0 @@
-## 整数中1出现的次数
-
-### 题目描述
-求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
-
-### 解法
-- 编程之美上给出的规律:
-
- 1. 如果第i位(自右至左,从1开始标号)上的数字为0,则第i位可能出现1的次数由更高位决定(若没有高位,视高位为0),等于更高位数字X当前位数的权重10^(i-1)。
- 2. 如果第i位上的数字为1,则第i位上可能出现1的次数不仅受更高位影响,还受低位影响(若没有低位,视低位为0),等于更高位数字X当前位数的权重10^(i-1)+(低位数字+1)。
- 3. 如果第i位上的数字大于1,则第i位上可能出现1的次数仅由更高位决定(若没有高位,视高位为0),等于(更高位数字+1)X当前位数的权重10^(i-1)。
-
- 总结一下以上的算法,可以看到,当计算右数第 i 位包含的 X 的个数时:
-
- 1. 取第 i 位左边(高位)的数字,乘以 10i−1,得到**基础值** a。
- 2. 取第 i 位数字,计算**修正值**:
- 1. 如果大于 X,则结果为 a+10i−1。
- 2. 如果小于 X,则结果为 a。
- 3. 如果等 X,则取第 i 位右边(低位)数字,设为 b,最后结果为 a+b+1。
-
- 相应的代码非常简单,效率也非常高,时间复杂度只有 O(logn)。
-
-```java
-
-/**
- * @author mcrwayfun
- * @version 1.0
- * @description
- * @date Created in 2019/1/17
- */
-public class Solution {
-
- public int NumberOf1Between1AndN_Solution(int n) {
-
- if (n < 1) {
- return 0;
- }
-
- int high, low, curr, tmp, i = 1;
- high = n;
- int number = 0;
- while (high != 0) {
- // 获取第i位的高位
- high = n / (int) Math.pow(10, i);
- tmp = n % (int) Math.pow(10, i);
- // 获取第i位
- curr = tmp / (int) Math.pow(10, i - 1);
- // 获取第i位的低位
- low = tmp % (int) Math.pow(10, i - 1);
- if (curr == 1) {
- number += high * (int) Math.pow(10, i - 1) + low + 1;
- } else if (curr < 1) {
- number += high * (int) Math.pow(10, i - 1);
- } else {
- number += (high + 1) * (int) Math.pow(10, i - 1);
- }
- i++;
- }
- return number;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入1~n的数字);
-2. 特殊输入测试(输入的数字小于0)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/44_DigitsInSequence.md b/docs/jianzhioffer/java/44_DigitsInSequence.md
deleted file mode 100644
index 427f37445..000000000
--- a/docs/jianzhioffer/java/44_DigitsInSequence.md
+++ /dev/null
@@ -1,71 +0,0 @@
-## 数字序列中某一位的数字
-
-### 题目描述
-数字以 `0123456789101112131415…` 的格式序列化到一个字符序列中。
-
-在这个序列中,第 5 位(从 0 开始计数)是 5,第 13 位是 1,第 19 位是 4,等等。
-
-请写一个函数求任意位对应的数字。
-
-### 解法
-举个栗子,求序列第 1001 位。
-
-序列的前 10 位是 `0~9`, 这 10 个只有一位的数字。显然第 1001 位在这 10 个数字之后,因此这 10 个数字可以直接跳过。再从后面序列中找第 991(991=1001-10) 位的数字。接下来有 90 个两位数,共 180 位,由于 991>180,所以继续跳过。从 881 找...最后可以找到对应的数字以及数字的某一位。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/7
- */
-
-public class Solution {
- /**
- * 求数字序列中某一位的数字
- *
- * @param n 第n位
- * @return 第n位的数字
- */
- public int digitAtIndex(int n) {
- if (n < 0) {
- return -1;
- }
- int digits = 1;
- while (true) {
- long numbers = countOfIntegers(digits);
- if (n < digits * numbers) {
- break;
- }
- n -= numbers * digits;
- ++digits;
- }
- return digitAtIndex(digits, n);
-
- }
-
- private long countOfIntegers(int digits) {
- return digits == 1
- ? 10
- : (int) (9 * Math.pow(10, digits - 1));
- }
-
- private int digitAtIndex(int digits, int n) {
- int beginNumber = getBeginNumber(digits);
- int val = beginNumber + n / digits;
- int indexFromRight = digits - n % digits;
- for (int i = 1; i < indexFromRight; ++i) {
- val /= 10;
- }
- return val % 10;
- }
-
- private int getBeginNumber(int digits) {
- return digits == 1
- ? 0
- : (int) Math.pow(10, digits - 1);
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入 10、190、1000);
-2. 边界值测试(输入 0、1)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/45_SortArrayForMinNumber.md b/docs/jianzhioffer/java/45_SortArrayForMinNumber.md
deleted file mode 100644
index b563cb46e..000000000
--- a/docs/jianzhioffer/java/45_SortArrayForMinNumber.md
+++ /dev/null
@@ -1,50 +0,0 @@
-## 把数组排成最小的数
-
-### 题目描述
-输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
-
-例如输入数组 `[3, 32, 321]`,则打印出这3个数字能排成的最小数字`321323`。
-
-### 解法
-
-
-```java
-import java.util.Arrays;
-
-/**
- * @author bingo
- * @since 2018/12/8
- */
-
-class Solution {
-
- /**
- * 打印数组元素组成的最小的数字
- *
- * @param nums 数组
- * @return 最小的数字
- */
- public String printMinNumber(int[] nums) {
- if (nums == null || nums.length == 0) {
- return "";
- }
- int n = nums.length;
- String[] strNums = new String[n];
- for (int i = 0; i < n; ++i) {
- strNums[i] = String.valueOf(nums[i]);
- }
-
- Arrays.sort(strNums, (o1, o2) -> (o1 + o2).compareTo(o2 + o1));
-
- StringBuilder sb = new StringBuilder();
- for (String str : strNums) {
- sb.append(str);
- }
- return sb.toString();
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的数组中有多个数字;输入的数组中的数字有重复的数位;输入的数组中只有一个数字);
-2. 特殊输入测试(表示数组的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/46_TranslateNumbersToStrings.md b/docs/jianzhioffer/java/46_TranslateNumbersToStrings.md
deleted file mode 100644
index 759b1f9c3..000000000
--- a/docs/jianzhioffer/java/46_TranslateNumbersToStrings.md
+++ /dev/null
@@ -1,56 +0,0 @@
-## 把数字翻译成字符串
-
-### 题目描述
-给定一个数字,我们按照如下规则把它翻译为字符串:
-
-0 翻译成 ”a”,1 翻译成 ”b”,……,11 翻译成 ”l”,……,25 翻译成 ”z”。
-
-一个数字可能有多个翻译。例如 12258 有 5 种不同的翻译,它们分别是 ”bccfi”、”bwfi”、”bczi”、”mcfi”和”mzi”。
-
-请编程实现一个函数用来计算一个数字有多少种不同的翻译方法。
-
-### 解法
-先写入递推式,res 表示共有多少种翻译方法。看最后一个字符,判断它与前一个字符能否构成有效翻译,计算 res[i]:
-
-- 能,那么 `res[i] = res[i - 1] + res[i - 2]`;
-- 不能,那么 `res[i] = res[i - 1]`。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/8
- */
-
-class Solution {
- /**
- * 获取翻译字符串的方法个数
- *
- * @param s 字符串
- * @return 个数
- */
- public int getTranslationCount(String s) {
- if (s == null || s.length() < 2) {
- return 1;
- }
- char[] chars = s.toCharArray();
- int n = chars.length;
- int[] res = new int[n];
- res[0] = 1;
- res[1] = isInRange(chars[0], chars[1]) ? 2 : 1;
- for (int i = 2; i < n; ++i) {
- res[i] = res[i - 1] + (isInRange(chars[i - 1], chars[i]) ? res[i - 2] : 0);
- }
- return res[n - 1];
- }
-
- private boolean isInRange(char a, char b) {
- int s = (a - '0') * 10 + (b -'0');
- return s >= 10 && s <= 25;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(只有一位数字;包含多位数字);
-2. 特殊输入测试(负数;0;包含 25、26 的数字)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/47_MaxValueOfGifts.md b/docs/jianzhioffer/java/47_MaxValueOfGifts.md
deleted file mode 100644
index 8af6ff5b2..000000000
--- a/docs/jianzhioffer/java/47_MaxValueOfGifts.md
+++ /dev/null
@@ -1,57 +0,0 @@
-## 礼物的最大价值
-
-### 题目描述
-在一个 `m×n` 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。
-
-你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格直到到达棋盘的右下角。
-
-给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?
-
-### 解法
-写出递推式,res 表示获得的最大礼物。
-
-```java
-res[i][j] = Math.max(res[i - 1][j], res[i][j - 1]) + grid[i][j];
-```
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/8
- */
-
-class Solution {
- /**
- * 获取礼物的最大价值
- *
- * @param grid 数组
- * @return 最大价值
- */
- public int getMaxValue(int[][] grid) {
- if (grid == null || grid.length == 0) {
- return 0;
- }
- int m = grid.length;
- int n = grid[0].length;
- int[][] res = new int[m][n];
- res[0][0] = grid[0][0];
- for (int j = 1; j < n; ++j) {
- res[0][j] = res[0][j - 1] + grid[0][j];
- }
- for (int i = 1; i < m; ++i) {
- res[i][0] = res[i - 1][0] + grid[i][0];
- }
- for (int i = 1; i < m; ++i) {
- for (int j = 1; j < n; ++j) {
- res[i][j] = Math.max(res[i - 1][j], res[i][j - 1]) + grid[i][j];
- }
- }
- return res[m - 1][n - 1];
- }
-}
-```
-
-### 测试用例
-1. 功能测试(多行多列的矩阵;一行或者一列的矩阵;只有一个数字的矩阵);
-2. 特殊输入测试(指向矩阵数组的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/48_LongestSubstringWithoutDup.md b/docs/jianzhioffer/java/48_LongestSubstringWithoutDup.md
deleted file mode 100644
index 0012f287b..000000000
--- a/docs/jianzhioffer/java/48_LongestSubstringWithoutDup.md
+++ /dev/null
@@ -1,63 +0,0 @@
-## 最长不含重复字符的子字符串
-
-### 题目描述
-请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
-
-假设字符串中只包含从 `a` 到 `z`的字符。
-
-### 解法
-动态规划。
-
-`res[i]` 表示以 `s[i]` 字符结尾的最长不重复字符串的长度。判断 `s[i]`:
-- 若 `s[i]` 在前面没出现过,那么 `res[i] = res[i - 1] + 1`;
-- 若 `s[i]` 在前面有出现过,判断它上一次出现的位置 `index` 到 `i` 的距离 `d` 与 `res[i - 1]` 的大小关系:
- - 若 `d <= res[i - 1]`,说明它被包含在 `res[i - 1]` 构成的子串中,那么 `res[i] = d`;
- - 若 `d > res[i - 1]`,说明它在 `res[i - 1]` 构成的子串的左侧,那么 `res[i] = res[i - 1] + 1`。
-
-需要用一个数组 t 记录一下当前出现的字符在哪个位置。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/8
- */
-
-class Solution {
- /**
- * 最长不含重复字符的子字符串
- *
- * @param s 字符串
- * @return 最长不重复字符子串
- */
- public int longestSubstringWithoutDuplication(String s) {
- if (s == null || s.length() == 0) {
- return 0;
- }
- char[] chars = s.toCharArray();
- int[] t = new int[26];
- for (int i = 0; i < 26; ++i) {
- t[i] = -1;
- }
- t[chars[0] - 'a'] = 0;
- int n = chars.length;
- int[] res = new int[n];
- res[0] = 1;
- int max = res[0];
- for (int i = 1; i < n; ++i) {
- int index = t[chars[i] - 'a'];
- int d = i - index;
- res[i] = (index == -1 || d > res[i - 1])
- ? res[i - 1] + 1
- : d;
-
- t[chars[i] - 'a'] = i;
- max = Math.max(max, res[i]);
- }
- return max;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(包含多个字符的字符串;只有一个字符的字符串;所有字符都唯一的字符串;所有字符都相同的字符串);
-2. 特殊输入测试(空字符串)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/49_UglyNumber.md b/docs/jianzhioffer/java/49_UglyNumber.md
deleted file mode 100644
index bec37fd34..000000000
--- a/docs/jianzhioffer/java/49_UglyNumber.md
+++ /dev/null
@@ -1,106 +0,0 @@
-## 丑数
-
-### 题目描述
-把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
-
-### 解法1
-由题目可以得知,丑数必定可以整除2、3或者5(除了丑数1之外),也就是说,如果一个数能够被2整除,就连续除以2;能够被3整除,就连续除以3;能够被5整除,就连续除以5;如果最后得到1,那么这个数便是丑数。因此我们可以使用暴力的方式遍历到第N个丑数。
-
-该解法的time complexity为O(count),比如第1500个丑数为859963392,那么就需要枚举1到859963392
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/01/23
- * @description
- */
-public class Solution {
-
- private boolean isUgly(int number){
- if(number % 2 == 0)
- number /= 2;
- if(number % 3 == 0)
- number /= 3;
- if(number % 5 == 0)
- number /= 5;
- return number == 1;
- }
-
- public int GetUglyNumber_Solution(int index){
- if(index <= 0)
- return 0;
-
- int number = 0;
- int count = 0;
- while(count < index){
- number++;
- if(isUgly(number)){
- count++;
- }
- }
-
- return number;
- }
-}
-```
-
-### 解法2
-
-把15以内的丑数列出来:`1、2、3、4、5、6、8、9、10、12、15` ,你会发现新丑数必定是旧丑数乘以因子2、3或者5得来的。所以可以使用一个list来存储已经出现的丑数以此来计算出新的丑数,从而避免对非丑数的计算。
-
-通过维护3个下标i2,i3,i5和它们对应的值m2,m3,m5,每次向list中添加的为m2,m3,m5中的最小值,以此来维护list的有序性。
-
-该解法的time complexity为O(n),space complexity为O(n),属于典型的用空间换时间的解决方法。
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/01/23
- * @description
- */
-public class Solution {
-
- public int GetUglyNumber_Solution(int index) {
-
- if (index <= 0)
- return 0;
-
- List reList = new ArrayList<>();
- // 第一个丑数为1
- reList.add(1);
- int i2 = 0, i3 = 0, i5 = 0;
- while (reList.size() < index) {
-
- int m2 = reList.get(i2) * 2;
- int m3 = reList.get(i3) * 3;
- int m5 = reList.get(i5) * 5;
-
- // 求出m2、m3、m5中的最小值,该值为加入list的丑数
- int min = Math.min(m2, Math.min(m3, m5));
-
- if (m2 == min) {
- i2++;
- }
- if (m3 == min) {
- i3++;
- }
- if (m5 == min) {
- i5++;
- }
-
- reList.add(min);
- }
-
- // O(1)
- return reList.get(reList.size() - 1);
- }
-}
-```
-
-### 测试用例
-
-1. 功能测试(输入2、3、4、5、6等)。
-2. 特殊输入测试(边界值1;无效输入0)。
-3. 性能测试(输入较大的数字,比如1500)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/50_01_FirstNotRepeatingChar.md b/docs/jianzhioffer/java/50_01_FirstNotRepeatingChar.md
deleted file mode 100644
index ebf2baeb5..000000000
--- a/docs/jianzhioffer/java/50_01_FirstNotRepeatingChar.md
+++ /dev/null
@@ -1,43 +0,0 @@
-## 第一个只出现一次的字符
-
-### 题目描述
-在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
-
-### 解法1
-使用HashMap来统计字符出现的次数,因为字符的多少是固定的(大小写字母一共52个),所以可以认为使用HashMap的空间复杂度为O(1)。该解法时间复杂度为O(n)。
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/01/24
- * @description
- */
-public class Solution {
-
- public int FirstNotRepeatingChar(String str) {
-
- if (str == null || str.length() == 0) {
- return -1;
- }
-
- Map characterMap = new HashMap<>();
- // hashMap is HashTable,search cost O(1)
- for (int i = 0; i < str.length(); i++) {
- characterMap.put(str.charAt(i), characterMap.getOrDefault(str.charAt(i), 0) + 1);
- }
-
- for (int i = 0; i < str.length(); i++) {
- if (characterMap.get(str.charAt(i)) == 1) {
- return i;
- }
- }
-
- return -1;
- }
-}
-```
-### 测试用例
-
-1. 功能测试(字符串中仅存在只出现一次的字符;字符串中不存在只出现一次的字符;字符串中所有字符都只出现一次)。
-2. 特殊输入测试(字符串为null)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/50_02_FristCharacterInStream.md b/docs/jianzhioffer/java/50_02_FristCharacterInStream.md
deleted file mode 100644
index 2d67dbcca..000000000
--- a/docs/jianzhioffer/java/50_02_FristCharacterInStream.md
+++ /dev/null
@@ -1,45 +0,0 @@
-## 字符流中第一个不重复的字符
-
-### 题目描述
-
-请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。如果当前字符流没有存在出现一次的字符,返回#字符。
-
-
-### 解法1
-与上一道题的思路是一致的。
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/01/25
- * @description
- */
-public class Solution {
-
- private StringBuilder res = new StringBuilder();
- private Map characterMap = new HashMap<>();
-
- // Insert one char from stringstream
- public void Insert(char ch) {
- res.append(ch);
- characterMap.put(ch, characterMap.getOrDefault(ch, 0) + 1);
- }
-
- // return the first appearence once char in current stringstream
- public char FirstAppearingOnce() {
-
- for (char c : res.toString().toCharArray()) {
- if (characterMap.get(c) == 1) {
- return c;
- }
- }
-
- return '#';
- }
-}
-```
-### 测试用例
-
-1. 功能测试(读入一个字符;读入多个字符;读入的所有字符都是唯一的;读入的所有字符都是重复出现的)。
-2. 特殊输入测试(读入0个字符)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/52_FirstCommonNodesInLists.md b/docs/jianzhioffer/java/52_FirstCommonNodesInLists.md
deleted file mode 100644
index 78fe0068b..000000000
--- a/docs/jianzhioffer/java/52_FirstCommonNodesInLists.md
+++ /dev/null
@@ -1,86 +0,0 @@
-## 两个链表的第一个公共结点
-
-### 题目描述
-输入两个链表,找出它们的第一个公共结点。
-
-**样例**
-```
-给出两个链表如下所示:
-A: a1 → a2
- ↘
- c1 → c2 → c3
- ↗
-B: b1 → b2 → b3
-
-输出第一个公共节点c1
-```
-
-### 解法
-先遍历两链表,求出两链表的长度,再求长度差 `|n1 - n2|`。
-
-较长的链表先走 `|n1 - n2|` 步,之后两链表再同时走,首次相遇时的节点即为两链表的第一个公共节点。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/8
- */
-
-/**
- * Definition for singly-linked list.
- * public class ListNode {
- * int val;
- * ListNode next;
- * ListNode(int x) {
- * val = x;
- * next = null;
- * }
- * }
- */
-class Solution {
-
- /**
- * 求两链表第一个公共节点
- *
- * @param headA 链表A
- * @param headB 链表B
- * @return 第一个公共节点
- */
- public ListNode findFirstCommonNode(ListNode headA, ListNode headB) {
- if (headA == null || headB == null) {
- return null;
- }
- int n1 = len(headA), n2 = len(headB);
- ListNode p1 = headA, p2 = headB;
- if (n1 > n2) {
- for (int i = 0; i < n1 - n2; ++i) {
- p1 = p1.next;
- }
- } else if (n1 < n2) {
- for (int i = 0; i < n2 - n1; ++i) {
- p2 = p2.next;
- }
- }
- while (p1 != p2 && p1 != null && p2 != null) {
- p1 = p1.next;
- p2 = p2.next;
- }
- return (p1 == null || p2 == null) ? null : p1;
- }
-
- private int len(ListNode head) {
- int n = 0;
- ListNode cur = head;
- while (cur != null) {
- ++n;
- cur = cur.next;
- }
- return n;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入的两个链表有公共节点;第一个公共节点在链表的中间,第一个公共节点在链表的末尾,第一个公共节点是链表的头节点;输入的两个链表没有公共节点);
-2. 特殊输入测试(输入的链表头节点是空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/53_01_NumberOfK.md b/docs/jianzhioffer/java/53_01_NumberOfK.md
deleted file mode 100644
index 76cb7d228..000000000
--- a/docs/jianzhioffer/java/53_01_NumberOfK.md
+++ /dev/null
@@ -1,99 +0,0 @@
-## 数字在排序数组中出现的次数
-
-### 题目描述
-统计一个数字在排序数组中出现的次数。
-
-例如输入排序数组 `[1, 2, 3, 3, 3, 3, 4, 5]` 和数字 3,由于 3 在这个数组中出现了 4 次,因此输出 4。
-
-**样例**
-
-```
-输入:[1, 2, 3, 3, 3, 3, 4, 5] , 3
-
-输出:4
-```
-
-### 解法
-找出第一个 k 和最后一个 k 出现的位置。
-
-找第一个 k 时,利用二分法,如果 `nums[m] == k`,判断它的前一个位置是不是也是 k,如果不是,说明这是第一个 k,直接返回。如果是,那么递归在左边查找第一个 k。
-
-找最后一个 k 也同理。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/8
- */
-
-class Solution {
- /**
- * 求数字k在排序数组中出现的次数
- *
- * @param nums 数组
- * @param k 数字k
- * @return k在数组中出现的次数
- */
- public int getNumberOfK(int[] nums, int k) {
- if (nums == null || nums.length == 0) {
- return 0;
- }
- int start = 0, end = nums.length - 1;
- int first = getFirstK(nums, start, end, k);
- int last = getLastK(nums, start, end, k);
- if (first > -1 && last > -1) {
- return last - first + 1;
- }
- return 0;
- }
-
- private int getFirstK(int[] nums, int start, int end, int k) {
- if (start > end) {
- return -1;
- }
- int m = start + ((end - start) >> 1);
- if (nums[m] == k) {
- if (m == 0 || (m > 0 && nums[m - 1] != k)) {
- return m;
- } else {
- end = m - 1;
- }
- } else {
- if (nums[m] > k) {
- end = m - 1;
- } else {
- start = m + 1;
- }
- }
- return getFirstK(nums, start, end, k);
- }
-
- private int getLastK(int[] nums, int start, int end, int k) {
- if (start > end) {
- return -1;
- }
- int m = start + ((end - start) >> 1);
- if (nums[m] == k) {
- if (m == nums.length - 1 || (m < nums.length - 1 && nums[m + 1] != k)) {
- return m;
- } else {
- start = m + 1;
- }
- } else {
- if (nums[m] > k) {
- end = m - 1;
- } else {
- start = m + 1;
- }
- }
- return getLastK(nums, start, end, k);
-
- }
-}
-```
-
-### 测试用例
-1. 功能测试(数组中包含要查找的数字;数组中没有要查找的数字;要查找的数字在数组中出现一次/多次);
-2. 边界值测试(查找数组中的最大值、最小值;数组中只有一个数字);
-3. 特殊输入测试(表示数组的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/53_02_MissingNumber.md b/docs/jianzhioffer/java/53_02_MissingNumber.md
deleted file mode 100644
index ab3f8db5b..000000000
--- a/docs/jianzhioffer/java/53_02_MissingNumber.md
+++ /dev/null
@@ -1,62 +0,0 @@
-## 0到n-1中缺失的数字
-
-### 题目描述
-一个长度为 `n-1` 的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围 `0` 到 `n-1` 之内。
-
-在范围 `0` 到 `n-1` 的 `n` 个数字中有且只有一个数字不在该数组中,请找出这个数字。
-
-**样例**
-```
-输入:[0,1,2,4]
-
-输出:3
-```
-
-### 解法
-找出第一个与下标不对应的数字即可。
-
-特殊情况:
-- 下标都对应,那么应该返回 `最后一个数+1`;
-- 缺失的数字是第一个,那么返回 0。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/8
- */
-
-class Solution {
- /**
- * 获取0~n-1缺失的数字
- *
- * @param nums 数组
- * @return 缺失的数字
- */
- public int getMissingNumber(int[] nums) {
- if (nums == null || nums.length == 0) {
- return 0;
- }
- int n = nums.length;
- int start = 0, end = n - 1;
- while (start <= end) {
- int mid = start + ((end - start) >> 1);
- if (nums[mid] != mid) {
- if (mid == 0 || nums[mid - 1] == mid - 1) {
- return mid;
- }
- end = mid - 1;
- } else {
- start = mid + 1;
- }
- }
- return start == n ? n : -1;
-
- }
-}
-```
-
-### 测试用例
-1. 功能测试(缺失的数字位于数组的开始、中间或者末尾);
-2. 边界值测试(数组中只有一个数字 0);
-3. 特殊输入测试(表示数组的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/53_03_IntegerIdenticalToIndex.md b/docs/jianzhioffer/java/53_03_IntegerIdenticalToIndex.md
deleted file mode 100644
index 6ea63a4a4..000000000
--- a/docs/jianzhioffer/java/53_03_IntegerIdenticalToIndex.md
+++ /dev/null
@@ -1,63 +0,0 @@
-## 数组中数值和下标相等的元素
-
-### 题目描述
-假设一个单调递增的数组里的每个元素都是整数并且是唯一的。
-
-请编程实现一个函数找出数组中任意一个数值等于其下标的元素。
-
-例如,在数组 `[-3, -1, 1, 3, 5]` 中,数字 3 和它的下标相等。
-
-**样例**
-```
-输入:[-3, -1, 1, 3, 5]
-
-输出:3
-```
-
-**注意**:如果不存在,则返回 -1。
-
-### 解法
-二分法查找。
-- 当前元素等于对应的下标,直接返回该下标;
-- 当前元素大于该下标,在左边查找;
-- 当前元素小于该下标,在右边查找。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/10
- */
-
-class Solution {
- /**
- * 找出单调递增数组中数值和下标相等的元素
- *
- * @param nums 数组
- * @return 数值与下标相等的元素
- */
- public int getNumberSameAsIndex(int[] nums) {
- if (nums == null || nums.length == 0) {
- return -1;
- }
- int start = 0, end = nums.length - 1;
- while (start <= end) {
- int mid = start + ((end - start) >> 1);
- if (nums[mid] == mid) {
- return mid;
- }
- if (nums[mid] < mid) {
- start = mid + 1;
- } else {
- end = mid - 1;
- }
- }
- return -1;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(数组中包含或者不包含数值和下标相等的元素);
-2. 边界值测试(数组中只有一个数字;数值和下标相等的元素位于数组的开头或者结尾);
-3. 特殊输入测试(表示数组的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/54_KthNodeInBST.md b/docs/jianzhioffer/java/54_KthNodeInBST.md
deleted file mode 100644
index be0bc7996..000000000
--- a/docs/jianzhioffer/java/54_KthNodeInBST.md
+++ /dev/null
@@ -1,54 +0,0 @@
-## 二叉搜索树的第k个结点
-
-### 题目描述
-给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4
-
-### 解法
-因为BST的中序遍历得到的是一个升序的列表,所以在进行中序遍历行进行判断即可。所以该算法的时间复杂度为O(logn)
-
-
-```java
-/**
- * @author mcrwayfun
- * @version 1.0
- * @description
- * @date Created in 2019/1/28
- */
-class Solution {
-
- private int count = 0;
-
- public TreeNode KthNode(TreeNode pRoot, int k) {
-
- if (pRoot == null || k == 0) {
- return null;
- }
-
- // 左递归
- TreeNode retNode = KthNode(pRoot.left, k);
-
- if (retNode != null) {
- return retNode;
- }
-
- // 符合条件则返回
- count++;
- if (count == k) {
- return pRoot;
- }
-
- // 右递归
- retNode = KthNode(pRoot.right, k);
- if (retNode != null) {
- return retNode;
- }
-
- return null;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(各种形态不同的二叉搜索树);
-2. 边界值测试(输入k为0、1、二叉搜索树的结点数、二叉搜索树的结点数+1);
-3. 特殊输入测试(指向二叉搜索树的节点的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/55_01_TreeDepth.md b/docs/jianzhioffer/java/55_01_TreeDepth.md
deleted file mode 100644
index 99797309c..000000000
--- a/docs/jianzhioffer/java/55_01_TreeDepth.md
+++ /dev/null
@@ -1,59 +0,0 @@
-## 二叉树的深度
-
-### 题目描述
-输入一棵二叉树的根结点,求该树的深度。
-
-从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
-
-**样例**
-```
-输入:二叉树[8, 12, 2, null, null, 6, 4, null, null, null, null]如下图所示:
- 8
- / \
- 12 2
- / \
- 6 4
-
-输出:3
-```
-
-### 解法
-递归即可。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/10
- */
-
-/**
- * Definition for a binary tree node.
- * public class TreeNode {
- * int val;
- * TreeNode left;
- * TreeNode right;
- * TreeNode(int x) { val = x; }
- * }
- */
-class Solution {
- /**
- * 求二叉树的深度
- *
- * @param root 二叉树根结点
- * @return 深度
- */
- public int treeDepth(TreeNode root) {
- if (root == null) {
- return 0;
- }
- int lDepth = treeDepth(root.left);
- int rDepth = treeDepth(root.right);
- return 1 + Math.max(lDepth, rDepth);
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入普通的二叉树;二叉树中所有节点都没有左/右子树);
-2. 特殊输入测试(二叉树只有一个节点;二叉树的头节点为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/55_02_BalancedBinaryTree.md b/docs/jianzhioffer/java/55_02_BalancedBinaryTree.md
deleted file mode 100644
index 521e1ceb7..000000000
--- a/docs/jianzhioffer/java/55_02_BalancedBinaryTree.md
+++ /dev/null
@@ -1,127 +0,0 @@
-## 平衡二叉树
-
-### 题目描述
-输入一棵二叉树的根结点,判断该树是不是平衡二叉树。
-
-如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
-
-**注意:**
-
-- 规定空树也是一棵平衡二叉树。
-
-**样例**
-```
-输入:二叉树[5,7,11,null,null,12,9,null,null,null,null]如下所示,
- 5
- / \
- 7 11
- / \
- 12 9
-
-输出:true
-```
-
-### 解法
-#### 解法一
-求每个节点左右孩子的深度,判断该节点是否平衡。
-
-这种方法需要重复遍历节点多次,不推荐。
-
-
-```java
-/**
- * @author bingo
- * @since 2018/12/10
- */
-
-/**
- * Definition for a binary tree node.
- * public class TreeNode {
- * int val;
- * TreeNode left;
- * TreeNode right;
- * TreeNode(int x) { val = x; }
- * }
- */
-class Solution {
- /**
- * 判断是否是平衡二叉树
- *
- * @param root 二叉树根结点
- * @return 是否是平衡二叉树
- */
- public boolean isBalanced(TreeNode root) {
- if (root == null) {
- return true;
- }
- if (Math.abs(treeDepth(root.left) - treeDepth(root.right)) > 1) {
- return false;
- }
- return isBalanced(root.left) && isBalanced(root.right);
- }
-
- private int treeDepth(TreeNode root) {
- if (root == null) {
- return 0;
- }
- int lDepth = treeDepth(root.left);
- int rDepth = treeDepth(root.right);
- return 1 + Math.max(lDepth, rDepth);
- }
-}
-```
-
-#### 解法二
-
-```java
-/**
- * @author bingo
- * @since 2018/12/10
- */
-
-/**
- * Definition for a binary tree node.
- * public class TreeNode {
- * int val;
- * TreeNode left;
- * TreeNode right;
- * TreeNode(int x) { val = x; }
- * }
- */
-class Solution {
- private boolean isBalanced;
-
- /**
- * 判断是否是平衡二叉树
- *
- * @param root 二叉树根结点
- * @return 是否是平衡二叉树
- */
- public boolean isBalanced(TreeNode root) {
- if (root == null) {
- return true;
- }
- isBalanced = true;
- treeDepth(root);
- return isBalanced;
- }
-
- private int treeDepth(TreeNode root) {
- if (root == null || !isBalanced) {
- return 0;
- }
- int lDepth = treeDepth(root.left);
- int rDepth = treeDepth(root.right);
- if (Math.abs(lDepth - rDepth) > 1) {
- isBalanced = false;
- }
- return 1 + Math.max(lDepth, rDepth);
-
- }
-}
-```
-
-
-### 测试用例
-1. 功能测试(平衡的二叉树;不是平衡的二叉树;二叉树中所有节点都没有左/右子树);
-2. 特殊输入测试(二叉树只有一个节点;二叉树的头节点为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/56_01_NumbersAppearOnce.md b/docs/jianzhioffer/java/56_01_NumbersAppearOnce.md
deleted file mode 100644
index 1576feee2..000000000
--- a/docs/jianzhioffer/java/56_01_NumbersAppearOnce.md
+++ /dev/null
@@ -1,77 +0,0 @@
-## 数组中只出现一次的两个数字
-
-### 题目描述
-一个整型数组里除了两个数字之外,其他的数字都出现了两次。
-
-请写程序找出这两个只出现一次的数字。
-
-你可以假设这两个数字一定存在。
-
-**样例**
-```
-输入:[1,2,3,3,4,4]
-
-输出:[1,2]
-```
-
-### 解法
-如果数组有一个数字出现一次,其它数字都出现两次。那么我们很容易通过异或 `^` 运算求出来。
-
-而现在是有两个数字出现一次,那么我们考虑一下怎么将这两个数字隔开,之后我们对隔开的数组分别进行异或,不就求出来了?
-
-我们先异或,求得的结果是两个不相同的数字异或的结果,结果一定不为 0。那么它的二进制表示中一定有 1。我们根据这个 1 在二进制中出现的位置。将数组划分,这样,两个只出现一次的数字就会被隔开,之后求异或即可。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/10
- */
-
-class Solution {
- /**
- * 求数组中只出现一次的两个数字
- *
- * @param nums 数字
- * @return 两个数字组成的数组
- */
- public int[] findNumsAppearOnce(int[] nums) {
- if (nums == null || nums.length < 2) {
- return null;
- }
- int xorRes = 0;
- for (int e : nums) {
- xorRes ^= e;
- }
- int[] res = new int[2];
- int index = indexOf1(xorRes);
- for (int e : nums) {
- if (isBit1(e, index)) {
- res[0] ^= e;
- } else {
- res[1] ^= e;
- }
- }
- return res;
-
-
- }
-
- private int indexOf1(int val) {
- int index = 0;
- while ((val & 1) == 0) {
- val = val >> 1;
- ++index;
- }
- return index;
- }
-
- private boolean isBit1(int val, int index) {
- val = val >> index;
- return (val & 1) == 1;
- }
-}
-```
-
-
-### 测试用例
-1. 功能测试(数组中有多对重复的数字;数组中没有重复的数字)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/56_02_NumberAppearingOnce.md b/docs/jianzhioffer/java/56_02_NumberAppearingOnce.md
deleted file mode 100644
index f6e101c3c..000000000
--- a/docs/jianzhioffer/java/56_02_NumberAppearingOnce.md
+++ /dev/null
@@ -1,55 +0,0 @@
-## 数组中唯一只出现一次的数字
-
-### 题目描述
-在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。
-
-请找出那个只出现一次的数字。
-
-你可以假设满足条件的数字一定存在。
-
-**思考题:**
-
-- 如果要求只使用 `O(n)` 的时间和额外 `O(1)` 的空间,该怎么做呢?
-
-### 解法
-分别累加数组中每个元素的二进制中出现的数字,那么出现三次的数字,二进制位上最后累加的结果一定能被 3 整除。不能被 3 整除的位,就属于只出现一次的数字。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/10
- */
-
-class Solution {
- /**
- * 找出数组中只出现一次的数字,其它数字都出现三次
- *
- * @param nums 数字
- * @return 只出现一次的数字
- */
- public int findNumberAppearingOnce(int[] nums) {
- if (nums == null || nums.length == 0) {
- return 0;
- }
- int[] bits = new int[32];
- int n = nums.length;
- for (int i = 0; i < n; ++i) {
- int val = nums[i];
- for (int j = 0; j < 32; ++j) {
- bits[j] += (val & 1);
- val = val >> 1;
- }
- }
- int res = 0;
- for (int i = 0; i < 32; ++i) {
- if (bits[i] % 3 != 0) {
- res += Math.pow(2, i);
- }
- }
- return res;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(唯一只出现一次的数字分别是 0、正数、负数;重复出现三次的数字分别是 0、正数、负数)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/57_01_TwoNumbersWithSum.md b/docs/jianzhioffer/java/57_01_TwoNumbersWithSum.md
deleted file mode 100644
index 0b4770178..000000000
--- a/docs/jianzhioffer/java/57_01_TwoNumbersWithSum.md
+++ /dev/null
@@ -1,55 +0,0 @@
-## 和为S的两个数字
-
-### 题目描述
-输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。ps:对应每个测试案例,输出两个数,小的先输出。
-
-### 解法
-定义两个指针,start指向数组头,end指向数组末尾。如果:
-
-- `sum == array[start] + array[end]`,则返回结果
-- `sum > array[start] + array[end]`,则start++,因为数组是递增的,所以从小数右边找一个大数与 `array[end]` 求和再次判断
-- 否则 end--
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/02/02
- * @description
- */
-public class Solution {
-
- public ArrayList FindNumbersWithSum(int[] array, int sum) {
-
- ArrayList reList = new ArrayList<>();
-
- if (array == null || array.length < 2 || sum <= array[0]) {
- return reList;
- }
-
- int start = 0;
- int end = array.length - 1;
-
- while (start < end) {
-
- int curSum = array[start] + array[end];
- if (curSum == sum) {
- reList.add(array[start]);
- reList.add(array[end]);
- return reList;
- } else if (curSum < sum) {
- start++;
- } else {
- end--;
- }
- }
-
- // 查无
- return reList;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(数组中存在和为 s 的两个数;数组中不存在和为 s 的两个数);
-2. 特殊输入测试(表示数组的指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/57_02_ContinuousSquenceWithSum.md b/docs/jianzhioffer/java/57_02_ContinuousSquenceWithSum.md
deleted file mode 100644
index c837b5875..000000000
--- a/docs/jianzhioffer/java/57_02_ContinuousSquenceWithSum.md
+++ /dev/null
@@ -1,77 +0,0 @@
-## 和为S的连续正数序列
-
-### 题目描述
-输入一个正数 s,打印出所有和为 s 的连续正数序列(至少含有两个数)。
-
-例如输入 15,由于 `1+2+3+4+5=4+5+6=7+8=15`,所以结果打印出 3 个连续序列 1~5、4~6 和 7~8。
-
-**样例**
-```
-输入:15
-
-输出:[[1,2,3,4,5],[4,5,6],[7,8]]
-```
-
-### 解法
-这道题同样利用两个指针left和right,将(1,2)作为初始序列。当序列和大于所求值,则left向前走,把最小的数排除了;当序列和小于所求值,则right向前走,把一个更大的数包进序列中;如果序列和等于所求值,则求值区间[left,right]中的所有数并加入到列表中,并且right向前走,把一个更大的值包入序列中。循环直到 `left < (sum + 1)/2` 。
-
-这道题的time complexity为O(n^2),space complexity为O(1)
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/02/03
- * @description
- */
-public class Solution {
-
- public List> findContinuousSequence(int sum) {
-
- List> reList = new ArrayList<>();
-
- if (sum < 3) {
- return reList;
- }
-
- int left = 1;
- int right = 2;
- int mid = (sum + 1) / 2;
- int curSum = left + right;
-
- // left小于sum一半即可(1/2n)
- while (left < mid) {
-
- // 等与sum则加入列表中(2~1/2n)
- if (curSum == sum) {
- reList.add(getListFromleftToright(left, right));
- // right增加并重新寻找序列
- right++;
- curSum += right;
- } else if (curSum > sum) {
- curSum -= left;
- left++;
- } else {
- right++;
- curSum += right;
- }
- }
-
- return reList;
- }
-
- private List getListFromleftToright(int left, int right) {
-
- List tempList = new ArrayList<>();
- for (int i = left; i <= right; i++) {
- tempList.add(i);
- }
-
- return tempList;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(存在和为 s 的连续序列,如 9、100 等;不存在和为 s 的连续序列,如 4、0 等);
-2. 边界值测试(连续序列的最小和 3)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/58_01_ReverseWordsInSentence.md b/docs/jianzhioffer/java/58_01_ReverseWordsInSentence.md
deleted file mode 100644
index 87f557479..000000000
--- a/docs/jianzhioffer/java/58_01_ReverseWordsInSentence.md
+++ /dev/null
@@ -1,55 +0,0 @@
-## 翻转单词顺序
-
-### 题目描述
-输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
-
-为简单起见,标点符号和普通字母一样处理。
-
-例如输入字符串 `"I am a student."`,则输出 `"student. a am I"`。
-
-**样例**
-```
-输入:"I am a student."
-
-输出:"student. a am I"
-```
-
-### 解法
-先对字符串按空格切割成数组,再逆序数组后,最后将元素拼接并返回。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/12
- */
-
-class Solution {
- /**
- * 翻转单词
- *
- * @param s 字符串
- * @return 翻转后的字符串
- */
- public String reverseWords(String s) {
- if (s == null || s.length() == 0 || s.trim().equals("")) {
- return s;
- }
-
- String[] arr = s.split(" ");
- int p = 0, q = arr.length - 1;
- while (p < q) {
- swap(arr, p++, q--);
- }
- return String.join(" ", arr);
- }
- private void swap(String[] arr, int p, int q) {
- String t = arr[p];
- arr[p] = arr[q];
- arr[q] = t;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(句子中有多个单词;句子中只有一个单词);
-2. 特殊输入测试(字符串指针为空指针;字符串的内容为空;字符串中只有空格)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/58_02_LeftRotateString.md b/docs/jianzhioffer/java/58_02_LeftRotateString.md
deleted file mode 100644
index e78dc16bd..000000000
--- a/docs/jianzhioffer/java/58_02_LeftRotateString.md
+++ /dev/null
@@ -1,67 +0,0 @@
-## 左旋转字符串
-
-### 题目描述
-字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。
-
-请定义一个函数实现字符串左旋转操作的功能。
-
-比如输入字符串 `"abcdefg"` 和数字 2,该函数将返回左旋转 2 位得到的结果 `"cdefgab"`。
-
-**注意:**
-
-- 数据保证 n 小于等于输入字符串的长度。
-
-**样例**
-```
-输入:"abcdefg" , n=2
-
-输出:"cdefgab"
-```
-
-### 解法
-先翻转前 n 个字符,再翻转后面的字符,最后整体翻转。
-
-```java
-/**
- * @author bingo
- * @since 2018/12/12
- */
-
-class Solution {
-
- /**
- * 左旋转字符串
- *
- * @param str 字符串
- * @param n 左旋的位数
- * @return 旋转后的字符串
- */
- public String leftRotateString(String str, int n) {
- if (str == null || n < 1 || n > str.length()) {
- return str;
- }
- char[] chars = str.toCharArray();
- int len = chars.length;
- reverse(chars, 0, n - 1);
- reverse(chars, n, len - 1);
- reverse(chars, 0, len - 1);
- return new String(chars);
- }
-
- private void reverse(char[] chars, int p, int q) {
- while (p < q) {
- swap(chars, p++, q--);
- }
- }
-
- private void swap(char[] chars, int p, int q) {
- char t = chars[p];
- chars[p] = chars[q];
- chars[q] = t;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(把长度为 n 的字符串左旋转 0/1/2/n-1/n/n+1 个字符);
-2. 特殊输入测试(字符串指针为空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/59_01_MaxInSlidingWindow.md b/docs/jianzhioffer/java/59_01_MaxInSlidingWindow.md
deleted file mode 100644
index f568e9b30..000000000
--- a/docs/jianzhioffer/java/59_01_MaxInSlidingWindow.md
+++ /dev/null
@@ -1,75 +0,0 @@
-## 滑动窗口的最大值
-
-### 题目描述
-给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。
-
-例如,如果输入数组 `[2, 3, 4, 2, 6, 2, 5, 1]` 及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,它们的最大值分别为 `[4, 4, 6, 6, 6, 5]`。
-
-**注意:**
-
-- 数据保证 k 大于 0,且 k 小于等于数组长度。
-
-**样例**
-
-```
-输入:[2, 3, 4, 2, 6, 2, 5, 1] , k=3
-
-输出: [4, 4, 6, 6, 6, 5]
-```
-
-### 解法
-使用一个双端队列,保证队首存放的是窗口最大值的下标。遍历数组,
-
-1. 队尾元素比要入队的元素小,则把其移除(因为不可能成为窗口最大值)。
-2. 队首下标对应的元素不在窗口内(即窗口最大值),将其从队列中移除。
-3. 把每次滑动值的下标加入队列中(经过步骤1、2,此时加入队列的下标要么是当前窗口最大值的下标,要么是小于窗口最大值的下标)。
-4. 滑动窗口的首地址i大于size就写入窗口最大值。
-
-time complexity:O(n)
-
-space complexity:O(k) , k is the size
-
-```java
-/**
- * @author mcrwayfun
- * @version v1.0
- * @date Created in 2019/02/05
- * @description
- */
-class Solution {
-
- public ArrayList maxInWindows(int[] num, int size) {
-
- ArrayList reList = new ArrayList<>();
- if (num == null || num.length < size || size < 1) {
- return reList;
- }
-
- Deque deque = new LinkedList<>();
- for (int i = 0; i < num.length; i++) {
-
- // 队尾元素比要入队的元素小,则把其移除(因为不可能成为窗口最大值)
- while (!deque.isEmpty() && num[deque.getLast()] <= num[i]) {
- deque.pollLast();
- }
- // 队首下标对应的元素不在窗口内(即窗口最大值),将其从队列中移除
- while (!deque.isEmpty() && (i - deque.getFirst() + 1 > size)) {
- deque.pollFirst();
- }
- // 把每次滑动的值加入到队列中
- deque.add(i);
- // 滑动窗口的首地址i大于size就写入窗口最大值
- if (!deque.isEmpty() && i + 1 >= size) {
- reList.add(num[deque.getFirst()]);
- }
- }
-
- return reList;
- }
-}
-```
-
-### 测试用例
-1. 功能测试(输入数组的数字大小无序;输入数组的数字单调递增;输入数组的数字单调递减);
-2. 边界值测试(滑动窗口的大小为 0、1、等于输入数组的长度、大于输入数组的长度);
-3. 特殊输入测试(输入数组为空)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/61_ContinousCards.md b/docs/jianzhioffer/java/61_ContinousCards.md
deleted file mode 100644
index 9ff94a437..000000000
--- a/docs/jianzhioffer/java/61_ContinousCards.md
+++ /dev/null
@@ -1,78 +0,0 @@
-## 扑克牌的顺子
-
-### 题目描述
-从扑克牌中随机抽 `5` 张牌,判断是不是一个顺子,即这5张牌是不是连续的。
-
-`2~10` 为数字本身,`A` 为`1`,`J` 为 `11`,`Q` 为 `12`,`K` 为 `13`,大小王可以看做任意数字。
-
-为了方便,大小王均以 `0` 来表示,并且假设这副牌中大小王均有两张。
-
-**样例1**
-```
-输入:[8,9,10,11,12]
-
-输出:true
-```
-
-**样例2**
-```
-输入:[0,8,9,11,12]
-
-输出:true
-```
-
-### 解法
-- 对数组排序;
-- 计算出 0 的个数 `zeroCount`;
-- 从第一个不是 0 的数字开始遍历,与后一个数字比较,如果相等,直接返回 `false`;否则累计 `gap`;
-- 判断 `zeroCount` 是否大于等于 `gap`。
-
-
-```java
-import java.util.Arrays;
-
-/**
- * @author bingo
- * @since 2018/12/12
- */
-
-class Solution {
-
- /**
- * 判断是否是连续的数字
- *
- * @param numbers 数组
- * @return 是否是顺子
- */
- public boolean isContinuous(int [] numbers) {
- if (numbers == null || numbers.length == 0) {
- return false;
- }
- int zeroCount = 0;
- Arrays.sort(numbers);
- for (int e : numbers) {
- if (e > 0) {
- break;
- }
- ++zeroCount;
- }
-
- int p = zeroCount, q = p + 1, n = numbers.length;
- int gap = 0;
- while (q < n) {
- if (numbers[p] == numbers[q]) {
- return false;
- }
- gap += (numbers[q] - numbers[p] - 1);
- p = q;
- ++q;
- }
- return gap <= zeroCount;
-
- }
-}
-```
-
-### 测试用例
-1. 功能测试(抽出的牌中有一个或者多个大、小王;抽出的牌中没有大、小王;抽出的牌中有对子);
-2. 特殊输入测试(输入空指针)。
\ No newline at end of file
diff --git a/docs/jianzhioffer/java/README.md b/docs/jianzhioffer/java/README.md
deleted file mode 100644
index a7e31d6e0..000000000
--- a/docs/jianzhioffer/java/README.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# 剑指 Offer Java 题解
-
-> 来源:[《剑指 Offer》 Java 版实现](https://github.com/doocs/coding-interview)
-
-| # | Title |
-|---|---|
-| 03_01 | [Find Duplication In Array](/docs/剑指offer/Java/03_01_DuplicationInArray) |
-| 03_02 | [Find Duplication In Array II](/docs/剑指offer/Java/03_02_DuplicationInArrayNoEdit) |
-| 04 | [Find In Partially Sorted Matrix](/docs/剑指offer/Java/04_FindInPartiallySortedMatrix) |
-| 05 | [Replace Spaces](/docs/剑指offer/Java/05_ReplaceSpaces) |
-| 06 | [Print List In Reversed Order](/docs/剑指offer/Java/06_PrintListInReversedOrder) |
-| 07 | [Construct Binary Tree](/docs/剑指offer/Java/07_ConstructBinaryTree) |
-| 08 | [Next Node In Binary Trees](/docs/剑指offer/Java/08_NextNodeInBinaryTrees) |
-| 09_01 | [Queue With Two Stacks](/docs/剑指offer/Java/09_01_QueueWithTwoStacks) |
-| 09_02 | [Stack With Two Queues](/docs/剑指offer/Java/09_02_StackWithTwoQueues) |
-| 10_01 | [Fibonacci](/docs/剑指offer/Java/10_01_Fibonacci) |
-| 10_02 | [Jump Floor](/docs/剑指offer/Java/10_02_JumpFloor) |
-| 10_03 | [Jump Floor II](/docs/剑指offer/Java/10_03_JumpFloorII) |
-| 10_04 | [Rect Cover](/docs/剑指offer/Java/10_04_RectCover) |
-| 11 | [Min Number In Rotated Array](/docs/剑指offer/Java/11_MinNumberInRotatedArray) |
-| 12 | [String Path In Matrix](/docs/剑指offer/Java/12_StringPathInMatrix) |
-| 13 | [Robot Move](/docs/剑指offer/Java/13_RobotMove) |
-| 14 | [Cutting Rope](/docs/剑指offer/Java/14_CuttingRope) |
-| 15 | [Number Of 1 In Binary](/docs/剑指offer/Java/15_NumberOf1InBinary) |
-| 16 | [Power](/docs/剑指offer/Java/16_Power) |
-| 17 | [Print 1 To Max Of N Digits](/docs/剑指offer/Java/17_Print1ToMaxOfNDigits) |
-| 18_01 | [Delete Node In List](/docs/剑指offer/Java/18_01_DeleteNodeInList) |
-| 18_02 | [Delete Duplicated Node](/docs/剑指offer/Java/18_02_DeleteDuplicatedNode) |
-| 19 | [Regular Expressions Matching](/docs/剑指offer/Java/19_RegularExpressionsMatching) |
-| 20 | [Numeric Strings](/docs/剑指offer/Java/20_NumericStrings) |
-| 21 | [Reorder Array](/docs/剑指offer/Java/21_ReorderArray) |
-| 22 | [Kth Node From End](/docs/剑指offer/Java/22_KthNodeFromEnd) |
-| 23 | [Entry Node In List Loop](/docs/剑指offer/Java/23_EntryNodeInListLoop) |
-| 24 | [Reverse List](/docs/剑指offer/Java/24_ReverseList) |
-| 25 | [Merge Sorted Lists](/docs/剑指offer/Java/25_MergeSortedLists) |
-| 26 | [Substructure In Tree](/docs/剑指offer/Java/26_SubstructureInTree) |
-| 27 | [Mirror Of Binary Tree](/docs/剑指offer/Java/27_MirrorOfBinaryTree) |
-| 28 | [Symmetrical Binary Tree](/docs/剑指offer/Java/28_SymmetricalBinaryTree) |
-| 29 | [Print Matrix](/docs/剑指offer/Java/29_PrintMatrix) |
-| 30 | [Min In Stack](/docs/剑指offer/Java/30_MinInStack) |
-| 31 | [Stack Push Pop Order](/docs/剑指offer/Java/31_StackPushPopOrder) |
-| 32_01 | [Print Tree From Top To Bottom](/docs/剑指offer/Java/32_01_PrintTreeFromTopToBottom) |
-| 32_02 | [Print Trees In Lines](/docs/剑指offer/Java/32_02_PrintTreesInLines) |
-| 32_03 | [Print Trees In Zigzag](/docs/剑指offer/Java/32_03_PrintTreesInZigzag) |
-| 33 | [Squence Of BST](/docs/剑指offer/Java/33_SquenceOfBST) |
-| 34 | [Path In Tree](/docs/剑指offer/Java/34_PathInTree) |
-| 35 | [Copy Complex List](/docs/剑指offer/Java/35_CopyComplexList) |
-| 36 | [Convert Binary Search Tree](/docs/剑指offer/Java/36_ConvertBinarySearchTree) |
-| 39 | [More Than Half Number](/docs/剑指offer/Java/39_MoreThanHalfNumber) |
-| 40 | [K Least Numbers](/docs/剑指offer/Java/40_KLeastNumbers) |
-| 41 | [Stream Median](/docs/剑指offer/Java/41_StreamMedian) |
-| 42 | [Greatest Sum Of Subarrays](/docs/剑指offer/Java/42_GreatestSumOfSubarrays) |
-| 44 | [Digits In Sequence](/docs/剑指offer/Java/44_DigitsInSequence) |
-| 45 | [Sort Array For Min Number](/docs/剑指offer/Java/45_SortArrayForMinNumber) |
-| 46 | [Translate Numbers To Strings](/docs/剑指offer/Java/46_TranslateNumbersToStrings) |
-| 47 | [Max Value Of Gifts](/docs/剑指offer/Java/47_MaxValueOfGifts) |
-| 48 | [Longest Substring Without Dup](/docs/剑指offer/Java/48_LongestSubstringWithoutDup) |
-| 52 | [First Common Nodes In Lists](/docs/剑指offer/Java/52_FirstCommonNodesInLists) |
-| 53_01 | [Number Of K](/docs/剑指offer/Java/53_01_NumberOfK) |
-| 53_02 | [Missing Number](/docs/剑指offer/Java/53_02_MissingNumber) |
-| 53_03 | [Integer Identical To Index](/docs/剑指offer/Java/53_03_IntegerIdenticalToIndex) |
-| 55_01 | [Tree Depth](/docs/剑指offer/Java/55_01_TreeDepth) |
-| 55_02 | [Balanced Binary Tree](/docs/剑指offer/Java/55_02_BalancedBinaryTree) |
-| 56_01 | [Numbers Appear Once](/docs/剑指offer/Java/56_01_NumbersAppearOnce) |
-| 56_02 | [Number Appearing Once](/docs/剑指offer/Java/56_02_NumberAppearingOnce) |
-| 57_01 | [Two Numbers With Sum](/docs/剑指offer/Java/57_01_TwoNumbersWithSum) |
-| 57_02 | [Continuous Squence With Sum](/docs/剑指offer/Java/57_02_ContinuousSquenceWithSum) |
-| 58_01 | [Reverse Words In Sentence](/docs/剑指offer/Java/58_01_ReverseWordsInSentence) |
-| 58_02 | [Left Rotate String](/docs/剑指offer/Java/58_02_LeftRotateString) |
-| 59_01 | [Max In Sliding Window](/docs/剑指offer/Java/59_01_MaxInSlidingWindow) |
-| 61 | [Continous Cards](/docs/剑指offer/Java/61_ContinousCards) |
diff --git a/docs/jianzhioffer/java/SUMMARY.md b/docs/jianzhioffer/java/SUMMARY.md
deleted file mode 100644
index 528c38641..000000000
--- a/docs/jianzhioffer/java/SUMMARY.md
+++ /dev/null
@@ -1,73 +0,0 @@
-+ [剑指 Offer Java 题解](README.md)
-+ [找出数组中重复的数字](03_01_DuplicationInArray.md)
-+ [不修改数组找出重复的数字](03_02_DuplicationInArrayNoEdit.md)
-+ [二维数组中的查找](04_FindInPartiallySortedMatrix.md)
-+ [替换空格](05_ReplaceSpaces.md)
-+ [从尾到头打印链表](06_PrintListInReversedOrder.md)
-+ [重建二叉树](07_ConstructBinaryTree.md)
-+ [二叉树的下一个结点](08_NextNodeInBinaryTrees.md)
-+ [用两个栈实现队列](09_01_QueueWithTwoStacks.md)
-+ [用两个队列实现栈](09_02_StackWithTwoQueues.md)
-+ [斐波那契数列](10_01_Fibonacci.md)
-+ [跳台阶](10_02_JumpFloor.md)
-+ [变态跳台阶](10_03_JumpFloorII.md)
-+ [矩形覆盖](10_04_RectCover.md)
-+ [旋转数组的最小数字](11_MinNumberInRotatedArray.md)
-+ [矩阵中的路径](12_StringPathInMatrix.md)
-+ [机器人的移动范围](13_RobotMove.md)
-+ [剪绳子](14_CuttingRope.md)
-+ [二进制中 1 的个数](15_NumberOf1InBinary.md)
-+ [数值的整数次方](16_Power.md)
-+ [打印从 1 到最大的 n 位数](17_Print1ToMaxOfNDigits.md)
-+ [在O(1)时间内删除链表节点](18_01_DeleteNodeInList.md)
-+ [删除链表中重复的节点](18_02_DeleteDuplicatedNode.md)
-+ [正则表达式匹配](19_RegularExpressionsMatching.md)
-+ [表示数值的字符串](20_NumericStrings.md)
-+ [调整数组顺序使奇数位于偶数前面](21_ReorderArray.md)
-+ [链表中倒数第k个结点](22_KthNodeFromEnd.md)
-+ [链表中环的入口结点](23_EntryNodeInListLoop.md)
-+ [反转链表](24_ReverseList.md)
-+ [合并两个排序的链表](25_MergeSortedLists.md)
-+ [树的子结构](26_SubstructureInTree.md)
-+ [二叉树的镜像](27_MirrorOfBinaryTree.md)
-+ [对称的二叉树](28_SymmetricalBinaryTree.md)
-+ [顺时针打印矩阵](29_PrintMatrix.md)
-+ [包含min函数的栈](30_MinInStack.md)
-+ [栈的压入、弹出序列](31_StackPushPopOrder.md)
-+ [不分行从上到下打印二叉树](32_01_PrintTreeFromTopToBottom.md)
-+ [把二叉树打印成多行](32_02_PrintTreesInLines.md)
-+ [按之字形打印二叉树](32_03_PrintTreesInZigzag.md)
-+ [二叉搜索树的后序遍历序列](33_SquenceOfBST.md)
-+ [二叉树中和为某一值的路径](34_PathInTree.md)
-+ [复杂链表的复制](35_CopyComplexList.md)
-+ [二叉搜索树与双向链表](36_ConvertBinarySearchTree.md)
-+ [序列化二叉树](37_SerializeBinaryTrees.md)
-+ [字符串的排列](38_StringPermutation.md)
-+ [数组中出现次数超过一半的数字](39_MoreThanHalfNumber.md)
-+ [获取数组中最小的k个数](40_KLeastNumbers.md)
-+ [数据流中的中位数](41_StreamMedian.md)
-+ [连续子数组的最大和](42_GreatestSumOfSubarrays.md)
-+ [整数中1出现的次数](43_NumberOf1.md)
-+ [数字序列中某一位的数字](44_DigitsInSequence.md)
-+ [把数组排成最小的数](45_SortArrayForMinNumber.md)
-+ [把数字翻译成字符串](46_TranslateNumbersToStrings.md)
-+ [礼物的最大价值](47_MaxValueOfGifts.md)
-+ [最长不含重复字符的子字符串](48_LongestSubstringWithoutDup.md)
-+ [丑数](49_UglyNumber.md)
-+ [第一个只出现一次的字符](50_01_FirstNotRepeatingChar.md)
-+ [字符流中第一个不重复的字符](50_02_FristCharacterInStream.md)
-+ [两个链表的第一个公共结点](52_FirstCommonNodesInLists.md)
-+ [数字在排序数组中出现的次数](53_01_NumberOfK.md)
-+ [0到n-1中缺失的数字](53_02_MissingNumber.md)
-+ [数组中数值和下标相等的元素](53_03_IntegerIdenticalToIndex.md)
-+ [二叉搜索树的第k个结点](54_KthNodeInBST.md)
-+ [二叉树的深度](55_01_TreeDepth.md)
-+ [平衡二叉树](55_02_BalancedBinaryTree.md)
-+ [数组中只出现一次的两个数字](56_01_NumbersAppearOnce.md)
-+ [数组中唯一只出现一次的数字](56_02_NumberAppearingOnce.md)
-+ [和为S的两个数字](57_01_TwoNumbersWithSum.md)
-+ [和为S的连续正数序列](57_02_ContinuousSquenceWithSum.md)
-+ [翻转单词顺序](58_01_ReverseWordsInSentence.md)
-+ [左旋转字符串](58_02_LeftRotateString.md)
-+ [滑动窗口的最大值](59_01_MaxInSlidingWindow.md)
-+ [扑克牌的顺子](61_ContinousCards.md)
diff --git a/docs/leetcode/cpp/0002._Add_Two_Numbers.md b/docs/leetcode/cpp/0002._Add_Two_Numbers.md
deleted file mode 100644
index 728077ac6..000000000
--- a/docs/leetcode/cpp/0002._Add_Two_Numbers.md
+++ /dev/null
@@ -1,70 +0,0 @@
-# 2. Add Two Numbers
-
-**难度:Medium**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/add-two-numbers
-
-> 内容描述
-
-```
-给定两个链表代表两个非负数,求这两个数的和
-(2 -> 4 -> 3) + (5 -> 6 -> 4)
-因为 342 + 465 = 807
-所以返回 7 -> 0 -> 8
-```
-
-## 解题方案
-
-> 思路
-
-
-这题的的关键在于链表的数储存是倒序的,因此只要从链表头相加,再将所得数挨个储存即可,但是要注意两数相加有可能大于10要进一位。
-```cpp
-/**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * ListNode *next;
- * ListNode(int x) : val(x), next(NULL) {}
- * };
- */
-class Solution {
-public:
- ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
- ListNode* current;
- ListNode* ret = nullptr;
- int num = 0;
- while(l1 && l2)
- {
- int sum = l1 ->val + l2 ->val + num;
- ListNode* node = new ListNode(sum % 10);
- num = sum / 10;
- ret ? current ->next = node : ret = node;
- current = node;
- l1 = l1 ->next;
- l2 = l2 ->next;
- }
- if(l2)
- l1 = l2;
- while(l1)
- {
- int sum = num + l1 ->val;
- ListNode* node = new ListNode(sum % 10);
- num = sum / 10;
- current ->next = node;
- current = node;
- l1 = l1 ->next;
- }
- if(num)
- {
- ListNode* node = new ListNode(num);
- current ->next = node;
- }
- return ret;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0003._Longest_Substring_Without_Repeating_Characters.md b/docs/leetcode/cpp/0003._Longest_Substring_Without_Repeating_Characters.md
deleted file mode 100644
index 983bad57c..000000000
--- a/docs/leetcode/cpp/0003._Longest_Substring_Without_Repeating_Characters.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# 3. Longest Substring Without Repeating Characters
-
-**难度:Medium**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/longest-substring-without-repeating-characters
-
-> 内容描述
-
-```
-
-Given a string, find the length of the longest substring without repeating characters.
-
-Example 1:
-
-Input: "abcabcbb"
-Output: 3
-Explanation: The answer is "abc", with the length of 3.
-Example 2:
-
-Input: "bbbbb"
-Output: 1
-Explanation: The answer is "b", with the length of 1.
-Example 3:
-
-Input: "pwwkew"
-Output: 3
-Explanation: The answer is "wke", with the length of 3.
- Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
-```
-
-## 解题方案
-
-> 思路 1
-******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
-
-
-用 map储存 key为字符,value 为这个字符的位置,我们可以维护一个子字符串(无重复字符),记录它的起始位置,遍历 string s 当无法在map中找到字符或者小于子字符串的起始位置,就是没有在这个字符串中出现,反之则字符重复,不过 map查找为 O(lgn),因此总的时间复杂度为O(NlgN)
-```cpp
-class Solution {
-public:
- int lengthOfLongestSubstring(string s) {
- map m;
- int beg = 0,length = s.length(),ll = 0,ans = 0;
- for(int i = 0;i < length;++i)
- {
- if(m.find(s[i]) == m.end() || m[s[i]] < beg)
- ll++;
- else
- {
- int pos = m[s[i]];
- ans = max(ll,ans);
- ll = ll - (pos - beg);
- beg = pos + 1;
- }
- m[s[i]] = i;
- }
- ans = max(ans,ll);
- return ans;
- }
-};
-```
-
-> 思路 2
-******- 时间复杂度: O(NlgN)******- 空间复杂度: O(1)******
-
-这个思路和上面差不多,用到了一个小窍门,因为储存的是字符,char为8位,因此能储存的最大数为256,这样空间复杂度就为O(1)
-
-```cpp
-class Solution {
-public:
- int lengthOfLongestSubstring(string s) {
- int m[256];
- for(int i = 0;i < 256;++i)
- m[i] = -1;
- int beg = 0,length = s.length(),ll = 0,ans = 0;
- for(int i = 0;i < length;++i)
- {
- if(m[s[i]] < beg)
- ll++;
- else
- {
- int pos = m[s[i]];
- ans = max(ll,ans);
- ll = ll - (pos - beg);
- beg = pos + 1;
- }
- m[s[i]] = i;
- }
- ans = max(ans,ll);
- return ans;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0004._Median_of_Two_Sorted_Arrays.md b/docs/leetcode/cpp/0004._Median_of_Two_Sorted_Arrays.md
deleted file mode 100644
index be2f433bb..000000000
--- a/docs/leetcode/cpp/0004._Median_of_Two_Sorted_Arrays.md
+++ /dev/null
@@ -1,159 +0,0 @@
-# 004. Median of Two Sorted Arrays
-
-**难度Hard**
-
-## 刷题内容
-> 原题连接
-
-* https://leetcode.com/problems/median-of-two-sorted-arrays/submissions/
-
-> 内容描述
-
-```
-There are two sorted arrays nums1 and nums2 of size m and n respectively.
-
-Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
-
-You may assume nums1 and nums2 cannot be both empty.
-
-Example 1:
-
-nums1 = [1, 3]
-nums2 = [2]
-
-The median is 2.0
-Example 2:
-
-nums1 = [1, 2]
-nums2 = [3, 4]
-
-The median is (2 + 3)/2 = 2.5
-```
-
-> 思路1
-******- 时间复杂度: O(n + m)******- 空间复杂度: O(1)******
-
-直接用暴利搜索,类似与归并两个有序的数组。遍历两个数组,当总长度等于(m+n)/ 2,注意区分总长度奇数和偶数
-```cpp
-class Solution {
-public:
- double findMedianSortedArrays(vector& nums1, vector& nums2) {
- int temp = (nums1.size() + nums2.size()) / 2,count1 = 0,i = 0,j = 0,current,pre;
- while(i < nums1.size() && j < nums2.size() && count1 <= temp)
- {
- pre = current;
- if(nums1[i] > nums2[j])
- current = nums2[j++];
- else
- current = nums1[i++];
- ++count1;
- }
- if(count1 <= temp)
- {
- if(i < nums1.size())
- while(count1 <= temp)
- {
- pre = current;
- current = nums1[i++];
- ++count1;
- }
- else
- while(count1 <= temp)
- {
- pre = current;
- current = nums2[j++];
- ++count1;
- }
- }
- if((nums1.size() + nums2.size()) % 2)
- return current;
- double ans = (current + pre) / 2.0;
- return ans;
- }
-};
-```
-> 思路2
-******- 时间复杂度: O(lg(min(n.m)))******- 空间复杂度: O(1)******
-
-我们可以通过二分查找优化算法,利用中位数的定义,将两个数组划分为左右两个部分,nums1左半部分加nums2左半部分等于nums1右半部分加nums2的右半部分,如果总长度为偶数,那么nums1左半部分加nums2左半部分等于nums1右半部分加nums2的右半部分加1。并且```max(nums1[i],nums2[j]) <= max(nums1[i + 1],nums2[j + 1])```,接下来我们只要二分查找找i,并且要注意边界情况
-
-```cpp
-class Solution {
-public:
- double findMedianSortedArrays(vector& nums1, vector& nums2) {
- int m = nums1.size(),n = nums2.size(),sum = m + n;
- if(!nums1.size())
- return sum % 2 ? nums2[sum / 2] : (nums2[sum /2] + nums2[sum / 2 - 1]) / 2.0;
- if(!nums2.size())
- return sum % 2 ? nums1[sum / 2] : (nums1[sum /2] + nums1[sum / 2 - 1]) / 2.0;
- if(m > n)
- return findMedianSortedArrays(nums2,nums1);
- int l = 0,r = m - 1;
- while(l < r)
- {
- int mid = (l + r) / 2;
- int j = (sum + 1) / 2 - mid - 2;
- int min1 = max(nums1[mid],nums2[j]),max1 = min(nums1[mid + 1],nums2[j + 1]);
- if(min1 <= max1)
- return sum % 2 ? min1 : (min1 + max1) / 2.0;
- else if(nums1[mid] > nums2[j])
- r = mid - 1;
- else
- l = mid + 1;
- }
- int j = (sum + 1) / 2 - l - 2;
- int min1,max1;
- if(j < 0)
- min1 = nums1[l];
- else
- min1 = max(nums1[l],nums2[j]);
- if(l == nums1.size() - 1)
- max1 = nums2[j + 1];
- else
- max1 = min(nums1[l + 1],nums2[j + 1]);
- if(min1 <= max1)
- return sum % 2 ? min1 : (min1 + max1) / 2.0;
- j++;
- if(j < nums2.size() - 1)
- max1 = min(nums1[l],nums2[j + 1]);
- else
- max1 = nums1[l];
- min1 = nums2[j];
- return sum % 2 ? min1 : (min1 + max1) / 2.0;
- }
-};
-```
-> 思路3
-******- 时间复杂度: O(lg(n+m))******- 空间复杂度: O(1)******
-
-由于题目中建议我们在时间复杂度O(lg(m+n))中完成,我们可以把这题看成寻找第k大的值,这样我们可以递归的去做,每次查找k/2,知道k等于1,注意边界值的处理
-```cpp
-class Solution {
-public:
-int getKth(vector nums1, int start1, int end1, vector nums2, int start2, int end2, int k) {
- int len1 = end1 - start1 + 1;
- int len2 = end2 - start2 + 1;
- if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
- if (len1 == 0) return nums2[start2 + k - 1];
-
- if (k == 1) return min(nums1[start1], nums2[start2]);
-
- int i = start1 + min(len1, k / 2) - 1;
- int j = start2 + min(len2, k / 2) - 1;
-
- if (nums1[i] > nums2[j]) {
- return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
- }
- else {
- return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
- }
- }
-double findMedianSortedArrays(vector nums1, vector nums2) {
- int n = nums1.size();
- int m = nums2.size();
- int left = (n + m + 1) / 2;
- int right = (n + m + 2) / 2;
- return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;
-}
-};
-```
diff --git a/docs/leetcode/cpp/0005._Longest_Palindromic_Substring.md b/docs/leetcode/cpp/0005._Longest_Palindromic_Substring.md
deleted file mode 100644
index b535fbe5d..000000000
--- a/docs/leetcode/cpp/0005._Longest_Palindromic_Substring.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# 5. Longest Palindromic Substring
-
-**难度:Medium**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/longest-palindromic-substring
-
-> 内容描述
-
-```
-Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
-
-Example 1:
-
-Input: "babad"
-Output: "bab"
-Note: "aba" is also a valid answer.
-Example 2:
-
-Input: "cbbd"
-Output: "bb"
-```
-
-## 解题方案
-
-> 思路 1
-******- 时间复杂度: O(N^2)******- 空间复杂度: O(N^2)******
-
-
-这题如果用单纯暴力的解法,时间复杂度为 O(n ^ 3),肯定超时,那么就要对这个算法进行优化,这里采用的是DP思想,定义 p(i,j)为s中的第i个数到s中的第j个数的子串,不难看出 p(i,j)中的子串有重复计算,接下来就可以写出状态转移方程 P(i,j)=(P(i+1,j?1) and S[i] == S[j])
-
-```cpp
-class Solution {
-public:
- int dp[1000][1000] = {0};
- string longestPalindrome(string s) {
- int beg = 0,en = 1,ans = 0;
- int length = s.length();
- for(int i = 0;i < length;++i)
- {
- dp[i][i] = 1;
- if(i + 1 < length && s[i] == s[i + 1])
- dp[i][i + 1] = 1;
- }
- for(int i = 0;i < length;++i)
- for(int j = 0;j <= i;++j)
- {
- if(i > j + 1)
- dp[j][i] = (dp[j + 1][i - 1] && s[i] == s[j]);
- if(dp[j][i] && i - j + 1 > ans)
- {
- ans = i - j + 1;
- beg = j;
- en = i + 1;
- }
- }
- string ret(s.begin() + beg,s.begin() + en);
- return ret;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0006._ZigZag_Conversion.md b/docs/leetcode/cpp/0006._ZigZag_Conversion.md
deleted file mode 100644
index 6cbbc25c6..000000000
--- a/docs/leetcode/cpp/0006._ZigZag_Conversion.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# 6. ZigZag Conversion
-
-**难度:Medium**
-
-## 刷题内容
-
-> 原题连接
-
-*https://leetcode.com/problems/zigzag-conversion
-*
-> 内容描述
-
-```
-The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
-
-P A H N
-A P L S I I G
-Y I R
-And then read line by line: "PAHNAPLSIIGYIR"
-
-Write the code that will take a string and make this conversion given a number of rows:
-
-string convert(string s, int numRows);
-Example 1:
-
-Input: s = "PAYPALISHIRING", numRows = 3
-Output: "PAHNAPLSIIGYIR"
-Example 2:
-
-Input: s = "PAYPALISHIRING", numRows = 4
-Output: "PINALSIGYAHRPI"
-Explanation:
-
-P I N
-A L S I G
-Y A H R
-P I
-```
-
-## 解题方案
-
-> 思路1
-******- 时间复杂度: O(N)******- 空间复杂度: O(N + numRows)******
-
-
-这道题理解了题目意思其实不难,一般人可能会开一个二维数组,然后就按题目意思储存,这样做的话时间复杂度和空间复杂度都比较大,这里我用的方法先用一个 string 类型变量 str ,resize 和输入的 s 长度相等,接着只要遍历找到 s[i] 在 str 中的位置即可
-
-
-```cpp
-class Solution {
-public:
- string convert(string s, int numRows) {
- string newStr;
- if(!s.length() || numRows == 1)
- return s;
- newStr.resize(s.length());
- int num = numRows * 2 - 2,col = s.length() / num,rem = (s.length() - 1) % num;
- vector rowNum;
- for(int i = 0;i < numRows;++i)
- if(!i)
- s.length() % num ? rowNum.push_back(col + 1) : rowNum.push_back(col);
- else
- {
- if(i == numRows - 1)
- rem >= i ? rowNum.push_back(rowNum[i - 1] + (s.length() - 1) / num + 1) : rowNum.push_back(rowNum[i - 1] + (s.length() - 1) / num);
- else
- {
- int temp = 2 * numRows - i - 2,col1 = (s.length() - 1) / num;
- if(rem >= temp)
- rowNum.push_back(rowNum[i - 1] + (col1 + 1) * 2);
- else if(rem >= i)
- rowNum.push_back(rowNum[i - 1] + col1 * 2 + 1);
- else
- rowNum.push_back(rowNum[i - 1] + col1 * 2);
- }
- }
- for(int i = 0;i < s.length();++i)
- {
- int index1 = i % num;
- int index2 = i / num;
- if(!index1)
- newStr[index2] = s[i];
- else if(index1 == numRows - 1)
- newStr[index2 + rowNum[index1 - 1]] = s[i];
- else if(index1 < numRows)
- newStr[index2 * 2 + rowNum[index1 - 1]] = s[i];
- else
- {
- int index3 = 2 * numRows - index1 - 2;
- newStr[index2 * 2 + 1 + rowNum[index3 - 1]] = s[i];
- }
- }
- return newStr;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0007._Reverse_Integer.md b/docs/leetcode/cpp/0007._Reverse_Integer.md
deleted file mode 100644
index 296913158..000000000
--- a/docs/leetcode/cpp/0007._Reverse_Integer.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# 7. Reverse Integer
-
-**�Ѷ�:Easy**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/reverse-integer/
-
-> ��������
-
-```
-Given a 32-bit signed integer, reverse digits of an integer.
-
-Example 1:
-
-Input: 123
-Output: 321
-Example 2:
-
-Input: -123
-Output: -321
-Example 3:
-
-Input: 120
-Output: 21
-Note:
-Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?231, 231 ? 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(1)******
-
-һ��easy����Ŀ�����μ������λ����������Ҫע�ⳬ��int�ķ�Χ��
-
-```cpp
-class Solution {
-public:
- int reverse(int x) {
- long long val = 0;
- do
- {
- val = val * 10 + x % 10;
- x /= 10;
- } while (x);
-
- return (val > INT_MAX || val < INT_MIN) ? 0 : val;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0008._String_to_Integer_(atoi).md b/docs/leetcode/cpp/0008._String_to_Integer_(atoi).md
deleted file mode 100644
index 66c9454fa..000000000
--- a/docs/leetcode/cpp/0008._String_to_Integer_(atoi).md
+++ /dev/null
@@ -1,104 +0,0 @@
-# 8. String to Integer (atoi)
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/string-to-integer-atoi/
-
-> ��������
-
-```
-Implement atoi which converts a string to an integer.
-
-The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
-
-The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
-
-If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
-
-If no valid conversion could be performed, a zero value is returned.
-
-Note:
-
-Only the space character ' ' is considered as whitespace character.
-Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?231, 231 ? 1]. If the numerical value is out of the range of representable values, INT_MAX (231 ? 1) or INT_MIN (?231) is returned.
-Example 1:
-
-Input: "42"
-Output: 42
-Example 2:
-
-Input: " -42"
-Output: -42
-Explanation: The first non-whitespace character is '-', which is the minus sign.
- Then take as many numerical digits as possible, which gets 42.
-Example 3:
-
-Input: "4193 with words"
-Output: 4193
-Explanation: Conversion stops at digit '3' as the next character is not a numerical digit.
-Example 4:
-
-Input: "words and 987"
-Output: 0
-Explanation: The first non-whitespace character is 'w', which is not a numerical
- digit or a +/- sign. Therefore no valid conversion could be performed.
-Example 5:
-
-Input: "-91283472332"
-Output: -2147483648
-Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer.
- Thefore INT_MIN (?231) is returned.
-```
-
-> ˼·
-******- ʱ�临�Ӷ�: O(N)******- �ռ临�Ӷ�: O(N)******
-
-��һ���ַ���ת�����֣�����ַ���ֻ������ֻҪ�����ַ���ת��int���͵����ּ��ɣ������������������ģ����Ҫע��߽�ֵ���ж����ֵ�����������Ϊ�����Ч�ʡ��ȼ�����10��32�η���10��n�η���ֵ��
-
-```cpp
-class Solution {
-public:
- int myAtoi(string str) {
- int i = 0,count1 = 0;
- long long arr[34];
- arr[0] = 1;
- for(int i = 1;i < 34;++i)
- arr[i] = arr[i - 1] * 10;
- while(str[i] == ' ')
- i++;
- if(str[i] == '-' || str[i] == '+')
- {
- if(str[i] == '-')
- count1 = 1;
- i++;
- }
- if(!isdigit(str[i]))
- return 0;
- while(str[i] == '0')
- i++;
- long long num = 0;
- int j = i;
- while(j < str.length() && isdigit(str[j]))
- j++;
- if(j - i > 33)
- return count1 ? INT_MIN : INT_MAX;
- j--;
- int t = 0;
- while(j >= i)
- {
- num += (str[j] - '0') * arr[t++];
- if(!count1 && num > INT_MAX)
- return INT_MAX;
- if(count1 && num * -1 < INT_MIN)
- return INT_MIN;
- j--;
- }
- if(count1)
- num *= -1;
- return num;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0009._Palindrome_Number.md b/docs/leetcode/cpp/0009._Palindrome_Number.md
deleted file mode 100644
index 788beb123..000000000
--- a/docs/leetcode/cpp/0009._Palindrome_Number.md
+++ /dev/null
@@ -1,102 +0,0 @@
-# 9. Palindrome Number
-
-**难度:Medium**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/palindrome-number
-*
-> 内容描述
-
-```
-Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.
-
-Example 1:
-
-Input: 121
-Output: true
-Example 2:
-
-Input: -121
-Output: false
-Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.
-Example 3:
-
-Input: 10
-Output: false
-Explanation: Reads 01 from right to left. Therefore it is not a palindrome.
-Follow up:
-
-Coud you solve it without converting the integer to a string?
-```
-
-## 解题方案
-
-> 思路1
-******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
-
-
-这题的难度不大,由于是数字,判断回文只需要求出倒过来的数字,判断两者是否相等,不过要注意负数一定不是回文
-
-
-```cpp
-class Solution {
-public:
- bool isPalindrome(int x) {
- long long ret = 0;
- int num = x;
- if(x < 0)
- return false;
- while(num)
- {
- ret = 10 * ret + num % 10;
- num /= 10;
- }
- if(ret == x)
- return true;
- return false;
- }
-};
-```
-> 思路2
-******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
-
-
-计算出数字的长度,用双指针法,一个指针指向头,另一个指向尾,相等就前一个指针加一,后一个指针减一,若不相等则返回 false
-
-
-```cpp
-class Solution {
-public:
- bool isPalindrome(int x) {
- if (x < 0)
- return false;
-
- int cnt = 0;
- long fac = 1;
- int div = INT_MAX;
- while (div != 0) {
- cnt++;
- fac *= 10;
- div = x/fac;
- }
-
- fac /= 10;
- for (int i=0; i难度: Hard**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/regular-expression-matching
-
-> 内容描述
-
-```
-Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
-
-'.' Matches any single character.
-'*' Matches zero or more of the preceding element.
-The matching should cover the entire input string (not partial).
-
-Note:
-
-s could be empty and contains only lowercase letters a-z.
-p could be empty and contains only lowercase letters a-z, and characters like . or *.
-
-Example 1:
-
-Input:
-s = "aa"
-p = "a"
-Output: false
-Explanation: "a" does not match the entire string "aa".
-
-Example 2:
-
-Input:
-s = "aa"
-p = "a*"
-Output: true
-Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
-
-Example 3:
-
-Input:
-s = "ab"
-p = ".*"
-Output: true
-Explanation: ".*" means "zero or more (*) of any character (.)".
-
-Example 4:
-
-Input:
-s = "aab"
-p = "c*a*b"
-Output: true
-Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".
-
-Example 5:
-
-Input:
-s = "mississippi"
-p = "mis*is*p*."
-Output: false
-```
-
-## 解题方案
-
-> 思路1
-******- 时间复杂度: O(n^2)******- 空间复杂度: O(n^2)******
-
-用动态规划的思路去解,dp[i][j]代表字符串s中第i个字符之前的字符串与p中第j个字符串之前的字符是否匹配。写出状态转移方程。当```s[i] == p[j] || p[j] == '.'```时。```dp[i + 1][j + 1] = dp[i][j]```。当```p[j] == '*'```时,可以匹配0个,1个或多个之前相同的字符。当之前的字符```s[i] == p[j - 1] || p[j - 1] == '*'```时。```dp[i + 1][j + 1] = dp[i][j] || dp[i][j + 1]```表示匹配1个或者多个。还可匹配0个。因此```dp[i + 1][j + 1] = dp[i + 1][j + 1] || dp[i + 1][j - 1]```
-
-```cpp
-class Solution {
-public:
- bool isMatch(string s, string p) {
- s.push_back(' ');
- p.push_back(' ');
- int len1 = s.length(),len2 = p.length();
- int dp[len1 + 1][len2 + 1];
- memset(dp,0,sizeof(dp));
- dp[0][0] = 1;
- for(int i = 1;i < len2;++i)
- if(p[i] == '*')
- dp[0][i + 1] = dp[0][i - 1];
- for(int i = 0;i < len1;++i)
- for(int j = 0;j < len2;++j)
- if(j && p[j] == '*')
- {
- dp[i + 1][j + 1] = (p[j - 1] == s[i] || p[j - 1] == '.') && (dp[i][j] || dp[i][j + 1]);
- dp[i + 1][j + 1] = dp[i + 1][j + 1] || dp[i + 1][j - 1];
- }
- else if(s[i] == p[j] || p[j] == '.')
- dp[i + 1][j + 1] = dp[i][j];
- return dp[len1][len2];
- }
-};
-```
diff --git a/docs/leetcode/cpp/0011._Container_With_Most_Water.md b/docs/leetcode/cpp/0011._Container_With_Most_Water.md
deleted file mode 100644
index 1a610d4da..000000000
--- a/docs/leetcode/cpp/0011._Container_With_Most_Water.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# 11. container with most water
-
-**难度:Medium**
-
-## 刷题内容
-
-> 原题连接
-
-*https://leetcode.com/problems/container-with-most-water/
-*
-> 内容描述
-
-```
-Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
-
-Note: You may not slant the container and n is at least 2.
-```
-
-## 解题方案
-
-> 思路
-******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
-
-这道题刚开始很容易想到用暴力的方法去解,但是时间复杂度为 O(n^2) 测试之后发现是 TLE,那么我们就要对算法进行优化,这里我们用双指针法,定义两个指针,一个指向头,另一个指向尾部,比较两个指针指向的数的大小,若头部的大,则指向头部的指针向后移动一位,反之,则指向尾部的指针向前移动一位。
-
-
-```cpp
-class Solution {
-public:
- int maxArea(vector& height) {
- int i = 0,j = height.size() - 1,ans = INT_MIN;
- while(i < j)
- {
- int t = min(height[i],height[j]);
- ans = max(ans,t * (j - i));
- height[i] < height[j] ? i++ : j--;
- }
- return ans;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0012._Integer_to_Roman.md b/docs/leetcode/cpp/0012._Integer_to_Roman.md
deleted file mode 100644
index e646d8a4c..000000000
--- a/docs/leetcode/cpp/0012._Integer_to_Roman.md
+++ /dev/null
@@ -1,164 +0,0 @@
-# 12. Integer to Roman
-
-**�Ѷ�:Medium**
-
-## ˢ������
-
-> ԭ������
-
-* https://leetcode.com/problems/rotate-list/
-
-> ��������
-
-```
-Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
-
-Symbol Value
-I 1
-V 5
-X 10
-L 50
-C 100
-D 500
-M 1000
-For example, two is written as II in Roman numeral, just two one's added together. Twelve is written as, XII, which is simply X + II. The number twenty seven is written as XXVII, which is XX + V + II.
-
-Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:
-
-I can be placed before V (5) and X (10) to make 4 and 9.
-X can be placed before L (50) and C (100) to make 40 and 90.
-C can be placed before D (500) and M (1000) to make 400 and 900.
-Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.
-
-Example 1:
-
-Input: 3
-Output: "III"
-Example 2:
-
-Input: 4
-Output: "IV"
-Example 3:
-
-Input: 9
-Output: "IX"
-Example 4:
-
-Input: 58
-Output: "LVIII"
-Explanation: L = 50, V = 5, III = 3.
-Example 5:
-
-Input: 1994
-Output: "MCMXCIV"
-Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
-
-```
-
-
-
-> ˼·1
-
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(n)******
-
-��Ŀ���ѣ�ֱ����һ�ֱ�����д��
-
-```cpp
-class Solution {
-public:
- string intToRoman(int num) {
- string ans;
- vector table;
- int a = 0;
- int count = 0;
- while(num){
- a = num%10;
- num /= 10;
- ++count;
- if(count==1){
- if(a==1) table.push_back("I");
- else if(a==2) table.push_back("II");
- else if(a==3) table.push_back("III");
- else if(a==4) table.push_back("IV");
- else if(a==5) table.push_back("V");
- else if(a==6) table.push_back("VI");
- else if(a==7) table.push_back("VII");
- else if(a==8) table.push_back("VIII");
- else if(a==9) table.push_back("IX");
- }
- else if(count==2){
- if(a==1) table.push_back("X");
- else if(a==2) table.push_back("XX");
- else if(a==3) table.push_back("XXX");
- else if(a==4) table.push_back("XL");
- else if(a==5) table.push_back("L");
- else if(a==6) table.push_back("LX");
- else if(a==7) table.push_back("LXX");
- else if(a==8) table.push_back("LXXX");
- else if(a==9) table.push_back("XC");
- }
- else if(count==3){
- if(a==1) table.push_back("C");
- else if(a==2) table.push_back("CC");
- else if(a==3) table.push_back("CCC");
- else if(a==4) table.push_back("CD");
- else if(a==5) table.push_back("D");
- else if(a==6) table.push_back("DC");
- else if(a==7) table.push_back("DCC");
- else if(a==8) table.push_back("DCCC");
- else if(a==9) table.push_back("CM");
- }
- else if(count==4){
- if(a==1) table.push_back("M");
- else if(a==2) table.push_back("MM");
- else if(a==3) table.push_back("MMM");
- }
- }
- for(int i = table.size()-1; i >= 0; --i){
- ans += table[i];
- }
- return ans;
- }
-};
-```
-
-> ˼·2
-
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(1)******
-
-̫���if else���IJ��ÿ������ǿ��Ի�һ�ָ����ŵ�д�����ô�����ÿ���
-
-```cpp
-class Solution {
-public:
- int arr[7] = {'I','V','X','L','C','D','M'};
- int arr1[13] = {1,4,5,9,10,40,50,90,100,400,500,900,1000};
- void f(int& num,int i,string& ans)
- {
- if(i % 2)
- {
- ans.push_back(arr[i / 4 * 2]);
- ans.push_back(arr[i / 2 + 1]);
- }
- else
- ans.push_back(arr[i / 2]);
- num -= arr1[i];
- }
- string intToRoman(int num) {
- string ans;
- while(num)
- {
- int i;
- for(i = 0;i < 13;++i)
- if(num < arr1[i])
- {
- f(num,i - 1,ans);
- break;
- }
- if(i == 13)
- f(num,i - 1,ans);
- }
- return ans;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0014._Longest_Common_Prefix.md b/docs/leetcode/cpp/0014._Longest_Common_Prefix.md
deleted file mode 100644
index d87e89f1d..000000000
--- a/docs/leetcode/cpp/0014._Longest_Common_Prefix.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# 14. Longest Common Prefix
-
-**�Ѷ�:Easy**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/longest-common-prefix/
-
-> ��������
-
-```
-Write a function to find the longest common prefix string amongst an array of strings.
-
-If there is no common prefix, return an empty string "".
-
-Example 1:
-
-Input: ["flower","flow","flight"]
-Output: "fl"
-Example 2:
-
-Input: ["dog","racecar","car"]
-Output: ""
-Explanation: There is no common prefix among the input strings.
-Note:
-
-All given inputs are in lowercase letters a-z.
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(n^2)******- �ռ临�Ӷ�: O(1)******
-
-���ǰ�����Ӵ���ֻ�б��������Ӵ������������Ӵ����ɣ�����Ҫע����ܴ��ڿ��ַ���
-
-```cpp
-class Solution {
-public:
- string longestCommonPrefix(vector& strs) {
- string temp;
- if(!strs.size() || !strs[0].length())
- return temp;
- int j = 0;
- while(1)
- {
- int i = 0;
- int ch = strs[0][j];
- for(;i < strs.size();++i)
- if(j >= strs[i].length() || strs[i][j] != ch)
- break;
- if(i != strs.size())
- break;
- temp.push_back(strs[0][j++]);
- }
- return temp;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0015._3sum.md b/docs/leetcode/cpp/0015._3sum.md
deleted file mode 100644
index bbcbb74e8..000000000
--- a/docs/leetcode/cpp/0015._3sum.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# 15. 3sum
-
-**难度:Medium**
-
-## 刷题内容
-
-> 原题连接
-
-*https://leetcode.com/problems/3sum
-*
-> 内容描述
-
-```
-Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
-
-Note:
-
-The solution set must not contain duplicate triplets.
-```
-
-## 解题方案
-
-> 思路
-******- 时间复杂度: O(N ^ 2)******- 空间复杂度: O(N)******
-
-之前做过两个数之和等于某个数的题目,其实这题也差不多,三数之和等于0,那么我们只要让另外两个数之和等于第三个数的相反数即可,不过这里要注意会存在重复,所以要去重
-
-
-```cpp
-class Solution {
-public:
- vector> threeSum(vector& nums) {
- vector > ret;
- sort(nums.begin(),nums.end());
- for(int i = 0;i < nums.size();++i)
- {
- int t1 = i + 1,t2 = nums.size() - 1;
- if(i && nums[i] == nums[i - 1])
- continue;
- while(t1 < t2)
- if(nums[t1] + nums[t2] == -nums[i])
- {
- vector v;
- v.push_back(nums[i]);
- v.push_back(nums[t1]);
- v.push_back(nums[t2]);
- ret.push_back(v);
- ++t1;
- --t2;
- }
- else if(nums[t1] + nums[t2] < -nums[i])
- ++t1;
- else
- --t2;
- }
- auto pos = unique(ret.begin(),ret.end());
- ret.erase(pos,ret.end());
- return ret;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0016._3Sum_Closest.md b/docs/leetcode/cpp/0016._3Sum_Closest.md
deleted file mode 100644
index 496ac062c..000000000
--- a/docs/leetcode/cpp/0016._3Sum_Closest.md
+++ /dev/null
@@ -1,45 +0,0 @@
-## 16. 3Sum Closest
-
-难度:Medium
-
-## 内容
-
-> 原题链接:https://leetcode.com/problems/3sum-closest
-
-Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
-
-Example:
-
-```
-Given array nums = [-1, 2, 1, -4], and target = 1.
-
-The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
-```
-
-## 思路
-
-先排序,遍历第一个数,第二和第三个数通过双指针查找,转化为2sum closest的问题。如果遇到和等于target的三个数,直接返回target。
-
-## 代码
-
-```
-class Solution {
-public:
- int threeSumClosest(vector& nums, int target) {
- std::sort(nums.begin(), nums.end());
- int min_distance{INT_MAX}, sum{0}, cur_sum{0};
- for (auto it = nums.cbegin(); it != nums.cend(); ++it)
- for (auto left_idx = std::next(it), right_idx = std::prev(nums.cend()); left_idx < right_idx; cur_sum > target ? --right_idx : ++left_idx) {
- cur_sum = *it + *left_idx + *right_idx;
- auto cur_distance = std::abs(cur_sum - target);
- if (cur_sum == target)
- return target;
- else if (cur_distance < min_distance) {
- min_distance = cur_distance;
- sum = cur_sum;
- }
- }
- return sum;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0017._Letter_Combinations_of_a_Phone_Number.md b/docs/leetcode/cpp/0017._Letter_Combinations_of_a_Phone_Number.md
deleted file mode 100644
index d7a240e85..000000000
--- a/docs/leetcode/cpp/0017._Letter_Combinations_of_a_Phone_Number.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# 17. Letter Combinations of a Phone Number
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/letter-combinations-of-a-phone-number/
-
-> ��������
-
-```
-Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.
-
-A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.
-
-
-
-Example:
-
-Input: "23"
-Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
-Note:
-
-Although the above answer is in lexicographical order, your answer could be in any order you want.
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(2^n)******- �ռ临�Ӷ�: O(1)******
-
-�û��ݷ�ȥ�⣬�Ƚ������ַ���ת�����֡�����7��9֮����������ֶ���3����ĸ�������ÿ�����ִ�������ĸ���������û��ݷ�
-
-```cpp
-class Solution {
-public:
- void DFS(string& s,int i,vector& ans,string& temp)
- {
- if(i == s.length())
- {
- ans.push_back(temp);
- return;
- }
- int t = s[i] - '2';
- int ch_beg;
- if(t < 6)
- ch_beg = 'a' + t * 3;
- else
- ch_beg = 'a' + (t - 1) * 3 + 4;
- int en = 3;
- if(t == 5 || t == 7)
- en = 4;
- for(int j = 0;j < en;++j)
- {
- temp.push_back(ch_beg + j);
- DFS(s,i + 1,ans,temp);
- temp.pop_back();
- }
- }
- vector letterCombinations(string digits) {
- vector ans;
- if(!digits.size())
- return ans;
- string temp;
- DFS(digits,0,ans,temp);
- return ans;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0018._4Sum.md b/docs/leetcode/cpp/0018._4Sum.md
deleted file mode 100644
index c3e0db2cb..000000000
--- a/docs/leetcode/cpp/0018._4Sum.md
+++ /dev/null
@@ -1,57 +0,0 @@
-## 18. 4Sum
-
-难度:Medium
-
-## 内容
-
-题目链接:https://leetcode.com/problems/4sum
-
-Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
-
-Note:
-
-The solution set must not contain duplicate quadruplets.
-
-Example:
-
-```
-Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.
-
-A solution set is:
-[
- [-1, 0, 0, 1],
- [-2, -1, 1, 2],
- [-2, 0, 0, 2]
-]
-```
-
-## 思路
-
-思路和 3Sum 类似,多了一层for循环。为了避免重复,在存储结果的时候使用STL的set。
-
-## 代码
-
-```
-class Solution {
-public:
- vector> fourSum(vector& nums, int target) {
- if (nums.size() < 4) return vector>{};
- std::set> res;
- std::sort(nums.begin(), nums.end());
- for (size_t i = 0; i < nums.size() - 3; ++i)
- for (size_t j = i + 1; j < nums.size() - 2; ++j) {
- auto left_idx = j + 1; auto right_idx = nums.size() - 1;
- int sum = 0;
- for (left_idx = j + 1, right_idx = nums.size() - 1; left_idx < right_idx; sum > target ? --right_idx : ++left_idx) {
- sum = nums[i] + nums[j] + nums[left_idx] + nums[right_idx];
- if (sum == target) {
- vector res_single{nums[i], nums[j], nums[left_idx], nums[right_idx]};
- res.insert(res_single);
- }
-
- }
- }
- return vector>(res.begin(), res.end());
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0019._Remove_Nth_Node_From_End_of_List.md b/docs/leetcode/cpp/0019._Remove_Nth_Node_From_End_of_List.md
deleted file mode 100644
index 2c1fc990f..000000000
--- a/docs/leetcode/cpp/0019._Remove_Nth_Node_From_End_of_List.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# 19. Remove Nth Node From End of List
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/remove-nth-node-from-end-of-list/
-
-> ��������
-
-```
-Given a linked list, remove the n-th node from the end of list and return its head.
-
-Example:
-
-Given linked list: 1->2->3->4->5, and n = 2.
-
-After removing the second node from the end, the linked list becomes 1->2->3->5.
-```
-
-> ˼·
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(1)******
-
-ɾ��������n������Ϊ�˷�ֹ��������Ϊ1ʱ�Ŀ�ָ���쳣���Ȳ���һ������ͷ����������ֻҪ�ȱ���������������������ܳ��ȣ������ܳ��ȼ�ȥ n ��������Ҫɾ��������ǰһ����������ͷ�ij��ȣ�������ֻҪ�ø�ѭ���ҵ���ɾ��Ҫɾ���Ľڵ㼴�ɡ�
-
-```cpp
-/**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * ListNode *next;
- * ListNode(int x) : val(x), next(NULL) {}
- * };
- */
-class Solution {
-public:
- ListNode* removeNthFromEnd(ListNode* head, int n) {
- ListNode* current = head;
- int num = 0;
- while(current)
- {
- num++;
- current = current ->next;
- }
- ListNode* n1 = new ListNode(0);
- n1 ->next = head;
- current = n1;
- num -= n;
- while(num)
- {
- num--;
- current = current ->next;
- }
- ListNode* temp = current ->next;
- current ->next = temp ->next;
- return n1 ->next;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0020._Valid_Parentheses.md b/docs/leetcode/cpp/0020._Valid_Parentheses.md
deleted file mode 100644
index 102c66ca6..000000000
--- a/docs/leetcode/cpp/0020._Valid_Parentheses.md
+++ /dev/null
@@ -1,55 +0,0 @@
-## 20. Valid Parentheses
- **难度: Easy**
-## 刷题内容
-> 原题连接
-* https://leetcode-cn.com/problems/valid-parentheses/
-> 内容描述
-```
-Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
-
-An input string is valid if:
-
-Open brackets must be closed by the same type of brackets.
-Open brackets must be closed in the correct order.
-Note that an empty string is also considered valid.
-
-### Example
-1. Input: "()" -> Output: true
-
-2. Input: "()[]{}" -> Output: true
-
-3. Input: "(]" -> Output: false
-
-4. Input: "([)]" -> Output: false
-
-5. Input: "{[]}" -> Output: true
-```
-## 解题方案
-> 思路:
-```
-利用栈先进后出的先天优势,解决匹配问题。
-```
-```cpp
-bool isValid(string s) {
- stack stacks;
- for(int i=0;i难度:Easy**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/merge-two-sorted-lists
-*
-> 内容描述
-
-```
-Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
-
-Example:
-
-Input: 1->2->4, 1->3->4
-Output: 1->1->2->3->4->4
-```
-
-## 解题方案
-
-> 思路
-******- 时间复杂度: O(N + M)******- 空间复杂度: O(1)******
-
-首先这两个链表是排序好的,那么我们先定义一个空链表,再定义两个指针 i,j,按照顺序比较两个链表,如果 i 指向的数字小于 j指向的数字,i 指向的节点插入新链表中,i = i -> next,反之则操作 j。不过要注意其中一个链表可能会先结束,所以另一个未结束的链表直接插入新链表即可
-
-
-```cpp
-/**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * ListNode *next;
- * ListNode(int x) : val(x), next(NULL) {}
- * };
- */
-class Solution {
-public:
- ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
- ListNode* h1 = l1;
- ListNode* h2 = l2;
- ListNode* t = new ListNode(0);
- ListNode* curr = t;
- while (h1 && h2)
- {
- if (h1->val <= h2->val) {
- curr->next = h1;
- h1 = h1->next;
- }
- else{
- curr->next = h2;
- h2 = h2->next;
- }
- curr = curr->next;
- }
- while (h1)
- {
- curr->next = h1;
- h1 = h1->next;
- curr = curr->next;
- }
- while(h2)
- {
- curr->next = h2;
- h2 = h2->next;
- curr = curr->next;
- }
- ListNode* res = t->next;
- delete t;
- return res;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0022._Generate_Parentheses.md b/docs/leetcode/cpp/0022._Generate_Parentheses.md
deleted file mode 100644
index 469322c3a..000000000
--- a/docs/leetcode/cpp/0022._Generate_Parentheses.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# 22. Generate Parentheses
-
- **难度: Medium**
-
- ## 刷题内容
-
- > 原题连接
-
-* https://leetcode-cn.com/problems/generate-parentheses/
-
- > 内容描述
-
- ```
-给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
-
-例如,给出 n = 3,生成结果为:
-
-[
- "((()))",
- "(()())",
- "(())()",
- "()(())",
- "()()()"
-]
- ```
-
-## 解题方案
-> 思路 1
-```
-回溯法
-```
-
-```cpp
-void dfs(int left, int total, string path, vector& ans){
- if(total==0&&left==0){
- ans.push_back(path);
- return ;
- }
- if(left>0)
- dfs(left-1, total-1, path+"(", ans);
- if(left generateParenthesis(int n) {
- vector ans;
- string path="";
- dfs(n, n*2, path, ans);
- return ans;
-}
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0023._Merge_K_Sorted_Lists.md b/docs/leetcode/cpp/0023._Merge_K_Sorted_Lists.md
deleted file mode 100644
index bddfa6bb4..000000000
--- a/docs/leetcode/cpp/0023._Merge_K_Sorted_Lists.md
+++ /dev/null
@@ -1,125 +0,0 @@
-# 23. merge k sorted lists
-
-**难度: Hard**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/merge-k-sorted-lists/
-
-> 内容描述
-
-```
-Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
-
-Example:
-
-Input:
-[
- 1->4->5,
- 1->3->4,
- 2->6
-]
-Output: 1->1->2->3->4->4->5->6
-```
-
-## 解题方案
-
-> 思路1
-******- 时间复杂度: O(Nlg(K))******- 空间复杂度: O(K)******
-
-这里运用最小堆,先去每个链表的第一个元素构建最小堆,由于链表都是已排序的,因此,每次堆的顶部都是最小的元素,这里用优先队列实现最小堆。
-
-
-```cpp
-/**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * ListNode *next;
- * ListNode(int x) : val(x), next(NULL) {}
- * };
- */
-class Solution {
-public:
- struct cmp
- {
- bool operator()(ListNode* a, ListNode* b) const
- {
- return a ->val > b ->val;
- }
- };
- ListNode* mergeKLists(vector& lists) {
- priority_queue,cmp> pq;
- ListNode* ret = nullptr;
- ListNode* current = nullptr;
- for(int i = 0;i < lists.size();++i)
- if(lists[i])
- pq.push(lists[i]);
- while(pq.size())
- {
- ListNode* temp = pq.top();
- pq.pop();
- if(!ret)
- ret = temp;
- else
- current ->next = temp;
- current = temp;
- if(temp ->next)
- pq.push(temp ->next);
- }
- return ret;
- }
-};
-```
-> 思路2
-******- 时间复杂度: O(Nlg(K))******- 空间复杂度: O(1)******
-
-这个思路用分治思想,我们可以通过归并排序解决,首先前面已经做过了两个有序链表的排序,我们可以把链表看做元素,只要对数组 Lists进行归并排序即可。
-
-```cpp
-class Solution {
-public:
- ListNode* merge(ListNode* list1, ListNode* list2) {
- ListNode head(0);
- ListNode* tail = &head;
- auto cur1 = list1;
- auto cur2 = list2;
- while (cur1 != nullptr && cur2 != nullptr) {
- if (cur1->val < cur2->val) {
- tail->next = cur1;
- tail = tail->next;
- cur1 = cur1->next;
- } else {
- tail->next = cur2;
- tail = tail->next;
- cur2 = cur2->next;
- }
- }
- auto cur = cur1 == nullptr ? cur2 : cur1;
- while (cur != nullptr) {
- tail->next = cur;
- tail = tail->next;
- cur = cur->next;
- }
- return head.next;
- }
- ListNode* mergeSort(vector& lists, int start, int end) {
- if (start > end) {
- return nullptr;
- }
- if (start == end) {
- return lists[start];
- }
- int mid = start + (end - start) / 2;
- auto list1 = mergeSort(lists, start, mid);
- auto list2 = mergeSort(lists, mid + 1, end);
- return merge(list1, list2);
- }
- ListNode* mergeKLists(vector& lists) {
- int n = lists.size();
- return mergeSort(lists, 0, n - 1);
- }
-};
-```
diff --git a/docs/leetcode/cpp/0024._Swap_Nodes_in_Pairs.md b/docs/leetcode/cpp/0024._Swap_Nodes_in_Pairs.md
deleted file mode 100644
index 4e812adab..000000000
--- a/docs/leetcode/cpp/0024._Swap_Nodes_in_Pairs.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# 24. Swap Nodes in Pairs
-
- **难度: Medium**
-
- ## 刷题内容
-
- > 原题连接
-
-* https://leetcode-cn.com/problems/swap-nodes-in-pairs/
-
- > 内容描述
-
- ```
-给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
-
-示例:
-
-给定 1->2->3->4, 你应该返回 2->1->4->3.
-说明:
-
-你的算法只能使用常数的额外空间。
-你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
- ```
-
-## 解题方案
-> 思路 1
-```
-链表反转
-```
-
-```cpp
-ListNode* swapPairs(ListNode* head) {
- if(head==NULL||head->next==NULL)
- return head;
-
- ListNode* slow=head;
- ListNode* fast=head->next;
- ListNode* pre=new ListNode(0);
- ListNode* ans = pre;
- while(slow&&fast){
- slow->next = fast->next;
- fast->next = slow;
- pre->next = fast;
- if(slow->next==NULL||slow->next->next==NULL){
- break;
- }
- fast = slow->next->next;
- pre = slow;
- slow = slow->next;
- }
- return ans->next;
-}
-```
diff --git a/docs/leetcode/cpp/0025._Reverse_Nodes_In_K_Group.md b/docs/leetcode/cpp/0025._Reverse_Nodes_In_K_Group.md
deleted file mode 100644
index cdc28074c..000000000
--- a/docs/leetcode/cpp/0025._Reverse_Nodes_In_K_Group.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# 25.reverse nodes in k group
-
-**�Ѷ�Hard**
-
-## ˢ������
-
-> ԭ������
-
-* https://leetcode.com/problems/reverse-nodes-in-k-group/
-
-> ��������
-
-```
-Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
-
-k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
-
-Example:
-
-Given this linked list: 1->2->3->4->5
-
-For k = 2, you should return: 2->1->4->3->5
-
-For k = 3, you should return: 3->2->1->4->5
-
-Note:
-
-Only constant extra memory is allowed.
-You may not alter the values in the list's nodes, only nodes itself may be changed.
-```
-> ˼·1
-******- ʱ�临�Ӷ�: O(N)******- �ռ临�Ӷ�: O(1)******
-
-��Ŀ�������ѣ����������˵ݹ�ķ���ȥ�⣬����Ŀ�е�note��˵�����ж���Ĵ���ռ䣬���ݹ�����ɸ����Ŀռ䣬���ѵݹ�ij�ѭ�����������»��ǵݹ�İ汾
-
-```cpp
-/**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * ListNode *next;
- * ListNode(int x) : val(x), next(NULL) {}
- * };
- */
-class Solution {
-public:
- ListNode* reverseKGroup(ListNode* head, int k) {
- if(!head)
- return head;
- ListNode* current = head,*next1,*pre = nullptr;
- int m = 1;
- while(m <= k && current)
- {
- next1 = current ->next;
- current ->next = pre;
- pre = current;
- current = next1;
- ++m;
- }
- if(m <= k)
- {
- while(current != head)
- {
- ListNode* temp = pre ->next;
- pre ->next = current;
- current = pre;
- pre = temp;
- }
- pre = head;
- }
- else
- head ->next = reverseKGroup(current,k);
- return pre;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0027._Remove_Element.md b/docs/leetcode/cpp/0027._Remove_Element.md
deleted file mode 100644
index 30694b543..000000000
--- a/docs/leetcode/cpp/0027._Remove_Element.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# 27.Remove Element
-
-**�Ѷ�Easy**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/remove-element/
-
-> ��������
-
-```
-Given an array nums and a value val, remove all instances of that value in-place and return the new length.
-
-Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
-
-The order of elements can be changed. It doesn't matter what you leave beyond the new length.
-
-Example 1:
-
-Given nums = [3,2,2,3], val = 3,
-
-Your function should return length = 2, with the first two elements of nums being 2.
-
-It doesn't matter what you leave beyond the returned length.
-Example 2:
-
-Given nums = [0,1,2,2,3,0,4,2], val = 2,
-
-Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4.
-
-Note that the order of those five elements can be arbitrary.
-
-It doesn't matter what values are set beyond the returned length.
-Clarification:
-
-Confused why the returned value is an integer but your answer is an array?
-
-Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.
-
-Internally you can think of this:
-
-// nums is passed in by reference. (i.e., without making a copy)
-int len = removeElement(nums, val);
-
-// any modification to nums in your function would be known by the caller.
-// using the length returned by your function, it prints the first len elements.
-for (int i = 0; i < len; i++) {
- print(nums[i]);
-}
-```
-> ˼·
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(1)******
-
-���ǿ��Ա������飬�ѵ��� val �����ŵ�����ĺ�벿�־��С����ǿ�����˫ָ��ʵ�֡��� nums[i] != val ʱ��nums[j++] = nums[i]
-```cpp
-class Solution {
-public:
- int removeElement(vector& nums, int val) {
- int i ,count = 0,j = 0,numsSize = nums.size();
- for(i = 0;i < numsSize;i++)
- {
- if(nums[i] == val)
- {
- count++;
- }
- else
- nums[j++] = nums[i];
- }
- return numsSize - count;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0028._Implement_Strstr.md b/docs/leetcode/cpp/0028._Implement_Strstr.md
deleted file mode 100644
index b80786a76..000000000
--- a/docs/leetcode/cpp/0028._Implement_Strstr.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# 28.implement strstr
-
-**�Ѷ�Easy**
-
-## ˢ������
-
-> ԭ������
-
-* https://leetcode.com/problems/implement-strstr/
-> ��������
-
-```
-Implement strStr().
-
-Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
-
-Example 1:
-
-Input: haystack = "hello", needle = "ll"
-Output: 2
-Example 2:
-
-Input: haystack = "aaaaa", needle = "bba"
-Output: -1
-Clarification:
-
-What should we return when needle is an empty string? This is a great question to ask during an interview.
-
-For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf().
-```
-> ˼·
-******- ʱ�临�Ӷ�: O(N)******- �ռ临�Ӷ�: O(1)******
-
-����ֱ�ӱ��� haystack ��ƥ�䵽�� needle ��һ���ַ����ʱ���ͱ��� needle�������Ƚ��ַ���
-
-```cpp
-class Solution {
-public:
- int strStr(string haystack, string needle) {
- int j = 0,i = 0,index= 0;
- while(i < haystack.size() && j < needle.size())
- {
- if(haystack[i] == needle[j])
- {
- if(!j)
- index = i;
- j++;
- i++;
- }
- else
- {
- i = ++index;
- j = 0;
- }
- }
- if(j == needle.size())
- return index;
- return -1;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0029._Divide_Two_Integers.md b/docs/leetcode/cpp/0029._Divide_Two_Integers.md
deleted file mode 100644
index 432bb349a..000000000
--- a/docs/leetcode/cpp/0029._Divide_Two_Integers.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# 29.divide two integers
-
-**�Ѷ�Medium**
-
-## ˢ������
-
-> ԭ������
-
-* https://leetcode.com/problems/divide-two-integers/
-> ��������
-
-```
-Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.
-
-Return the quotient after dividing dividend by divisor.
-
-The integer division should truncate toward zero.
-
-Example 1:
-
-Input: dividend = 10, divisor = 3
-Output: 3
-Example 2:
-
-Input: dividend = 7, divisor = -3
-Output: -2
-Note:
-
-Both dividend and divisor will be 32-bit signed integers.
-The divisor will never be 0.
-Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?231, 231 ? 1]. For the purpose of this problem, assume that your function returns 231 ? 1 when the division result overflows.
-
-```
-> ˼·
-******- ʱ�临�Ӷ�: O(N)******- �ռ临�Ӷ�: O(1)******
-
-�������ֱ���ñ����ķ����϶���ʱ�������������˿ռ任ʱ�䣬�������� int ���Ϊ2^31 - 1 ��������Ĵ�СҲ�ǹ̶��ġ����������ñ��������ȶ���һ��res = 0��ÿ�ζ����� res += divisor * 2^n ֱ������dividend �������ٴ� res = divisor * 2^(n-1)��ʼ��ֱ��ij��res + divisor > dividend
-
-
-```cpp
-class Solution {
-public:
- int divide(int dividend, int divisor) {
- if(!dividend)
- return 0;
- long long arr[33];
- arr[0] = 1;
- for(int i = 1;i < 33;++i)
- arr[i] = arr[i - 1] * 2;
- long long temp1 = dividend,temp2 = divisor;
- if(temp1 < 0)
- temp1 *= -1;
- if(temp2 < 0)
- temp2 *= -1;
- long long res,pre = 0,ret = 0;
- int count1 = 0;
- while(1)
- {
- res = pre + arr[count1] * temp2;
- if(res > temp1)
- {
- if(!count1)
- break;
- pre = pre + arr[count1 - 1] * temp2;
- ret += arr[count1 - 1];
- count1 = 0;
- }
- else
- count1++;
- }
- if(dividend < 0)
- ret *= -1;
- if(divisor < 0)
- ret *= -1;
- if(ret == 2147483648)
- return ret - 1;
- return ret;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0030._Substring_With_Concatenation_Of_All_Words.md b/docs/leetcode/cpp/0030._Substring_With_Concatenation_Of_All_Words.md
deleted file mode 100644
index 52efa1f10..000000000
--- a/docs/leetcode/cpp/0030._Substring_With_Concatenation_Of_All_Words.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# 30.substring with concatenation of all words
-
-**难度Hard**
-
-## 刷题内容
-
-> 原题连接
-
-* https://leetcode.com/problems/substring-with-concatenation-of-all-words/
-
-> 内容描述
-
-```
-You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
-
-Example 1:
-
-Input:
- s = "barfoothefoobarman",
- words = ["foo","bar"]
-Output: [0,9]
-Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
-The output order does not matter, returning [9,0] is fine too.
-Example 2:
-
-Input:
- s = "wordgoodstudentgoodword",
- words = ["word","student"]
-Output: []
-
-```
-> 思路
-******- 时间复杂度: O(mlgn)******- 空间复杂度: O(m+n)******
-
-这题可以两个 map 来解决,第一个 map 中存放了 words 中的所有单词和出现的次数,接下来遍历字符串,固定区间的大小为 words 的长度,存入另一个map,两个 map 相等就放入返回数组中
-
-```cpp
-class Solution {
-public:
- vector findSubstring(string s, vector& words) {
- vector ans;
- if(!s.length() || !words.size())
- return ans;
- unordered_map m1;
- int len = words.size(),wl = words[0].length(),sl = s.length();
- for(int i = 0;i < words.size();++i)
- m1[words[i]]++;
- int count1 = 0,reLen = wl * len,left = 0;
- for(int i = 0;i < sl - wl * len + 1;++i)
- {
- unordered_map m2;
- for(int j = 0,left = i;j < len;j ++)
- {
- string temp = s.substr(left,wl);
- left += wl;
- m2[temp]++;
- }
- if(m2 == m1)
- ans.push_back(i);
- }
- return ans;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0031._Next_Permutatio.md b/docs/leetcode/cpp/0031._Next_Permutatio.md
deleted file mode 100644
index 5266def01..000000000
--- a/docs/leetcode/cpp/0031._Next_Permutatio.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# 31.Next Permutatio
-
-**难度Medium**
-
-## 刷题内容
-> 原题连接
-
-* https://leetcode.com/problems/next-permutation/
-
-> 内容描述
-
-```
-Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
-
-If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
-
-The replacement must be in-place and use only constant extra memory.
-
-Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
-
-1,2,3 → 1,3,2
-3,2,1 → 1,2,3
-1,1,5 → 1,5,1
-```
-> 思路
-******- 时间复杂度: O(n)******- 空间复杂度: O(1)******
-
-我们可以用两个指针表示需要交换的两个数,遍历数组。这题的最坏的情况下,数组降序排列,排序算法的复杂度也是O(n)。
-
-```cpp
-class Solution {
-public:
- void nextPermutation(vector& nums) {
- int n1 = 0,n2 = 0;
- for(int i = 1;i < nums.size();++i)
- if(nums[i] > nums[n2])
- {
- n1 = n2;
- n2 = i;
- }
- else if((nums[i] < nums[n2] && nums[i] > nums[n1]) || nums[i] == nums[n2])
- n2 = i;
- else if(nums[i] <= nums[n1])
- {
- int j = i;
- for(;j < nums.size() - 1;++j)
- if(nums[j + 1] > nums[j])
- {
- n1 = j;
- n2 = j + 1;
- break;
- }
- i = j + 1;
- }
- if(n1 == n2)
- sort(nums.begin(),nums.end());
- else
- {
- swap(nums[n1],nums[n2]);
- sort(nums.begin() + n1 + 1,nums.end());
- }
- }
-};
-```
diff --git a/docs/leetcode/cpp/0032._Longest_Valid_Parentheses.md b/docs/leetcode/cpp/0032._Longest_Valid_Parentheses.md
deleted file mode 100644
index dfa13eae0..000000000
--- a/docs/leetcode/cpp/0032._Longest_Valid_Parentheses.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# 32. Longest Valid Parentheses
-
-**�Ѷ�:Hard**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/longest-valid-parentheses/
-
-> ��������
-
-```
-Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
-
-Example 1:
-
-Input: "(()"
-Output: 2
-Explanation: The longest valid parentheses substring is "()"
-Example 2:
-
-Input: ")()())"
-Output: 4
-Explanation: The longest valid parentheses substring is "()()"
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(n)******
-
-��DP�ķ��������⡣������һ��ջȥ����������ߵIJ��֣���'('��λ�ã�ֱ��������һ��')'ʱ���ͼ�¼ջ����'('λ�ã����������ǾͿ���д��״̬ת�Ʒ��̡���������dp[i]�����ַ����е�i������������Զ��λ�á�����һ������')'ʱ��dp[i] = ջ��'('��λ�á����ڿ��Դ������������ţ���dp[dp[i] - 1]���ڣ���dp[i] = dp[dp[i] - 1]����Ҫע��߽缴�ɡ�
-
-```cpp
-class Solution {
-public:
- int longestValidParentheses(string s) {
- int len = s.length();
- if(!len)
- return 0;
- int dp[len];
- memset(dp,-1,sizeof(dp));
- int ans = 0;
- vector v;
- for(int i = 0;i < len;++i)
- if(s[i] == '(')
- v.push_back(i);
- else if(s[i] == ')' && v.size())
- {
- dp[i] = v[v.size() - 1];
- if(dp[i] && dp[dp[i] - 1] >= 0)
- dp[i] = dp[dp[i] - 1];
- ans = max(ans,i - dp[i] + 1);
- v.pop_back();
- }
- return ans;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0033._Search_in_Rotated_Sorted_Array.md b/docs/leetcode/cpp/0033._Search_in_Rotated_Sorted_Array.md
deleted file mode 100644
index 275307b05..000000000
--- a/docs/leetcode/cpp/0033._Search_in_Rotated_Sorted_Array.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# 033. Search in Rotated Sorted Array
-
-**难度Medium**
-
-## 刷题内容
-> 原题连接
-
-* https://leetcode.com/problems/search-in-rotated-sorted-array/
-
-> 内容描述
-
-```
-Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
-
-(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
-
-You are given a target value to search. If found in the array return its index, otherwise return -1.
-
-You may assume no duplicate exists in the array.
-
-Your algorithm's runtime complexity must be in the order of O(log n).
-
-Example 1:
-
-Input: nums = [4,5,6,7,0,1,2], target = 0
-Output: 4
-Example 2:
-
-Input: nums = [4,5,6,7,0,1,2], target = 3
-Output: -1
-```
-> 思路1
-******- 时间复杂度: O(n)******- 空间复杂度: O(1)******
-
-第一个方法是直接遍历数组,找到返回数组下标,找不到就返回-1
-
-```cpp
-class Solution {
-public:
- int search(vector& nums, int target) {
- for(int i = 0;i < nums.size();++i)
- if(nums[i] == target)
- return i;
- return -1;
- }
-};
-```
-> 思路2
-******- 时间复杂度: O(lgn)*****- 空间复杂度: O(1)******
-
-第二个方法是用二分法找到旋转轴,再用二分法找到目标数
-```cpp
-class Solution {
-public:
- int search(vector& nums, int target) {
- int i = 0,j = nums.size() - 1;
- if(!nums.size())
- return -1;
- while(i < j - 1)
- {
- int mid = (i + j) / 2;
- if(nums[i] < nums[mid])
- i = mid;
- else
- j = mid;
- //cout << i << j << endl;
- }
- if(nums[i] <= nums[j])
- j = i;
- //cout << j;
- auto pos = lower_bound(nums.begin(),nums.begin() + j,target);
- if(pos != nums.end() && (*pos) == target)
- return pos - nums.begin();
- pos = lower_bound(nums.begin() + j,nums.end(),target);
- if(pos != nums.end() && (*pos) == target)
- return pos - nums.begin();
- return -1;
- }
-};
-```
diff --git a/docs/leetcode/cpp/0034._Find_First_and_Last_Position_of_Element_in_Sorted_Array.md b/docs/leetcode/cpp/0034._Find_First_and_Last_Position_of_Element_in_Sorted_Array.md
deleted file mode 100644
index 27a9b7bf7..000000000
--- a/docs/leetcode/cpp/0034._Find_First_and_Last_Position_of_Element_in_Sorted_Array.md
+++ /dev/null
@@ -1,105 +0,0 @@
-# 34. Find First and Last Position of Element in Sorted Array
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
-
-> ��������
-
-```
-Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.
-
-Your algorithm's runtime complexity must be in the order of O(log n).
-
-If the target is not found in the array, return [-1, -1].
-
-Example 1:
-
-Input: nums = [5,7,7,8,8,10], target = 8
-Output: [3,4]
-Example 2:
-
-Input: nums = [5,7,7,8,8,10], target = 6
-Output: [-1,-1]
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(lgn)******- �ռ临�Ӷ�: O(1)******
-
-���͵Ķ����������Ȳ���Ŀ���������Ƿ���target���ڷֱ�����ҵ�һ�����ֵ�target�����һ��target��
-
-```cpp
-class Solution {
-public:
- vector searchRange(vector& nums, int target) {
- int l = 0,r = nums.size();
- vector ans = {-1,-1};
- int mid = -1;
- while(l < r)
- {
- mid = (r + l) / 2;
- if(nums[mid] < target)
- l = mid + 1;
- else if(nums[mid] > target)
- r = mid;
- else
- break;
- }
- if(mid == -1 || nums[mid] != target)
- return ans;
- int mid1 = l = mid;
- r = nums.size();
- while(l < r)
- {
- mid = (r + l) / 2;
- if(mid == nums.size())
- break;
- if(nums[mid] > target)
- r = mid;
- else
- l = mid + 1;
- }
- if(nums[mid] > target)
- mid--;
- ans[1] = mid;
- l = 0;
- r = mid1 + 1;
- while(l < r)
- {
- mid = (r + l) / 2;
- if(nums[mid] < target)
- l = mid + 1;
- else
- r = mid;
- }
- if(nums[mid] < target)
- mid++;
- ans[0] = mid;
- return ans;
- }
-};
-```
-
-> ˼·2
-******- ʱ�临�Ӷ�: O(lgn)******- �ռ临�Ӷ�: O(1)******
-
-���������õ���c++���������������lower_bound��upper_bound
-
-```cpp
-class Solution {
-public:
- vector searchRange(vector& nums, int target) {
- auto pos1 = lower_bound(nums.begin(),nums.end(),target);
- vector ans = {-1,-1};
- if(pos1 == nums.end() || (*pos1) != target)
- return ans;
- ans[0] = pos1 - nums.begin();
- auto pos2 = upper_bound(nums.begin(),nums.end(),target);
- ans[1] = pos2 - nums.begin() - 1;
- return ans;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0035._Search_Insert_Position.md b/docs/leetcode/cpp/0035._Search_Insert_Position.md
deleted file mode 100644
index 03ee90eab..000000000
--- a/docs/leetcode/cpp/0035._Search_Insert_Position.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# 35.search insert position
-
-**难度:Easy**
-
-## 刷题内容
-
-> 原题连接
-
-*https://leetcode.com/problems/search-insert-position/
-*
-> 内容描述
-
-```
-Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
-
-You may assume no duplicates in the array.
-```
-> 思路1
-******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
-
-由于数组是已经排序好的,这就是一个很典型的二分法
-
-```cpp
-class Solution {
-public:
- int searchInsert(vector& nums, int target) {
- int first = 0,last = nums.size() - 1;
- while(last > (first + 1))
- {
- int medium = (last + first) / 2;
- if(nums[medium] == target)
- return medium;
- else if(nums[medium] < target)
- first = medium;
- else
- last = medium;
- }
- if(target > nums[last])
- return last + 1;
- else if((target < nums[first]) || (target == nums[first]))
- return first;
- else
- return last;
- }
-};
-```
-> 思路2
-******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
-
-其实这个思路也是二分法,只不过c++中已经给我们封装好了lower_bound,我们直接调用即可
-代码看上去也简洁很多
-```cpp
-class Solution {
-public:
- int searchInsert(vector& nums, int target) {
- auto pos = lower_bound(nums.begin(),nums.end(),target);
- return pos - nums.begin();
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0036._Valid_Sudoku.md b/docs/leetcode/cpp/0036._Valid_Sudoku.md
deleted file mode 100644
index 48d5cdaac..000000000
--- a/docs/leetcode/cpp/0036._Valid_Sudoku.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# 36. Valid Sudoku
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/valid-sudoku/
-
-> ��������
-
-```
-Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
-
-Each row must contain the digits 1-9 without repetition.
-Each column must contain the digits 1-9 without repetition.
-Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.
-A partially filled sudoku which is valid.
-
-The Sudoku board could be partially filled, where empty cells are filled with the character '.'.
-Example 1:
-
-Input:
-[
- ["5","3",".",".","7",".",".",".","."],
- ["6",".",".","1","9","5",".",".","."],
- [".","9","8",".",".",".",".","6","."],
- ["8",".",".",".","6",".",".",".","3"],
- ["4",".",".","8",".","3",".",".","1"],
- ["7",".",".",".","2",".",".",".","6"],
- [".","6",".",".",".",".","2","8","."],
- [".",".",".","4","1","9",".",".","5"],
- [".",".",".",".","8",".",".","7","9"]
-]
-Output: true
-Example 2:
-
-Input:
-[
- ["8","3",".",".","7",".",".",".","."],
- ["6",".",".","1","9","5",".",".","."],
- [".","9","8",".",".",".",".","6","."],
- ["8",".",".",".","6",".",".",".","3"],
- ["4",".",".","8",".","3",".",".","1"],
- ["7",".",".",".","2",".",".",".","6"],
- [".","6",".",".",".",".","2","8","."],
- [".",".",".","4","1","9",".",".","5"],
- [".",".",".",".","8",".",".","7","9"]
-]
-Output: false
-Explanation: Same as Example 1, except with the 5 in the top left corner being
- modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
-Note:
-
-A Sudoku board (partially filled) could be valid but is not necessarily solvable.
-Only the filled cells need to be validated according to the mentioned rules.
-The given board contain only digits 1-9 and the character '.'.
-The given board size is always 9x9.
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(n^2)******- �ռ临�Ӷ�: O(1)******
-
-����board��9x9�ģ�ʵ�ʵ�ʱ�临�Ӷ�Ҳ��9x9�ġ���������ֻҪ�ֱ��ж�ÿ��ÿ�к�ÿ9��С�������Ƿ����ظ��������ɡ��ѶȲ���
-
-
-```cpp
-class Solution {
-public:
- bool isValidSudoku(vector>& board) {
- int arr[9][9];
- int arr1[9][9];
- int arr2[9][9];
- memset(arr,0,sizeof(arr));
- memset(arr2,0,sizeof(arr1));
- memset(arr1,0,sizeof(arr1));
- for(int i = 0;i < 9;++i)
- for(int j = 0;j < 9;++j)
- if(board[i][j] != '.')
- {
- if(arr[i][board[i][j] - '1'] || arr1[j][board[i][j] -'1'] || arr2[3 * (i / 3) + (j / 3)][board[i][j] -'1'])
- return 0;
- arr[i][board[i][j] - '1'] = 1;
- arr1[j][board[i][j] -'1'] = 1;
- arr2[3 * (i / 3) + (j / 3)][board[i][j] -'1'] = 1;
- }
- return 1;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0038._Count_and_Say.md b/docs/leetcode/cpp/0038._Count_and_Say.md
deleted file mode 100644
index 3051bf77c..000000000
--- a/docs/leetcode/cpp/0038._Count_and_Say.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# 38. Count and Say
-
-**�Ѷ�:Easy**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/count-and-say/
-
-> ��������
-
-```
-The count-and-say sequence is the sequence of integers with the first five terms as following:
-
-1. 1
-2. 11
-3. 21
-4. 1211
-5. 111221
-1 is read off as "one 1" or 11.
-11 is read off as "two 1s" or 21.
-21 is read off as "one 2, then one 1" or 1211.
-
-Given an integer n where 1 �� n �� 30, generate the nth term of the count-and-say sequence.
-
-Note: Each term of the sequence of integers will be represented as a string.
-
-
-Example 1:
-
-Input: 1
-Output: "1"
-Example 2:
-
-Input: 4
-Output: "1211"
-```
-
-> ˼·
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(1)******
-
-����ҪŪ�����Ŀ����˼n == 1ʱ����1��������һ��1���� one 1��n == 2ʱ���ǡ�11����������2��1���� two 1��n == 3ʱ���ǡ�21��������1��2��1��1���� one 2 one 1��n == 4ʱ���ǡ�1211���������������ƣ�����д��ѭ��ģ������IJ������ɡ�
-
-```cpp
-class Solution {
-public:
- string countAndSay(int n) {
- string str;
- str.push_back('0' + 1);
- n--;
- while(n)
- {
- string temp;
- for(int i = 0;i < str.length();)
- {
- int j = 0;
- while(i + j < str.length() && str[i] == str[j + i])
- ++j;
- temp.push_back('0' + j);
- temp.push_back(str[i]);
- i += j;
- }
- --n;
- str = temp;
- }
- return str;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0039._Combination_Sum.md b/docs/leetcode/cpp/0039._Combination_Sum.md
deleted file mode 100644
index 37226b709..000000000
--- a/docs/leetcode/cpp/0039._Combination_Sum.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# 39. Combination Sum
-
- **难度: Middle**
-
- ## 刷题内容
-
- > 原题连接
-
-* https://leetcode-cn.com/problems/combination-sum/
-
- > 内容描述
-
- ```
-给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
-
-candidates 中的数字可以无限制重复被选取。
-
-说明:
-
-所有数字(包括 target)都是正整数。
-解集不能包含重复的组合。
-示例 1:
-
-输入: candidates = [2,3,6,7], target = 7,
-所求解集为:
-[
- [7],
- [2,2,3]
-]
-示例 2:
-
-输入: candidates = [2,3,5], target = 8,
-所求解集为:
-[
- [2,2,2,2],
- [2,3,3],
- [3,5]
-]
- ```
-
-## 解题方案
-> 思路 1
-```
-回溯
-```
-
-```cpp
-void dfs(vector& candidates, int target, int index, vector& path, vector>& ans){
- if(target<0)
- return ;
- if(target == 0){
- ans.push_back(path);
- return ;
- }
- for(int i=index;i> combinationSum(vector& candidates, int target) {
- sort(candidates.begin(), candidates.end());
- vector> ans;
- vector path;
- dfs(candidates, target, 0, path, ans);
- return ans;
-}
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0040._Combination_Sum_II.md b/docs/leetcode/cpp/0040._Combination_Sum_II.md
deleted file mode 100644
index f837be356..000000000
--- a/docs/leetcode/cpp/0040._Combination_Sum_II.md
+++ /dev/null
@@ -1,70 +0,0 @@
-# 40. Combination Sum II
-
- **难度: Medium**
-
- ## 刷题内容
-
- > 原题连接
-
-* https://leetcode-cn.com/problems/combination-sum-ii/
-
- > 内容描述
-
- ```
-给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
-
-candidates 中的每个数字在每个组合中只能使用一次。
-
-说明:
-
-所有数字(包括目标数)都是正整数。
-解集不能包含重复的组合。
-示例 1:
-
-输入: candidates = [10,1,2,7,6,1,5], target = 8,
-所求解集为:
-[
- [1, 7],
- [1, 2, 5],
- [2, 6],
- [1, 1, 6]
-]
-示例 2:
-
-输入: candidates = [2,5,2,1,2], target = 5,
-所求解集为:
-[
- [1,2,2],
- [5]
-]
- ```
-
-## 解题方案
-> 思路 1
-```
-回溯
-```
-
-```cpp
-void dfs(vector& candidates, int target, int index, vector& path, vector>& ans){
- if(target<0)
- return ;
- if(target == 0){
- ans.push_back(path);
- return ;
- }
- for(int i=index;i index && candidates[i] == candidates[i - 1]) continue;
- path.push_back(candidates[i]);
- dfs(candidates, target-candidates[i], i+1, path, ans);
- path.pop_back();
- }
-}
-vector> combinationSum2(vector& candidates, int target) {
- vector> ans;
- vector path;
- sort(candidates.begin(), candidates.end());
- dfs(candidates, target, 0, path, ans);
- return ans;
-}
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0041._First_Missing_Positive.md b/docs/leetcode/cpp/0041._First_Missing_Positive.md
deleted file mode 100644
index 8c3b40a76..000000000
--- a/docs/leetcode/cpp/0041._First_Missing_Positive.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# 041.First Missing Positive
-
-**�Ѷ�Hard**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/first-missing-positive/
-
-> ��������
-
-```
-Given an unsorted integer array, find the smallest missing positive integer.
-
-Example 1:
-
-Input: [1,2,0]
-Output: 3
-Example 2:
-
-Input: [3,4,-1,1]
-Output: 2
-Example 3:
-
-Input: [7,8,9,11,12]
-Output: 1
-```
-> ˼·
-******- ʱ�临�Ӷ�: O(n)******- �ռ临�Ӷ�: O(1)******
-
-�տ�ʼ��Ŀ����˼������ˣ�֮�������AC�ˡ���ʵ�����������������������Ĵ���ռ䣬Ӧ�û������뵽��ֱ�� hash �����У��������ǿ��Ա������飬���������1����������ĵ�һ������1����2���ڣ���������ĵڶ���λ�ӣ���������
-
-```cpp
-class Solution {
-public:
- int firstMissingPositive(vector& nums) {
- if(!nums.size())
- return 1;
- for(int i = 0;i < nums.size();)
- {
- if(nums[i] < nums.size() && nums[i] != nums[nums[i] - 1])
- swap(nums[i],nums[nums[i] - 1]);
- else
- ++i;
- }
- for(int i = 0;i < nums.size();++i)
- if(nums[i] != i + 1)
- return i + 1;
- return nums.size() + 1;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0042._Trapping_Rain_Water.md b/docs/leetcode/cpp/0042._Trapping_Rain_Water.md
deleted file mode 100644
index 55cb1d390..000000000
--- a/docs/leetcode/cpp/0042._Trapping_Rain_Water.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# 42. Trapping Rain Water
-
-**�Ѷ�Hard**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/trapping-rain-water/
-
-> ��������
-
-```
-Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
-
-Example:
-
-Input: [0,1,0,2,1,0,1,3,2,1,2,1]
-Output: 6
-```
-
-��¼ l = 0��������������飬��� height[i] < height[l],��˵����λ������ˮ����¼����ˮ���������� height[i] >= height[l]����˵��[i,l]�������ڿ��Ի�ˮ��Ȼ���ȥ����ˮ��������ǻ�ˮ�����������������֮����� l != height.size() - 1������������飬�����������衣
-> ˼·
-******- ʱ�临�Ӷ�: O(N)******- �ռ临�Ӷ�: O(1)******
-
-```cpp
-class Solution {
-public:
- int trap(vector& height) {
- int l = 0,sum1 = 0,water = 0,i;
- for(i = 1;i < height.size();++i)
- if(height[i] >= height[l])
- {
- water = water + height[l] * (i - l - 1) - sum1;
- l = i;
- sum1 = 0;
- }
- else
- sum1 += height[i];
- if(l != (height.size() - 1))
- {
- int temp = l;
- sum1 = 0;
- for(i = height.size() - 2,l = height.size() - 1;i >= temp;--i)
- if(height[i] >= height[l])
- {
- water = water + height[l] * (l- i - 1) - sum1;
- l = i;
- sum1 = 0;
- }
- else
- sum1 += height[i];
- }
- return water;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0043._Multiply_Strings.md b/docs/leetcode/cpp/0043._Multiply_Strings.md
deleted file mode 100644
index 402275e25..000000000
--- a/docs/leetcode/cpp/0043._Multiply_Strings.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# 43. Multiply Strings
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/multiply-strings/
-
-> ��������
-
-```
-Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string.
-
-Example 1:
-
-Input: num1 = "2", num2 = "3"
-Output: "6"
-Example 2:
-
-Input: num1 = "123", num2 = "456"
-Output: "56088"
-Note:
-
-The length of both num1 and num2 is < 110.
-Both num1 and num2 contain only digits 0-9.
-Both num1 and num2 do not contain any leading zero, except the number 0 itself.
-You must not use any built-in BigInteger library or convert the inputs to integer directly.
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(n^2)******- �ռ临�Ӷ�: O(1)******
-
-������������ֱȽϴ���long long�����ֵ����˲���ת�����֣�������������ģ���������ֵij˷�����ÿһλ��¼��һ���ַ����С�
-
-```cpp
-class Solution {
-public:
- string multiply(string num1, string num2) {
- string ans;
- int d[120][120];
- memset(d,0,sizeof(d));
- for(int i = num2.size() - 1;i >= 0;--i)
- {
- int count1 = 0;
- for(int j = num1.size()- 1;j >= 0;--j)
- {
- int pro_ans = (num1[j] - '0') * (num2[i] - '0');
- d[num2.size() - 1 - i][num1.size() - j - 1] = pro_ans % 10 + count1;
- count1 = pro_ans / 10;
- if(d[num2.size() - 1 - i][num1.size() - j - 1] >= 10)
- {
- count1++;
- d[num2.size() - 1 - i][num1.size() - j - 1] %= 10;
- }
- }
- d[num2.size() - 1 - i][num1.size()] = count1;
- }
- int count1 = 0;
- for(int j = 0;j < num1.size() + num2.size();++j)
- {
- for(int i = 0;i <= num2.size();++i)
- if(j - i >= 0 && j - i <= num1.size())
- count1 += d[i][j - i];
- ans.push_back(count1 % 10 + '0');
- count1 /= 10;
- }
- while(ans.length() > 1 && ans[ans.length() - 1] == '0')
- ans.pop_back();
- reverse(ans.begin(),ans.end());
- return ans;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0044._Wildcard_Matching.md b/docs/leetcode/cpp/0044._Wildcard_Matching.md
deleted file mode 100644
index 86a0eecbc..000000000
--- a/docs/leetcode/cpp/0044._Wildcard_Matching.md
+++ /dev/null
@@ -1,98 +0,0 @@
-# 44. Wildcard Matching
-
-**�Ѷ�:Hard**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/wildcard-matching/
-
-> ��������
-
-```
-Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.
-
-'?' Matches any single character.
-'*' Matches any sequence of characters (including the empty sequence).
-The matching should cover the entire input string (not partial).
-
-Note:
-
-s could be empty and contains only lowercase letters a-z.
-p could be empty and contains only lowercase letters a-z, and characters like ? or *.
-Example 1:
-
-Input:
-s = "aa"
-p = "a"
-Output: false
-Explanation: "a" does not match the entire string "aa".
-Example 2:
-
-Input:
-s = "aa"
-p = "*"
-Output: true
-Explanation: '*' matches any sequence.
-Example 3:
-
-Input:
-s = "cb"
-p = "?a"
-Output: false
-Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
-Example 4:
-
-Input:
-s = "adceb"
-p = "*a*b"
-Output: true
-Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
-Example 5:
-
-Input:
-s = "acdcb"
-p = "a*c?b"
-Output: false
-```
-
-> ˼·
-******- ʱ�临�Ӷ�: O(n^2)******- �ռ临�Ӷ�: O(n^2)******
-
-�տ�ʼ����ʱ����Ϊ��һ����ģ���⣬��������ʱ��ŷ��ֿ�����DP����ʹ��DPʱ���ҵ�״̬ת�Ʒ��̡��������Ƕ�������dp[i][j]��ʾ���ַ��� p �е� i - 1����ĸ֮ǰ���ַ������ַ��� s �еĵ� j - 1����ĸ֮ǰ���Ӵ�ƥ�䣬���ǾͿ���д����Ӧ��״̬ת�Ʒ��̵�p[i] == '?'����p[i] == s[j]ʱ��dp[i + 1][j + 1] = dp[i][j],��p[i] == '*'ʱ��j < p.length(),����dp[i + 1][j + 1] = dp[i][j],����dp[i + 1][j] = dp[i][j],���dp[p.length()][s.length() - 1]
-
-```cpp
-class Solution {
-public:
- bool isMatch(string s, string p) {
- if(!p.length())
- return !s.length();
- s.push_back(' ');
- int dp[p.length() + 1][s.length() + 1];
- for(int i =0;i <= p.length();++i)
- for(int j = 0;j <= s.length();++j)
- dp[i][j] = 0;
-
- int count1 = 1;
- dp[0][0] = 1;
- for(int i = 0;i < p.length();++i)
- {
- for(int j = 0;j < s.length();++j)
- if(p[i] == '?' || p[i] == s[j])
- dp[i + 1][j + 1] = dp[i][j];
- else if(p[i] == '*' && dp[i][j])
- {
- dp[i + 1][j + 1] = 1;
- dp[i + 1][j] = 1;
- ++j;
- while(j < s.length())
- {
- dp[i + 1][j + 1] = 1;
- ++j;
- }
- }
- }
- return dp[p.length()][s.length() - 1];
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0045._Jump_Game_II.md b/docs/leetcode/cpp/0045._Jump_Game_II.md
deleted file mode 100644
index adbc9cfdd..000000000
--- a/docs/leetcode/cpp/0045._Jump_Game_II.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# 045. Jump Game II
-
-**�Ѷ�Hard**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/jump-game-ii/
-
-> ��������
-
-```
-Given an array of non-negative integers, you are initially positioned at the first index of the array.
-
-Each element in the array represents your maximum jump length at that position.
-
-Your goal is to reach the last index in the minimum number of jumps.
-
-Example:
-
-Input: [2,3,1,1,4]
-Output: 2
-Explanation: The minimum number of jumps to reach the last index is 2.
- Jump 1 step from index 0 to 1, then 3 steps to the last index.
-```
-
-> ˼·
-******- ʱ�临�Ӷ�: O(n)*****- �ռ临�Ӷ�: O(1)******
-
-�տ�ʼ�뵽ʹ�ö�̬�滮��ʱ�临�Ӷ�ΪO(n)������TLE�ˣ���ʵ������O(n)��ʱ�临�Ӷ�����ɵġ��������飬ÿ�ζ��ߵ���nums[i]�ķ�Χ�����ߵ�����Զ�ľ��롣��¼ans��
-```cpp
-class Solution {
-public:
- int jump(vector& nums) {
- int i = 0,length = nums.size(),next = nums[0],ans = 0;
- if(length < 2)
- return 0;
- while(i < length)
- {
- ++ans;
- if(next >= length - 1)
- return ans;
- int current = i;
- for(int j = current+1;j <= min(next,length - 1);++j)
- {
- i = max(i,nums[j] + j);
- cout << i << " ";
- }
- swap(i,next);
- cout << i << " "<< next << endl;
- }
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0046._Permutations.md b/docs/leetcode/cpp/0046._Permutations.md
deleted file mode 100644
index f2a9e583e..000000000
--- a/docs/leetcode/cpp/0046._Permutations.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# 46. Permutations
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/permutations/
-
-> ��������
-
-```
-Given a collection of distinct integers, return all possible permutations.
-
-Example:
-
-Input: [1,2,3]
-Output:
-[
- [1,2,3],
- [1,3,2],
- [2,1,3],
- [2,3,1],
- [3,1,2],
- [3,2,1]
-]
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(n!*n)******- �ռ临�Ӷ�: O(n)******
-
-�ܲ����Ŀ���ݹ��һ���⣬ÿ�ζ�����һ����֮������������ɡ�
-
-```cpp
-class Solution {
-public:
- vector> permute(vector& nums) {
- vector > ans;
- if(!nums.size())
- return ans;
- if(nums.size() == 1)
- ans.push_back(nums);
- for(int i = 0;i < nums.size();++i)
- {
- swap(nums[0],nums[i]);
- vector v(nums.begin() + 1,nums.end());
- vector > ret = permute(v);
- for(int i = 0;i < ret.size();++i)
- {
- ret[i].push_back(nums[0]);
- ans.push_back(ret[i]);
- }
- swap(nums[0],nums[i]);
- }
- return ans;
- }
-};
-```
-> ˼·2
-******- ʱ�临�Ӷ�: O(n!)******- �ռ临�Ӷ�: O(n)******
-
-���ǿ��Զ�������㷨�����Ż�����DFS�ķ�����ÿ�μ�¼�Ѿ������������ֽ��еݹ鼴��
-
-```cpp
-class Solution {
-public:
-void DFS(int* visited,vector& nums,vector >& ans,vector temp)
-{
- int count1 = 0;
- for(int i = 0;i < nums.size();++i)
- if(!visited[i])
- {
- temp.push_back(nums[i]);
- visited[i] = 1;
- DFS(visited,nums,ans,temp);
- temp.pop_back();
- visited[i] = 0;
- count1 = 1;
- }
- if(!count1)
- ans.push_back(temp);
-}
-vector> permute(vector& nums) {
- vector > ans;
- int visited[nums.size()];
- memset(visited,0,sizeof(visited));
- vector temp;
- for(int i = 0; i < nums.size();++i)
- {
- visited[i] = 1;
- temp.push_back(nums[i]);
- DFS(visited,nums,ans,temp);
- temp.pop_back();
- visited[i] = 0;
- }
- return ans;
- }
-};
-```
\ No newline at end of file
diff --git a/docs/leetcode/cpp/0047._Permutations_II.md b/docs/leetcode/cpp/0047._Permutations_II.md
deleted file mode 100644
index ed5ec1283..000000000
--- a/docs/leetcode/cpp/0047._Permutations_II.md
+++ /dev/null
@@ -1,102 +0,0 @@
-# 47. Permutations II
-
-**�Ѷ�:Medium**
-
-## ˢ������
-> ԭ������
-
-* https://leetcode.com/problems/permutations-ii/
-
-> ��������
-
-```
-Given a collection of numbers that might contain duplicates, return all possible unique permutations.
-
-Example:
-
-Input: [1,1,2]
-Output:
-[
- [1,1,2],
- [1,2,1],
- [2,1,1]
-]
-```
-
-> ˼·1
-******- ʱ�临�Ӷ�: O(n!*nlgn)******- �ռ临�Ӷ�: O(n)******
-
-��ǰ����ǵ����е����ƣ����Բο�֮ǰ�Ľⷨ����������֮ǰ����Ŀ����ֱ�Ӿ���setȥ���ˣ���Ȼͨ���ˣ�����ʱ�临�ӶȱȽϸߣ������Ҫ�����Ż�
-
-```cpp
-class Solution {
-public:
- void DFS(int* visited,vector& nums,set >& ans,vector temp)
- {
- int count1 = 0;
- for(int i = 0;i < nums.size();++i)
- if(!visited[i])
- {
- temp.push_back(nums[i]);
- visited[i] = 1;
- DFS(visited,nums,ans,temp);
- temp.pop_back();
- visited[i] = 0;
- count1 = 1;
- }
- if(!count1)
- ans.insert(temp);
- }
- vector