From 896a4a8530399a4b9e21a8d7c9ddde0fa42a0d6c Mon Sep 17 00:00:00 2001 From: mqray Date: Tue, 9 Jun 2020 22:55:17 +0800 Subject: [PATCH 001/105] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E7=A7=BB=E5=8A=A80?= =?UTF-8?q?=E5=92=8C=E7=9B=9B=E6=B0=B4=E6=9C=80=E5=A4=9A=E7=9A=84=E5=AE=B9?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/Week01.iml | 12 ++ Week01/.idea/leetcode/editor.xml | 25 +++ Week01/.idea/misc.xml | 7 + Week01/.idea/modules.xml | 8 + Week01/.idea/vcs.xml | 6 + Week01/.idea/workspace.xml | 325 +++++++++++++++++++++++++++++++ Week01/maxArea.py | 51 +++++ Week01/move0.py | 67 +++++++ 8 files changed, 501 insertions(+) create mode 100644 Week01/.idea/Week01.iml create mode 100644 Week01/.idea/leetcode/editor.xml create mode 100644 Week01/.idea/misc.xml create mode 100644 Week01/.idea/modules.xml create mode 100644 Week01/.idea/vcs.xml create mode 100644 Week01/.idea/workspace.xml create mode 100644 Week01/maxArea.py create mode 100644 Week01/move0.py diff --git a/Week01/.idea/Week01.iml b/Week01/.idea/Week01.iml new file mode 100644 index 000000000..7c9d48f0f --- /dev/null +++ b/Week01/.idea/Week01.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml new file mode 100644 index 000000000..2346dd399 --- /dev/null +++ b/Week01/.idea/leetcode/editor.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/Week01/.idea/misc.xml b/Week01/.idea/misc.xml new file mode 100644 index 000000000..399908725 --- /dev/null +++ b/Week01/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Week01/.idea/modules.xml b/Week01/.idea/modules.xml new file mode 100644 index 000000000..8c762a0d7 --- /dev/null +++ b/Week01/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Week01/.idea/vcs.xml b/Week01/.idea/vcs.xml new file mode 100644 index 000000000..6c0b86358 --- /dev/null +++ b/Week01/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml new file mode 100644 index 000000000..302fb76ee --- /dev/null +++ b/Week01/.idea/workspace.xml @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + @@ -321,7 +323,7 @@ - + @@ -334,9 +336,9 @@ - + - + @@ -432,13 +434,6 @@ - - - - - - - @@ -498,6 +493,13 @@ + + + + + + + @@ -505,31 +507,48 @@ - + - - + + - + - - + + - + + + + + + + + - - + + - - + + + + + + + + + + + + diff --git a/Week01/hasCycleII.py b/Week01/hasCycleII.py new file mode 100644 index 000000000..ae0f9f03a --- /dev/null +++ b/Week01/hasCycleII.py @@ -0,0 +1,95 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/12 4:47 PM + + +# 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 +# +# 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 +# +# 说明:不允许修改给定的链表。 +# +# +# +# 示例 1: +# +# 输入:head = [3,2,0,-4], pos = 1 +# 输出:tail connects to node index 1 +# 解释:链表中有一个环,其尾部连接到第二个节点。 +# +# +# +# +# 示例 2: +# +# 输入:head = [1,2], pos = 0 +# 输出:tail connects to node index 0 +# 解释:链表中有一个环,其尾部连接到第一个节点。 +# +# +# +# +# 示例 3: +# +# 输入:head = [1], pos = -1 +# 输出:no cycle +# 解释:链表中没有环。 +# +# +# +# +# +# +# 进阶: +# 你是否可以不用额外空间解决此题? +# Related Topics 链表 双指针 + + +# leetcode submit region begin(Prohibit modification and deletion) +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + +class Solution(object): + # def detectCycle(self, head): + # """ + # :type head: ListNode + # :rtype: ListNode + # """ + # # 1.hashtable beat 97% + # hashtable = {} + # while head: + # # if not in the hashtable + # if not hashtable.get(head): + # hashtable[head] = head + # # must move back the head pointer, so it can continue while loop + # head = head.next + # else: + # # if the node in hashtable, it must be the loop header + # return head + # # if walk here head==None, so we just return None + # return None + # 击败28% + def detectCycle(self, head: ListNode) -> ListNode: + if not head: + return None + intersect_node = self.interseet(head) + if not intersect_node: # if interset is None + return None + tmp = head + while tmp != intersect_node: + tmp, intersect_node = tmp.next, intersect_node.next + return intersect_node + + def interseet(self, head: ListNode) -> ListNode: + fast, slow = head, head + while fast.next and fast.next.next: + fast = fast.next.next + slow = slow.next + if slow == fast: + return slow # return the intersect + return None + +# leetcode submit region end(Prohibit modification and deletion) From 6bcb7c03ffd9f5221ba100a6dac649379bea032b Mon Sep 17 00:00:00 2001 From: mqray Date: Fri, 12 Jun 2020 22:14:19 +0800 Subject: [PATCH 012/105] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9C=89=E7=8E=AF?= =?UTF-8?q?=E9=93=BE=E8=A1=A8=E4=BB=A5=E5=8F=8A=E5=A2=9E=E6=B7=BBk?= =?UTF-8?q?=E4=B8=BA=E4=B8=80=E7=BB=84=E7=BF=BB=E8=BD=AC=E9=93=BE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/leetcode/editor.xml | 8 ++ Week01/.idea/workspace.xml | 228 ++++++++++++++++++++++++------- Week01/hasCycleII.py | 58 +++++--- Week01/linkListTest.py | 100 ++++++++++++++ Week01/reverseKGroup.py | 77 +++++++++++ 5 files changed, 401 insertions(+), 70 deletions(-) create mode 100644 Week01/linkListTest.py create mode 100644 Week01/reverseKGroup.py diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml index a302b7396..966c00c1b 100644 --- a/Week01/.idea/leetcode/editor.xml +++ b/Week01/.idea/leetcode/editor.xml @@ -59,6 +59,14 @@ + + + + + + diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index f8467c980..5f152d279 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,9 +2,11 @@ - + + + + + @@ -31,23 +35,23 @@ - + - + - + - + @@ -55,72 +59,82 @@ - - + + + + + + - + - - + + - + - - + + + + + - + - - + + - + - - + + - + - + - - + + + + + - + - - + + - + - - + + @@ -137,8 +151,8 @@ - - + + @@ -174,6 +188,8 @@ @@ -226,7 +242,7 @@ - + + + + + + + + + + + @@ -323,29 +387,53 @@ - + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - @@ -521,6 +602,20 @@ + + + + + + + + + + + + + + @@ -528,26 +623,53 @@ - + - - + + - + + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/Week01/hasCycleII.py b/Week01/hasCycleII.py index ae0f9f03a..2ef05f687 100644 --- a/Week01/hasCycleII.py +++ b/Week01/hasCycleII.py @@ -72,24 +72,48 @@ class Solution(object): # # if walk here head==None, so we just return None # return None # 击败28% + # def detectCycle(self, head: ListNode) -> ListNode: + # if not head: + # return None + # intersect_node = self.interseet(head) + # if not intersect_node: # if interset is None + # return None + # tmp = head + # while tmp != intersect_node: + # tmp, intersect_node = tmp.next, intersect_node.next + # return intersect_node + # + # def interseet(self, head: ListNode) -> ListNode: + # fast, slow = head, head + # while fast and fast.next: + # fast = fast.next.next + # slow = slow.next + # if slow == fast: + # return slow # return the intersect + # return None + #击败47% + # def detectCycle(self, head: ListNode) -> ListNode: + # slow = fast = head + # while fast and fast.next: + # slow, fast = slow.next, fast.next.next + # if slow == fast: + # break + # else: + # return None + # while head != slow: + # slow, head = slow.next, head.next + # return head + #击败65% def detectCycle(self, head: ListNode) -> ListNode: - if not head: - return None - intersect_node = self.interseet(head) - if not intersect_node: # if interset is None - return None - tmp = head - while tmp != intersect_node: - tmp, intersect_node = tmp.next, intersect_node.next - return intersect_node - - def interseet(self, head: ListNode) -> ListNode: - fast, slow = head, head - while fast.next and fast.next.next: - fast = fast.next.next - slow = slow.next - if slow == fast: - return slow # return the intersect + fast = slow = finder = head + while fast and fast.next: + fast, slow = fast.next.next, slow.next + if fast == slow: + while slow != finder: + slow, finder = slow.next, finder.next + return slow return None + + # leetcode submit region end(Prohibit modification and deletion) diff --git a/Week01/linkListTest.py b/Week01/linkListTest.py new file mode 100644 index 000000000..845babe61 --- /dev/null +++ b/Week01/linkListTest.py @@ -0,0 +1,100 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/12 8:51 PM + +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None +class LinkList: + def __init__(self): + self.head = None + + def initList(self,data): + self.head = ListNode(data[0])#链表头 + r,p = self.head,self.head + for i in data[1:]:#循环创建链表 + node = ListNode(i) + p.next = node + p = p.next + return r#返回头指针 + + def printLinkList(self,head): + if not head: + return + node = head + while node != None: + print(node.val,'->',end='') + node = node.next +class Solution(object): + def reverseKGroup(self, head, k): + dummy = ListNode(-1) #dummy是用来返回最后的链表 + dummy.next = head + pre = dummy#pre记录翻转过程每次翻转链表的前一个元素 + while head: + tail = pre# last用以记录k个node的最后一个 + # 取出k个node + for i in range(k): + tail = tail.next + if tail is None:#说明在取元素的时候没能够取到K个元素,返回的应该是头节点 + return dummy.next + next_head = tail.next#记录下个K组的首节点 + head,tail = self.reverseLinkList(head, tail)#这里传next_head,当做最后一个节点 + #将翻转后的链表接到原始链表上 + pre.next = head + tail.next = next_head + #调整此时的head和pre + pre = tail + head = next_head + return dummy.next + def reverseLinkList(self,head,tail): + prev = tail.next + tail_node = head#记录这K个node的第一个元素,最后将它作为尾元素返回 以连接到原始链表中 + while prev != tail: + tmp = head.next + head.next = prev + prev = head + head = tmp + return tail, tail_node +# leetcode submit region end(Prohibit modification and deletion) + +class Solution1: + # 翻转一个子链表,并且返回新的头与尾 + def reverse(self, head: ListNode, tail: ListNode): + prev = tail.next + p = head + while prev != tail: + nex = p.next + p.next = prev + prev = p + p = nex + return tail, head + + def reverseKGroup(self, head: ListNode, k: int) -> ListNode: + hair = ListNode(0) + hair.next = head + pre = hair + + while head: + tail = pre + # 查看剩余部分长度是否大于等于 k + for i in range(k): + tail = tail.next + if not tail: + return hair.next + nex = tail.next + head, tail = self.reverse(head, tail) + # 把子链表重新接回原链表 + pre.next = head + tail.next = nex + pre = tail + head = tail.next + + return hair.next + +ll = LinkList() +a = ll.initList([1,2,3,4,5,6]) +# ll.printLinkList(a) +s = Solution() +res = s.reverseKGroup(a,2) +ll.printLinkList(res) \ No newline at end of file diff --git a/Week01/reverseKGroup.py b/Week01/reverseKGroup.py new file mode 100644 index 000000000..14cf3415a --- /dev/null +++ b/Week01/reverseKGroup.py @@ -0,0 +1,77 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/12 6:33 PM + +# 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。 +# +# k 是一个正整数,它的值小于或等于链表的长度。 +# +# 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 +# +# +# +# 示例: +# +# 给你这个链表:1->2->3->4->5 +# +# 当 k = 2 时,应当返回: 2->1->4->3->5 +# +# 当 k = 3 时,应当返回: 3->2->1->4->5 +# +# +# +# 说明: +# +# +# 你的算法只能使用常数的额外空间。 +# 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。 +# +# Related Topics 链表 + + +# leetcode submit region begin(Prohibit modification and deletion) +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + +class Solution(object): + def reverseKGroup(self, head, k): + """ + :type head: ListNode + :type k: int + :rtype: ListNode + """ + + dummy = ListNode(-1)#dummy是用来返回最后的链表 + dummy.next = head + pre = dummy#pre记录翻转过程每次翻转链表的前一个元素 + + while head: + tail = pre# last用以记录k个node的最后一个 + for i in range(k): + tail = tail.next + if not tail: + return dummy.next#说明在取元素的时候没能够取到K个元素,返回的应该是头节点 + next_head = tail.next#记录下个K组的首节点 + head, tail = self.reverseList(head, tail) + # 将翻转后的链表接到原始链表上 + pre.next = head + tail.next = next_head + # 调整此时的head和pre + head = next_head + pre = tail + return dummy.next + + # 记录这K个node的第一个元素,最后将它作为尾元素返回 以连接到原始链表中 + def reverseList(self, head, tail): + prev = tail.next + tail_node = head + while prev != tail: + tmp = head.next + head.next = prev + prev = head + head = tmp + return tail, tail_node +# leetcode submit region end(Prohibit modification and deletion) From ffef4519f33410a3067708d4a6ec2f8af9deacaf Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 13 Jun 2020 00:12:35 +0800 Subject: [PATCH 013/105] =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E7=9A=84=E6=8B=AC=E5=8F=B7=E4=BB=A5=E5=8F=8A=E6=9C=80=E5=B0=8F?= =?UTF-8?q?=E6=A0=88=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/leetcode/editor.xml | 24 ++++++ Week01/.idea/workspace.xml | 131 +++++++++++++++++++------------ Week01/MinStack.py | 94 ++++++++++++++++++++++ Week01/isValidbrackets.py | 66 ++++++++++++++++ 4 files changed, 263 insertions(+), 52 deletions(-) create mode 100644 Week01/MinStack.py create mode 100644 Week01/isValidbrackets.py diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml index 966c00c1b..c750167e2 100644 --- a/Week01/.idea/leetcode/editor.xml +++ b/Week01/.idea/leetcode/editor.xml @@ -27,6 +27,14 @@ + + + + + + @@ -51,6 +59,14 @@ + + + + + + @@ -75,6 +91,14 @@ + + + + + + diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 5f152d279..1961b6d4a 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,11 +2,10 @@ - - + + - + + + @@ -67,15 +69,6 @@ - - - - - - - - - @@ -89,18 +82,9 @@ - - - - - - - - - - + @@ -110,49 +94,56 @@ - + - - - - - - + - + - - + + + + + + + + + + + - + - - + + - + - - + + + + + - + - - + + @@ -190,6 +181,9 @@ @@ -387,12 +381,12 @@ - + - + - + @@ -402,11 +396,11 @@ - + - + @@ -666,7 +660,7 @@ - + @@ -674,6 +668,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Week01/MinStack.py b/Week01/MinStack.py new file mode 100644 index 000000000..3d2116b89 --- /dev/null +++ b/Week01/MinStack.py @@ -0,0 +1,94 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/13 12:08 AM +# 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 +# +# +# push(x) —— 将元素 x 推入栈中。 +# pop() —— 删除栈顶的元素。 +# top() —— 获取栈顶元素。 +# getMin() —— 检索栈中的最小元素。 +# +# +# +# +# 示例: +# +# 输入: +# ["MinStack","push","push","push","getMin","pop","top","getMin"] +# [[],[-2],[0],[-3],[],[],[],[]] +# +# 输出: +# [null,null,null,null,-3,null,0,-2] +# +# 解释: +# MinStack minStack = new MinStack(); +# minStack.push(-2); +# minStack.push(0); +# minStack.push(-3); +# minStack.getMin(); --> 返回 -3. +# minStack.pop(); +# minStack.top(); --> 返回 0. +# minStack.getMin(); --> 返回 -2. +# +# +# +# +# 提示: +# +# +# pop、top 和 getMin 操作总是在 非空栈 上调用。 +# +# Related Topics 栈 设计 + + +# leetcode submit region begin(Prohibit modification and deletion) + +class MinStack: + + def __init__(self): + """ + initialize your data structure here. + """ + self.stack = [] + self.min_stack = [] + #击败92% + def push(self, x: int) -> None: + self.stack.append(x) + #如果当前元素比最小栈中的元素小,则将此元素放入最小栈中 + #如果当前最小栈为空,将此元素放入最小栈中 + if not self.min_stack : + self.min_stack.append(x) + elif x <= self.min_stack[-1]: + self.min_stack.append(x) + + def pop(self) -> None: + if self.stack.pop() == self.min_stack[-1]: + return self.min_stack.pop() + + def top(self) -> int: + return self.stack[-1] + + def getMin(self) -> int: + return self.min_stack[-1] + + + +# Your MinStack object will be instantiated and called as such: +# obj = MinStack() +# obj.push(x) +# obj.pop() +# param_3 = obj.top() +# param_4 = obj.getMin() + + + + + +# Your MinStack object will be instantiated and called as such: +# obj = MinStack() +# obj.push(x) +# obj.pop() +# param_3 = obj.top() +# param_4 = obj.getMin() +# leetcode submit region end(Prohibit modification and deletion) diff --git a/Week01/isValidbrackets.py b/Week01/isValidbrackets.py new file mode 100644 index 000000000..2564acc30 --- /dev/null +++ b/Week01/isValidbrackets.py @@ -0,0 +1,66 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/12 11:22 PM + +# 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 +# +# 有效字符串需满足: +# +# +# 左括号必须用相同类型的右括号闭合。 +# 左括号必须以正确的顺序闭合。 +# +# +# 注意空字符串可被认为是有效字符串。 +# +# 示例 1: +# +# 输入: "()" +# 输出: true +# +# +# 示例 2: +# +# 输入: "()[]{}" +# 输出: true +# +# +# 示例 3: +# +# 输入: "(]" +# 输出: false +# +# +# 示例 4: +# +# 输入: "([)]" +# 输出: false +# +# +# 示例 5: +# +# 输入: "{[]}" +# 输出: true +# Related Topics 栈 字符串 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def isValid(self, s): + """ + :type s: str + :rtype: bool + """ + #击败96% + stack = [] + dic = {')':'(',']':'[','}':'{'} + for item in s: + if item not in dic:#如果是左括号,入栈 + stack.append(item) + else:#如果是右括号 + top = stack.pop() if stack else '#'#判断是否与当前栈顶元素相匹配 + if top != item:#不匹配,则返回False + return False + #如果刚开始是左括号,入栈后就结束了,明显是不匹配的,所以最终结果需要根据stack是否空来返回 + return not stack + # leetcode submit region end(Prohibit modification and deletion) From 50e248c8786b00391c6ba35c751a9ef4955ad7a1 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 13 Jun 2020 10:03:56 +0800 Subject: [PATCH 014/105] =?UTF-8?q?=E6=9F=B1=E7=8A=B6=E5=9B=BE=E7=9A=84?= =?UTF-8?q?=E6=9C=80=E5=A4=A7=E9=9D=A2=E7=A7=AF=E6=9A=B4=E5=8A=9B=E8=A7=A3?= =?UTF-8?q?=E3=80=81=E5=8D=95=E8=B0=83=E6=A0=88=E4=BB=A5=E5=8F=8A=E7=94=A8?= =?UTF-8?q?=E5=93=A8=E5=85=B5=E4=BC=98=E5=8C=96=E7=9A=84=E5=8D=95=E8=B0=83?= =?UTF-8?q?=E6=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/leetcode/editor.xml | 8 ++ Week01/.idea/workspace.xml | 184 ++++++++++++++++++++++++------- Week01/largestRectangleArea.py | 111 +++++++++++++++++++ 3 files changed, 261 insertions(+), 42 deletions(-) create mode 100644 Week01/largestRectangleArea.py diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml index c750167e2..9942e728a 100644 --- a/Week01/.idea/leetcode/editor.xml +++ b/Week01/.idea/leetcode/editor.xml @@ -107,6 +107,14 @@ + + + + + + diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 1961b6d4a..7c6ad8d62 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,8 +2,7 @@ - - + @@ -17,6 +16,8 @@ + + @@ -34,23 +35,23 @@ - + - + - - + + - + @@ -60,15 +61,6 @@ - - - - - - - - - @@ -109,15 +101,36 @@ - + - + + + + + + + + + + + + + + + + + + + + + + @@ -139,15 +152,6 @@ - - - - - - - - - @@ -184,6 +188,8 @@ @@ -236,7 +242,7 @@ - + - + - + - + - - + + + + - - @@ -386,7 +392,7 @@ - + @@ -396,11 +402,11 @@ - + - + @@ -498,6 +504,76 @@ 88 @@ -696,11 +772,35 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Week01/largestRectangleArea.py b/Week01/largestRectangleArea.py new file mode 100644 index 000000000..fd0582e1f --- /dev/null +++ b/Week01/largestRectangleArea.py @@ -0,0 +1,111 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/13 12:59 AM + +# 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 +# +# 求在该柱状图中,能够勾勒出来的矩形的最大面积。 +# +# +# +# +# +# 以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。 +# +# +# +# +# +# 图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。 +# +# +# +# 示例: +# +# 输入: [2,1,5,6,2,3] +# 输出: 10 +# Related Topics 栈 数组 + + +# leetcode submit region begin(Prohibit modification and deletion) +# class Solution(object): +# def largestRectangleArea(self, heights): +# """ +# :type heights: List[int] +# :rtype: int +# """ + # 1.暴力解 超出时间限制 + # size = len(heights) + # res = 0 + # for i in range(size): + # left = i + # cur_height = heights[i] + # while left > 0 and heights[left - 1] >= cur_height: + # left -= 1 + # + # right = i + # while right < size - 1 and heights[right + 1] >= cur_height: + # right += 1 + # res = max(res, (right - left + 1) * cur_height) + # return res +from typing import List + +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + size = len(heights)#[2,1,5,6,2,3] + res = 0 + stack = [] + for i in range(size): + while len(stack) > 0 and heights[i] < heights[stack[-1]]: + # 如果当前height的右边height严格小于height,则确定了此轮的height + cur_height = heights[stack.pop()] + + # while len(stack) > 0 and cur_height == heights[stack[-1]]: + # stack.pop() + + if len(stack) > 0: + cur_width = i - stack[-1] - 1 + else: + cur_width = i + + res = max(res, cur_height * cur_width) + stack.append(i)#记录的是heights的下标 + + while len(stack) > 0 is not None:#处理还未出栈的高度 + cur_height = heights[stack.pop()] + # while len(stack) > 0 and cur_height == heights[stack[-1]]:#处理相邻高度一致的情形 + # stack.pop() + + if len(stack) > 0: + cur_width = size - stack[-1] - 1 + else: + cur_width = size + res = max(res, cur_height * cur_width) + return res + + +class SolutionI: + #哨兵优化 击败73% + def largestRectangleArea(self, heights: List[int]) -> int: + max_area = 0 + heights = [0]+heights+[0] + stack = [0] + for i in range(len(heights)): + while heights[i] < heights[stack[-1]]:#如果当前高度小,就可以确定以上一个height为高的最大面积 + cur_height = heights[stack.pop()]#此时计算高度为前一个height的值 + cur_width = i - stack[-1] - 1 + max_area = max(max_area, cur_height*cur_width) + stack.append(i) + return max_area + + + + + + + +# leetcode submit region end(Prohibit modification and deletion) + +s = SolutionI() +res = s.largestRectangleArea([2,1,5,6,2,3]) +print(res) \ No newline at end of file From 56cd4303b1ea29b81bbde4fb167d08fec85a2e1e Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 13 Jun 2020 11:33:09 +0800 Subject: [PATCH 015/105] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E5=A4=A7=E5=80=BC=20=E6=9A=B4=E5=8A=9B?= =?UTF-8?q?=E8=A7=A3=E6=B3=95=E5=92=8C=E5=8F=8C=E7=AB=AF=E9=98=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/leetcode/editor.xml | 8 +++ Week01/.idea/workspace.xml | 102 ++++++++++++++++++++----------- Week01/maxSlidingWindow.py | 95 ++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 37 deletions(-) create mode 100644 Week01/maxSlidingWindow.py diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml index 9942e728a..70821ad64 100644 --- a/Week01/.idea/leetcode/editor.xml +++ b/Week01/.idea/leetcode/editor.xml @@ -67,6 +67,14 @@ + + + + + + diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 7c6ad8d62..296eae3d1 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,7 +2,7 @@ - + @@ -19,6 +19,7 @@ + @@ -35,23 +36,23 @@ - + - + - - + + - + @@ -61,18 +62,6 @@ - - - - - - - - - - - - @@ -110,7 +99,7 @@ - + @@ -122,6 +111,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -190,6 +200,7 @@ @@ -242,8 +253,8 @@ - - + + - + - + - + - + + - @@ -393,7 +404,7 @@ - + @@ -406,8 +417,8 @@ - - + + @@ -801,6 +812,23 @@ + + + + + + + + + + + + + + + + + diff --git a/Week01/maxSlidingWindow.py b/Week01/maxSlidingWindow.py new file mode 100644 index 000000000..2dcaa5d8f --- /dev/null +++ b/Week01/maxSlidingWindow.py @@ -0,0 +1,95 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/13 10:04 AM +# 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 +# +# +# 返回滑动窗口中的最大值。 +# +# +# +# 进阶: +# +# 你能在线性时间复杂度内解决此题吗? +# +# +# +# 示例: +# +# 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 +# 输出: [3,3,5,5,6,7] +# 解释: +# +# 滑动窗口的位置 最大值 +# --------------- ----- +# [1 3 -1] -3 5 3 6 7 3 +# 1 [3 -1 -3] 5 3 6 7 3 +# 1 3 [-1 -3 5] 3 6 7 5 +# 1 3 -1 [-3 5 3] 6 7 5 +# 1 3 -1 -3 [5 3 6] 7 6 +# 1 3 -1 -3 5 [3 6 7] 7 +# +# +# +# 提示: +# +# +# 1 <= nums.length <= 10^5 +# -10^4 <= nums[i] <= 10^4 +# 1 <= k <= nums.length +# +# Related Topics 堆 Sliding Window + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def maxSlidingWindow(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: List[int] + """ + # 1.暴力解 + # res = [] + # for i in range(0, len(nums) - k + 1): + # window = nums[i:i+k] + # res.append(max(window)) + # return res + # return [max(nums[i:i + k]) for i in range(n - k + 1)] + + +from collections import deque +class SolutionII: + def maxSlidingWindow(self, nums: 'List[int]', k: 'int') -> 'List[int]': + #双端队列 击败30% + size = len(nums) + if size == 0 or k == 0: + return [] + if k == 1: + return nums + def ope_deque(i): + if deq and deq[0] == i-k: # [7,2,4],2 滑动过程中,将window的最左元素出掉 + deq.popleft() + while deq and nums[i] > nums[deq[-1]]:# 整体上滑动的过程还是一个先进先出队列的形式 + deq.pop() + max_index = 0 + deq = deque() + res = [] + for i in range(k): + ope_deque(i) + deq.append(i) + if nums[i] > nums[max_index]: + max_index = i + res.append(nums[max_index]) + + for i in range(k,size): + ope_deque(i) + deq.append(i) + res.append(nums[deq[0]])#窗口开始滑动,要记录此时窗口的最大值 + return res +# leetcode submit region end(Prohibit modification and deletion) + + +s = SolutionII() +res = s.maxSlidingWindow([1,3,-1,-3,5,3,6,7],3) +print(res) \ No newline at end of file From 105e455166a29df99a9ea9a9c20a683bd3762889 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 13 Jun 2020 12:28:45 +0800 Subject: [PATCH 016/105] =?UTF-8?q?=E6=AF=8F=E6=97=A5=E4=B8=80=E9=A2=986?= =?UTF-8?q?=5F13=E7=88=AC=E6=A5=BC=E6=A2=AF=E4=B8=89=E7=A7=8D=E8=A7=A3?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/workspace.xml | 48 ++++++++++--------- ...3_\347\210\254\346\245\274\346\242\257.py" | 29 +++++++++++ 2 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 "Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_13_\347\210\254\346\245\274\346\242\257.py" diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 296eae3d1..101604a54 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,8 +2,7 @@ - - + @@ -201,6 +197,7 @@ @@ -403,7 +400,7 @@ - + @@ -413,7 +410,7 @@ - + @@ -829,6 +826,13 @@ + + + + + + + diff --git "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_13_\347\210\254\346\245\274\346\242\257.py" "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_13_\347\210\254\346\245\274\346\242\257.py" new file mode 100644 index 000000000..32d88e296 --- /dev/null +++ "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_13_\347\210\254\346\245\274\346\242\257.py" @@ -0,0 +1,29 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/13 11:59 AM + +class Solution: + def climbStairs(self, n: int) -> int: + # 1.无脑递归 未通过 + # if n==1: return 1 + # if n==2: return 2 + # return self.climbStairs(n-1)+self.climbStairs(n-2) + # 2.递归+备忘录,记录climbstairs(n) + # 击败39% + # mem = [0,1,2] + # if n==1:return mem[1] + # if n==2:return mem[2] + # for i in range(3,n+1): + # mem.append(mem[i-1]+mem[i-2]) + # return mem[-1] + # 3. 备忘录解法中相当于是存了1-n所有的结果,但是没有必要 + # 优化 击败83% + a, b = 1, 2 + if n == 1: return 1 + if n == 2: return 2 + for i in range(3, n + 1): + a, b = b, a + b + return b + + + From 9da3e0ccee13632a43555e2553b308166b65cd57 Mon Sep 17 00:00:00 2001 From: mqray Date: Sun, 14 Jun 2020 17:33:07 +0800 Subject: [PATCH 017/105] =?UTF-8?q?=E6=AF=8F=E6=97=A5=E4=B8=80=E9=A2=986?= =?UTF-8?q?=5F14=5F=E8=BD=AC=E5=8F=98=E6=95=B0=E7=BB=84=E4=BD=BF=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E5=92=8C=E6=8E=A5=E8=BF=91=E7=9B=AE=E6=A0=87=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/workspace.xml | 42 ++++++++++--------- ...21\347\233\256\346\240\207\345\200\274.py" | 19 +++++++++ 2 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 "Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 101604a54..115dd7c43 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,8 +2,7 @@ - - + - - - - - - - - - - - - @@ -122,7 +109,7 @@ - + @@ -131,6 +118,15 @@ + + + + + + + + + @@ -198,6 +194,7 @@ @@ -395,7 +392,7 @@ - + @@ -410,7 +407,7 @@ - + @@ -833,6 +830,13 @@ + + + + + + + diff --git "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" new file mode 100644 index 000000000..53c30065c --- /dev/null +++ "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" @@ -0,0 +1,19 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/14 5:32 PM + +class Solution: + def findBestValue(self, arr: List[int], target: int) -> int: + #这种接法就是应该是贪心吧??如果匹配过程中,该元素都与均值匹配,那么就替换 + #每次都是与期望的均值作比较 + arr.sort() + size = len(arr) + for i in range(size): + average = target / (size-i)# + if arr[i] <= average:#如果当前元素小于平均值,那么再下次匹配时,希望的平均值就应当大一些 + target = target - arr[i] + else:#如果当前的元素大于average,那么这个值就是可以修改的 + return int(average+0.49) + #如果遍历完之后还没有返回这个value,说明整个数组整体的值都偏小,导致没法匹配到average值 + # 这个时候就返回排序数组最后的元素 + return arr[-1] \ No newline at end of file From 06b14b5398c141c031248655bd1f709279c6f12f Mon Sep 17 00:00:00 2001 From: mqray Date: Sun, 14 Jun 2020 18:58:41 +0800 Subject: [PATCH 018/105] =?UTF-8?q?python=20quene=E3=80=81deque=E3=80=81he?= =?UTF-8?q?apq=E6=BA=90=E7=A0=81=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/workspace.xml | 24 +- Week01/NOTE.md | 3 +- ...ene_deque_heap\345\210\206\346\236\220.md" | 418 ++++++++++++++++++ ...21\347\233\256\346\240\207\345\200\274.py" | 2 +- 4 files changed, 434 insertions(+), 13 deletions(-) create mode 100644 "Week01/quene_deque_heap\345\210\206\346\236\220.md" diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 115dd7c43..b85fc1ca1 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,7 +2,8 @@ - + + - + + @@ -389,7 +391,7 @@ - + @@ -407,7 +409,7 @@ - + @@ -832,8 +834,8 @@ - - + + diff --git a/Week01/NOTE.md b/Week01/NOTE.md index 50de30414..74aac9022 100644 --- a/Week01/NOTE.md +++ b/Week01/NOTE.md @@ -1 +1,2 @@ -学习笔记 \ No newline at end of file +学习笔记 + diff --git "a/Week01/quene_deque_heap\345\210\206\346\236\220.md" "b/Week01/quene_deque_heap\345\210\206\346\236\220.md" new file mode 100644 index 000000000..a2e7efa28 --- /dev/null +++ "b/Week01/quene_deque_heap\345\210\206\346\236\220.md" @@ -0,0 +1,418 @@ + 1. 谷歌搜索[python quene](https://docs.python.org/3/library/queue.html) + 2. 点开第一个连接[A synchronized queue class](https://docs.python.org/3/library/queue.html) + 3. 能看到关于quene的代码都被保存在**Lib/queue.py**,可以下载python源码进行查阅。 + +这个模块中实现了三种类型的队列 + +``` +class queue.Queue(maxsize=0)#FIFO队列 +class queue.LifoQueue(maxsize=0)#LIFO队列 +class queue.PriorityQueue(maxsize=0)#优先级队列,通常需要借助heapq模块 +``` +>队列模块实现了多生产者、多使用者队列。当信息必须在多个线程之间安全地交换时,它在线程编程中特别有用。这个模块中的Queue类实现了所有所需的锁定语义。 +除此之外,还实现了名为`class queue.SimpleQueue`,它是最基本的FIFO队列,缺少任务追踪等功能。 + + +### `Quene()` + +#### __init__() +实例方法,定义了队列相关操作需要的锁、标识符等 + +``` +def __init__(self, maxsize=0): + self.maxsize = maxsize + self._init(maxsize) + + # mutex must be held whenever the queue is mutating. All methods + # that acquire mutex must release it before returning. mutex + # is shared between the three conditions, so acquiring and + # releasing the conditions also acquires and releases mutex. + self.mutex = threading.Lock() + + # Notify not_empty whenever an item is added to the queue; a + # thread waiting to get is notified then. + self.not_empty = threading.Condition(self.mutex) + + # Notify not_full whenever an item is removed from the queue; + # a thread waiting to put is notified then. + self.not_full = threading.Condition(self.mutex) + + # Notify all_tasks_done whenever the number of unfinished tasks + # drops to zero; thread waiting to join() is notified to resume + self.all_tasks_done = threading.Condition(self.mutex) + self.unfinished_tasks = 0 +``` + + +#### task_done 标识前面的入队任务已完成 +由队列使用者线程使用。对于用于获取任务的每个`get()`,后续调用`task_done()`告诉队列任务的处理已完成。 + +``` + def task_done(self): + '''Indicate that a formerly enqueued task is complete. + + Used by Queue consumer threads. For each get() used to fetch a task, + a subsequent call to task_done() tells the queue that the processing + on the task is complete. + + If a join() is currently blocking, it will resume when all items + have been processed (meaning that a task_done() call was received + for every item that had been put() into the queue). + + Raises a ValueError if called more times than there were items + placed in the queue. + ''' + with self.all_tasks_done: + unfinished = self.unfinished_tasks - 1 + if unfinished <= 0: + if unfinished < 0: + raise ValueError('task_done() called too many times') + self.all_tasks_done.notify_all() + self.unfinished_tasks = unfinished +``` + +#### join 阻塞直到队列中所有元素被处理 + +每当有任务添加到队列中时,未完成的任务count计数增加;当消费者进程调用`task_done()`标识任务已被释放所有工作已完成时,任务计数减少。 +``` + def join(self): + '''Blocks until all items in the Queue have been gotten and processed. + + The count of unfinished tasks goes up whenever an item is added to the + queue. The count goes down whenever a consumer thread calls task_done() + to indicate the item was retrieved and all work on it is complete. + + When the count of unfinished tasks drops to zero, join() unblocks. + ''' + with self.all_tasks_done: + while self.unfinished_tasks: + self.all_tasks_done.wait() +``` + +#### qsize 返回队列的大致大小 +``` +def qsize(self): + '''Return the approximate size of the queue (not reliable!).''' + with self.mutex: + return self._qsize() +``` +#### empty 判断队列是否为空 +``` +def empty(self): + '''Return True if the queue is empty, False otherwise (not reliable!). + + This method is likely to be removed at some point. Use qsize() == 0 + as a direct substitute, but be aware that either approach risks a race + condition where a queue can grow before the result of empty() or + qsize() can be used. + + To create code that needs to wait for all queued tasks to be + completed, the preferred technique is to use the join() method. + ''' + with self.mutex: + return not self._qsize() +``` + +#### full 判断队列是否已满 +``` +def full(self): + '''Return True if the queue is full, False otherwise (not reliable!). + + This method is likely to be removed at some point. Use qsize() >= n + as a direct substitute, but be aware that either approach risks a race + condition where a queue can shrink before the result of full() or + qsize() can be used. + ''' + with self.mutex: + return 0 < self.maxsize <= self._qsize() +``` + +#### put 入队列 +``` +def put(self, item, block=True, timeout=None): + '''Put an item into the queue. + + If optional args 'block' is true and 'timeout' is None (the default), + block if necessary until a free slot is available. If 'timeout' is + a non-negative number, it blocks at most 'timeout' seconds and raises + the Full exception if no free slot was available within that time. + Otherwise ('block' is false), put an item on the queue if a free slot + is immediately available, else raise the Full exception ('timeout' + is ignored in that case). + ''' + with self.not_full: + if self.maxsize > 0: + if not block: + if self._qsize() >= self.maxsize: + raise Full + elif timeout is None: + while self._qsize() >= self.maxsize: + self.not_full.wait() + elif timeout < 0: + raise ValueError("'timeout' must be a non-negative number") + else: + endtime = time() + timeout + while self._qsize() >= self.maxsize: + remaining = endtime - time() + if remaining <= 0.0: + raise Full + self.not_full.wait(remaining) + self._put(item) + self.unfinished_tasks += 1 + self.not_empty.notify() +``` + +#### get 从队列中取出元素 +``` +def get(self, block=True, timeout=None): + '''Remove and return an item from the queue. + + If optional args 'block' is true and 'timeout' is None (the default), + block if necessary until an item is available. If 'timeout' is + a non-negative number, it blocks at most 'timeout' seconds and raises + the Empty exception if no item was available within that time. + Otherwise ('block' is false), return an item if one is immediately + available, else raise the Empty exception ('timeout' is ignored + in that case). + ''' + with self.not_empty: + if not block: + if not self._qsize(): + raise Empty + elif timeout is None: + while not self._qsize(): + self.not_empty.wait() + elif timeout < 0: + raise ValueError("'timeout' must be a non-negative number") + else: + endtime = time() + timeout + while not self._qsize(): + remaining = endtime - time() + if remaining <= 0.0: + raise Empty + self.not_empty.wait(remaining) + item = self._get() + self.not_full.notify() + return item + + def put_nowait(self, item): + '''Put an item into the queue without blocking. + + Only enqueue the item if a free slot is immediately available. + Otherwise raise the Full exception. + ''' + return self.put(item, block=False) +``` +#### put_nowait 在不阻塞的情况下入队列 +``` + def put_nowait(self, item): + '''Put an item into the queue without blocking. + + Only enqueue the item if a free slot is immediately available. + Otherwise raise the Full exception. + ''' + return self.put(item, block=False) +``` +#### get_nowait 不阻塞的情况下出队列 +``` + def get_nowait(self): + '''Remove and return an item from the queue without blocking. + + Only get an item if one is immediately available. Otherwise + raise the Empty exception. + ''' + return self.get(block=False) +``` +#### 被继承时,必须重写的方法 +`_init()`方法中默认使用`deque`实现队列 + +``` +# Initialize the queue representation + def _init(self, maxsize): + self.queue = deque() + + def _qsize(self): + return len(self.queue) + + # Put a new item in the queue + def _put(self, item): + self.queue.append(item) + + # Get an item from the queue + def _get(self): + return self.queue.popleft() +``` + +### PriorityQueue(Queue) +继承自`Quene`,`deque`使用`[]`实现;但是注意到入队和出队操作实际调用的是`heappush`和`heappop `,显然内部实现优先级队列的时候是采用的`heapq`实现的 + + +``` +class PriorityQueue(Queue): + '''Variant of Queue that retrieves open entries in priority order (lowest first). + + Entries are typically tuples of the form: (priority number, data). + ''' + + def _init(self, maxsize): + self.queue = [] + + def _qsize(self): + return len(self.queue) + + def _put(self, item): + heappush(self.queue, item) + + def _get(self): + return heappop(self.queue) +``` + +### LifoQueue(Queue) +继承自`Quene`,`deque`使用`[]`实现;内部入队出队操作调用的是`List`的`append`和`pop`方法。 + +``` +class LifoQueue(Queue): + '''Variant of Queue that retrieves most recently added entries first.''' + + def _init(self, maxsize): + self.queue = [] + + def _qsize(self): + return len(self.queue) + + def _put(self, item): + self.queue.append(item) + + def _get(self): + return self.queue.pop() +``` + +### heapq +链接在此[heapq](https://docs.python.org/2/library/heapq.html),可以看到对应的源码在`Lib/heapq.py`文件下 + +>python中的优先级队列是使用`heapq`(默认小根堆)来实现的,而`堆`的实现方式多种多样,这里是用数组存储的`二叉树`实现的。 + +堆是二叉树,每个父节点的值小于或等于其子节点的值。使用数组`List`实现`heap[k] <= heap[2*k+1] `和 `heap[k] <= heap[2*k+2]`(k从0计数)以满足堆的结构 +其内部实现的方法较多,这里捡几个常用的说 + +#### heappush 往堆里插入元素 +``` +def heappush(heap, item): + """Push item onto heap, maintaining the heap invariant.""" + heap.append(item) + _siftdown(heap, 0, len(heap)-1) +``` + +#### heappop 从堆顶出元素 +``` +def heappop(heap): + """Pop the smallest item off the heap, maintaining the heap invariant.""" + lastelt = heap.pop() # raises appropriate IndexError if heap is empty + if heap: + returnitem = heap[0] + heap[0] = lastelt + _siftup(heap, 0) + return returnitem + return lastelt +``` + +#### heapreplace 替换元素 +等价于`heappop`+`heappush`,更推荐使用。 +``` +def heapreplace(heap, item): + """Pop and return the current smallest value, and add the new item. + + This is more efficient than heappop() followed by heappush(), and can be + more appropriate when using a fixed-size heap. Note that the value + returned may be larger than item! That constrains reasonable uses of + this routine unless written as part of a conditional replacement: + + if item > heap[0]: + item = heapreplace(heap, item) + """ + returnitem = heap[0] # raises appropriate IndexError if heap is empty + heap[0] = item + _siftup(heap, 0) + return returnitem +``` + +#### heappushpop +等价于`heappush` + `heappop` +``` +def heappushpop(heap, item): + """Fast version of a heappush followed by a heappop.""" + if heap and heap[0] < item: + item, heap[0] = heap[0], item + _siftup(heap, 0) + return item +``` + +#### heapify 堆化 +原地将List转化为堆,内部调用`_siftup`和`_siftdown`实现,建堆时,无需考虑叶子节点,所以只用考察数组头、中部之间的元素 +``` +def heapify(x): + """Transform list into a heap, in-place, in O(len(x)) time.""" + n = len(x) + # Transform bottom-up. The largest index there's any point to looking at + # is the largest with a child index in-range, so must have 2*i + 1 < n, + # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so + # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is + # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1. + for i in reversed(range(n//2)): + _siftup(x, i) +``` + +#### _siftup +``` +def _siftup(heap, pos): + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the smaller child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of smaller child. + rightpos = childpos + 1 + if rightpos < endpos and not heap[childpos] < heap[rightpos]: + childpos = rightpos + # Move the smaller child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown(heap, startpos, pos) +``` + +#### _siftdown +``` +def _siftdown(heap, startpos, pos): + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if newitem < parent: + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem +``` + + + +### deque 双端队列 +连接在此[deque](https://docs.python.org/2/library/collections.html),支持从两端插入和删除元素。源代码在`Lib/collections/__init__.py`。 +`deque`是线程安全且内存搞笑的插入和删除操作,从两端插入删除的时间复杂度可视作O(1) + +常见的操作有: + +`append、appendleft、clear、copy、count、extend、extendleft` +`pop、popleft、remove、reverse、rotate` + + + + diff --git "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" index 53c30065c..96465f027 100644 --- "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" +++ "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_14_\350\275\254\345\217\230\346\225\260\347\273\204\344\275\277\346\225\260\347\273\204\345\222\214\346\216\245\350\277\221\347\233\256\346\240\207\345\200\274.py" @@ -1,7 +1,7 @@ # -*- coding:utf-8 -*- # Author : Ray # Data : 2020/6/14 5:32 PM - +from typing import List class Solution: def findBestValue(self, arr: List[int], target: int) -> int: #这种接法就是应该是贪心吧??如果匹配过程中,该元素都与均值匹配,那么就替换 From 4cfbedbe6604e782626744d0b7703451412b1604 Mon Sep 17 00:00:00 2001 From: mqray Date: Sun, 14 Jun 2020 20:56:15 +0800 Subject: [PATCH 019/105] =?UTF-8?q?=E6=80=9D=E7=BB=B4=E5=AF=BC=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.DS_Store | Bin 0 -> 6148 bytes Week01/.idea/workspace.xml | 27 +- .../QuickLook/Preview.jpg" | Bin 0 -> 267479 bytes .../contents.xml" | Bin 0 -> 25966 bytes .../style.mindnodestyle/contents.xml" | 274 ++++++++++++++++++ .../style.mindnodestyle/metadata.plist" | 14 + .../viewState.plist" | Bin 0 -> 147 bytes 7 files changed, 301 insertions(+), 14 deletions(-) create mode 100644 Week01/.DS_Store create mode 100644 "Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/QuickLook/Preview.jpg" create mode 100644 "Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/contents.xml" create mode 100644 "Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/contents.xml" create mode 100644 "Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/style.mindnodestyle/metadata.plist" create mode 100644 "Week01/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225.mindnode/viewState.plist" diff --git a/Week01/.DS_Store b/Week01/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ed6956f82a385ddfb294271a09cf59406fcee1dc GIT binary patch literal 6148 zcmeHKJ4ysW5Up}I7!YJa6Qxfe>8fsCmtIce&YU@rn@FIKrl2f-uv8>u9Vzax$=ktTp zhvV<@${+E%%MWYhfT`SE0aw5ka0Og}Q3Y^ki)FitUb_OWfGhB>fSeBjMKBunis|S; zl~MqpJfoArms~va0P}6O!PCC`~L*L%xIE7r1+OB;0pXR1$bI4ia9oAck8F^$z2;zE>OfIt``Re mfA9#vhnyq(sZ;xd_=t;!y`qdF?THTbhd>g - - + diff --git a/Week01/twoSum.py b/Week01/2Sum.py similarity index 97% rename from Week01/twoSum.py rename to Week01/2Sum.py index b33b8eb64..688b0e591 100644 --- a/Week01/twoSum.py +++ b/Week01/2Sum.py @@ -27,7 +27,7 @@ def twoSum(self, nums, target): # 2.hash表记录 两次hash # 3.一次hash表 # 击败18% - # for i in range(len(nums)): + # for i in range(len(nums)-1): # for j in range(i + 1, len(nums)): # if nums[i] + nums[j] == target: # return [i, j] diff --git a/Week01/3Sum.py b/Week01/3Sum.py index 20a44248b..be458e530 100644 --- a/Week01/3Sum.py +++ b/Week01/3Sum.py @@ -39,18 +39,18 @@ def threeSum(self, nums): # res.add((nums[i],nums[j],nums[m])) # return list([list(item) for item in res]) # 2.hash表+两重循环 击败5% - # hashmap = {} - # nums.sort() - # res = set() - # for ind, num in enumerate(nums): - # hashmap[num] = ind - # for i in range(len(nums)): - # for j in range(i + 1, len(nums)): - # target = 0 - nums[i] - nums[j] - # if hashmap.get(target) is not None and hashmap[target] > j: - # # Only need to check if the target value on the right side of (j) - # res.add((nums[i], nums[j], target)) - # return list(res) + hashmap = {} + nums.sort() + res = set() + for ind, num in enumerate(nums): + hashmap[num] = ind + for i in range(len(nums)): + for j in range(i + 1, len(nums)): + target = 0 - nums[i] - nums[j] + if hashmap.get(target) is not None and hashmap[target] > j: + # Only need to check if the target value on the right side of (j) + res.add((nums[i], nums[j], target)) + return list(res) # 外层循环+双指针 击败7% # nums.sort() diff --git a/Week01/NOTE.md b/Week01/NOTE.md index 74aac9022..7ed5a5f15 100644 --- a/Week01/NOTE.md +++ b/Week01/NOTE.md @@ -1,2 +1,254 @@ 学习笔记 +#### 两数之和 +1. 暴力解法 两次遍历枚举出所有可能的数的配对 时间复杂度是O(N^2) + 两重循环的标准写法: + +``` +for i in range(len(nums)-1):#给第二个指针预留一个位置 +for j in range(i + 1, len(nums)):#这里从第一个指针的下一个位置开始 + if nums[i] + nums[j] == target: + return [i, j] +``` + +2. 两次hash表 第一次遍历数组,将所有元素的对应解`target-nums[i]`作为`key`存入hash表中 + 下一次遍历此数组时,查询hash表中的内容 + +``` +dict = {} +for ind, num in enumerate(nums): # 创建hash表 + dict[num] = ind +for ind, num in enumerate(nums): # 遍历hash表 + j = dict.get(target - num) + if j and ind != j: # 排除[2,3] 4这种情况 + return [ind, j] +``` +3. 一次hash表 上面的两次hash表中,会存表示同样一组解的情形,比如`{'2':4}`和`{'4':2}`,所以可以在一次遍历时,先判断是否在hash表中,不在则加入;在即返回对应结果 +``` +dict = {} +for ind, num in enumerate(nums): + if dict.get(target - num) is not None: + return [dict.get(target - num), ind] + dict[num] = ind + ``` + +-- +#### 三数之和 +1.同样可以采用暴力解法,三重循环枚举出所有可能的三元组,时间复杂度是O(N^3) + 三重循环的标准写法: + +``` +nums.sort() +res = set() +for i in range(len(nums)-2): + for j in range(i+1,len(nums)-1): + for m in range(j+1,len(nums)): + if nums[i] + nums[j] + nums[m] == 0: + res.add((nums[i],nums[j],nums[m])) +return list([list(item) for item in res]) +``` + +2. 排序+set去重+两次循环+二重循环+hash表 + 第一次遍历时,构建hash表 `{'nums[i]':ind}` + 第二次循环,枚举可能的二元组,同时查询hash表检测是否存在 + +``` +hashmap = {} +nums.sort() +res = set() +for ind, num in enumerate(nums): + hashmap[num] = ind +for i in range(len(nums)): + for j in range(i + 1, len(nums)): + target = 0 - nums[i] - nums[j] + if hashmap.get(target) is not None and hashmap[target] > j: + # Only need to check if the target value on the right side of (j) + res.add((nums[i], nums[j], target)) +return list(res) +``` +3. 排序+set去重+双指针+过滤解+排序数组首元素过滤正数优化 + +``` +nums.sort() +res = [] +for i in range(len(nums)-2): + if nums[i]>0:#plus this line ,you can beat 93% + break + if i > 0 and nums[i] == nums[i - 1]: + continue + left, right = i + 1, len(nums) - 1 + while (left < right): + tmp = nums[i] + nums[left] + nums[right] + if tmp < 0: + left = left + 1 + elif tmp > 0: + right = right - 1 + else: + res.append((nums[i], nums[left], nums[right])) + while (left < right) and nums[left] == nums[left + 1]: + left = left + 1 + while (left < right) and nums[right] == nums[right - 1]: + right = right - 1 + left = left + 1 #put the two lines, you can + right = right - 1 +return res +``` +-- + +#### 移动0 +1.暴力解法 遇到则将0移动到数组末尾 + 每次遇到0,先加入到末尾,再删除这个0以调整数组,时间复杂度O(N^2) + +``` +for num in nums: +if num == 0: + nums.append(0) + nums.remove(0) +``` +2.统计0的个数 同时删除这个0 如果不为0 则将它放到前面那个0的位置 + 最后返回数组时,将count个0放到数组的末尾len-count开始的count个位置 + +``` +count = 0 +for i in range(len(nums)): + if nums[i]==0: + count = count + 1 + else:#[0,1,0,3,12] + nums[i-count] = nums[i] +for i in range(len(nums)-count,len(nums)): + nums[i] = 0 +``` + +3.用指针记录当前0的个数 遇上不为0的数,则将它与前面记录的0的位置的元素进行交换 + +``` +index_0 = 0 +for i in range(len(nums)): + if nums[i] != 0: + nums[index_0], nums[i] = nums[i], nums[index_0] + index_0 = index_0 + 1 +return nums +``` + +-- + +#### 爬楼梯 +1.蠢递归 + +``` +if n == 1: return 1 +if n == 2: return 2 +return self.climbStairs(n - 1) + self.climbStairs(n - 2) +``` +2.递归+数组备忘录 + +``` +if n == 1: return 1 +tmp = [0 for _ in range(n)] # 开辟额外数组空间 +tmp[0], tmp[1] = 1, 2 +for i in range(2, n): + tmp[i] = tmp[i - 1] + tmp[i - 2] +return tmp[-1] +``` +3.递归+变量缓存 + +``` +if n == 1: return 1 +a, b = 1, 2 +for i in range(2, n): + a, b = b, a + b +return b +``` +-- +#### 容器的最大面积 +1.暴力枚举所有可能的面积 时间复杂度O(N^2) + +``` +max_area = 0 + for i in range(len(height)): + for j in range(i, len(height)): + area = (j - i) * min(height[j], height[i]) + if max_area < area: max_area = area + return max_area +``` + +2.双指针 + +``` +left,right,area = 0,len(height)-1,0 +while left ListNode: + fast = slow = finder = head + while fast and fast.next: + fast, slow = fast.next.next, slow.next + if fast == slow: + while slow != finder: + slow, finder = slow.next, finder.next + return slow + return None +``` +2. hash表 + +``` +hashtable = {} +while head: + # if not in the hashtable + if not hashtable.get(head): + hashtable[head] = head + # must move back the head pointer, so it can continue while loop + head = head.next + else: + # if the node in hashtable, it must be the loop header + return head +# if walk here head==None, so we just return None +return None +``` + + + + diff --git a/Week01/move0.py b/Week01/move0.py index 0b42d21fd..1e8b2d65f 100644 --- a/Week01/move0.py +++ b/Week01/move0.py @@ -54,7 +54,7 @@ def moveZeroes(self, nums): index_0 = 0 for i in range(len(nums)): if nums[i] != 0: - nums[index_0],nums[i] = nums[i],nums[index_0] + nums[index_0], nums[i] = nums[i], nums[index_0] index_0 = index_0 + 1 return nums From 2526e4a0033069550d8434f09c8d4b97593068bf Mon Sep 17 00:00:00 2001 From: mqray Date: Sun, 14 Jun 2020 22:14:48 +0800 Subject: [PATCH 021/105] =?UTF-8?q?note=E6=A0=BC=E5=BC=8F=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.DS_Store | Bin 6148 -> 6148 bytes Week01/.idea/workspace.xml | 8 +------- Week01/NOTE.md | 20 ++++++++++++++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Week01/.DS_Store b/Week01/.DS_Store index ed6956f82a385ddfb294271a09cf59406fcee1dc..6aa8cb46990868750376abf07b844689c47a4a78 100644 GIT binary patch delta 58 zcmZoMXffDe%gD?!_5WlCMgxw%Stsslc^`5Fa?~czW8`853rt?iXu`yDVe>~uF}8^f Le4E)h{_+C=ds`K5 delta 58 zcmZoMXffDe%gD^|Ds!>}qXEYRxw|2<-iI849JR^w7`a%%0+ZJ=nlLdcZ2rh7#x}8m KZ! - - - - - - - + @@ -207,6 +238,11 @@ + + + + + @@ -274,8 +268,8 @@ - - + + - + - + - + - + + - @@ -419,13 +413,13 @@ - + - - + + @@ -611,6 +605,21 @@ 37 @@ -923,6 +932,20 @@ + + + + + + + + + + + + + + diff --git a/Week01/NOTE.md b/Week01/NOTE.md index 3756a1755..5a83d4de6 100644 --- a/Week01/NOTE.md +++ b/Week01/NOTE.md @@ -351,6 +351,19 @@ return nums1 -- +#### 删除排序数组中的重复数 +1.双指针 用指针记录不同元素的个数 思路比较天马行空 但是有迹可循 就是 用一个指针记录当前不同元素的个数,每次不相同时,就将这个指针更新,并且将num[i+1]赋值给指针指向的地址 +``` +point = 0 # 指向前一个重复的数值 +for i in range(len(nums) - 1): + if nums[i] == nums[i + 1]: + continue + else: + point = point + 1 + nums[point] = nums[i+1] +return point+1 +``` + diff --git a/Week01/removeDuplicates.py b/Week01/removeDuplicates.py new file mode 100644 index 000000000..32144a47f --- /dev/null +++ b/Week01/removeDuplicates.py @@ -0,0 +1,73 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/15 5:13 PM + +# 给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 +# +# 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 +# +# +# +# 示例 1: +# +# 给定数组 nums = [1,1,2], +# +# 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 +# +# 你不需要考虑数组中超出新长度后面的元素。 +# +# 示例 2: +# +# 给定 nums = [0,0,1,1,1,2,2,3,3,4], +# +# 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 +# +# 你不需要考虑数组中超出新长度后面的元素。 +# +# +# +# +# 说明: +# +# 为什么返回数值是整数,但输出的答案是数组呢? +# +# 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 +# +# 你可以想象内部操作如下: +# +# // nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 +# int len = removeDuplicates(nums); +# +# // 在函数里修改输入数组对于调用者是可见的。 +# // 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。 +# for (int i = 0; i < len; i++) { +#     print(nums[i]); +# } +# +# Related Topics 数组 双指针 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def removeDuplicates(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + point = 0# 指向前一个重复的数值 + for i in range(len(nums) - 1): + # if nums[i] == nums[i + 1]: + # continue + # else: + # point = point + 1 + # nums[point] = nums[i+1] + if nums[i]!=nums[i+1]: #击败99.7% + point = point+1 + nums[point] = nums[i+1] + # return nums[:point+1] + return point + 1#需要的返回值是不相同的元素个数 +# leetcode submit region end(Prohibit modification and deletion) + +s = Solution() +res = s.removeDuplicates([0,0,1,1,1,2,2,3,3,4]) +print(res) \ No newline at end of file From d69846516e8b7ea159ea0a6061d2fb47970bf415 Mon Sep 17 00:00:00 2001 From: mqray Date: Mon, 15 Jun 2020 17:39:25 +0800 Subject: [PATCH 025/105] =?UTF-8?q?=E5=90=88=E5=B9=B6=E4=B8=A4=E4=B8=AA?= =?UTF-8?q?=E6=9C=89=E5=BA=8F=E9=93=BE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/leetcode/editor.xml | 8 ++++ Week01/.idea/workspace.xml | 64 +++++++++++++++++++------------- Week01/NOTE.md | 28 +++++++++++++- Week01/mergeTwoList.py | 49 ++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 26 deletions(-) create mode 100644 Week01/mergeTwoList.py diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml index be7e591a9..61e0c6f7f 100644 --- a/Week01/.idea/leetcode/editor.xml +++ b/Week01/.idea/leetcode/editor.xml @@ -163,6 +163,14 @@ + + + + + + diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index b7e14fc5a..2028bcf94 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,10 +2,9 @@ - + - - - - - - - - - - @@ -91,15 +81,6 @@ - - - - - - - - - @@ -136,7 +117,7 @@ - + @@ -145,6 +126,24 @@ + + + + + + + + + + + + + + + + + + @@ -210,6 +209,7 @@ @@ -413,12 +413,12 @@ - + - + @@ -946,6 +946,20 @@ + + + + + + + + + + + + + + diff --git a/Week01/NOTE.md b/Week01/NOTE.md index 5a83d4de6..6f86c0020 100644 --- a/Week01/NOTE.md +++ b/Week01/NOTE.md @@ -307,7 +307,7 @@ for i in range(k%len(nums)): # 旋转k次 -- -#### 合并两个有效数组 +#### 合并两个有序数组 1.暴力解法 将两个数组合并后重新排序 ``` @@ -351,6 +351,32 @@ return nums1 -- +#### 合并两个有序链表 + +``` +def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: + if not l1:#如果l1为空,直接返回l2 + return l2 + if not l2:#如果l2为空,直接返回l1 + return l1 + rhead = ListNode(None)#用来返回最后的结果的节点 + pre = rhead #用来添加比较过的节点 + while l1 and l2:#循环直到某链表没有值结束,刚开始这里写的是l1.next and l2.next 返回的结果是[1,1,2,4] + if l1.val <= l2.val: + tmp,l1 = l1,l1.next# + pre.next = tmp + pre = tmp + else: + tmp,l2 = l2,l2.next + pre.next = tmp + pre = tmp + if not l1: + pre.next = l2 + if not l2: + pre.next = l1 + return rhead.next +``` + #### 删除排序数组中的重复数 1.双指针 用指针记录不同元素的个数 思路比较天马行空 但是有迹可循 就是 用一个指针记录当前不同元素的个数,每次不相同时,就将这个指针更新,并且将num[i+1]赋值给指针指向的地址 ``` diff --git a/Week01/mergeTwoList.py b/Week01/mergeTwoList.py new file mode 100644 index 000000000..41bb99e5f --- /dev/null +++ b/Week01/mergeTwoList.py @@ -0,0 +1,49 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/15 5:37 PM + +# 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。 +# +# 示例1: +# +# 输入:1->2->4, 1->3->4 +# 输出:1->1->2->3->4->4 +# +# 限制: +# +# 0 <= 链表长度 <= 1000 +# +# 注意:本题与主站 21 题相同:https://leetcode-cn.com/problems/merge-two-sorted-lists/ +# Related Topics 分治算法 + + +# leetcode submit region begin(Prohibit modification and deletion) +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + +class Solution(object): + def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: + if not l1: # 如果l1为空,直接返回l2 + return l2 + if not l2: # 如果l2为空,直接返回l1 + return l1 + rhead = ListNode(None) # 用来返回最后的结果的节点 + pre = rhead # 用来添加比较过的节点 + while l1 and l2: # 循环直到某链表没有值结束,刚开始这里写的是l1.next and l2.next 返回的结果是[1,1,2,4] + if l1.val <= l2.val: + tmp, l1 = l1, l1.next # + pre.next = tmp + pre = tmp + else: + tmp, l2 = l2, l2.next + pre.next = tmp + pre = tmp + if not l1: + pre.next = l2 + if not l2: + pre.next = l1 + return rhead.next +# leetcode submit region end(Prohibit modification and deletion) From 8a6e889dcbe2269e17b3d4b2dfa6240ea5975223 Mon Sep 17 00:00:00 2001 From: mqray Date: Mon, 15 Jun 2020 19:33:08 +0800 Subject: [PATCH 026/105] =?UTF-8?q?=E6=9C=80=E9=95=BF=E5=85=AC=E5=85=B1?= =?UTF-8?q?=E5=89=8D=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/leetcode/editor.xml | 8 ++ Week01/.idea/workspace.xml | 134 ++++++++++-------- Week01/NOTE.md | 22 +++ ...54\345\205\261\345\211\215\347\274\200.py" | 54 +++++++ 4 files changed, 158 insertions(+), 60 deletions(-) create mode 100644 "Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_15_\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py" diff --git a/Week01/.idea/leetcode/editor.xml b/Week01/.idea/leetcode/editor.xml index 61e0c6f7f..274582e1b 100644 --- a/Week01/.idea/leetcode/editor.xml +++ b/Week01/.idea/leetcode/editor.xml @@ -27,6 +27,14 @@ + + + + + + diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 2028bcf94..23a03b18a 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,9 +2,10 @@ - + + + + - + - @@ -42,27 +44,27 @@ - + - + - - + + - - + + @@ -72,24 +74,6 @@ - - - - - - - - - - - - - - - - - - @@ -135,7 +119,7 @@ - + @@ -144,6 +128,24 @@ + + + + + + + + + + + + + + + + + + @@ -210,6 +212,8 @@ @@ -268,8 +272,8 @@ - - + + - + + - @@ -413,12 +417,12 @@ - + - + @@ -432,34 +436,10 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - @@ -960,6 +960,20 @@ + + + + + + + + + + + + + + diff --git a/Week01/NOTE.md b/Week01/NOTE.md index 6f86c0020..af51a578c 100644 --- a/Week01/NOTE.md +++ b/Week01/NOTE.md @@ -379,6 +379,7 @@ def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: #### 删除排序数组中的重复数 1.双指针 用指针记录不同元素的个数 思路比较天马行空 但是有迹可循 就是 用一个指针记录当前不同元素的个数,每次不相同时,就将这个指针更新,并且将num[i+1]赋值给指针指向的地址 + ``` point = 0 # 指向前一个重复的数值 for i in range(len(nums) - 1): @@ -390,6 +391,27 @@ for i in range(len(nums) - 1): return point+1 ``` +#### 最长公共前缀 +1. 先确定列表中最短字符串的长度size LCP应该小于等于它 然后外层循环遍历size长度,内层循环取每个字符的前size位,如果所有的都相匹配,则返回 + +``` +if not strs: return '' +min_size = min([len(x) for x in strs]) # 公共前缀最长只会这么长 +for i in range(min_size, 0, -1): + tmp = strs[0][:i] # 当前待比较的公共前缀子串 + if all(s[:i] == tmp for s in strs): + return tmp +return '' +``` +改进版 +``` +prefix = strs[0] if strs else '' +while True: + if all(s.startswith(prefix) for s in strs): + return prefix + prefix = prefix[:-1] +``` + diff --git "a/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_15_\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py" "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_15_\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py" new file mode 100644 index 000000000..66ef8433b --- /dev/null +++ "b/Week01/\346\257\217\346\227\245\344\270\200\351\242\2306_15_\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.py" @@ -0,0 +1,54 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/15 5:40 PM + +# 编写一个函数来查找字符串数组中的最长公共前缀。 +# +# 如果不存在公共前缀,返回空字符串 ""。 +# +# 示例 1: +# +# 输入: ["flower","flow","flight"] +# 输出: "fl" +# +# +# 示例 2: +# +# 输入: ["dog","racecar","car"] +# 输出: "" +# 解释: 输入不存在公共前缀。 +# +# +# 说明: +# +# 所有输入只包含小写字母 a-z 。 +# Related Topics 字符串 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def longestCommonPrefix(self, strs): + """ + :type strs: List[str] + :rtype: str + """ + #击败59% + # if not strs: return '' + # min_size = min([len(x) for x in strs]) # 公共前缀最长只会这么长 + # for i in range(min_size, 0, -1): + # tmp = strs[0][:i] # 当前待比较的公共前缀子串 + # if all(s[:i] == tmp for s in strs): + # return tmp + # return '' + #击败78% + prefix = strs[0] if strs else '' + while True: + if all(s.startswith(prefix) for s in strs): + return prefix + prefix = prefix[:-1] + +# leetcode submit region end(Prohibit modification and deletion) + +s = Solution() +res = s.longestCommonPrefix(["dog","racecar","car"]) +print(res) From 67ff388a1e0192fd51752cada64fef936de8928f Mon Sep 17 00:00:00 2001 From: mqray Date: Mon, 15 Jun 2020 20:39:54 +0800 Subject: [PATCH 027/105] =?UTF-8?q?=E6=9C=89=E6=95=88=E7=9A=84=E5=AD=97?= =?UTF-8?q?=E6=AF=8D=E5=BC=82=E4=BD=8D=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/.idea/Week02.iml | 12 ++ Week02/.idea/leetcode/editor.xml | 17 +++ Week02/.idea/misc.xml | 7 + Week02/.idea/modules.xml | 8 + Week02/.idea/vcs.xml | 6 + Week02/.idea/workspace.xml | 241 +++++++++++++++++++++++++++++++ Week02/NOTE.md | 60 +++++++- Week02/isAnagram.py | 84 +++++++++++ 8 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 Week02/.idea/Week02.iml create mode 100644 Week02/.idea/leetcode/editor.xml create mode 100644 Week02/.idea/misc.xml create mode 100644 Week02/.idea/modules.xml create mode 100644 Week02/.idea/vcs.xml create mode 100644 Week02/.idea/workspace.xml create mode 100644 Week02/isAnagram.py diff --git a/Week02/.idea/Week02.iml b/Week02/.idea/Week02.iml new file mode 100644 index 000000000..7c9d48f0f --- /dev/null +++ b/Week02/.idea/Week02.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Week02/.idea/leetcode/editor.xml b/Week02/.idea/leetcode/editor.xml new file mode 100644 index 000000000..982d0cf3c --- /dev/null +++ b/Week02/.idea/leetcode/editor.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/Week02/.idea/misc.xml b/Week02/.idea/misc.xml new file mode 100644 index 000000000..399908725 --- /dev/null +++ b/Week02/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Week02/.idea/modules.xml b/Week02/.idea/modules.xml new file mode 100644 index 000000000..feb2b8699 --- /dev/null +++ b/Week02/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Week02/.idea/vcs.xml b/Week02/.idea/vcs.xml new file mode 100644 index 000000000..6c0b86358 --- /dev/null +++ b/Week02/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Week02/.idea/workspace.xml b/Week02/.idea/workspace.xml new file mode 100644 index 000000000..2abc8e084 --- /dev/null +++ b/Week02/.idea/workspace.xml @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + @@ -279,15 +290,9 @@ - - + - - - - - - + @@ -295,12 +300,18 @@ - - - + + + + + + + + + @@ -355,30 +366,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -386,16 +375,6 @@ - - - - - - - - - - @@ -415,8 +394,8 @@ - - + + @@ -424,9 +403,16 @@ + + + + + + + - + @@ -434,20 +420,37 @@ + + + + + + + - - + + - + - + - - + + + + + + + + + + + + diff --git a/Week02/NOTE.md b/Week02/NOTE.md index 8a26acf3c..c9b7b85ee 100644 --- a/Week02/NOTE.md +++ b/Week02/NOTE.md @@ -201,4 +201,46 @@ class Solution(object): stack1.append(node.right) stack2.append(node.val) return stack2#这里是层序遍历就不用反转了 +``` + + +#### N叉树的层序遍历 +刚开始是这么写的,看起来算法逻辑没什么问题,但是这里我相当于是将cur当做一个list在做 +而实际上cur只是一个Node,哪怕它是root.children它也是个Node,所以没法将其进行迭代 +```angular2html +def levelOrder(self, root: 'Node') -> List[List[int]]: + if root is None: return [] + quene,res = [root],[] + while quene: + cur = stack1.pop() + if cur is not None: + print(type(cur))#cur is Node + tmp = [] + for item in cur: + tmp.append(item.val) + res.append(tmp) + for child in cur.children: + stack1.append(child) + return res +``` +改进之后,这里 实际上quene每次存储的都是每一层的所有节点, +每次都将quene所有元素记录到tmp中,将所有节点合并为list之后存入res +同时,在加入的过程中,用tmp_quene记录下一层的节点值, +在遍历完上层节点后,将下层节点赋给quene +```angular2html +def levelOrder(self,root): + #击败55% + if root is None: return [] + quene,res = [root],[] + while quene: + #将当前层的所有元素出队列,记录其值存入res中,由于输出格式的限制,要用tmp先存放 + #并且将其孩子全部记录在下一个quene中,这样保证了上层节点全部被加入到res中,而不会发生交替现象 + tmp, tmp_quene = [], []#这个tmp_quene是为了暂存下一层的所有节点 + for node in quene: + tmp.append(node.val) + for child in node.children: + tmp_quene.append(child) + res.append(tmp) + quene = tmp_quene + return res ``` \ No newline at end of file diff --git a/Week02/NlevelOrder.py b/Week02/NlevelOrder.py new file mode 100644 index 000000000..5edb59310 --- /dev/null +++ b/Week02/NlevelOrder.py @@ -0,0 +1,29 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/17 10:27 PM + +""" +# Definition for a Node. +class Node: + def __init__(self, val=None, children=None): + self.val = val + self.children = children +""" + +class Solution: + # def levelOrder(self, root: 'Node') -> List[List[int]]: + def levelOrder(self,root): + #击败55% + if root is None: return [] + quene,res = [root],[] + while quene: + #将当前层的所有元素出队列,记录其值存入res中,由于输出格式的限制,要用tmp先存放 + #并且将其孩子全部记录在下一个quene中,这样保证了上层节点全部被加入到res中,而不会发生交替现象 + tmp, tmp_quene = [], []#这个tmp_quene是为了暂存下一层的所有节点 + for node in quene: + tmp.append(node.val) + for child in node.children: + tmp_quene.append(child) + res.append(tmp) + quene = tmp_quene + return res \ No newline at end of file diff --git a/Week02/NpreorderTraversal.py b/Week02/NpreorderTraversal.py index 63952b6e2..924a129bd 100644 --- a/Week02/NpreorderTraversal.py +++ b/Week02/NpreorderTraversal.py @@ -55,10 +55,6 @@ def preorderTraversal(self, root): # for child in root.children: # self.Npreorder(child, res) - - - - #击败69% def traversal(self,root): if not root: return [] From 9fc7823d95389ff314ad2b3147f05d89d4620d1d Mon Sep 17 00:00:00 2001 From: mqray Date: Thu, 18 Jun 2020 22:45:04 +0800 Subject: [PATCH 034/105] =?UTF-8?q?=E6=95=B0=E7=BB=84=E4=B8=AD=E6=9C=80?= =?UTF-8?q?=E5=B0=8F=E7=9A=84k=E4=B8=AA=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/NOTE.md | 62 ++++++++++++++++++++++++++++++++++++--- Week02/getLeastNumbers.py | 57 +++++++++++++++++++++++++++++++++++ Week02/heap_sort.py | 3 ++ 3 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 Week02/getLeastNumbers.py create mode 100644 Week02/heap_sort.py diff --git a/Week02/NOTE.md b/Week02/NOTE.md index c9b7b85ee..afebef649 100644 --- a/Week02/NOTE.md +++ b/Week02/NOTE.md @@ -215,10 +215,11 @@ def levelOrder(self, root: 'Node') -> List[List[int]]: cur = stack1.pop() if cur is not None: print(type(cur))#cur is Node - tmp = [] - for item in cur: - tmp.append(item.val) - res.append(tmp) + #tmp = [] + #for item in cur: + # tmp.append(item.val) + #res.append(tmp) + res.append([item.val for item in cur]) for child in cur.children: stack1.append(child) return res @@ -243,4 +244,57 @@ def levelOrder(self,root): res.append(tmp) quene = tmp_quene return res +``` + + +-- +#### 数组中最小的k个数 +1.暴力解法 对数组进行排序,返回前k个 +```angular2html +arr.sort() +return arr[:k] +``` +2.小根堆 借助python内置的heapq实现 +```angular2html +if k == 0: + return [] +heap = [-x for x in arr[:k]] # 只用维护一个大小为k的小根堆 +heapq.heapify(heap) # 这k个元素一定满足三角顶最小的原则 +for i in range(k, len(arr)): + if -heap[0] > arr[i]: + heapq.heappop(heap) # 如果堆中的元素大于入堆元素,则将原堆顶元素出堆 + heapq.heappush(heap, -arr[i]) # 将这个元素放入小根堆中,heappop中调用了siftup调整了堆 +res = [-x for x in heap] +return res +``` +3.快排思想 +```angular2html +def partition(self, nums, left, right): + pivot = nums[left] + while left < right: + while left < right and pivot <= nums[right]: + right -= 1 + nums[left] = nums[right] + while left < right and nums[left] <= pivot: + left += 1 + nums[right] = nums[left] + nums[left] = pivot + return left + +def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: + # 快速排序法: + size = len(arr) + if size == 0 or k > size: return + if size == 1 or size == k: + return arr + left, right = 0, size - 1 + while left <= right: # 这里其实也相当于是二分法 + pivot = self.partition(arr, left, right) # left, right, split_ind 都是原始 index + if pivot == k: # 在 split_ind 左边有 k 个元素,全部不大于 pivot + break + elif pivot > k: + right = pivot - 1 # 不-1 会陷入死循环 + else: + left = pivot + 1 # 不 +1 会陷入死循环 + return arr[:k] ``` \ No newline at end of file diff --git a/Week02/getLeastNumbers.py b/Week02/getLeastNumbers.py new file mode 100644 index 000000000..6796dc785 --- /dev/null +++ b/Week02/getLeastNumbers.py @@ -0,0 +1,57 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/17 11:06 PM + +from typing import List +import heapq +# class Solution: +# def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: +# #暴力破解 击败64% +# arr.sort() +# return arr[:k] +# # +# # #击败59% +# if k == 0: +# return [] +# heap = [-x for x in arr[:k]] # 只用维护一个大小为k的小根堆 +# heapq.heapify(heap) # 这k个元素一定满足三角顶最小的原则 +# for i in range(k, len(arr)): +# if -heap[0] > arr[i]: +# heapq.heappop(heap) # 如果堆中的元素大于入堆元素,则将原堆顶元素出堆 +# heapq.heappush(heap, -arr[i]) # 将这个元素放入小根堆中,heappop中调用了siftup调整了堆 +# res = [-x for x in heap] +# return res + +class Solution: + def partition(self, nums, left, right): + pivot = nums[left] + while left < right: + while left < right and pivot <= nums[right]: + right -= 1 + nums[left] = nums[right] + while left < right and nums[left] <= pivot: + left += 1 + nums[right] = nums[left] + nums[left] = pivot + return left + + def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: + # 快速排序法: + size = len(arr) + if size == 0 or k > size: return + if size == 1 or size == k: + return arr + left, right = 0, size - 1 + while left <= right: # 这里其实也相当于是二分法 + pivot = self.partition(arr, left, right) # left, right, split_ind 都是原始 index + if pivot == k: # 在 split_ind 左边有 k 个元素,全部不大于 pivot + break + elif pivot > k: + right = pivot - 1 # 不-1 会陷入死循环 + else: + left = pivot + 1 # 不 +1 会陷入死循环 + return arr[:k] +s = Solution() +nums = [1, 4, 2, 5, 10, 3, -1] +res = s.getLeastNumbers(nums,2) +print(res) \ No newline at end of file diff --git a/Week02/heap_sort.py b/Week02/heap_sort.py new file mode 100644 index 000000000..bb1bbbe00 --- /dev/null +++ b/Week02/heap_sort.py @@ -0,0 +1,3 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/18 7:06 PM \ No newline at end of file From 87e282ab8784c2f3e6d05b533eab1cf3d6eabc17 Mon Sep 17 00:00:00 2001 From: mqray Date: Thu, 18 Jun 2020 23:59:47 +0800 Subject: [PATCH 035/105] =?UTF-8?q?=E5=A0=86=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/heap_sort.py | 90 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/Week02/heap_sort.py b/Week02/heap_sort.py index bb1bbbe00..3e6f84859 100644 --- a/Week02/heap_sort.py +++ b/Week02/heap_sort.py @@ -1,3 +1,87 @@ -# -*- coding:utf-8 -*- -# Author : Ray -# Data : 2020/6/18 7:06 PM \ No newline at end of file +# # -*- coding:utf-8 -*- +# # Author : Ray +# # Data : 2020/6/18 7:06 PM +# +# # !/usr/bin/env python +# # -*- coding: utf-8 -*- +# #  @Time    : 2019/12/2 18:25 +# #  @Author  : mqray +# #  @File    : 选择排序之堆排序# +# +class HeapSort(): + ''' + 时间复杂度为NlogN,logN为建立大根堆/小根堆的时间复杂度, + N为对已经构成的堆排序反向遍历的时间复杂度 + ''' + def heapify(self, nums, size, i):#heapify过程就是递归考量三角是否满足条件 + max_index = i + left, right = 2*i+1,2*i+2 + if left < size and nums[left] > nums[max_index]: + max_index = left + if right < size and nums[right] > nums[max_index]: + max_index = right + if max_index != i:#存在交换的情形 + nums[i], nums[max_index] = nums[max_index], nums[i] + self.heapify(nums, size, max_index) + + def heap_sort(self,nums): + size = len(nums) + for i in range(size//2-1,-1,-1): + self.heapify(nums,size,i) + + for i in range(size-1,0,-1):#排序需要对整个堆进行调整 + nums[i], nums[0] = nums[0], nums[i]#交换末尾元素与堆顶元素 + self.heapify(nums,i,0)#交换之后,要确定这个堆是否合乎条件,进行堆化, + #要注意到,每次堆化时,就已经把一个元素排好了,放在最末尾了,以后就不许要再考虑这个元素了 + + +# +# def heapify(self, nums, n, i): +# ''' +# 堆化操作,将数组转化为小根堆 +# :param nums: 完全二叉树对应的数组 +# :param n: 元素个数 +# :param i: 进行堆化的数组下标 +# ''' +# #取当前节点,将其与左右孩子中较大的元素进行调换 +# if i >= n: +# return +# c1, c2 = 2 * i + 1, 2 * i + 2 +# max = i # 暂存最大数对应index +# if c1 < n and nums[c1] > nums[max]: +# max = c1 +# if c2 < n and nums[c2] > nums[max]: +# max = c2 +# print(nums) +# if max != i: +# nums[i], nums[max] = nums[max], nums[i] +# self.heapify(nums, n, max) +# +# def build_heap(self, nums, n): +# last_node = n - 1 # 堆化过程只需要考虑最后一个节点的父节点及其之前的节点 +# parent = (last_node - 1) // 2 +# for i in range(parent, -1, -1): +# self.heapify(nums, n, i) +# +# def heap_sort(self, nums, n): +# self.build_heap(nums, len(nums)) +# print('build finished') +# for i in range(n-1, -1, -1): +# nums[i], nums[0] = nums[0], nums[i] # 交换堆顶与最后一个元素,将交换后得到的最大数砍断 +# self.heapify(nums, i, 0) # 后续操作一样,只不过后续的最大索引值变小了 +# +# +nums = [4, 10, 3, 5, 1, 2] +s = HeapSort() +s.heap_sort(nums) +print(nums) + + + + + + + + + + From 01f3e2e2e41de900d3716a1f90dfe4e51d43c322 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 20 Jun 2020 22:56:40 +0800 Subject: [PATCH 036/105] =?UTF-8?q?=E5=88=A4=E6=96=AD=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E4=B8=91=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/isUglyNumber.py | 22 +++++++++++++++++++ Week02/nthUglyNumber.py | 3 +++ Week02/topKFrequent.py | 3 +++ ...76\345\274\217\345\214\271\351\205\215.py" | 3 +++ 4 files changed, 31 insertions(+) create mode 100644 Week02/isUglyNumber.py create mode 100644 Week02/nthUglyNumber.py create mode 100644 Week02/topKFrequent.py create mode 100644 "Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_20_\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py" diff --git a/Week02/isUglyNumber.py b/Week02/isUglyNumber.py new file mode 100644 index 000000000..5196535f3 --- /dev/null +++ b/Week02/isUglyNumber.py @@ -0,0 +1,22 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/19 8:07 PM + +class Solution: + def isUgly(self, num: int) -> bool: + #如果一个数是丑数那肯定满足这种定义num = 2^i*3^j*5^k + # for item in [2,3,5]: + # while num%item==0:#依次除尽2,3,5 + # num = num/item + # # return True if num==1 else False #击败50% + # return num==1#击败87% + if num == 0: return False + while num % 5 == 0: num /= 5 + while num % 3 == 0: num /= 3 + while num % 2 == 0: num /= 2 + return num == 1#击败98%,省去了迭代的过程 + + +s = Solution() +res = s.isUgly(7) +print(res) \ No newline at end of file diff --git a/Week02/nthUglyNumber.py b/Week02/nthUglyNumber.py new file mode 100644 index 000000000..51086faf4 --- /dev/null +++ b/Week02/nthUglyNumber.py @@ -0,0 +1,3 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/19 12:33 AM \ No newline at end of file diff --git a/Week02/topKFrequent.py b/Week02/topKFrequent.py new file mode 100644 index 000000000..815d22d0f --- /dev/null +++ b/Week02/topKFrequent.py @@ -0,0 +1,3 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/19 8:41 PM \ No newline at end of file diff --git "a/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_20_\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py" "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_20_\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py" new file mode 100644 index 000000000..c739190a7 --- /dev/null +++ "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_20_\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py" @@ -0,0 +1,3 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/20 10:11 PM \ No newline at end of file From 4ad652e1a6da68771093585295d29a5ad7c9e8a0 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 20 Jun 2020 22:57:33 +0800 Subject: [PATCH 037/105] =?UTF-8?q?=E6=B1=82=E7=AC=ACn=E4=B8=AA=E4=B8=91?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/nthUglyNumber.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Week02/nthUglyNumber.py b/Week02/nthUglyNumber.py index 51086faf4..2890e1325 100644 --- a/Week02/nthUglyNumber.py +++ b/Week02/nthUglyNumber.py @@ -1,3 +1,17 @@ # -*- coding:utf-8 -*- # Author : Ray -# Data : 2020/6/19 12:33 AM \ No newline at end of file +# Data : 2020/6/19 12:33 AM + +class Solution: + def nthUglyNumber(self, n: int) -> int: + # 1、2、3、5、4、6、8、9、10 + if n==0: + return 0 + res = [1]*n + p2,p3,p5 = 0,0,0#指向三个队列的指针 + for i in range(1,n): + res[i] = min(res[p2]*2,res[p3]*3,res[p5]*5) + if res[i] == res[p2]*2: p2 = p2+1 + if res[i] == res[p3]*3: p3 = p3+1 + if res[i] == res[p5]*5: p5 = p5+1 + return res[-1] \ No newline at end of file From ce41d6a541ba78a3fcba7f17a424e0c4574320c7 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 20 Jun 2020 22:58:25 +0800 Subject: [PATCH 038/105] =?UTF-8?q?=E5=A0=86=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/heap_sort.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Week02/heap_sort.py b/Week02/heap_sort.py index 3e6f84859..5262551bc 100644 --- a/Week02/heap_sort.py +++ b/Week02/heap_sort.py @@ -11,6 +11,7 @@ class HeapSort(): ''' 时间复杂度为NlogN,logN为建立大根堆/小根堆的时间复杂度, + heapify的时间复杂度是O(logN)的因为,最坏情况下,每一层都需要判断 N为对已经构成的堆排序反向遍历的时间复杂度 ''' def heapify(self, nums, size, i):#heapify过程就是递归考量三角是否满足条件 From 07c963a58a944b2bbc5b90fefe380ca39369b28c Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 20 Jun 2020 22:59:10 +0800 Subject: [PATCH 039/105] =?UTF-8?q?=E5=87=BA=E7=8E=B0=E9=A2=91=E7=8E=87?= =?UTF-8?q?=E6=9C=80=E9=AB=98=E7=9A=84k=E4=B8=AA=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/topKFrequent.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Week02/topKFrequent.py b/Week02/topKFrequent.py index 815d22d0f..d64aa60e2 100644 --- a/Week02/topKFrequent.py +++ b/Week02/topKFrequent.py @@ -1,3 +1,20 @@ # -*- coding:utf-8 -*- # Author : Ray -# Data : 2020/6/19 8:41 PM \ No newline at end of file +# Data : 2020/6/19 8:41 PM +from typing import List +class Solution: + # : List[int], k: int + def topKFrequent(self, nums) -> List[int]: + dic = {} + for num in nums: + if not dic.get(num): + dic[num] = 1 + else: + dic[num] += 1 + res = sorted(dic.items(),key=lambda item:item[1]) + return res + +nums = [1,1,1,2,2,3] +s = Solution() +res = s.topKFrequent(nums) +print(res) \ No newline at end of file From b711752b75f183ff45cff239437606c6c87d63e8 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 20 Jun 2020 23:06:30 +0800 Subject: [PATCH 040/105] =?UTF-8?q?=E9=AA=8C=E8=AF=81=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=9B=9E=E6=96=87=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/isPalindrome.py | 42 +++++++++++++++++++ ...7\347\232\204k\344\270\252\346\225\260.py" | 0 ...57\345\220\246\344\270\221\346\225\260.py" | 0 3 files changed, 42 insertions(+) create mode 100644 Week02/isPalindrome.py rename Week02/getLeastNumbers.py => "Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_18_\346\234\200\345\260\217\347\232\204k\344\270\252\346\225\260.py" (100%) rename Week02/isUglyNumber.py => "Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\345\210\244\346\226\255\346\230\257\345\220\246\344\270\221\346\225\260.py" (100%) diff --git a/Week02/isPalindrome.py b/Week02/isPalindrome.py new file mode 100644 index 000000000..e54994c89 --- /dev/null +++ b/Week02/isPalindrome.py @@ -0,0 +1,42 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/20 11:03 PM + +# 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。 +# +# 说明:本题中,我们将空字符串定义为有效的回文串。 +# +# 示例 1: +# +# 输入: "A man, a plan, a canal: Panama" +# 输出: true +# +# +# 示例 2: +# +# 输入: "race a car" +# 输出: false +# +# Related Topics 双指针 字符串 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def isPalindrome(self, s): + """ + :type s: str + :rtype: bool + """ + #1. 翻转字符串 看是否相同 击败81% + # tmp = "".join(ch.lower() for ch in s if ch.isalnum()) + # return tmp == tmp[::-1] + #2.双指针 击败61% + tmp = "".join(ch.lower() for ch in s if ch.isalnum()) + n = len(tmp) + left, right = 0, n - 1 + while left < right: + if tmp[left] != tmp[right]: + return False + left, right = left + 1, right - 1 + return True +# leetcode submit region end(Prohibit modification and deletion) diff --git a/Week02/getLeastNumbers.py "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_18_\346\234\200\345\260\217\347\232\204k\344\270\252\346\225\260.py" similarity index 100% rename from Week02/getLeastNumbers.py rename to "Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_18_\346\234\200\345\260\217\347\232\204k\344\270\252\346\225\260.py" diff --git a/Week02/isUglyNumber.py "b/Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\345\210\244\346\226\255\346\230\257\345\220\246\344\270\221\346\225\260.py" similarity index 100% rename from Week02/isUglyNumber.py rename to "Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\345\210\244\346\226\255\346\230\257\345\220\246\344\270\221\346\225\260.py" From bff8407ebb50945ebd61a591365cf79e28639d67 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 20 Jun 2020 23:08:58 +0800 Subject: [PATCH 041/105] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/.idea/leetcode/editor.xml | 24 ++ Week02/.idea/workspace.xml | 374 ++++++++++++++---- ...46\345\233\236\346\226\207\344\270\262.py" | 0 ...76\345\274\217\345\214\271\351\205\215.py" | 97 ++++- 4 files changed, 419 insertions(+), 76 deletions(-) rename Week02/isPalindrome.py => "Week02/\346\257\217\346\227\245\344\270\200\351\242\2306_19_\351\252\214\350\257\201\346\230\257\345\220\246\345\233\236\346\226\207\344\270\262.py" (100%) diff --git a/Week02/.idea/leetcode/editor.xml b/Week02/.idea/leetcode/editor.xml index b3dec8b86..0d23ff760 100644 --- a/Week02/.idea/leetcode/editor.xml +++ b/Week02/.idea/leetcode/editor.xml @@ -3,6 +3,22 @@ diff --git a/Week02/.idea/workspace.xml b/Week02/.idea/workspace.xml index fd125f3b5..e4949e516 100644 --- a/Week02/.idea/workspace.xml +++ b/Week02/.idea/workspace.xml @@ -2,11 +2,11 @@ - + - - + + + + + + - + - + + - - + + - - + + - - - - + + + + - - - + + + + - + - - + + @@ -72,69 +78,97 @@ - + + + + + + + + + + - - + + + + + + + + + + + - - + + - + - - + + - + - - + + + + + + - + - - + + - + - - - - - + + - + - - + + - + + + + + + + + + + @@ -164,6 +198,13 @@ @@ -184,6 +225,7 @@ + @@ -195,7 +237,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1592831728412 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Week03/NOTE.md b/Week03/NOTE.md index 50de30414..14f758171 100644 --- a/Week03/NOTE.md +++ b/Week03/NOTE.md @@ -1 +1,161 @@ -学习笔记 \ No newline at end of file +学习笔记 + +#### 括号生成 +1.因为括号类别已经确定,可以想象为左右括号最多N个 +左括号出现次数小于N即可,右括号小于左括号个数 +```angular2html +def generateParenthesis(self,n): + result = [] + self._generate_parenthesis(0, 0, n, '',result) + return result + +def _generate_parenthesis(self, left, right, n, res, result): + # recursive terminator + if left == n and right == n: + result.append(res) + return + # current process + if left < n: self._generate_parenthesis(left + 1, right, n, res + '(', result) + if left > right: self._generate_parenthesis(left, right + 1, n, res + ')', result) + + # drill down + + # reverse state +``` +上面这种解法,由于最后要返回res,所以在递归时传入的参数较多,可以简化一下 +```angular2html +def generateParenthesis(self,n): + result = [] + def _generate_parenthesis( left, right, n, res): + # recursive terminator + if left == n and right == n: + result.append(res) + return + # current process + if left < n: _generate_parenthesis(left + 1, right, n, res + '(') + if left > right: _generate_parenthesis(left, right + 1, n, res + ')') + _generate_parenthesis(0, 0, n, '') + return result +``` + +#### 翻转二叉树 +1.递归 +我刚开始的想法是,考虑左右孩子节点,这个连接指向修改了就好了 +然后写的代码如下 +```angular2html +def invertTree(self, root: TreeNode) -> TreeNode: + #recursive terminator + if root is None: return + #current process + if root.right: + root.left = self.invertTree(root.right) + if root.left: + root.right = self.invertTree(root.left) + #drill down + #reverse states + return root +``` +上述代码的问题在于,if root.right:执行过后,左孩子已经修改了;在想要执行if root.left:时已经是同一个指向了 +所以需要修改 +```angular2html +def invertTree(self, root: TreeNode) -> TreeNode: + # recursive terminator + #击败70% + if root is None: return + # current process + left = self.invertTree(root.right) + right = self.invertTree(root.left) + root.left = left + root.right = right + # drill down + # reverse states + return root + +``` +2.迭代 类似层序遍历,将每一层访问到的节点存到quene中 +如果quene不为空,取出队尾元素 对于当前节点,交换左右孩子后,将其添加到quene中,继续进行判断 +```angular2html +def invertTree(self, root: TreeNode) -> TreeNode: + if root is None: return None + quene = [root] + while quene: + cur = quene.pop() + cur.left, cur.right = cur.right, cur.left + if cur.left is not None: quene.append(cur.left) + if cur.right is not None: quene.append(cur.right) + return root +``` + +#### 验证是否搜索二叉树 +1.递归,判断左子树是否小于根,右子树是否大于根 +```angular2html +if root is None: return True +#确定左子树是否符合排序二叉树,如果不满足,就返回False +if not self.isValidBST(root.left): return False +if root.val <= self.pre_val: return False#不满足左子树小于根节点 +self.pre_val = root.val#记录上一个访问的节点的值 +#访问右子树 # drill down +return self.isValidBST(root.right) +``` +2.迭代 由于二叉搜索树的特性 中序遍历比较方便 这里就借用二叉树的中序遍历的非递归实现完成 +```angular2html +stack, pre_val = [], float('-inf') +cur = root +while stack or cur is not None: + while cur is not None:#一直往下找,到左叶节点 + stack.append(cur) + cur = cur.left + cur = stack.pop() + if cur.val <= pre_val: return False#判断左节点值与根节点的大小关系 + pre_val = cur.val#修改当前的根节点大小 + cur = cur.right +return True +``` + +#### 二叉树的最大深度 +1.递归代码 这个代码我真的印象超级深 +```angular2html +if root is None: return 0 +return max(self.maxDepth(root.left),self.maxDepth(root.right))+1 +``` +2.迭代 借助DFS思想,借助栈,每次入栈时 记录当前节点的深度 +将遍历左右孩子时,将节点和当前深度+1压入栈中 +```angular2html +if root is None: return 0 +stack = [(1, root)]#栈中记录当前节点和此时的高度 +depth = 0 +while stack != []: + current_depth, root = stack.pop()#这里pop(0)和pop()都可以 + if root is not None: + depth = max(depth, current_depth)#记录当前节点的高度 + stack.append((current_depth + 1, root.left))#当前深度+1 + stack.append((current_depth + 1, root.right)) +return depth +``` + +#### 二叉树的最小深度 +1.递归 递归时需要弄清楚递归的结束条件 +```angular2html +def minDepth(self, root: TreeNode) -> int: + #1.根节点为空 return 0 + #2. 左右节点为空 return 1 + #3.左节点或右节点为空 return 左/右+1 + #4.左右节点都不为空 return min(left,right)+1 + if root is None: return 0 + if root.left is None and root.right is None: return 1 + left_height, right_height = self.minDepth(root.left),self.minDepth(root.right) + if root.left is None or root.right is None: return left_height+right_height+1#有一个为0 + #其余情况 返回较小值+1 + return min(left_height,right_height)+1 +``` +2.借助层序遍历 不需要遍历所有节点 只需要遍历到第一个叶子节点就能返回 +```angular2html +if not root: return 0 +quene = [(1, root)] +while quene: + #[3,9,20,null,null,15,7] + depth, root = quene.pop(0) # 保证从左往右看,如果是pop(0),那么可能往右看的过程中返回了,而丢失了应有的最小值 + if not root.left and not root.right: return depth # 如果此节点左右为空 返回当前depth + if root.left: quene.append((depth + 1, root.left)) + if root.right: quene.append((depth + 1, root.right)) +``` diff --git a/Week03/recursive_general_mode.py b/Week03/recursive_general_mode.py deleted file mode 100644 index a142f9f93..000000000 --- a/Week03/recursive_general_mode.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding:utf-8 -*- -# Author : Ray -# Data : 2020/6/22 9:16 PM \ No newline at end of file diff --git "a/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py" "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py" new file mode 100644 index 000000000..492d38aad --- /dev/null +++ "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py" @@ -0,0 +1,28 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/23 7:58 PM + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution: + def maxDepth(self, root: TreeNode) -> int: + #1.递归 击败50% + # if root is None: return 0 + # return max(self.maxDepth(root.left),self.maxDepth(root.right))+1 + #2.迭代 击败77% BFS + if root is None: return 0 + stack = [(1, root)]#栈中记录当前节点和此时的高度 + depth = 0 + while stack: + current_depth, root = stack.pop() + if root is not None: + depth = max(depth, current_depth)#记录当前节点的高度 + stack.append((current_depth + 1, root.left)) + stack.append((current_depth + 1, root.right)) + return depth + diff --git "a/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py" "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py" new file mode 100644 index 000000000..0e7497cc4 --- /dev/null +++ "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py" @@ -0,0 +1,38 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/23 8:52 PM + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution: + def minDepth(self, root: TreeNode) -> int: + #击败21% + #recursive terminator + #1.根节点为空 return 0 + #2. 左右节点为空 return 1 + #3.左节点或右节点为空 return 左/右+1 + #4.左右节点都不为空 return min(left,right)+1 + # if root is None: return 0 + # if root.left is None and root.right is None: return 1 + # left_height, right_height = self.minDepth(root.left),self.minDepth(root.right) + # if root.left is None or root.right is None: return left_height+right_height+1#有一个为0 + # #其余情况 返回较小值+1 + # return min(left_height,right_height)+1 + + # 2.深度优先搜索 + + # 3.广度优先搜索 + #借助双端队列 击败86% + if not root: return 0 + quene = [(1, root)] + while quene: + #[3,9,20,null,null,15,7] + depth, root = quene.pop(0) # 保证从左往右看,如果是pop(0),那么可能往右看的过程中返回了,而丢失了应有的最小值 + if not root.left and not root.right: return depth # 如果此节点左右为空 返回当前depth + if root.left: quene.append((depth + 1, root.left)) + if root.right: quene.append((depth + 1, root.right)) \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" index 6afaef984..c2fd2ba42 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" @@ -1,3 +1,75 @@ # -*- coding:utf-8 -*- # Author : Ray -# Data : 2020/6/22 9:30 PM \ No newline at end of file +# Data : 2020/6/22 9:30 PM +# 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 +# +# +# +# 示例: +# +# 输入:n = 3 +# 输出:[ +# "((()))", +# "(()())", +# "(())()", +# "()(())", +# "()()()" +# ] +# +# Related Topics 字符串 回溯算法 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + #1.递归的参数,递归的level + # def _generate_parenthesis(self,level,max_level,strs): + # #recursive terminator + # if level>=max_level: + # print(strs) + # return + # #current process + # #drill down + # self._generate_parenthesis(level+1,max_level,strs+'(') + # self._generate_parenthesis(level+1,max_level,strs+')') + # def generateParenthesis(self,n): + # """ + # :type n: int + # :rtype: List[str] + # """ + # self._generate_parenthesis(0, 2*n, '') + #击败43% + def generateParenthesis(self, n): + result = [] + self._generate_parenthesis(0, 0, n, '', result) + return result + + def _generate_parenthesis(self, left, right, n, res, result): + # recursive terminator + if left == n and right == n: + result.append(res) + return + # current process + if left < n: self._generate_parenthesis(left + 1, right, n, res + '(', result) + if left > right: self._generate_parenthesis(left, right + 1, n, res + ')', result) + #击败82%,不需要传递五个变量 + def generateParenthesisII(self, n): + result = [] + def _generate_parenthesis(left, right, n, res): + # recursive terminator + if left == n and right == n: + result.append(res) + return + # current process + if left < n: _generate_parenthesis(left + 1, right, n, res + '(') + if left > right: _generate_parenthesis(left, right + 1, n, res + ')') + + _generate_parenthesis(0, 0, n, '') + return result + +# leetcode submit region end(Prohibit modification and deletion) + +s = Solution() +res = s.generateParenthesis(3) +print(res) + + diff --git "a/Week03/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py" "b/Week03/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py" new file mode 100644 index 000000000..70946c820 --- /dev/null +++ "b/Week03/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py" @@ -0,0 +1,41 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/22 11:08 PM + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution: + def invertTree(self, root: TreeNode) -> TreeNode: + # recursive terminator + #击败70% + # if root is None: return + # # current process + # left = self.invertTree(root.right) + # right = self.invertTree(root.left) + # root.left = left + # root.right = right + # # drill down + # # reverse states + # return root + #非递归写法,深度优先遍历过程中,交换左右孩子,然后继续向下做同样的操作 + #类似层序遍历,用quene存储访问到的节点 + #击败87% + if root is None: return None + quene = [root] + while quene: + cur = quene.pop() + tmp = cur.left + cur.left = cur.right + cur.right = tmp + if cur.left is not None: quene.append(cur.left) + if cur.right is not None: quene.append(cur.right) + return root + + + + diff --git "a/Week03/\351\200\222\345\275\222\346\250\241\346\235\277.py" "b/Week03/\351\200\222\345\275\222\346\250\241\346\235\277.py" new file mode 100644 index 000000000..80360055b --- /dev/null +++ "b/Week03/\351\200\222\345\275\222\346\250\241\346\235\277.py" @@ -0,0 +1,16 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/22 9:16 PM + +def recursive(level,*args,**kwargs): + #recursive terminator + if level>max_level: + process_resoult + return + + #logic process in current level + process(level,data) + #drill down + recursive(level+1,*args,**kwargs) + + # reverse the current state if needed diff --git "a/Week03/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" "b/Week03/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" new file mode 100644 index 000000000..24b68ef12 --- /dev/null +++ "b/Week03/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" @@ -0,0 +1,83 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/22 11:50 PM + +# 给定一个二叉树,判断其是否是一个有效的二叉搜索树。 +# +# 假设一个二叉搜索树具有如下特征: +# +# +# 节点的左子树只包含小于当前节点的数。 +# 节点的右子树只包含大于当前节点的数。 +# 所有左子树和右子树自身必须也是二叉搜索树。 +# +# +# 示例 1: +# +# 输入: +# 2 +# / \ +# 1 3 +# 输出: true +# +# +# 示例 2: +# +# 输入: +# 5 +# / \ +# 1 4 +#   / \ +#   3 6 +# 输出: false +# 解释: 输入为: [5,1,4,null,null,3,6]。 +#   根节点的值为 5 ,但是其右子节点值为 4 。 +# +# Related Topics 树 深度优先搜索 + + +# leetcode submit region begin(Prohibit modification and deletion) +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + pre_val = float('-inf') + def isValidBST(self, root): + """ + :type cur: TreeNode + :rtype: bool + """ + #依据是 二叉搜索树的中序遍历是有递增的 击败11% + #recursive terminator + if root is None: return True + #current prpcess + #确定左子树是否符合排序二叉树,如果不满足,就返回False + if not self.isValidBST(root.left): return False + if root.val <= self.pre_val: return False#不满足左子树小于根节点 + self.pre_val = root.val#记录上一个访问的节点的值 + #访问右子树 + + # drill down + return self.isValidBST(root.right) + + #中序遍历 迭代 击败73% + stack, pre_val = [], float('-inf') + cur = root + while stack or cur is not None: + while cur is not None: + stack.append(cur) + cur = cur.left + cur = stack.pop() + if cur.val <= pre_val: return False + pre_val = cur.val + cur = cur.right + return True + + + + +# leetcode submit region end(Prohibit modification and deletion) From 9ef89b73666ce18e5e1b6ea9082e5b63cac8a8ec Mon Sep 17 00:00:00 2001 From: mqray Date: Thu, 25 Jun 2020 10:10:42 +0800 Subject: [PATCH 063/105] =?UTF-8?q?=E4=BA=8C=E8=BF=9B=E5=88=B6=E6=B1=82?= =?UTF-8?q?=E5=92=8C=E3=80=81=E5=8D=95=E8=AF=8D=E6=8B=86=E5=88=86=E3=80=81?= =?UTF-8?q?=E6=9C=80=E6=8E=A5=E8=BF=91=E7=9A=84=E4=B8=89=E6=95=B0=E4=B9=8B?= =?UTF-8?q?=E5=92=8C=E3=80=81=E6=9C=80=E9=95=BF=E5=9B=9E=E6=96=87=E5=AD=90?= =?UTF-8?q?=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week03/.idea/leetcode/editor.xml | 24 ++ Week03/.idea/workspace.xml | 296 +++++++++++++----- Week03/NOTE.md | 81 +++++ ...33\345\210\266\346\261\202\345\222\214.py" | 55 ++++ ...11\346\225\260\344\271\213\345\222\214.py" | 54 ++++ ...25\350\257\215\346\213\206\345\210\206.py" | 83 +++++ ...36\346\226\207\345\255\220\344\270\262.py" | 3 + 7 files changed, 515 insertions(+), 81 deletions(-) create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_23_\344\272\214\350\277\233\345\210\266\346\261\202\345\222\214.py" create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_24_\346\234\200\346\216\245\350\277\221\347\232\204\344\270\211\346\225\260\344\271\213\345\222\214.py" create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\345\215\225\350\257\215\346\213\206\345\210\206.py" create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_25_\346\234\200\351\225\277\345\233\236\346\226\207\345\255\220\344\270\262.py" diff --git a/Week03/.idea/leetcode/editor.xml b/Week03/.idea/leetcode/editor.xml index d8e88144d..7eb0df6e3 100644 --- a/Week03/.idea/leetcode/editor.xml +++ b/Week03/.idea/leetcode/editor.xml @@ -3,6 +3,22 @@ - + + + + + + + + + + + + + + @@ -284,7 +307,7 @@ - + @@ -294,18 +317,42 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Week03/.idea/workspace.xml b/Week03/.idea/workspace.xml index ae585589f..887d575bc 100644 --- a/Week03/.idea/workspace.xml +++ b/Week03/.idea/workspace.xml @@ -2,12 +2,17 @@ - + + + + + + - + + @@ -31,29 +37,29 @@ - + - + - + - - + + - + - + @@ -61,80 +67,100 @@ - + - - + + - - - - + + + + + + + - + - - - - - - + + - + - - + + - - - - - - - + + + + + + + + + + - + - - + + + + + + + + + + + - + - - + + - + - - + + + + + + + + + + + @@ -156,7 +182,6 @@ @@ -221,7 +252,7 @@ - + + + + + + @@ -343,18 +398,18 @@ - + - + - + @@ -489,6 +544,36 @@ 51 diff --git a/Week03/NOTE.md b/Week03/NOTE.md index 293a67643..59a79cfee 100644 --- a/Week03/NOTE.md +++ b/Week03/NOTE.md @@ -361,4 +361,116 @@ def deserializeCore(self,data): root.left = self.deserializeCore(data) root.right = self.deserializeCore(data) return root -``` \ No newline at end of file +``` + +#### 二叉树的最近公共祖先 +1.递归 +class Solution: +```angular2html +#1.递归 分析出找到最近公共祖先节点的情形,如果p,q由同一祖先节点 则p、q要么位于某棵树的左右子树 + #要么在同一棵树上,在同一棵树上又有 p或q为根 另外存在p或q在其左右子树中 + res = None + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + self.dfs(root,p,q) + return self.res + + def dfs(self,root,p,q): + # recursive terminator + if root is None: return False + #current process + #drill down + root_left = self.dfs(root.left,q,p)#判断这颗树的子树中是否含有q节点或者q节点 + root_right = self.dfs(root.right,p,q) + #要判断p、q的最近公共祖先,我们从根节点开始寻找,查探root的左子树和右子树是否包含q节点或p节点,此时最近公共最先就是root;另外的,如果p或q为子树根节点,且p或q处在这棵子树下面,则最进公共祖先就是p或q节点 + if root_left and root_right or ((root.val==p.val or root.val==q.val) and(root_left or root_right) ):#对于5,1这种情况,这是后就要返回p为true给上层递归 + self.res = root#那么就返回当前树的根节点 + #reverse states + return root_left or root_right or(root.val==p.val or root.val==q.val) +``` +写的更简洁一点 +```angular2html +def lowestCommonAncestor(self, root, p, q): + if not root or p==root or q==root: + return root + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + if left and right: + return root + return left if left else right +``` + +2.记录父节点 +```angular2html +class Solution: + # ,然后我们就可以利用节点的父节点信息从p结点开始不断往上跳,并记录已经访问过的节点,再从q节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。 + all_parents = {} + p_parents = {} + + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + self.all_parents[root.val] = None + self.dfs(root) # 用哈希表存储所有节点的父节点 + # 在all_parents找p的根节点,并且记录找到的父节点 + while p != None: + self.p_parents[p.val] = True + p = self.all_parents.get(p.val) + while q != None: # 因为p、q是必有公共父节点的,所以一定能在p_parents里面找到父节点 + if self.p_parents.get(q.val): # 如果如果在p的parent中找到 + return q + q = self.all_parents.get(q.val) # 如果没找到,说明q可能还要向上一层才能找到 + return None + + def dfs(self, root): # 从root开始遍历子节点 记录子节点值作为key,值为root节点 + if root.left is not None: + self.all_parents[root.left.val] = root + self.dfs(root.left) + if root.right is not None: + self.all_parents[root.right.val] = root + self.dfs(root.right) +``` + +#### 根据二叉树的前中序列重建二叉树 +手动模拟根据二叉树的前中序列生成二叉树的过程,不难发现每次都是先确定根节点,以根节点划分出左右子树 +对应到两个序列,递归的进行确定根节点,左右子树序列 +所以我们在重建时,先确定根节点、然后为其分配左右子树, +处理左右子树时,先确定并对应其前中序列,进行相同的处理 +```angular2html +def buildTree(self, pre: List[int], inorder: List[int]) -> TreeNode: + if not pre or not inorder: + return None + root = TreeNode(pre[0]) + index = inorder.index(root.val)#记录root在中序序列中的位置 + root.left = self.buildTree(pre[1:index+1],inorder[:index]) + root.right = self.buildTree(pre[index+1:],inorder[index+1:]) + return root +``` + + +#### 删除未排序链表中的重复元素 +1.使用set实现存储未重复元素,然后重建 (超时)尽管时间复杂度是O(N),但是相当于遍历了两次 +```angular2html +if head is None or head.next is None: return head + once = set() + while head is not None: + if head.val not in once: + once.add(head.val) + head = head.next + head = pre = ListNode(None) + while once: + head.next = ListNode(once.pop()) + head = head.next + return pre.next +``` +可以知道,如果当前元素已经出现过,那么如果遍历时记录了前一个指针,那么可以直接删除掉这个节点元素 +```angular2html +if not head: return head + once = {head.val} + pre = head + while head.next:#如果有下一个节点 + cur = head.next + if not cur.val in once: + once.add(cur.val) + head = head.next + else:#如果这个元素已经出现,那就直接删除掉 + head.next = head.next.next + return pre +``` diff --git "a/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.py" "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.py" new file mode 100644 index 000000000..857348777 --- /dev/null +++ "b/Week03/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.py" @@ -0,0 +1,58 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/26 1:11 PM + +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + #1.递归 分析出找到最近公共祖先节点的情形,如果p,q由同一祖先节点 则p、q要么位于某棵树的左右子树 + #要么在同一棵树上,在同一棵树上又有 p或q为根 另外存在p或q在其左右子树中 + res = None + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + self.dfs(root,p,q) + return self.res + + def dfs(self,root,p,q): + # recursive terminator + if root is None: return False + #current process + #drill down + root_left = self.dfs(root.left,q,p)#判断这颗树的子树中是否含有q节点或者q节点 + root_right = self.dfs(root.right,p,q) + #要判断p、q的最近公共祖先,我们从根节点开始寻找,查探root的左子树和右子树是否包含q节点或p节点,此时最近公共最先就是root;另外的,如果p或q为子树根节点,且p或q处在这棵子树下面,则最进公共祖先就是p或q节点 + if root_left and root_right or ((root.val==p.val or root.val==q.val) and(root_left or root_right) ):#对于5,1这种情况,这是后就要返回p为true给上层递归 + self.res = root#那么就返回当前树的根节点 + #reverse states + return root_left or root_right or(root.val==p.val or root.val==q.val) + +#2.记录父节点 +class SolutionI: + # ,然后我们就可以利用节点的父节点信息从p结点开始不断往上跳,并记录已经访问过的节点,再从q节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。 + all_parents = {} + p_parents = {} + + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + self.all_parents[root.val] = None + self.dfs(root) # 用哈希表存储所有节点的父节点 + # 在all_parents找p的根节点,并且记录找到的父节点 + while p != None: + self.p_parents[p.val] = True + p = self.all_parents.get(p.val) + while q != None: # 因为p、q是必有公共父节点的,所以一定能在p_parents里面找到父节点 + if self.p_parents.get(q.val): # 如果如果在p的parent中找到 + return q + q = self.all_parents.get(q.val) # 如果没找到,说明q可能还要向上一层才能找到 + return None + + def dfs(self, root): # 从root开始遍历子节点 记录子节点值作为key,值为root节点 + if root.left is not None: + self.all_parents[root.left.val] = root + self.dfs(root.left) + if root.right is not None: + self.all_parents[root.right.val] = root + self.dfs(root.right) diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" index c2fd2ba42..820a991de 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_22_\346\213\254\345\217\267\347\224\237\346\210\220.py" @@ -53,16 +53,17 @@ def _generate_parenthesis(self, left, right, n, res, result): if left > right: self._generate_parenthesis(left, right + 1, n, res + ')', result) #击败82%,不需要传递五个变量 def generateParenthesisII(self, n): - result = [] + def _generate_parenthesis(left, right, n, res): # recursive terminator - if left == n and right == n: + if left == n and right == n:#触发结束条件 result.append(res) return - # current process + # current process #排除不合法的选择 做选择 进入下一层决策树 if left < n: _generate_parenthesis(left + 1, right, n, res + '(') if left > right: _generate_parenthesis(left, right + 1, n, res + ')') - + #取消选择 + result = [] _generate_parenthesis(0, 0, n, '') return result diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\247\273\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\247\273\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271.py" new file mode 100644 index 000000000..914d37610 --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\247\273\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271.py" @@ -0,0 +1,58 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/26 5:38 PM + +# 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。 +# +# 示例1: +# +# +# 输入:[1, 2, 3, 3, 2, 1] +# 输出:[1, 2, 3] +# +# +# 示例2: +# +# +# 输入:[1, 1, 1, 1, 2] +# 输出:[1, 2] +# +# +# 提示: +# +# +# 链表长度在[0, 20000]范围内。 +# 链表元素在[0, 20000]范围内。 +# +# +# 进阶: +# +# 如果不得使用临时缓冲区,该怎么解决? +# Related Topics 链表 + + +# leetcode submit region begin(Prohibit modification and deletion) +# Definition for singly-linked list. +# class ListNode(object): +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution(object): + def removeDuplicateNodes(self, head): + """ + :type head: ListNode + :rtype: ListNode + """ + if not head: return head + once = {head.val} + pre = head + while head.next: # 如果有下一个节点 + cur = head.next + if not cur.val in once: + once.add(cur.val) + head = head.next + else: # 如果这个元素已经出现,那就直接删除掉 + head.next = head.next.next + return pre +# leetcode submit region end(Prohibit modification and deletion) diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\273\204\345\220\210.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\273\204\345\220\210.py" new file mode 100644 index 000000000..2a78841fb --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26_\347\273\204\345\220\210.py" @@ -0,0 +1,23 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/26 10:02 PM + +class Solution(object): + def combine(self, n, k): + """ + :type n: int + :type k: int + :rtype: List[List[int]] + """ + def backtracing(first=1, tmp=[]): + if len(tmp) == k: #触发结束条件 如果当前元素 已经有k个,就将它加入res中 + res.append(tmp[:]) + for i in range(first, n + 1): # 如果当前元素个数小于k,则加入cur中 + # 做选择 + tmp.append(i) + backtracing(i + 1, tmp) # 进入下一层决策 + tmp.pop() # 撤销刚才的选择 + + res = [] + backtracing() + return res diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26\345\211\215\344\270\255\345\272\217\345\210\227\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26\345\211\215\344\270\255\345\272\217\345\210\227\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py" new file mode 100644 index 000000000..c5ef59f31 --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_26\345\211\215\344\270\255\345\272\217\345\210\227\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.py" @@ -0,0 +1,20 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/26 5:29 PM + +from typing import List +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution: + def buildTree(self, pre: List[int], inorder: List[int]) -> TreeNode: + if not pre or not inorder: + return None + root = TreeNode(pre[0]) + index = inorder.index(root.val)#记录root在中序序列中的位置 + root.left = self.buildTree(pre[1:index+1],inorder[:index]) + root.right = self.buildTree(pre[index+1:],inorder[index+1:]) + return root \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" new file mode 100644 index 000000000..0484d8b2c --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" @@ -0,0 +1,40 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/26 10:27 PM + +class Solution(object): + # def permute(self, nums): + # def backtracing(first=0): + # if first == size: + # result.append(nums[:]) + # for i in range(first, size): + # nums[first], nums[i] = nums[i], nums[first] + # backtracing(first+1) + # nums[first], nums[i] = nums[i], nums[first] + # size = len(nums) + # result = [] + # #l路径 + # #选择列表 就是除去已经被加入到cur中的其余元素 + # backtracing() + # return result + def permute(self,nums): + res = [] + self.backtracing(res,nums,[]) + return res + def backtracing(self,res,nums,tmp): + #触发结束条件 + if len(nums) == len(tmp): + res.append(tmp[:]) + return #返回上一层调用 + for i in range(len(nums)): + #排除不合法的 + if nums[i] in tmp: continue + #做选择 + tmp.append(nums[i]) + #进入下一层 + self.backtracing(res,nums,tmp) + tmp.pop() +s = Solution() +nums = [1,2,3] +res = s.permute(nums) +print(res) \ No newline at end of file From c5959ccb8b1a20fe64028f1aa8c3cec4dbf5567b Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 27 Jun 2020 00:48:56 +0800 Subject: [PATCH 066/105] =?UTF-8?q?=E5=85=A8=E6=8E=92=E5=88=97=E3=80=81?= =?UTF-8?q?=E5=85=A8=E6=8E=92=E5=88=97II?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week03/.idea/workspace.xml | 241 ++++++++++-------- Week03/NOTE.md | 147 ++++++++--- ...7_\345\205\250\346\216\222\345\210\227.py" | 78 +++--- ...\345\205\250\346\216\222\345\210\227II.py" | 41 +++ 4 files changed, 342 insertions(+), 165 deletions(-) create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" diff --git a/Week03/.idea/workspace.xml b/Week03/.idea/workspace.xml index 887d575bc..e6cadc626 100644 --- a/Week03/.idea/workspace.xml +++ b/Week03/.idea/workspace.xml @@ -2,17 +2,12 @@ - - - - - + - - + - + + @@ -37,50 +33,41 @@ - + - + - - + + - - + + - + - - - - - - - - - - + - - + + @@ -99,27 +86,37 @@ - - + + - + - - + + - - - - + + + + + + + + + + + + + + @@ -141,7 +138,7 @@ - + @@ -194,11 +191,12 @@ @@ -253,7 +251,7 @@ - + - + - + - + - + - + + - @@ -405,11 +403,11 @@ - + - - + + @@ -546,38 +544,73 @@ file://$PROJECT_DIR$/每日一题6_27_全排列.py - 6 + 7 file://$PROJECT_DIR$/每日一题6_27_全排列.py - 7 + 8 file://$PROJECT_DIR$/每日一题6_27_全排列.py - 9 + 10 file://$PROJECT_DIR$/每日一题6_27_全排列.py - 10 + 11 file://$PROJECT_DIR$/每日一题6_27_全排列.py - 11 + 12 file://$PROJECT_DIR$/每日一题6_27_全排列.py - 12 + 13 + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 27 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 28 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 31 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 34 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 23 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 39 + + + + + + @@ -711,13 +744,6 @@ - - - - - - - @@ -725,16 +751,6 @@ - - - - - - - - - - @@ -742,20 +758,6 @@ - - - - - - - - - - - - - - @@ -772,26 +774,65 @@ - + + + + + + + + - - + + + + + + + + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Week03/NOTE.md b/Week03/NOTE.md index 59a79cfee..6469e70ff 100644 --- a/Week03/NOTE.md +++ b/Week03/NOTE.md @@ -1,42 +1,6 @@ 学习笔记 -#### 括号生成 -1.因为括号类别已经确定,可以想象为左右括号最多N个 -左括号出现次数小于N即可,右括号小于左括号个数 -```angular2html -def generateParenthesis(self,n): - result = [] - self._generate_parenthesis(0, 0, n, '',result) - return result -def _generate_parenthesis(self, left, right, n, res, result): - # recursive terminator - if left == n and right == n: - result.append(res) - return - # current process - if left < n: self._generate_parenthesis(left + 1, right, n, res + '(', result) - if left > right: self._generate_parenthesis(left, right + 1, n, res + ')', result) - - # drill down - - # reverse state -``` -上面这种解法,由于最后要返回res,所以在递归时传入的参数较多,可以简化一下 -```angular2html -def generateParenthesis(self,n): - result = [] - def _generate_parenthesis( left, right, n, res): - # recursive terminator - if left == n and right == n: - result.append(res) - return - # current process - if left < n: _generate_parenthesis(left + 1, right, n, res + '(') - if left > right: _generate_parenthesis(left, right + 1, n, res + ')') - _generate_parenthesis(0, 0, n, '') - return result -``` #### 翻转二叉树 1.递归 @@ -474,3 +438,114 @@ if not head: return head head.next = head.next.next return pre ``` + +#### 括号生成 +1.因为括号类别已经确定,可以想象为左右括号最多N个 +左括号出现次数小于N即可,右括号小于左括号个数 +```angular2html +def generateParenthesis(self,n): + result = [] + self._generate_parenthesis(0, 0, n, '',result) + return result + +def _generate_parenthesis(self, left, right, n, res, result): + # recursive terminator + if left == n and right == n: + result.append(res) + return + # current process + if left < n: self._generate_parenthesis(left + 1, right, n, res + '(', result) + if left > right: self._generate_parenthesis(left, right + 1, n, res + ')', result) + + # drill down + + # reverse state +``` +上面这种解法,由于最后要返回res,所以在递归时传入的参数较多,可以简化一下 +```angular2html +def generateParenthesis(self,n): + result = [] + def _generate_parenthesis( left, right, n, res): + # recursive terminator + if left == n and right == n: + result.append(res) + return + # current process + if left < n: _generate_parenthesis(left + 1, right, n, res + '(') + if left > right: _generate_parenthesis(left, right + 1, n, res + ')') + _generate_parenthesis(0, 0, n, '') + return result +``` + +#### 组合 +碰到组合、全排列、括号生成这种打印类的题,一般都是 回溯算法,回溯算法有一个基本模板: +```angular2html +def backtracing(路径,可选路径): + #触发结束条件 + #for i in range(): + #处理不符合条件的 + #执行当前选择 路径+,可选路径- + #进入下一层决策 + #进行有必要的撤销选择以进行回溯 + +``` + +```angular2html +def combine(self, n, k): + def backtracing(first=1, tmp=[]): + #触发结束条件 + if len(tmp) == k: # 如果当前元素 已经有k个,就将它加入res中 + res.append(tmp[:]) + for i in range(first, n + 1): # 如果当前元素个数小于k,则加入cur中 + # 做选择 + tmp.append(i) + # 进入下一层决策 + backtracing(i + 1, tmp) + # 撤销刚才的选择 + tmp.pop() + res = [] + backtracing() + return res +``` + + +#### 组合II + +#### 全排列 +```angular2html +def permute(self, nums: List[int]) -> List[List[int]]: + def backtrace(nums, tmp): + #触发结束条件 + if not nums: + res.append(tmp[:]) + for i in range(len(nums)): + #排除不合法或已存在的 + if nums[i] in tmp: continue + #做选择 修改已选路径和能选择的路径 + #进入下一次决策、回溯之前的决策 + backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 + res = [] + backtrace(nums, []) + return res +``` + +#### 全排列II +```angular2html +def permuteUnique(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + def backtrace(nums, tmp): + if not nums: + res.append(tmp[:]) + visited = set() + for i in range(len(nums)): + if nums[i] in visited: continue + backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 + visited.add(nums[i]) + + res = [] + backtrace(nums, []) + return res +``` \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" index 0484d8b2c..e1a743e04 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" @@ -2,39 +2,59 @@ # Author : Ray # Data : 2020/6/26 10:27 PM +from typing import List class Solution(object): # def permute(self, nums): - # def backtracing(first=0): - # if first == size: - # result.append(nums[:]) - # for i in range(first, size): - # nums[first], nums[i] = nums[i], nums[first] - # backtracing(first+1) - # nums[first], nums[i] = nums[i], nums[first] - # size = len(nums) - # result = [] - # #l路径 - # #选择列表 就是除去已经被加入到cur中的其余元素 - # backtracing() - # return result - def permute(self,nums): + # def backtracing(first=0): + # if first == size: + # result.append(nums[:]) + # for i in range(first, size): + # nums[first], nums[i] = nums[i], nums[first] + # backtracing(first+1) + # nums[first], nums[i] = nums[i], nums[first] + + # size = len(nums) + # result = [] + # #l路径 + # #选择列表 就是除去已经被加入到cur中的其余元素 + # backtracing() + # return result + # def permute(self,nums): + # res = [] + # self.backtracing(res,nums,[]) + # return res + # def backtracing(self,res,nums,tmp): + # #触发结束条件 + # if len(nums) == len(tmp): + # res.append(tmp[:]) + # # return #返回上一层调用 + # for i in range(len(nums)): + # #排除不合法的,处理了好多 + # if nums[i] in tmp: continue + # #做选择 + # tmp.append(nums[i]) + # #进入下一层 + # self.backtracing(res,nums,tmp) + # tmp.pop() + def permute(self, nums: List[int]) -> List[List[int]]: + def backtrace(nums, tmp): + #触发结束条件 + if not nums: + res.append(tmp[:]) + for i in range(len(nums)): + #排除不合法或已存在的 + if nums[i] in tmp: continue + #做选择 修改已选路径和能选择的路径 + #进入下一次决策、回溯之前的决策 + backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 res = [] - self.backtracing(res,nums,[]) + backtrace(nums, []) return res - def backtracing(self,res,nums,tmp): - #触发结束条件 - if len(nums) == len(tmp): - res.append(tmp[:]) - return #返回上一层调用 - for i in range(len(nums)): - #排除不合法的 - if nums[i] in tmp: continue - #做选择 - tmp.append(nums[i]) - #进入下一层 - self.backtracing(res,nums,tmp) - tmp.pop() + + + + s = Solution() -nums = [1,2,3] +nums = [1,3,2] res = s.permute(nums) print(res) \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" new file mode 100644 index 000000000..d280af3f5 --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" @@ -0,0 +1,41 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/26 11:55 PM + +class Solution(object): + def permuteUnique(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + def backtrace(nums, tmp): + if not nums: + res.append(tmp[:]) + visited = set() + for i in range(len(nums)): + if nums[i] in visited: continue + backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 + visited.add(nums[i]) + + res = [] + backtrace(nums, []) + return res + # res = [] + # self.backtracing(res,nums,[]) + # return res + # def backtracing(self,res,nums,tmp): + # #触发结束条件 + # if len(nums)==len(tmp): + # res.append(tmp[:]) + # for i in range(len(nums)): + # #排除不合法条件 + # if nums[i] in tmp: + # continue + # #做选择 + # tmp.append(nums[i]) + # #进入下一层决策 + # self.backtracing(res,nums,tmp) + # tmp.pop() +s = Solution() +res = s.permuteUnique([1,1,2]) +print(res) \ No newline at end of file From 20a4da00ca5b042867006b8bd375911250410332 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 27 Jun 2020 11:15:47 +0800 Subject: [PATCH 067/105] Pow(x,n) --- ...57\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" new file mode 100644 index 000000000..89af59f23 --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" @@ -0,0 +1,3 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/27 10:45 AM \ No newline at end of file From 3950fb22fac18212f3dea5b15a0a600c03851080 Mon Sep 17 00:00:00 2001 From: mqray Date: Sun, 28 Jun 2020 22:31:45 +0800 Subject: [PATCH 068/105] =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=E7=9B=B8?= =?UTF-8?q?=E5=8A=A0=E3=80=81=E7=9B=B8=E4=B9=98=E3=80=81=E9=95=BF=E5=BA=A6?= =?UTF-8?q?=E6=9C=80=E5=B0=8F=E7=9A=84=E5=AD=90=E6=95=B0=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week03/.idea/leetcode/editor.xml | 24 + Week03/.idea/workspace.xml | 511 +++++++++++++----- Week03/NOTE.md | 133 ++++- ...5\344\270\200\351\242\2306_27_Pow(x,n).py" | 11 +- ...\345\205\250\346\216\222\345\210\227II.py" | 4 +- ...1\242\2306_27_\345\255\220\351\233\206.py" | 39 ++ ...46\344\270\262\347\233\270\344\271\230.py" | 51 ++ ...46\344\270\262\347\233\270\345\212\240.py" | 44 ++ ...04\345\255\220\346\225\260\347\273\204.py" | 59 ++ 9 files changed, 722 insertions(+), 154 deletions(-) create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\344\271\230.py" create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\345\212\240.py" create mode 100644 "Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204.py" diff --git a/Week03/.idea/leetcode/editor.xml b/Week03/.idea/leetcode/editor.xml index 33f18ef84..20fc4c471 100644 --- a/Week03/.idea/leetcode/editor.xml +++ b/Week03/.idea/leetcode/editor.xml @@ -19,6 +19,14 @@ + + + + + + @@ -27,6 +35,22 @@ + + + + + + + + + + + + diff --git a/Week03/.idea/workspace.xml b/Week03/.idea/workspace.xml index e6cadc626..d1fa8f889 100644 --- a/Week03/.idea/workspace.xml +++ b/Week03/.idea/workspace.xml @@ -2,12 +2,18 @@ - + + + + + + - + + - - + + + + @@ -26,138 +34,135 @@ + - + + - - + + - - + + - + - - + + - - + + - + - - - - - - - - - + + + + + + + + + + + + + + - + - - + + + + + - + - - + + - - - - - - - - - - - - + + + + + + + + - + - - + + - + - - - - - - - - - - - + + - + - - + + - + - - + + - + - - + + @@ -193,9 +198,15 @@ @@ -250,8 +261,8 @@ - - + + - + - + - + - + + + + + + + - - - - + + + + - + + + + - - - @@ -395,15 +450,9 @@ - - + - - - - - - + @@ -411,12 +460,18 @@ - - - + + + + + + + + + @@ -574,33 +629,138 @@ file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 27 - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 28 - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 31 - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 34 - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 23 - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 39 - + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 16 + + + file://$PROJECT_DIR$/每日一题6_27_子集.py + 29 + + + file://$PROJECT_DIR$/每日一题6_27_子集.py + 31 + + + file://$PROJECT_DIR$/每日一题6_27_子集.py + 37 + + + file://$PROJECT_DIR$/每日一题6_27_子集.py + 27 + + + file://$PROJECT_DIR$/每日一题6_28_字符串相加.py + 35 + + + file://$PROJECT_DIR$/每日一题6_28_字符串相加.py + 32 + + + file://$PROJECT_DIR$/每日一题6_28_字符串相加.py + 31 + + + file://$PROJECT_DIR$/每日一题6_28_字符串相加.py + 30 + + + file://$PROJECT_DIR$/每日一题6_28_字符串相加.py + 33 + + + file://$PROJECT_DIR$/每日一题6_28_字符串相加.py + 34 + + + file://$PROJECT_DIR$/每日一题6_28_字符串相加.py + 42 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 57 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 44 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 46 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 45 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 47 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 48 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 49 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 50 + + + file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py + 51 + @@ -614,21 +774,11 @@ - - - - - - - + - - - - @@ -758,9 +908,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -769,65 +968,81 @@ - - + - - + + + + + - + - - + + - - + + - + - - - - - - - - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/Week03/NOTE.md b/Week03/NOTE.md index 6469e70ff..7f96ea042 100644 --- a/Week03/NOTE.md +++ b/Week03/NOTE.md @@ -541,11 +541,138 @@ def permuteUnique(self, nums): res.append(tmp[:]) visited = set() for i in range(len(nums)): - if nums[i] in visited: continue - backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 + if nums[i] in visited: continue visited.add(nums[i]) + backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 res = [] backtrace(nums, []) return res -``` \ No newline at end of file +``` + +#### Pow(x,n) +1.遍历n次,时间复杂度O(N) +```angular2html +if n==0: return 1 +flag=False if n< 0 else True +times,res = abs(n),1 +while times>0: + res *= x + times -= 1 +return res if flag else 1/res +``` +递归形式如下 但是都超出时间限制 +```angular2html +if n == 1: return x +if n < 0: + return 1 / self.myPow(x, -n) +return self.myPow(x, n // 2) * self.myPow(x, n - n // 2) +``` + +2.我们可以将这个问题的时间复杂度缩减到O(logN),求x的N次方 我们可以化简为计算两次x的N/2次(判断奇偶) +```angular2html +if n == 1: return x +if n < 0: + return 1 / self.myPow(x, -n) +return self.myPow(x*x, n // 2) if n%2==0 else x*self.myPow(x, n-1) +``` + +#### 子集 +1.递归 +```angular2html +def subsets(self, nums: List[int]) -> List[List[int]]: + res = [[]] + for num in nums: + res += [tmp + [num] for tmp in res] + return res +``` +2.回溯 +```angular2html +def subsets(self, nums: List[int]) -> List[List[int]]: + def backtrack(first=0, tmp=[]): + #处理结束条件 + if len(tmp) == k: + res.append(tmp[:]) + for i in range(first, size): + #选择 + tmp.append(nums[i]) + # print(curr) + #下一层决策 + backtrack(i + 1, tmp) + tmp.pop() + res = [] + size = len(nums) + for k in range(size + 1): + backtrack() + return res + +``` +3.位运算 +```angular2html +def subsets(self, nums: List[int]) -> List[List[int]]: + size = len(nums) + res = [] + for i in range(2 ** size, 2 ** (size + 1)): + # generate bitmask, from 0..00 to 1..11 + bitmask = bin(i)[3:] + # append subset corresponding to that bitmask + res.append([nums[j] for j in range(size) if bitmask[j] == '1']) + return res +``` + +#### 字符串相加 +手动模拟数字进位加法,如果两个数长度不一致,就在将其作为0处理 +```angular2html +def addStrings(self, num1, num2): + """ + :type num1: str + :type num2: str + :rtype: str + """ + #1.转数字计算 + # return str(int(num1)+int(num2)) + # 2.手动模拟加法运算 + res = '' + i, j, carry = len(num1) - 1,len(num2) - 1, 0 + while i >= 0 or j >= 0: + n1 = int(num1[i]) if i >= 0 else 0 + n2 = int(num2[j]) if j >= 0 else 0 + tmp = n1 + n2 + carry + carry = tmp // 10 + res = str(tmp % 10) + res + i, j = i - 1, j - 1 + return '1' + res if carry else res +``` + +#### 长度最小的子数组 +1.枚举出长度为1,2,3...的数组,查看其值是否大于s,如果大于则可以直接返回 此时的枚举长度 但是时间复杂度高 O(N^2) +```angular2html +def minSubArrayLen(self, s, nums): +# 1. 穷举 超出时间限制 + for i in range(1, len(nums) + 1): + # 长度为1,2,3,穷举可能的解,找到则返回 + for j in range(len(nums) - i + 1): + if sum(nums[j:i + j]) >= s: return i + return 0 +``` +2.穷举的过程中,有很多不必要的开销,比如每次指定长度的窗口,但是大多数窗口都是无效的 +就像窗口为1时 计算和之后 判断了一次 如果不符合规定 就往后挪了一位 不符合需要继续后移 +窗口值为2时,又计算了前面的过程 +所以我们可以使用双指针 来界定是否是最短子数组 +双指针开始时指向 数组头 如果当前窗口和 小于s,end右移 以达到期望的s,如果此时已经到达s,记录下当前的窗口值 +将当前窗口往右移动 继续判断窗口值与s的关系,如果小了,就右移end;如果还是大于s,窗口继续右移 +```angular2html +def minSubArrayLen(self, s, nums): + if not nums: return 0 + size, res = len(nums), len(nums) + 1 + start, end = 0, 0 + tmp = 0 # 记录窗口和 + while end < size: + tmp = tmp + nums[end] + while tmp >= s: # 如果当前窗口和值大于s,收缩窗口 + res = min(res, end - start + 1) + tmp = tmp - nums[start] + start = start + 1 + end = end + 1 # 窗口扩张 + return 0 if end == size + 1 else res +``` diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" index 89af59f23..5bd680df8 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" @@ -1,3 +1,12 @@ # -*- coding:utf-8 -*- # Author : Ray -# Data : 2020/6/27 10:45 AM \ No newline at end of file +# Data : 2020/6/27 10:45 AM + +class Solution: + def myPow(self, x: float, n: int) -> float: + if n == 0: return 1 + if n == 1: return x + if n < 0: + return 1 / self.myPow(x, -n) + # return self.myPow(x, n // 2) * self.myPow(x, n - n // 2) + return self.myPow(x*x,n//2) if n%2==0 else x*self.myPow(x,n-1) \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" index d280af3f5..04a64d158 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" @@ -13,9 +13,9 @@ def backtrace(nums, tmp): res.append(tmp[:]) visited = set() for i in range(len(nums)): - if nums[i] in visited: continue - backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 + if nums[i] in visited: continue#在每一层剪枝 visited.add(nums[i]) + backtrace(nums[:i] + nums[i + 1:], tmp + [nums[i]])#修改选择项和路径 res = [] backtrace(nums, []) diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" new file mode 100644 index 000000000..1c34bdb41 --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" @@ -0,0 +1,39 @@ +from typing import List +class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + # res = [[]] + # for num in nums: + # res += [tmp + [num] for tmp in res] + # return res + # def backtrack(first=0, tmp=[]): + # #处理结束条件 + # if len(tmp) == k: + # res.append(tmp[:]) + # for i in range(first, size): + # #选择 + # tmp.append(nums[i]) + # # print(curr) + # #下一层决策 + # backtrack(i + 1, tmp) + # tmp.pop() + # + # res = [] + # size = len(nums) + # for k in range(size + 1): + # backtrack() + # return res + + size = len(nums) + res = [] + for i in range(2 ** size, 2 ** (size + 1)): + # generate bitmask, from 0..00 to 1..11 + bitmask = bin(i)[3:] + # append subset corresponding to that bitmask + res.append([nums[j] for j in range(size) if bitmask[j] == '1']) + return res + + + +s = Solution() +res = s.subsets([1,2,3]) +print(res) \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\344\271\230.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\344\271\230.py" new file mode 100644 index 000000000..96fcdf989 --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\344\271\230.py" @@ -0,0 +1,51 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/28 7:21 PM + +# 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 +# +# 示例 1: +# +# 输入: num1 = "2", num2 = "3" +# 输出: "6" +# +# 示例 2: +# +# 输入: num1 = "123", num2 = "456" +# 输出: "56088" +# +# 说明: +# +# +# num1 和 num2 的长度小于110。 +# num1 和 num2 只包含数字 0-9。 +# num1 和 num2 均不以零开头,除非是数字 0 本身。 +# 不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。 +# +# Related Topics 数学 字符串 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def multiply(self, num1, num2): + """ + :type num1: str + :type num2: str + :rtype: str + """ + if len(num1) < len(num2): # 确定num1是较长的 + num1, num2 = num2, num1 + tmp,tail = 0,0 + for i in range(len(num1)): + tail = tail + int(num1[i])*10**(len(num1)-i-1) + for ind in range(len(num2)-1, -1, -1):#将较长的作为底数,这样int()转换的时候不会出错 + # tmp = tmp + int(num1) * 10 ** (len(num2) - ind - 1) * int(num2[ind]) + tmp = tmp + tail * 10 ** (len(num2) - ind - 1) * int(num2[ind]) + return str(tmp) + +# leetcode submit region end(Prohibit modification and deletion) + +s = Solution() +num1, num2 = '123', '456' +res = s.multiply(num1, num2) +print(res) \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\345\212\240.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\345\212\240.py" new file mode 100644 index 000000000..e93a69a65 --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\345\255\227\347\254\246\344\270\262\347\233\270\345\212\240.py" @@ -0,0 +1,44 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/28 6:45 PM + +# 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。 +# +# 注意: +# +# +# num1 和num2 的长度都小于 5100. +# num1 和num2 都只包含数字 0-9. +# num1 和num2 都不包含任何前导零。 +# 你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式。 +# +# Related Topics 字符串 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def addStrings(self, num1, num2): + """ + :type num1: str + :type num2: str + :rtype: str + """ + #1.转数字计算 + # return str(int(num1)+int(num2)) + # 2.手动模拟加法运算 + res = '' + i, j, carry = len(num1) - 1,len(num2) - 1, 0 + while i >= 0 or j >= 0: + n1 = int(num1[i]) if i >= 0 else 0 + n2 = int(num2[j]) if j >= 0 else 0 + tmp = n1 + n2 + carry + carry = tmp // 10 + res = str(tmp % 10) + res + i, j = i - 1, j - 1 + return '1' + res if carry else res +# leetcode submit region end(Prohibit modification and deletion) + +s = Solution() +num1, num2 = '9', '99' +res = s.addStrings(num1,num2) +print(res) diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204.py" new file mode 100644 index 000000000..107df4c1c --- /dev/null +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_28_\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204.py" @@ -0,0 +1,59 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/6/28 8:29 PM +# 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回 +# 0。 +# +# +# +# 示例: +# +# 输入:s = 7, nums = [2,3,1,2,4,3] +# 输出:2 +# 解释:子数组 [4,3] 是该条件下的长度最小的连续子数组。 +# +# +# +# +# 进阶: +# +# +# 如果你已经完成了 O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。 +# +# Related Topics 数组 双指针 二分查找 + + +# leetcode submit region begin(Prohibit modification and deletion) +class Solution(object): + def minSubArrayLen(self, s, nums): + """ + :type s: int + :type nums: List[int] + :rtype: int + """ + # # 1. 穷举 超出时间限制 + # for i in range(1, len(nums) + 1): + # # 长度为1,2,3,穷举可能的解,找到则返回 + # for j in range(len(nums) - i + 1): + # if sum(nums[j:i + j]) >= s: return i + # return 0 + #2.双指针 + if not nums: return 0 + size, res = len(nums), len(nums) + 1 + start, end = 0, 0 + tmp = 0 # 记录窗口和 + while end < size: + tmp = tmp + nums[end] + while tmp >= s: # 如果当前窗口和值大于s,收缩窗口 + res = min(res, end - start + 1) + tmp = tmp - nums[start] + start = start + 1 + end = end + 1 # 窗口扩张 + return 0 if end == size + 1 else res +# leetcode submit region end(Prohibit modification and deletion) + +s = Solution() +# nums = [2,3,1,2,4,3] +nums = [1,2,3,4,5] +res= s.minSubArrayLen(1,nums) +print(res) \ No newline at end of file From 0b906981799651e5af9076fcda71ac9137319762 Mon Sep 17 00:00:00 2001 From: mqray Date: Mon, 29 Jun 2020 00:25:21 +0800 Subject: [PATCH 069/105] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week03/.idea/workspace.xml | 94 ++++++++++--------- Week03/NOTE.md | 1 + ...11\346\220\234\347\264\242\346\240\221.py" | 20 ++-- 3 files changed, 60 insertions(+), 55 deletions(-) diff --git a/Week03/.idea/workspace.xml b/Week03/.idea/workspace.xml index d1fa8f889..4bd47a68a 100644 --- a/Week03/.idea/workspace.xml +++ b/Week03/.idea/workspace.xml @@ -2,18 +2,10 @@ - - - - - - - - - + - + + + + + + + + + + + + + + @@ -340,29 +423,53 @@ - - + - - - - - - + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -451,13 +628,6 @@ - - - - - - - @@ -469,9 +639,6 @@ - - - @@ -482,26 +649,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -568,6 +715,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\351\233\266\351\222\261\345\205\221\346\215\242.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\351\233\266\351\222\261\345\205\221\346\215\242.py" new file mode 100644 index 000000000..cd16c55b0 --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_2_\351\233\266\351\222\261\345\205\221\346\215\242.py" @@ -0,0 +1,34 @@ +class Solution: + from typing import List + def coinChange(self, coins: List[int], amount: int) -> int: + def dfs(coins, amount, i, count, res): # 如果当前coin用完了,就换面值更小的 + if amount == 0: return min(count, res) + if i == -1: return res#已经遍历完所有coin + #current layer + multiple = amount//coins[i] + while multiple >= 0 and multiple + count < res:#这里往往是一个循环要么是for,要么是while + res = dfs(coins,amount-multiple*coins[i], i-1, count+multiple, res)#count用来记录上一层的组合数 + multiple -= 1 + return res # 回溯结束 + if amount == 0: return 0 + coins.sort() + result = dfs(coins, amount, len(coins)-1, 0, float('inf')) + return result if result != float('inf') else -1 + + #动态规划 + def coinChangeI(self, coins: List[int], amount: int) -> int: + dp = [float('inf')] * (amount + 1) + dp[0] = 0 + for cur in range(amount + 1): + for coin in coins: # 往当前位置的前[coins]个位置看,取最小的+1 + if cur >= coin: # 如果cur bool: + if not bills: return True + five, ten = 0, 0 + for bill in bills: + if bill == 5: + five += 1 + elif bill == 10: + if five == 0: return False + five, ten = five - 1, ten + 1 + else:#change 15 + if five and ten: + five, ten = five - 1, ten - 1 + elif five >= 3: + five = five - 3 + else: + return False + return True diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_3_\351\245\274\345\271\262\345\210\206\345\217\221.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_3_\351\245\274\345\271\262\345\210\206\345\217\221.py" new file mode 100644 index 000000000..4c82ebcb2 --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_3_\351\245\274\345\271\262\345\210\206\345\217\221.py" @@ -0,0 +1,18 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/3 10:08 PM + +class Solution: + #1.贪心法 + def findContentChildren(self, A: List[int], B: List[int]) -> int: + A.sort()#胃口 + B.sort()#饼干value + #优先满足胃口小的孩子 + res = 0 + i, j = 0, 0 + while j < len(B) and i < len(A): + if B[j]>=A[i]:#如果当前值大于胃口值 + res = res + 1 + i = i + 1 + j = j + 1 + return res \ No newline at end of file diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_4_\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_4_\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204.py" new file mode 100644 index 000000000..cbee7ff2b --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_4_\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204.py" @@ -0,0 +1,21 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/6 12:12 AM + +class Solution: + def search(self, nums: List[int], target: int) -> int: + if not nums: return -1 + left, right = 0, len(nums)-1 + while left <= right: + mid = (left + right)>>1 + if target == nums[mid]: + return mid + if nums[mid] >= nums[left]: + if nums[left] <= target <= nums[mid]:#用两个点夹住target + right = mid - 1 + else: left = mid + 1 + else: + if nums[mid] <= target <= nums[right]:#用两个点夹住target + left = mid + 1 + else: right = mid - 1 + return -1 \ No newline at end of file diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_5_x\347\232\204\345\271\263\346\226\271\346\240\271.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_5_x\347\232\204\345\271\263\346\226\271\346\240\271.py" new file mode 100644 index 000000000..208f0d783 --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_5_x\347\232\204\345\271\263\346\226\271\346\240\271.py" @@ -0,0 +1,28 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/5 10:27 PM + +class Solution: + def mySqrt(self, x: int) -> int: + #1.换底公式求解 + # if x == 0: return 0 + # res = int(math.exp(0.5 * math.log(x))) + # return res + 1 if (res + 1) ** 2 <= x else res + #2.二分法 + # left, right, = 0, x + # while left <= right: + # mid = (left + right) // 2 + # if mid ** 2 <= x: # x的整数部分的平方<=x + # res, left = mid, mid + 1 + # else: + # right = mid - 1 + # return res + #3.牛顿法迭代求解 + if x == 0: return 0 + x0 = A = float(x) + while True: + x1 = (x0 + A/x0)//2 + if abs(x1-x0)<1e-6: + break + x0 = x1 + return int(x0) \ No newline at end of file diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_5_\346\234\211\346\225\210\347\232\204\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_5_\346\234\211\346\225\210\347\232\204\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py" new file mode 100644 index 000000000..9459cba12 --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_5_\346\234\211\346\225\210\347\232\204\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py" @@ -0,0 +1,25 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/5 10:44 PM + +class Solution: + def isPerfectSquare(self, num: int) -> bool: + # 二分法 + # left, right, res = 0, num//2+1, 0 + # while left <= right: + # mid = (left+right)//2 + # if mid*mid < num: + # left = mid + 1 + # elif mid*mid >num: + # right = mid - 1 + # else: + # res = mid + # break + # return res**2 == num + # 拟牛顿法 + if num < 2: return True + x = num // 2 + while x * x > num: + x = (x + num // x) // 2 + return x * x == num + diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204.py" new file mode 100644 index 000000000..d1881d66d --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204.py" @@ -0,0 +1,23 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/6 6:57 PM +import math +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + #排列组合Cm-1,m+n-2 + # return int(math.factorial(m + n - 2) / math.factorial(m - 1) / math.factorial(n - 1)) + #动态规划 + dp = [[0] * n for _ in range(m)] + for i in range(n): + dp[0][i] = 1 + for j in range(m): + dp[j][0] = 1 + for i in range(1,m): + for j in range(1,n): + dp[i][j] = dp[i-1][j] + dp[i][j-1] + return dp[m - 1][n - 1] + +m, n = 3, 7 +s = Solution() +res = s.uniquePaths(m,n) +print(res) diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204II.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204II.py" new file mode 100644 index 000000000..28e273166 --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\270\215\345\220\214\350\267\257\345\276\204II.py" @@ -0,0 +1,30 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/6 7:36 PM +from typing import List +class Solution: + def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: + if not obstacleGrid or len(obstacleGrid)==0: return 0 + m, n = len(obstacleGrid),len(obstacleGrid[0]) + dp = [[0] * n for _ in range(m)] + for i in range(n): + if obstacleGrid[0][i]==0: + dp[0][i] = 1 + for j in range(m): + if obstacleGrid[j][0]==0: + dp[j][0] = 1 + for i in range(1,m): + for j in range(1,n): + if obstacleGrid[i][j]==0: + dp[i][j] = dp[i-1][j] + dp[i][j-1] + return dp[m - 1][n - 1] + +nums = [ + [0,0,0,0,0,0], + [0,1,0,0,0,0], + [0,0,0,0,0,0] +] +nums1 = [[1,0]] +s =Solution() +res = s.uniquePathsWithObstacles(nums1) +print(res) \ No newline at end of file diff --git "a/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py" "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py" new file mode 100644 index 000000000..4f69ef606 --- /dev/null +++ "b/Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py" @@ -0,0 +1,67 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/6 12:25 AM + +from typing import List +class Solution: + def searchMatrix(self, matrix: List[List[int]], target: int) -> bool: + if not matrix: return False + raws = len(matrix) + cols = len(matrix[0]) + if raws == 0 or cols == 0: + return False + raw, col = 0, cols - 1 + # 方法一:从右上角开始搜索,时间复杂度为O(N+M)) + while raw < raws and col >=0: + if matrix[raw][col] == target: + return True + elif matrix[raw][col] < target: + raw += 1 + else: + col -= 1 + return False + # 方法二:二分查找 + def searchMatrixI(self, matrix: List[List[int]], target: int) -> bool: + if not matrix: return False + raws = len(matrix) + if len(matrix[0]) == 0: return False + cols = len(matrix[0]) + if not matrix: return False + raws, cols = len(matrix), len(matrix[0]) + up, bottom = 0, raws - 1 + while up <= bottom: + row = (up + bottom) >> 1 + if matrix[row][0] == target: + return True + elif matrix[row][0] < target: + up = row + 1 + else: + bottom = row - 1 + raw = bottom + left, right = 0, cols - 1 + while left <= right: + mid = (left + right) >> 1 + if matrix[raw][mid] == target: + return True + elif matrix[raw][mid] < target: + left = mid + 1 + else: + right = mid - 1 + return False + #代码简化版 二分查找 + def searchMatrixII(self, matrix: List[List[int]], target: int) -> bool: + m = len(matrix) + if m == 0: return False + n = len(matrix[0]) + left, right = 0, m * n - 1 + while left <= right: + pivot_idx = (left + right) // 2 + pivot_element = matrix[pivot_idx // n][pivot_idx % n]#刚好可以得到行列号 + if target == pivot_element: + return True + else: + if target < pivot_element: + right = pivot_idx - 1 + else: + left = pivot_idx + 1 + return False From 9fc7c336f75244408d43cab334f03cd76c7c78ca Mon Sep 17 00:00:00 2001 From: mqray Date: Fri, 10 Jul 2020 00:50:16 +0800 Subject: [PATCH 077/105] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/.idea/workspace.xml | 145 ++++++++---------- Week02/NOTE.md | 2 +- ...57\345\276\204\346\200\273\345\222\214.py" | 3 + 3 files changed, 71 insertions(+), 79 deletions(-) create mode 100644 "Week04/\346\257\217\346\227\245\344\270\200\351\242\2307_6_\344\272\214\345\217\211\346\240\221\350\267\257\345\276\204\346\200\273\345\222\214.py" diff --git a/Week02/.idea/workspace.xml b/Week02/.idea/workspace.xml index 883ed115e..d5e802482 100644 --- a/Week02/.idea/workspace.xml +++ b/Week02/.idea/workspace.xml @@ -2,7 +2,13 @@ + + + + + + - + - - + + @@ -78,16 +85,16 @@ - + - + - - + + @@ -99,7 +106,6 @@ - @@ -117,7 +123,7 @@ - + @@ -129,7 +135,7 @@ - + @@ -150,7 +156,7 @@ - + @@ -233,7 +239,6 @@ - @@ -245,6 +250,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1594649979031 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Week06/NOTE.md b/Week06/NOTE.md index 50de30414..787d8255f 100644 --- a/Week06/NOTE.md +++ b/Week06/NOTE.md @@ -1 +1,195 @@ -学习笔记 \ No newline at end of file +学习笔记 + +#### 三角形的最小路径和 +1. 分治 | 递归模板 +每次只能走它下一层的左和右,那么自然想到分治算法 F[i,j] = min(F[i+1,j],F[i+1,j+1])+a[i,j] +写的过程中,就是递归的模板嘛 这种算法时间复杂度是O(2^N),没通过,加上缓存@lru_cache +```python +class Solution: + def minimumTotal(self, triangle: List[List[int]]) -> int: + # 分治 递归模板 + from functools import lru_cache + @lru_cache(None) + def dfs(i, j): + #terminator + if i == size-1: return triangle[i][j] + left = dfs(i+1,j)#加左边的值 + right = dfs(i+1,j+1) + min_val = min(left, right) + triangle[i][j] + return min_val + size = len(triangle) + return dfs(0,0) +``` +2.DP +DP过程: +1) opt subproblem,这个分治算法已经帮我们解决了 +2) DP Array,合理定义DP数组的含义 +3)DP transfer equal,写出状态转移方程 +DP通常由两种,top-down和bottom-up +还是按照分治思想,我们采用top-down的思想 +```python +class Solution: + def minimumTotal(self, triangle: List[List[int]]) -> int: + # 2.top-down + dp = triangle + for i in range(1, len(triangle)): + for j in range(len(triangle[i])): + if j == 0: + dp[i][j] += triangle[i-1][j] + elif j == len(triangle[i])-1: + dp[i][j] += triangle[i-1][j-1] + else: + dp[i][j] += min(triangle[i-1][j-1], triangle[i-1][j]) + return min(dp[-1]) +``` +可以看到上述top-down代码中有几个分支判断,这是由于能走的路径只是下三角,要考虑数组越界的情形。 +其次,上述的dp我们只是引用了,其实可以直接复用原数组 +3.bottom-up 空间复杂度只有O(N)了 +```python +class Solution: + def minimumTotal(self, triangle: List[List[int]]) -> int: + dp = triangle[-1] + for i in range(len(triangle) - 2, -1, -1): + for j in range(len(triangle[i])): + dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j] + return dp[0] +``` +4.复用原数组 节省空间 +```python +class Solution: + def minimumTotal(self, triangle: List[List[int]]) -> int: + for i in range(len(triangle)-2,-1,-1): + for j in range(len(triangle[i])): + triangle[i][j] += min(triangle[i+1][j],triangle[i+1][j+1]) + return triangle[0][0] +``` + +#### 最大子序和 +由于数组中有可能存在的赋负数,所以在累加的时候,如果f(i-1)+nums[i] < nums[i],就要丢弃前面f(i-1)的和了 +```python +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + dp = [0]*len(nums) + dp[0], max_val = nums[0], nums[0] + for i in range(1,len(nums)): + dp[i] = max(dp[i-1],0) + nums[i] + # max_val = max(dp[i], max_val) + return max(dp) + # return max_val +``` +当然,这里我们也可以复用原数组 +```python +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + for i in range(1,len(nums)): + nums[i] = max(nums[i-1], 0) + nums[i] + return max(nums) +``` + +#### 乘积最大的子数组 +```python +class Solution: + def maxProduct(self, nums: List[int]) -> int: + if not nums: return 0 + if len(nums) == 1: return nums[0] + dp_min, dp_max = [0] * len(nums), [0] * len(nums) # dp_max记录正负交替乘法中的最大值 + dp_min[0], dp_max[0] = nums[0], nums[0] + res = nums[0] + for i in range(1, len(nums)): + if nums[i] >= 0: + # 如果此时nums[i]大于0,如果之前是正数,那就乘上,如果是负数,那此时的最大值为此时的值 + dp_max[i] = max(nums[i], dp_max[i - 1] * nums[i]) + # 此时原本小于0,最小值就应该乘上nums[i];如果原本大于0,那最小的就应该是此时的值 + dp_min[i] = min(nums[i], dp_min[i - 1] * nums[i]) + else: # 此时nums[i]小于0 + # 如果原本dp_min小于0,它乘上num可能是最大值;如果原来是正值,(+值*负值和负值) 中要求大值 + dp_max[i] = max(dp_min[i - 1] * nums[i], nums[i]) + dp_min[i] = min(dp_max[i - 1] * nums[i], nums[i]) + res = max(res, dp_max[i]) + return res +``` +上面的代码看上去有些冗余,考虑是否能优化 +可以看到记录大值和小值时是用max和min,考虑以此考虑合并 +[说实话 我被这题搞吐了,气死我了😤] +```python +class Solution: + def maxProduct(self, nums: List[int]) -> int: + if not nums: return 0 + if len(nums) == 1: return nums[0] + dp_min, dp_max = [0] * len(nums), [0] * len(nums) # dp_max记录正负交替乘法中的最大值 + dp_min[0], dp_max[0] = nums[0], nums[0] + res = nums[0] + for i in range(1, len(nums)): + dp_max[i] = max(nums[i],nums[i]*dp_max[i-1],dp_min[i-1]*nums[i]) + dp_min[i] = min(nums[i],nums[i]*dp_max[i-1],dp_min[i-1]*nums[i]) + # dp_max[i] = max(max(nums[i],nums[i]*dp_max[i-1]),dp_min[i-1]*nums[i]) + # dp_min[i] = min(min(nums[i],nums[i]*dp_max[i-1]),dp_min[i-1]*nums[i]) + + # if nums[i] >= 0: + # dp_max[i] = max(nums[i], dp_max[i - 1] * nums[i]) + # dp_min[i] = min(nums[i], dp_min[i - 1] * nums[i]) + # else: # 此时nums[i]小于0 + # dp_max[i] = max(dp_min[i - 1] * nums[i], nums[i]) + # dp_min[i] = min(dp_max[i - 1] * nums[i], nums[i]) + res = max(res, dp_max[i]) + return res +``` +观察上面的执行过程,其实我们使用到的dp_max和dp_min我们在计算过程中,都只使用到了最后一个,考虑进行空间优化 +```python +class Solution: + def maxProduct(self, nums: List[int]) -> int: + if not nums: return + res,pre_max,pre_min = nums[0],nums[0],nums[0] + for num in nums[1:]: + cur_max = max(pre_max * num, pre_min * num, num) + cur_min = min(pre_max * num, pre_min * num, num) + res = max(res, cur_max) + pre_max = cur_max + pre_min = cur_min + return res +``` + +#### 打家劫舍 +1.定义`dp[i][0,1]`为到第i个房子能取得的max_val,0代表不取,1代表取 +所以有 `dp[i][0]=max(dp[i-1][0],dp[i-1][1])`i不偷,那么i-1可偷可不偷 +`dp[i][1]=dp[i-1][0]+nums[i]`确定i偷,那么i-1不偷 +```python +class Solution: + def rob(self, nums: List[int]) -> int: + if not nums: return 0 + dp = [[0]*2 for _ in range(len(nums))] + dp[0][0],dp[0][1] = 0, nums[0] + for i in range(1,len(nums)): + dp[i][0] = max(dp[i-1][0],dp[i-1][1])#i不偷,那么i-1可偷可不偷 + dp[i][1] = dp[i-1][0] + nums[i]#确定i偷,那么i-1不偷 + return max(dp[-1][0],dp[-1][1]) +``` +2.定义为dp[i]为i偷的时候的最大值,那么有:`dp[i]=max(dp[i-1],dp[i-2]+nums[i])` +```python +class Solution: + def rob(self, nums: List[int]) -> int: + if not nums: return 0 + dp = [0]*(len(nums)+1) + dp[1] = nums[0] + for i in range(2,len(nums)+1): + dp[i] = max(dp[i-1],dp[i-2]+nums[i-1]) + return dp[-1] +``` +同样的在更新dp的时候也只是使用到了前面两个值,这里考虑空间优化 +```python +class Solution: + def rob(self, nums: List[int]) -> int: + pre_max, cur_max = 0,0 + for i in range(len(nums)): + # tmp = cur_max + # cur_max = max(cur_max,nums+pre_max) + # pre_max = tmp + pre_max, cur_max = cur_max, max(cur_max,pre_max+nums[i]) + return cur_max +``` + + + + + + diff --git "a/Week06/\344\270\215\345\220\214\350\267\257\345\276\204.py" "b/Week06/\344\270\215\345\220\214\350\267\257\345\276\204.py" new file mode 100644 index 000000000..f8937ddec --- /dev/null +++ "b/Week06/\344\270\215\345\220\214\350\267\257\345\276\204.py" @@ -0,0 +1,3 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/13 10:19 PM \ No newline at end of file diff --git "a/Week06/\344\270\215\345\220\214\350\267\257\345\276\204II.py" "b/Week06/\344\270\215\345\220\214\350\267\257\345\276\204II.py" new file mode 100644 index 000000000..9b9ba30e0 --- /dev/null +++ "b/Week06/\344\270\215\345\220\214\350\267\257\345\276\204II.py" @@ -0,0 +1,28 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/13 10:20 PM +from typing import List +class Solution: + def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: + m, n = len(obstacleGrid), len(obstacleGrid[0]) + if obstacleGrid[0][0] == 1:return 0 + dp = [[0 for _ in range(n)] for _ in range(m)] + dp[0][0] = 1 + for i in range(1, m): + if obstacleGrid[i][0] == 0: + dp[i][0] = dp[i-1][0]#在dp数组中进行转移 + for j in range(1, n): + if obstacleGrid[0][j] == 0: + dp[0][j] = dp[0][j-1] + print(dp) + for i in range(1, m): + for j in range(1, n): + if obstacleGrid[i][j] == 1: + dp[i][j] = 0 + else: + dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + return dp[m - 1][n - 1] + +s = Solution() +res = s.uniquePathsWithObstacles([[0,0],[1,1],[0,0]]) +print(res) \ No newline at end of file diff --git "a/Week06/\344\271\230\347\247\257\346\234\200\345\244\247\347\232\204\345\255\220\346\225\260\347\273\204.py" "b/Week06/\344\271\230\347\247\257\346\234\200\345\244\247\347\232\204\345\255\220\346\225\260\347\273\204.py" new file mode 100644 index 000000000..b86d1a2f3 --- /dev/null +++ "b/Week06/\344\271\230\347\247\257\346\234\200\345\244\247\347\232\204\345\255\220\346\225\260\347\273\204.py" @@ -0,0 +1,41 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/14 9:15 PM + +from typing import List +class Solution: + def maxProduct(self, nums: List[int]) -> int: + if not nums: return 0 + if len(nums) == 1: return nums[0] + dp_min, dp_max = [0] * len(nums), [0] * len(nums) # dp_max记录正负交替乘法中的最大值 + dp_min[0], dp_max[0] = nums[0], nums[0] + res = nums[0] + for i in range(1, len(nums)): + if nums[i] >= 0: + # 如果此时nums[i]大于0,如果之前是正数,那就乘上,如果是负数,那此时的最大值为此时的值 + dp_max[i] = max(nums[i], dp_max[i - 1] * nums[i]) + # 此时原本小于0,最小值就应该乘上nums[i];如果原本大于0,那最小的就应该是此时的值 + dp_min[i] = min(nums[i], dp_min[i - 1] * nums[i]) + else: # 此时nums[i]小于0 + # 如果原本dp_min小于0,它乘上num可能是最大值;如果原来是正值,(+值*负值和负值) 中要求大值 + dp_max[i] = max(dp_min[i - 1] * nums[i], nums[i]) + dp_min[i] = min(dp_max[i - 1] * nums[i], nums[i]) + res = max(res, dp_max[i]) + return res + # dp_max = [1] * (len(nums)+1) + # dp_min = [1] * (len(nums)+1) + # for i in range(1, len(nums)+1): + # dp_max[i] = max(dp_max[i - 1] * nums[i-1], dp_min[i - 1] * nums[i-1], nums[i-1]) + # dp_min[i] = min(dp_max[i - 1] * nums[i-1], dp_min[i - 1] * nums[i-1], nums[i-1]) + # return max(dp_max) + + + +s = Solution() +# nums = [2,3,-2,-4] +# nums = [3,-1,4] +# nums = [0, 2] +# nums = [2,3,-2,4] +nums = [2,-5,-2,-4,3] +res = s.maxProduct(nums) +print(res) diff --git "a/Week06/\345\207\272\347\216\260\346\254\241\346\225\260\346\234\200\345\244\232\347\232\204\345\205\203\347\264\240.py" "b/Week06/\345\207\272\347\216\260\346\254\241\346\225\260\346\234\200\345\244\232\347\232\204\345\205\203\347\264\240.py" new file mode 100644 index 000000000..4e4a5aede --- /dev/null +++ "b/Week06/\345\207\272\347\216\260\346\254\241\346\225\260\346\234\200\345\244\232\347\232\204\345\205\203\347\264\240.py" @@ -0,0 +1,20 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/14 6:41 PM + +nums = [2,5,5,2,4,4] +size = len(nums) +delta = 1000 +for i in range(size): + times = nums[i] %delta + nums[times] += delta + nums[i] -= times + print(nums) +MAX=0 +res=0 +for i in range(size): + print("数字",i,"在数组中出现的次数:",nums[i]//delta) + if MAX <= nums[i]//delta: + MAX = nums[i]//delta + res = i +print("出现次数最多的数字",res) \ No newline at end of file diff --git "a/Week06/\346\211\223\345\256\266\345\212\253\350\210\215I.py" "b/Week06/\346\211\223\345\256\266\345\212\253\350\210\215I.py" new file mode 100644 index 000000000..86fe7e718 --- /dev/null +++ "b/Week06/\346\211\223\345\256\266\345\212\253\350\210\215I.py" @@ -0,0 +1,30 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/15 11:13 PM + +from typing import List +class Solution: + def rob(self, nums: List[int]) -> int: + # if not nums: return 0 + # dp = [[0]*2 for _ in range(len(nums))] + # dp[0][0],dp[0][1] = 0, nums[0] + # for i in range(1,len(nums)): + # dp[i][0] = max(dp[i-1][0],dp[i-1][1])#i不偷,那么i-1可偷可不偷 + # dp[i][1] = dp[i-1][0] + nums[i]#确定i偷,那么i-1不偷 + # return max(dp[-1][0],dp[-1][1]) + + # i偷的max_val = max(f(i-1),f(i-2)+nums[i]) + # if not nums: return 0 + # dp = [0]*(len(nums)+1) + # dp[1] = nums[0] + # for i in range(2,len(nums)+1): + # dp[i] = max(dp[i-1],dp[i-2]+nums[i-1]) + # return dp[-1] + pre_max, cur_max = 0, 0 + for i in range(len(nums)): + # tmp = cur_max + # cur_max = max(cur_max,nums+pre_max) + # pre_max = tmp + pre_max, cur_max = cur_max, max(cur_max, pre_max + nums[i]) + return cur_max + diff --git "a/Week06/\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py" "b/Week06/\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py" new file mode 100644 index 000000000..95fc95d23 --- /dev/null +++ "b/Week06/\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py" @@ -0,0 +1,19 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/14 8:28 PM + +from typing import List +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + dp = [0] * len(nums) + dp[0], max_val = nums[0], nums[0] + for i in range(1, len(nums)): + dp[i] = max(dp[i - 1] + nums[i], nums[i]) + max_val = max(dp[i], max_val) + # return max(dp) + return max_val + + +s = Solution() +res = s.maxSubArray([-2,1,-3,4,-1,2,1,-5,4]) +print(res) diff --git "a/Week06/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" "b/Week06/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" new file mode 100644 index 000000000..c78aadb81 --- /dev/null +++ "b/Week06/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" @@ -0,0 +1,22 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/13 11:08 PM + +class Solution: + def longestCommonSubsequence(self, text1: str, text2: str) -> int: + if text1 == '' or text2 == '': return 0 + m, n = len(text1), len(text2) + dp = [[0]*(n + 1) for _ in range(m + 1)] + for i in range(1, m + 1): + for j in range(1, n + 1): + if text1[i-1] == text2[j-1]: + dp[i][j] = dp[i-1][j-1] + 1 + else: + dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + return dp[-1][-1] + +s = Solution() +text1 = "abcde" +text2 = "ace" +res = s.longestCommonSubsequence(text1,text2) +print(res) \ No newline at end of file diff --git "a/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206.py" "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206.py" new file mode 100644 index 000000000..73a76e57d --- /dev/null +++ "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206.py" @@ -0,0 +1,23 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/13 11:59 PM + +from typing import List +class Solution: + def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: + # 1.暴力解法 时间复杂度O(M*N),空间复杂度O(1) + # res = [num for num in nums1 if num in nums2] + # return set(res) + # 2.hashmap 时间复杂度O(M+N),空间复杂度O(min(M,N)) + # hashmap, res = {}, [] + # for num in nums1: + # hashmap[num] = hashmap.get(num, 0) + 1 + # for num in nums2: + # if hashmap.get(num): # 能get到内容时,才加入res + # res.append(num) + # hashmap[num] -= 1 + # return set(res) + # 3.奇技淫巧 时间复杂度应该是O(M+N),空间复杂度O(M+N) + set1 = set(nums1) + set2 = set(nums2) + return list(set1 ^ set2) diff --git "a/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II.py" "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II.py" new file mode 100644 index 000000000..7819af580 --- /dev/null +++ "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_13_\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II.py" @@ -0,0 +1,40 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/13 11:40 PM + +from typing import List +class Solution: + def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]: + #1.hashmap 时间复杂度O(M+N),空间复杂度O(max(M,N)),可以优化为min + # hashmap,res = {}, [] + # for num in nums1: + # hashmap[num] = hashmap.get(num,0) + 1 + # for num in nums2: + # if hashmap.get(num):#能get到内容时,才加入res + # res.append(num) + # hashmap[num] -= 1 + # return res + # 假如两个数组排好序,如何优化你的算法 + # 时间复杂度O(NlogN+MlogM),空间复杂度O(min(M,N)) + # 如果一个长度很短一个长度很小,采用法2好,查询开销小 + # 若内存有限,法1好,只涉及到查询,而不用在内存中排序 + nums1.sort() + nums2.sort() + res, p1, p2 = [], 0, 0 + size1, size2 = len(nums1), len(nums2) + while p1 < size1 and p2 < size2: + if nums1[p1] == nums2[p2]: + res.append(nums1[p1]) + p1, p2 = p1 + 1, p2 + 1 + elif nums1[p1] > nums2[p2]: + p2 = p2 + 1 + else: + p1 = p1 + 1 + return res +# nums1 = [1,2,2,1] +# nums2 = [2,2] +nums1 = [1,2,2,1] +nums2 = [2,2,2] +s = Solution() +res = s.intersect(nums1,nums2) +print(res) \ No newline at end of file diff --git "a/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" new file mode 100644 index 000000000..de45b1992 --- /dev/null +++ "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" @@ -0,0 +1,44 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/14 12:43 AM + +from typing import List +class Solution: + def minimumTotal(self, triangle: List[List[int]]) -> int: + # 1.分治 F[i,j] = min(F[i+1,j],f[i,j+1]) + a[i,j] + # from functools import lru_cache + # @lru_cache(None) + # def dfs(row,col): + # if row == size - 1:return triangle[row][col] + # left = dfs(row+1,col) + # right = dfs(row+1,col+1) + # return min(left,right) + triangle[row][col] + # size = len(triangle) + # return dfs(0,0) + + # res = triangle[-1] + # for i in xrange(len(triangle)-2, -1, -1): + # for j in xrange(len(triangle[i])): + # res[j] = min(res[j], res[j+1]) + triangle[i][j] + # return res[0] + # dp = triangle + # for i in range(len(dp)-2,-1,-1): + # for j in range(len(dp[i])): + # dp[i][j] = min(dp[i+1][j],dp[i+1][j+1]) + dp[i][j] + # return dp[0][0] + dp = triangle[-1] + for i in range(len(triangle) - 2, -1, -1): + for j in range(len(triangle[i])): + dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j] + return dp[0] + + +nums = [ + [2], + [3,4], + [6,5,7], + [4,1,8,3] +] +s = Solution() +res = s.minimumTotal(nums) +print(res) diff --git "a/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" new file mode 100644 index 000000000..15499717e --- /dev/null +++ "b/Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_14_\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" @@ -0,0 +1,14 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/15 12:41 AM + + +class Solution: + def numTrees(self, n: int) -> int: + # G = sum(F(I,N)) + G = [0]*(n+1) + G[0], G[1] = 1, 1 + for i in range(2, n+1): + for j in range(1, i+1): + G[i] += G[j-1] * G[i-j] + return G[n] diff --git "a/Week06/\351\233\266\351\222\261\345\205\221\346\215\242.py" "b/Week06/\351\233\266\351\222\261\345\205\221\346\215\242.py" new file mode 100644 index 000000000..297f78a2f --- /dev/null +++ "b/Week06/\351\233\266\351\222\261\345\205\221\346\215\242.py" @@ -0,0 +1,28 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/15 12:38 AM + +from typing import List +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + # @functools.lru_cache(amount) + # def dfs(coins,amount,i,count,res): + # if amount == 0: return min(count,res) + # if i == -1: return res#coins下标为0还没有使得amount=0,那么找不到了 + # m = amount//coins[i] + # while m >= 0 and m+count < res: + # res = dfs(coins,amount-m*coins[i],i-1,m+count,res) + # m = m - 1 + # return res + # coins.sort() + # res = dfs(coins,amount,len(coins)-1,0,float('inf')) + # return res if res!=float('inf') else -1 + dp = [float('inf')] * (amount + 1) + dp[0] = 0 + for i in range(amount + 1): + for coin in coins: + if i >= coin: # 实际上是min(dp[i-coin1]+1,dp[i-coin2]+1,dp[i-coin3]+1) + dp[i] = min(dp[i - coin] + 1, dp[i]) + return dp[-1] if dp[-1] != float('inf') else -1 + + From 810fecc03bccd4101cc1598d994b5dd026640175 Mon Sep 17 00:00:00 2001 From: mqray Date: Fri, 17 Jul 2020 02:27:53 +0800 Subject: [PATCH 081/105] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=82=A1=E7=A5=A8?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week06/.idea/workspace.xml | 295 ++++++++++++------ Week06/NOTE.md | 92 ++++++ ...0\344\275\263\346\227\266\346\234\272I.py" | 40 +++ ...\344\275\263\346\227\266\346\234\272II.py" | 14 + ...344\275\263\346\227\266\346\234\272III.py" | 59 ++++ ...3\345\256\266\345\212\253\350\210\215I.py" | 15 +- ...\345\256\266\345\212\253\350\210\215II.py" | 21 ++ 7 files changed, 444 insertions(+), 92 deletions(-) create mode 100644 "Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272I.py" create mode 100644 "Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II.py" create mode 100644 "Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" create mode 100644 "Week06/\346\211\223\345\256\266\345\212\253\350\210\215II.py" diff --git a/Week06/.idea/workspace.xml b/Week06/.idea/workspace.xml index 1e7b2f532..733b75859 100644 --- a/Week06/.idea/workspace.xml +++ b/Week06/.idea/workspace.xml @@ -2,30 +2,23 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + - + @@ -50,27 +45,27 @@ - + - + - - + + - + - + @@ -78,55 +73,79 @@ - + - - + + - + + + + + + + + + + + + + - + - - + + + + + - + - - + + + + + + + + + + + - + - - - - - - - + + + + + + + - - + + - + @@ -153,15 +172,6 @@ - - - - - - - - - @@ -171,15 +181,6 @@ - - - - - - - - - @@ -206,8 +207,12 @@ @@ -260,7 +265,7 @@ - + - + - + - + - + - - - - + + + + + + + + - - - - @@ -406,7 +411,7 @@ - + @@ -416,7 +421,7 @@ - + @@ -428,6 +433,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + file://$PROJECT_DIR$/打家劫舍II.py + 14 + + + file://$PROJECT_DIR$/打家劫舍II.py + 15 + + + file://$PROJECT_DIR$/打家劫舍II.py + 19 + + + file://$PROJECT_DIR$/买卖股票的最佳时机I.py + 38 + + + file://$PROJECT_DIR$/买卖股票的最佳时机I.py + 25 + + + file://$PROJECT_DIR$/买卖股票的最佳时机I.py + 26 + + + file://$PROJECT_DIR$/买卖股票的最佳时机I.py + 27 + + + file://$PROJECT_DIR$/买卖股票的最佳时机I.py + 28 + + + file://$PROJECT_DIR$/买卖股票的最佳时机I.py + 30 + + @@ -533,20 +609,57 @@ - - - - - - - + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Week06/NOTE.md b/Week06/NOTE.md index 787d8255f..f81c841d4 100644 --- a/Week06/NOTE.md +++ b/Week06/NOTE.md @@ -188,6 +188,98 @@ class Solution: return cur_max ``` +#### 买卖股票的最佳时机I +1.暴力解法 枚举每第i天买第j天抛除的所有可能,记录并返回最大值 (感觉是动态规划的一种) +```python +from typing import List +class Solution: + # 只能买卖一次 + def maxProfit(self, prices: List[int]) -> int: + # 暴力法 O(N^2)枚举第i天买入第j天卖出,记录最大值 + res = 0 + for i in range(len(prices)-1): + for j in range(i+1,len(prices)): + res = max(res,prices[j]-prices[i]) + return res +``` +2.动态规划 累计到第i天的最大收益为 第i-1天的最大收益值 和 第i天股票价格与当前历史最低股价差值 之间的最大值 +```python +from typing import List +class Solution: + # 只能买卖一次 + def maxProfit(self, prices: List[int]) -> int: + if not prices: return 0 + dp = [0] * len(prices) + lowest = prices[0] + for i in range(1, len(prices)): + if prices[i] < lowest: + lowest = prices[i] + dp[i] = max(dp[i - 1], prices[i] - lowest)#状态转移只与前一个状态有关 + return dp[-1] +``` +3. 看到labuladong的题解,里面对空间降维有这样一句描述 由于状态转化过程仅与前一个状态相关,所以可以用变量来存储 +对程序稍作修改,第一次难免会犯错 +```python +from typing import List +class Solution: + # 只能买卖一次 + def maxProfit(self, prices: List[int]) -> int: + pre, cur, lowest = 0,0,prices[0] + for i in range(len(prices)): + if prices[i] < lowest: + lowest = prices[i] + cur = max(cur,prices[i]-lowest) + # pre, cur = cur, max(cur, prices[i]-lowest) + print(pre,cur) + # return max(cur,pre) + return cur +``` +刚开始就想着那就拿两个数来存咯,然后在返回结果的时候就发现cur并不是最大的 打印pre,cur才知道转移过程写错了 +思考后,发现两个状态转移,一个变量就搞定了 所以有了上面的最终代码 + +#### 买卖股票的最佳时机II 可以买卖股票多次 +由于没有对买卖次数进行限制,我们可以找到股票图里所有上升段进行求和 +```python +from typing import List +class Solution: + #可以买卖K次 + def maxProfit(self, prices: List[int]) -> int: + if not prices: return 0 + res = 0 + for i in range(1,len(prices)): + if prices[i] > prices[i-1]: + res += prices[i] - prices[i-1] + return res +``` +#### 买卖股票的最佳时机III 只能买卖两次 +考虑用二维数组做,dp[i][0,1,2,3]表示到i天买卖0-3次时 最大收益,这样定义状态的原因是因为限定了k=2,所以只有五种状态(原始状态+1) +```python +from typing import List +class Solution: + def maxProfit(self, prices: List[int]) -> int: + if not prices: return 0 + #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次 + # dp = [[0]*len(prices) for _ in range(2*2+1)] + dp = [[0]*5 for _ in range(len(prices))] + dp[0][0] = dp[0][2] = dp[0][4] = 0 + dp[0][1] = dp[0][3] = -prices[0] + for i in range(1,len(prices)): + dp[i][0] = 0 #如果第i天没有买入,那么只可能i-1天没有买入 + #第i天买入一次,可能是i-1天未买i天买 或 第i-1天买i未买 + dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]) + #第i天买入一次卖出一次,可能是i-1天买入i天卖出或者i-1天已经买入卖出了 + dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]) + #第i天买入2次卖出1次,可能是i-1买卖(1,1)次,i天买入;也可能是是i-1天已经买卖(2,1)次 + dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i]) + # 第i天买卖(2,2)可能是i-1天买卖(2,2)也可能是i-1天买卖(2,1),i卖出 + dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i]) + #最后手头没有股票剩余,实际收益最高 + return dp[-1][4] +``` +很自然的看出,每一种状态的转移有着高度的相似性,我们考虑降维 + + + diff --git "a/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272I.py" "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272I.py" new file mode 100644 index 000000000..842b97aab --- /dev/null +++ "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272I.py" @@ -0,0 +1,40 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/16 9:06 PM + +from typing import List +class Solution: + # 只能买卖一次 + def maxProfit(self, prices: List[int]) -> int: + # 暴力法 O(N^2)枚举第i天买入第j天卖出,记录最大值 + # res = 0 + # for i in range(len(prices)-1): + # for j in range(i+1,len(prices)): + # res = max(res,prices[j]-prices[i]) + # return res + # 动态规划 到第i天获得的最大收益等于到第i-1天的最大收益 和 当前股价与当前最低股价差值之间的最大值 + + # if not prices: return 0 + # dp = [0] * len(prices) + # lowest = prices[0] + # for i in range(1, len(prices)): + # if prices[i] < lowest: + # lowest = prices[i] + # dp[i] = max(dp[i - 1], prices[i] - lowest)#状态转移只与前一个状态有关 + # return dp[-1] + # if not prices: return 0 + pre, cur, lowest = 0,0,prices[0] + for i in range(len(prices)): + if prices[i] < lowest: + lowest = prices[i] + # cur = max(cur,prices[i]-lowest) + pre, cur = cur, max(cur, prices[i]-lowest) + print(pre,cur) + # return max(cur,pre) + return cur + + + +s = Solution() +res = s.maxProfit([7,1,5,3,6,4,2,18,4]) +print(res) \ No newline at end of file diff --git "a/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II.py" "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II.py" new file mode 100644 index 000000000..ab2d2e428 --- /dev/null +++ "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II.py" @@ -0,0 +1,14 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/16 10:01 PM + +from typing import List +class Solution: + #可以买卖K次 + def maxProfit(self, prices: List[int]) -> int: + if not prices: return 0 + res = 0 + for i in range(1,len(prices)): + if prices[i] > prices[i-1]: + res += prices[i] - prices[i-1] + return res \ No newline at end of file diff --git "a/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" new file mode 100644 index 000000000..3af8a6018 --- /dev/null +++ "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" @@ -0,0 +1,59 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/17 1:36 AM + +from typing import List +class Solution: + def maxProfit(self, prices: List[int]) -> int: + if not prices: return 0 + #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次 + # dp = [[0]*len(prices) for _ in range(2*2+1)] + dp = [[0]*5 for _ in range(len(prices))] + dp[0][0] = dp[0][2] = dp[0][4] = 0 + dp[0][1] = dp[0][3] = -prices[0] + for i in range(1,len(prices)): + dp[i][0] = 0 #如果第i天没有买入,那么只可能i-1天没有买入 + #第i天买入一次,可能是i-1天未买i天买 或 第i-1天买i未买 + dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]) + #第i天买入一次卖出一次,可能是i-1天买入i天卖出或者i-1天已经买入卖出了 + dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]) + #第i天买入2次卖出1次,可能是i-1买卖(1,1)次,i天买入;也可能是是i-1天已经买卖(2,1)次 + dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i]) + # 第i天买卖(2,2)可能是i-1天买卖(2,2)也可能是i-1天买卖(2,1),i卖出 + dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i]) + #最后手头没有股票剩余,实际收益最高 + return dp[-1][4] + + + # if not prices: return 0 + #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次 + # dp = [[0]*len(prices) for _ in range(2*2+1)] + # dp = [[0]*5 for _ in range(len(prices))] + # dp[0][0] = dp[0][2] = dp[0][4] = 0 + # dp[0][1] = dp[0][3] = -prices[0] + # for i in range(1,len(prices)): + # dp[i][0] = 0 #如果第i天没有买入,那么只可能i-1天没有买入 + # #第i天买入一次,可能是i-1天未买i天买 或 第i-1天已买 + # dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]) + # #第i天买入一次卖出一次,可能是i-1天买入i天卖出或者i-1天已经买入卖出了 + # dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]) + # #第i天买入2次卖出1次,可能是i-1买卖(1,1)次,i天买入;也可能是是i-1天已经买卖(2,1)次 + # dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i]) + # # 第i天买卖(2,2)可能是i-1天买卖(2,2)也可能是i-1天买卖(2,1),i卖出 + # dp[i][4] = max(dp[i-1][4], dp[i-1][3]) + prices[i] #这一行写错了 + # #最后手头没有股票剩余,实际收益最高 + # return max(dp[-1][2],dp[-1][4]) + + # one_buy = two_buy = float('inf') + # one_profit = two_profit = 0 + # for p in prices: + # one_buy = min(one_buy, p) + # one_profit = max(one_profit, p - one_buy) + # two_buy = min(two_buy, p - one_profit) + # two_profit = max(two_profit, p - two_buy) + # return two_profit + +s = Solution() +nums = [3,3,5,0,0,3,1,4] +res = s.maxProfit(nums) +print(res) \ No newline at end of file diff --git "a/Week06/\346\211\223\345\256\266\345\212\253\350\210\215I.py" "b/Week06/\346\211\223\345\256\266\345\212\253\350\210\215I.py" index 86fe7e718..e213c415d 100644 --- "a/Week06/\346\211\223\345\256\266\345\212\253\350\210\215I.py" +++ "b/Week06/\346\211\223\345\256\266\345\212\253\350\210\215I.py" @@ -5,6 +5,15 @@ from typing import List class Solution: def rob(self, nums: List[int]) -> int: + # def dfs(nums, i): + # if i >= len(nums): + # return 0 + # # next1 = dfs(nums, start + 1) # 不打劫,去下家 + # # next2 = dfs(nums, start + 2) + nums[start] # 打劫这一家 + # # res = max(next1, next2) + # res = max(dfs(nums,i+1),dfs(nums,i+2)+nums[i]) + # return res + # return dfs(nums, 0) # if not nums: return 0 # dp = [[0]*2 for _ in range(len(nums))] # dp[0][0],dp[0][1] = 0, nums[0] @@ -23,8 +32,12 @@ def rob(self, nums: List[int]) -> int: pre_max, cur_max = 0, 0 for i in range(len(nums)): # tmp = cur_max - # cur_max = max(cur_max,nums+pre_max) + # cur_max = max(cur_max,nums+pre_max) #dp[i-1],dp[i-2] # pre_max = tmp pre_max, cur_max = cur_max, max(cur_max, pre_max + nums[i]) return cur_max +s = Solution() +res = s.rob([2,3,1]) +print(res) + diff --git "a/Week06/\346\211\223\345\256\266\345\212\253\350\210\215II.py" "b/Week06/\346\211\223\345\256\266\345\212\253\350\210\215II.py" new file mode 100644 index 000000000..0128b2ecf --- /dev/null +++ "b/Week06/\346\211\223\345\256\266\345\212\253\350\210\215II.py" @@ -0,0 +1,21 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/16 12:15 AM + +from typing import List +class Solution: + def rob(self, nums: List[int]) -> int: + def subRob(nums): + pre_max, cur_max = 0, 0 + for i in range(len(nums)): + pre_max, cur_max = cur_max, max(cur_max, pre_max + nums[i]) + return cur_max + + if not nums: return 0 + # a = subRob(nums[:-1])#抛除最后一个 + # b = subRob(nums[1:]) + return max(subRob(nums[:-1]),subRob(nums[1:])) if len(nums) != 1 else nums[0] + +s = Solution() +res = s.rob([1]) +print(res) \ No newline at end of file From f5ce40278d33c14053505ed9752df2db3d1af46c Mon Sep 17 00:00:00 2001 From: mqray Date: Fri, 17 Jul 2020 21:36:50 +0800 Subject: [PATCH 082/105] =?UTF-8?q?=E8=82=A1=E7=A5=A8=E4=B8=89=E5=9B=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week06/.idea/workspace.xml | 72 ++++++++++--------- Week06/NOTE.md | 46 ++++++++++++ ...344\275\263\346\227\266\346\234\272III.py" | 46 ++++-------- ...\344\275\263\346\227\266\346\234\272IV.py" | 37 ++++++++++ 4 files changed, 135 insertions(+), 66 deletions(-) create mode 100644 "Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272IV.py" diff --git a/Week06/.idea/workspace.xml b/Week06/.idea/workspace.xml index 733b75859..3e24f78f3 100644 --- a/Week06/.idea/workspace.xml +++ b/Week06/.idea/workspace.xml @@ -2,10 +2,7 @@ - - - - + @@ -18,7 +15,7 @@ - + - - - - - - - - - @@ -212,6 +210,7 @@ @@ -411,17 +410,17 @@ - + - + - + @@ -645,19 +644,26 @@ - - + + - + + + + + + + + - - + + diff --git a/Week06/NOTE.md b/Week06/NOTE.md index f81c841d4..5ec33cefb 100644 --- a/Week06/NOTE.md +++ b/Week06/NOTE.md @@ -277,7 +277,53 @@ class Solution: return dp[-1][4] ``` 很自然的看出,每一种状态的转移有着高度的相似性,我们考虑降维 +很显然这个状态转移,只与前一天相同状态dp[i-1][k]和前一天不同状态dp[i-1][k-1]有关,那么我们就能简化上述过程。 +【刚开始我也是去找别人的代码,发现状态转移稀奇古怪,】 +【要么是 对状态转移方程中对dp[i][1]和dp[i][3]做min操作,要么是做一些不直观的额外处理】 +【我想,既然是简化,那么状态转移过程应该与上述代码高度一致】 +【而不应该是在简化的状态转移方程中对dp[i][1]和dp[i][3]做min操作,也不应该做过多的边界处理】 +【按自己的思路对照上述方程,得如下】 +``` +class Solution: + def maxProfit(self, prices: List[int]) -> int: + in_1,in_2 = float('-inf'),float('-inf') + out_1,out_2 = 0,0 + for p in prices: + in_1 = max(in_1,-p) + out_1 = max(out_1, in_1 + p) + in_2 = max(in_2,out_1 - p) + out_2 = max(out_2, in_2 + p) + return out_2 +``` +【我做题的时候就最烦我的思路和别人不一样,要改弦更张,记忆的细节就更多了】 +【你看,现在是不是与前面的逻辑一毛一样,方便记忆】 +但是对于后面k很大,比如就是三的时候,刚开始的思路是正确,但是就要写很多,这道题我还没做,做的时候再考虑该怎么处理~ +#### 买卖股票的最佳时机IV +```python +from typing import List +class Solution: + def maxProfit(self, k: int, prices: List[int]) -> int: + def no_limit(prices): + res = 0 + for i in range(1, len(prices)): + if prices[i] > prices[i - 1]: + res += prices[i] - prices[i - 1] + return res + size = len(prices) + if k > size / 2: + return no_limit(prices) + dp = [[[0] * 2 for _ in range(k + 1)] for _ in range(size)] + for i in range(size): + for j in range(1, k + 1): + if i == 0: + dp[i][j][0] = 0 + dp[i][j][1] = -prices[i] + else: + dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1] + prices[i])#前一天持有并卖掉 + dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0] - prices[i])#前一天不持有,并买入 + return dp[size - 1][k][0] +``` diff --git "a/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" index 3af8a6018..345a15f77 100644 --- "a/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" +++ "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.py" @@ -5,53 +5,33 @@ from typing import List class Solution: def maxProfit(self, prices: List[int]) -> int: - if not prices: return 0 - #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次 - # dp = [[0]*len(prices) for _ in range(2*2+1)] - dp = [[0]*5 for _ in range(len(prices))] - dp[0][0] = dp[0][2] = dp[0][4] = 0 - dp[0][1] = dp[0][3] = -prices[0] - for i in range(1,len(prices)): - dp[i][0] = 0 #如果第i天没有买入,那么只可能i-1天没有买入 - #第i天买入一次,可能是i-1天未买i天买 或 第i-1天买i未买 - dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]) - #第i天买入一次卖出一次,可能是i-1天买入i天卖出或者i-1天已经买入卖出了 - dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]) - #第i天买入2次卖出1次,可能是i-1买卖(1,1)次,i天买入;也可能是是i-1天已经买卖(2,1)次 - dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i]) - # 第i天买卖(2,2)可能是i-1天买卖(2,2)也可能是i-1天买卖(2,1),i卖出 - dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i]) - #最后手头没有股票剩余,实际收益最高 - return dp[-1][4] - - # if not prices: return 0 - #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次 - # dp = [[0]*len(prices) for _ in range(2*2+1)] + # #0未买入 1 买入一次 2 卖出一次 3 买入两次 4 卖出2次 + # # dp = [[0]*len(prices) for _ in range(2*2+1)] # dp = [[0]*5 for _ in range(len(prices))] # dp[0][0] = dp[0][2] = dp[0][4] = 0 # dp[0][1] = dp[0][3] = -prices[0] # for i in range(1,len(prices)): # dp[i][0] = 0 #如果第i天没有买入,那么只可能i-1天没有买入 - # #第i天买入一次,可能是i-1天未买i天买 或 第i-1天已买 + # #第i天买入一次,可能是i-1天未买i天买 或 第i-1天买i未买 # dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]) # #第i天买入一次卖出一次,可能是i-1天买入i天卖出或者i-1天已经买入卖出了 # dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]) # #第i天买入2次卖出1次,可能是i-1买卖(1,1)次,i天买入;也可能是是i-1天已经买卖(2,1)次 # dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i]) # # 第i天买卖(2,2)可能是i-1天买卖(2,2)也可能是i-1天买卖(2,1),i卖出 - # dp[i][4] = max(dp[i-1][4], dp[i-1][3]) + prices[i] #这一行写错了 + # dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i]) # #最后手头没有股票剩余,实际收益最高 - # return max(dp[-1][2],dp[-1][4]) + # return dp[-1][4] + in_1, in_2 = float('-inf'), float('-inf') + out_1, out_2 = 0, 0 + for p in prices: + in_1 = max(in_1, -p) + out_1 = max(out_1, in_1 + p) + in_2 = max(in_2, out_1 - p) + out_2 = max(out_2, in_2 + p) + return out_2 - # one_buy = two_buy = float('inf') - # one_profit = two_profit = 0 - # for p in prices: - # one_buy = min(one_buy, p) - # one_profit = max(one_profit, p - one_buy) - # two_buy = min(two_buy, p - one_profit) - # two_profit = max(two_profit, p - two_buy) - # return two_profit s = Solution() nums = [3,3,5,0,0,3,1,4] diff --git "a/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272IV.py" "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272IV.py" new file mode 100644 index 000000000..e23d5786c --- /dev/null +++ "b/Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272IV.py" @@ -0,0 +1,37 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/17 9:09 PM +from typing import List +class Solution: + def maxProfit(self, k: int, prices: List[int]) -> int: + def no_limit(prices): + res = 0 + for i in range(1, len(prices)): + if prices[i] > prices[i - 1]: + res += prices[i] - prices[i - 1] + return res + size = len(prices) + if k > size / 2: + return no_limit(prices) + dp = [[[0] * 2 for _ in range(k + 1)] for _ in range(size)] + for i in range(size): + for j in range(1, k + 1): + if i == 0: + dp[i][j][0] = 0 + dp[i][j][1] = -prices[i] + else: + dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1] + prices[i])#前一天持有并卖掉 + dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0] - prices[i])#前一天不持有,并买入 + return dp[size - 1][k][0] + + # in_1_k = [float('-inf')] * k + # in_2_k = [float('-inf')] * k + # out_1_k = [0] * k + # out_2_k = [0] * k + # for j in range(0,k): + # for p in prices: + # in_1_k[j] = max(in_1_k[j], -p) + # out_1_k[j] = max(out_1_k[j], in_1_k[j] + p) + # in_2_k[j] = max(in_2_k[j], out_1_k[j] - p) + # out_2_k[j] = max(out_2_k[j], in_2_k[j] + p) + # return out_2_k[k] \ No newline at end of file From 0f20e70cfe7a824cefb3229db07be3e0b82dee21 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 18 Jul 2020 00:07:24 +0800 Subject: [PATCH 083/105] =?UTF-8?q?=E8=82=A1=E7=A5=A8=E4=BA=94=E5=85=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week06/.idea/workspace.xml | 249 +++++++++++------- Week06/NOTE.md | 80 +++++- ...I_\346\211\213\347\273\255\350\264\271.py" | 28 ++ ...2_\345\206\267\345\206\273\346\234\237.py" | 30 +++ ...22\345\205\245\344\275\215\347\275\256.py" | 15 ++ 5 files changed, 294 insertions(+), 108 deletions(-) create mode 100644 "Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272VI_\346\211\213\347\273\255\350\264\271.py" create mode 100644 "Week06/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272_\345\206\267\345\206\273\346\234\237.py" create mode 100644 "Week06/\346\257\217\346\227\245\344\270\200\351\242\2307_17_\346\220\234\347\264\242\346\217\222\345\205\245\344\275\215\347\275\256.py" diff --git a/Week06/.idea/workspace.xml b/Week06/.idea/workspace.xml index 3e24f78f3..cbf2b30c3 100644 --- a/Week06/.idea/workspace.xml +++ b/Week06/.idea/workspace.xml @@ -2,7 +2,9 @@ - + + + @@ -15,7 +17,6 @@ - + - + + - + - + - - + + - + - + - - - - - - - - - - - - - + - - + + @@ -95,42 +87,48 @@ - + - - + + - + - - - - - + + - + - - + + - + - - + + + + + + + + + + + - + @@ -139,7 +137,7 @@ - + @@ -160,7 +158,7 @@ - + @@ -169,7 +167,7 @@ - + @@ -211,7 +209,10 @@ @@ -231,7 +232,6 @@ - @@ -243,6 +243,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1595247635043 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/Week07/Trie\346\240\221.py" "b/Week07/Trie\346\240\221.py" new file mode 100644 index 000000000..38a4d08bb --- /dev/null +++ "b/Week07/Trie\346\240\221.py" @@ -0,0 +1,72 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/20 8:20 PM + +from collections import defaultdict +# class TrieNode: +# def __init__(self): +# self.children = defaultdict(TrieNode) +# self.is_word = False +# +# class Trie: +# def __init__(self): +# self.root = TrieNode() +# +# def insert(self, word: str) -> None:#Inserts a word into the trie. +# node = self.root +# for ch in word:#用word构建Trie树 +# node = node.children[ch] +# node.is_word = True +# +# def search(self, word: str) -> bool:#Returns if the word is in the trie. +# node = self.root +# for ch in word: +# if ch in node.children: +# node = node.children[ch] +# else: return False +# return node.is_word +# +# def startsWith(self, prefix: str) -> bool: +# # Returns if there is any word in the trie that starts with the given prefix. +# node = self.root +# for ch in prefix: +# if ch in node.children: +# node = node.children[ch] +# else: return False +# return True + +class Trie: + def __init__(self): + self.root = {} + self.end_of_word = '#' + + def insert(self,word): + node = self.root + for ch in word: + if ch in node: + node = node.setdefault(ch,{}) + node[self.end_of_word] = self.end_of_word + + def search(self,word): + node = self.root + for ch in word: + if ch in node: + node = node[ch] + else: return False + return self.end_of_word in node + + def startwiths(self,prefix): + node = self.root + for ch in prefix: + if ch in node: + node = node[ch] + else: return False + return True + + + +# Your Trie object will be instantiated and called as such: +# obj = Trie() +# obj.insert(word) +# param_2 = obj.search(word) +# param_3 = obj.startsWith(prefix) \ No newline at end of file diff --git "a/Week07/\345\215\225\350\257\215\346\220\234\347\264\242II.py" "b/Week07/\345\215\225\350\257\215\346\220\234\347\264\242II.py" new file mode 100644 index 000000000..546a28fe8 --- /dev/null +++ "b/Week07/\345\215\225\350\257\215\346\220\234\347\264\242II.py" @@ -0,0 +1,32 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/20 9:40 PM + +class Solution: + def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: + if not board or not board[0] or not words: return [] + root = {} + for word in words: + node = root + for ch in word: + node = node.setdefault(ch,{}) + node['end'] = 0 #将所有word构建为tree树 + rows, cols = len(board), len(board[0]) + res = set() + def dfs(i,j,root,s): + cur = board[i][j] + if cur not in root: return#剪枝 + root = root[cur]#下探 + if 'end' in root and root['end'] == 0: + res.add(s+cur)#到达叶节点,加入到结果集 + board[i][j] = '@'# + for x,y in [[-1,0],[1,0],[0,1],[0,-1]]: + tmp_i,tmp_j = x + i, y + j + if 0 <= tmp_i < rows and 0 <= tmp_j < cols and board[tmp_i][tmp_j]!='@': + dfs(tmp_i,tmp_j,root,s + cur) + board[i][j] = cur#reverse state + for i in range(rows): + for j in range(cols): + dfs(i,j,root,'') + return list(res) + diff --git "a/Week07/\345\271\266\346\237\245\351\233\206\346\250\241\346\235\277.py" "b/Week07/\345\271\266\346\237\245\351\233\206\346\250\241\346\235\277.py" new file mode 100644 index 000000000..be8d74db4 --- /dev/null +++ "b/Week07/\345\271\266\346\237\245\351\233\206\346\250\241\346\235\277.py" @@ -0,0 +1,26 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/20 11:12 PM + +SIZE = 7 +parent =[-1] * SIZE +rank = [0] * SIZE +def find(x, parent): + node = x + while parent[node] != -1: + node = parent[node] + return node + +def union(x, y): + x_root = find(x, parent) + y_root = find(y, parent) + if x_root == y_root: + return + # parent[y_root] = x_root + if rank[x_root] > rank[y_root]: + parent[y_root] = x_root + elif rank[y_root] > rank[x_root]: + parent[x_root] = y_root + else: + parent[x_root] = y_root + rank[y_root] += 1 \ No newline at end of file diff --git "a/Week07/\346\234\213\345\217\213\345\234\210.py" "b/Week07/\346\234\213\345\217\213\345\234\210.py" new file mode 100644 index 000000000..4faec387b --- /dev/null +++ "b/Week07/\346\234\213\345\217\213\345\234\210.py" @@ -0,0 +1,45 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/20 10:58 PM + +from typing import List + + +class Solution: + def findCircleNum(self, nums: List[List[int]]) -> int: + if not nums: return 0 + def find(x): + node = x + while parent[node] != -1: + node = parent[node] + return node + def union(x, y): + x_root = find(x) + y_root = find(y) + if x_root == y_root:#如果根节点一致,结束此次 + return + # parent[y_root] = x_root + if rank[x_root] > rank[y_root]: parent[y_root] = x_root + elif rank[y_root] > rank[x_root]: parent[x_root] = y_root + else: + parent[x_root] = y_root + rank[y_root] += 1 + size = len(nums) + parent = [-1] * size + rank = [0] * size + for i in range(size): + for j in range(size): + if i != j and nums[i][j] == 1: + union(i, j) + count = 0 + for i in parent: + if i < 0: + count += 1 + return count + +nums = [[1,1,0], + [1,1,0], + [0,0,1]] +s = Solution() +res = s.findCircleNum(nums) +print(res) \ No newline at end of file From 1a5027b0abe76fedce6395a4573a6aa4884db79a Mon Sep 17 00:00:00 2001 From: mqray Date: Wed, 22 Jul 2020 23:40:57 +0800 Subject: [PATCH 085/105] =?UTF-8?q?n=E7=9A=87=E5=90=8E=E5=92=8C=E6=9C=89?= =?UTF-8?q?=E6=95=88=E6=95=B0=E7=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week07/.idea/workspace.xml | 99 ++++++++++++++++--- "Week07/N\347\232\207\345\220\216.py" | 23 +++++ ...10\347\232\204\346\225\260\347\213\254.py" | 40 ++++++++ .../\350\247\243\346\225\260\347\213\254.py" | 51 ++++++++++ 4 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 "Week07/N\347\232\207\345\220\216.py" create mode 100644 "Week07/\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" create mode 100644 "Week07/\350\247\243\346\225\260\347\213\254.py" diff --git a/Week07/.idea/workspace.xml b/Week07/.idea/workspace.xml index a7f2ffbd4..405b91e26 100644 --- a/Week07/.idea/workspace.xml +++ b/Week07/.idea/workspace.xml @@ -2,12 +2,9 @@ - - - - - - + + + @@ -19,6 +16,8 @@ + + @@ -219,7 +249,7 @@ - + @@ -241,6 +271,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/Week07/N\347\232\207\345\220\216.py" "b/Week07/N\347\232\207\345\220\216.py" new file mode 100644 index 000000000..29dd4f742 --- /dev/null +++ "b/Week07/N\347\232\207\345\220\216.py" @@ -0,0 +1,23 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/21 9:15 PM + +class Solution: + def solveNQueens(self, n: int) -> List[List[str]]: + def dfs(row, record): + if row == n: + res.append(record) + return + for col in range(n): + if isvalid(row, col, record):#判断这一行的这一列 是否合法 + dfs(row+1, record+[col])#record下标为行值为列 + def isvalid(row,col, record): + if col in record: return False + for i in range(row): + if row + col == i + record[i] or row - col == i - record[i]: + return False + return True + res = [] + dfs(0,[]) + # print(res) + return [['.' * i + 'Q' + '.'* (n-i-1) for i in row] for row in res] \ No newline at end of file diff --git "a/Week07/\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" "b/Week07/\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" new file mode 100644 index 000000000..4a500f369 --- /dev/null +++ "b/Week07/\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" @@ -0,0 +1,40 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/21 9:15 PM + +from typing import List +class Solution: + def isValidSudoku(self, board: List[List[str]]) -> bool: + rows = [{} for i in range(9)] + cols = [{} for i in range(9)] + boxs = [{} for i in range(9)] + + for i in range(9): + for j in range(9): + num = board[i][j] + if num != '.': + # num = int(num) + box = (i // 3) * 3 + j // 3 + + rows[i][num] = rows[i].get(num, 0) + 1 + cols[j][num] = cols[j].get(num, 0) + 1 + boxs[box][num] = boxs[box].get(num, 0) + 1 + + if rows[i][num] > 1 or cols[j][num] > 1 or boxs[box][num] > 1: + return False + return True + + # rows = [set() for _ in range(9)] + # cols = [set() for _ in range(9)] + # boxs = [set() for _ in range(9)] + # for i in range(9): + # for j in range(9): + # box_index, num = i // 3 * 3 + j // 3, board[i][j] + # if num != '.': + # if num in rows[i] or num in cols[j] or num in boxs[box_index]: + # return False + # else: + # rows[i].add(num) + # cols[j].add(num) + # boxs[box_index].add(num) + # return True \ No newline at end of file diff --git "a/Week07/\350\247\243\346\225\260\347\213\254.py" "b/Week07/\350\247\243\346\225\260\347\213\254.py" new file mode 100644 index 000000000..63da90af5 --- /dev/null +++ "b/Week07/\350\247\243\346\225\260\347\213\254.py" @@ -0,0 +1,51 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/21 9:15 PM + +from typing import List +class Solution: + def solveSudoku(self, board: List[List[str]]) -> None: + cols = [set() for _ in range(9)] + rows = [set() for _ in range(9)] + boxs = [set() for _ in range(9)] + #预先扫描一次 + for i in range(9): + for j in range(9): + if board[i][j] != '.': + cols[i].add(board[i][j]) + rows[i].add(board[i][j]) + boxs[i//3*3+j//3].add(board[i][j]) + + def dfs(i, j): + if board[i][j] != '.': + if i == 8 and j == 8: + self.flag = True + return + if j < 8: + dfs(i, j + 1) + else: + dfs(i + 1, 0) + return + for ch in range(1, 10):#对于每一个位置,用1-9试探 + ch = str(ch) + if ch not in cols[j] and ch not in rows[i] and ch not in boxs[i // 3 * 3 + j // 3]: + #如果可以放置,更新三个set(),并将此刻的位置修改 + cols[j].add(ch) + rows[i].add(ch) + boxs[i // 3][j // 3].add(ch) + board[i][j] = ch + if i == 8 and j == 8: + self.flag = True + return + if j < 8: + dfs(i, j + 1) + else: + dfs(i + 1, 0) + if self.flag: return + board[i][j] = '.' + cols[j].remove(ch) + rows[i].remove(ch) + boxs[i // 3][j // 3].remove(ch) + + self.flag = False + dfs(0, 0) From 1a736e393190a676d60f6d65bb5273cec76dab93 Mon Sep 17 00:00:00 2001 From: mqray Date: Thu, 23 Jul 2020 00:25:18 +0800 Subject: [PATCH 086/105] =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=A0=91=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E6=B7=B1=E5=BA=A6=E3=80=81=E6=9C=80=E5=B0=8F=E6=B7=B1?= =?UTF-8?q?=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week03/.idea/workspace.xml | 569 ++++++------------ Week03/NOTE.md | 124 ++-- "Week03/\345\233\236\346\272\257.md" | 115 ++++ ...5\344\270\200\351\242\2306_27_Pow(x,n).py" | 24 +- ...1\242\2306_27_\345\255\220\351\233\206.py" | 44 +- ...\242\2306_27\345\255\220\351\233\206II.py" | 21 +- ...27\346\257\215\347\273\204\345\220\210.py" | 29 +- 7 files changed, 451 insertions(+), 475 deletions(-) diff --git a/Week03/.idea/workspace.xml b/Week03/.idea/workspace.xml index faf398229..df8dec3fd 100644 --- a/Week03/.idea/workspace.xml +++ b/Week03/.idea/workspace.xml @@ -2,10 +2,14 @@ + + + - + + @@ -17,18 +21,21 @@ + - + + + - + @@ -37,30 +44,30 @@ - - + + - - + + - + - - + + - + - + @@ -68,94 +75,94 @@ - + - - + + - + + + + + + - + - - + + + + + + - - - - - - - - - - - - - + - - - - - + + - - - - + + + + + + + - - + + - - + + - - - - + + + + + + + - + - - + + - + - + - - + + @@ -201,8 +208,6 @@ @@ -263,8 +273,8 @@ - - + + - + - + - + - + - - + + + + + + + - - @@ -450,13 +463,13 @@ - + - - + + @@ -469,33 +482,33 @@ - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + @@ -506,263 +519,6 @@ - - - file://$PROJECT_DIR$/每日一题6_25_单词拆分.py - 70 - - - file://$PROJECT_DIR$/每日一题6_25_单词拆分.py - 71 - - - file://$PROJECT_DIR$/每日一题6_25_单词拆分.py - 69 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 7 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 8 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 9 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 10 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 11 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 12 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 33 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 35 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 36 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 37 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 39 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 41 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 43 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 45 - - - file://$PROJECT_DIR$/每日一题6_25_最长回文子串.py - 51 - - - file://$PROJECT_DIR$/每日一题6_27_全排列.py - 7 - - - file://$PROJECT_DIR$/每日一题6_27_全排列.py - 8 - - - file://$PROJECT_DIR$/每日一题6_27_全排列.py - 10 - - - file://$PROJECT_DIR$/每日一题6_27_全排列.py - 11 - - - file://$PROJECT_DIR$/每日一题6_27_全排列.py - 12 - - - file://$PROJECT_DIR$/每日一题6_27_全排列.py - 13 - - - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 39 - - - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 11 - - - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 13 - - - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 14 - - - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 17 - - - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 15 - - - file://$PROJECT_DIR$/每日一题6_27_全排列II.py - 16 - - - file://$PROJECT_DIR$/每日一题6_27_子集.py - 29 - - - file://$PROJECT_DIR$/每日一题6_27_子集.py - 31 - - - file://$PROJECT_DIR$/每日一题6_27_子集.py - 37 - - - file://$PROJECT_DIR$/每日一题6_27_子集.py - 27 - - - file://$PROJECT_DIR$/每日一题6_28_字符串相加.py - 35 - - - file://$PROJECT_DIR$/每日一题6_28_字符串相加.py - 32 - - - file://$PROJECT_DIR$/每日一题6_28_字符串相加.py - 31 - - - file://$PROJECT_DIR$/每日一题6_28_字符串相加.py - 30 - - - file://$PROJECT_DIR$/每日一题6_28_字符串相加.py - 33 - - - file://$PROJECT_DIR$/每日一题6_28_字符串相加.py - 34 - - - file://$PROJECT_DIR$/每日一题6_28_字符串相加.py - 42 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 57 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 44 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 46 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 45 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 47 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 48 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 49 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 50 - - - file://$PROJECT_DIR$/每日一题6_28_长度最小的子数组.py - 51 - - @@ -891,13 +647,6 @@ - - - - - - - @@ -926,13 +675,6 @@ - - - - - - - @@ -948,31 +690,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1045,6 +762,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Week03/NOTE.md b/Week03/NOTE.md index f22936347..8ac6d1451 100644 --- a/Week03/NOTE.md +++ b/Week03/NOTE.md @@ -6,10 +6,10 @@ 1.递归 我刚开始的想法是,考虑左右孩子节点,这个连接指向修改了就好了 然后写的代码如下 -```angular2html +```python def invertTree(self, root: TreeNode) -> TreeNode: #recursive terminator - if root is None: return + if root is None: return #current process if root.right: root.left = self.invertTree(root.right) @@ -21,7 +21,7 @@ def invertTree(self, root: TreeNode) -> TreeNode: ``` 上述代码的问题在于,if root.right:执行过后,左孩子已经修改了;在想要执行if root.left:时已经是同一个指向了 所以需要修改 -```angular2html +```python def invertTree(self, root: TreeNode) -> TreeNode: # recursive terminator #击败70% @@ -38,7 +38,7 @@ def invertTree(self, root: TreeNode) -> TreeNode: ``` 2.迭代 类似层序遍历,将每一层访问到的节点存到quene中 如果quene不为空,取出队尾元素 对于当前节点,交换左右孩子后,将其添加到quene中,继续进行判断 -```angular2html +```python def invertTree(self, root: TreeNode) -> TreeNode: if root is None: return None quene = [root] @@ -52,7 +52,7 @@ def invertTree(self, root: TreeNode) -> TreeNode: #### 验证是否搜索二叉树 1.递归,判断左子树是否小于根,右子树是否大于根 -```angular2html +```python if root is None: return True #确定左子树是否符合排序二叉树,如果不满足,就返回False if not self.isValidBST(root.left): return False @@ -62,7 +62,7 @@ self.pre_val = root.val#记录上一个访问的节点的值 return self.isValidBST(root.right) ``` 2.迭代 由于二叉搜索树的特性 中序遍历比较方便 这里就借用二叉树的中序遍历的非递归实现完成 -```angular2html +```python stack, pre_val = [], float('-inf') cur = root while stack or cur is not None: @@ -77,14 +77,14 @@ return True ``` #### 二叉树的最大深度 -1.递归代码 这个代码我真的印象超级深 -```angular2html +1.递归代码 这个代码我真的印象超级深 +```python if root is None: return 0 return max(self.maxDepth(root.left),self.maxDepth(root.right))+1 ``` 2.迭代 借助DFS思想,借助栈,每次入栈时 记录当前节点的深度 将遍历左右孩子时,将节点和当前深度+1压入栈中 -```angular2html +```python if root is None: return 0 stack = [(1, root)]#栈中记录当前节点和此时的高度 depth = 0 @@ -96,11 +96,23 @@ while stack != []: stack.append((current_depth + 1, root.right)) return depth ``` +上述代码可以优化 +``` python + quene, depth = [root], 0 + while quene: + # cur_layer = [] + for _ in range(len(quene)): + root = quene.pop(0)#要确保将这一层的元素加入到quene中 + if root.left: quene.append(root.left) + if root.right: quene.append(root.right) + depth += 1 + return depth +``` #### 二叉树的最小深度 最小深度是从根节点到最近叶子节点的最短路径上的节点数量 1.递归 递归时需要弄清楚递归的结束条件 -```angular2html +```python def minDepth(self, root: TreeNode) -> int: #1.根节点为空 return 0 #2. 左右节点为空 return 1 @@ -111,10 +123,10 @@ def minDepth(self, root: TreeNode) -> int: left_height, right_height = self.minDepth(root.left),self.minDepth(root.right) if root.left is None or root.right is None: return left_height+right_height+1#有一个为0 #其余情况 返回较小值+1 - return min(left_height,right_height)+1 + return min(left_height,right_height) + 1#+1是加的根那一层 ``` 2.借助层序遍历 不需要遍历所有节点 只需要遍历到第一个叶子节点就能返回 -```angular2html +```python if not root: return 0 quene = [(1, root)] while quene: @@ -124,10 +136,22 @@ while quene: if root.left: quene.append((depth + 1, root.left)) if root.right: quene.append((depth + 1, root.right)) ``` +这里和上面最大深度逻辑一致,只要提前判断子树就可以返回深度了 +``` python +if not root: return 0 +quene, depth = [root], 1 +while quene: + for _ in range(len(quene)): + root = quene.pop(0) + if not root.left and not root.right: return depth#提前判断是否叶节点即可,由于depth是后加的,所以初值depth=1 + if root.left: quene.append(root.left) + if root.right: quene.append(root.right) + depth += 1 +``` #### 二进制求和 1.进制转换后求解 -```angular2html +```python return bin(int(a, 2)+int(b, 2))[2:] ``` 2. 如果不能使用加减乘除 @@ -144,7 +168,7 @@ return bin(x)[2:] #### 单词拆分 1.动态规划 时间复杂度O(N^2),空间复杂度O(N) -```angular2html +```python #动态规划 用大小为len(s)+1的数组保存转态结果 #dp[i]表示s的前i位是否能被worddict中的元素表示,最后只需要取转移数组的最后一位即可知道是否能够拆分 #如何转移呢? @@ -160,7 +184,7 @@ def wordBreak(self, s: str, wordDict: List[str]) -> bool: return dp[-1] ``` 2.备忘录回溯 -```angular2html +```python #备忘录回溯 def wordBreak(self, s: str, wordDict: List[str]) -> bool: import functools @@ -182,7 +206,7 @@ def wordBreak(self, s: str, wordDict: List[str]) -> bool: 如果当前的三数之和与target差值的绝对值 小于 abs(min_closer-tmp),就将min_closer=tmp 如果小于target,left+1 如果大于target,right-1 如果=target就返回这个三数之和 遍历结束之后 没有返回 说明没有=target的组合 那么就返回记录的最接近的三数之和min_closer -```angular2html +```python def threeSumClosest(self, nums: List[int], target: int) -> int: nums.sort() # 先排序 # [-4,-1,1,2],1 @@ -209,7 +233,7 @@ def threeSumClosest(self, nums: List[int], target: int) -> int: #### 最长回文子串 1.暴力解法 遍历出所有长度的子串,判断它是否是回文串,从结果中挑出最长的返回 时间复杂度是O(N^3) -```angular2html +```python def longestPalindrome(self, s: str) -> str: res,max_length = '',0 for i in range(len(s)): @@ -231,7 +255,7 @@ def isPalidrome(self,cur_string): ``` 2.动态规划 动态规划是指 如果这一刻的状态是可以由其他时刻的状态推导出来,那么我们可以记录该时刻的状态以推导此刻的状态 -```angular2html +```python #首先 长度为0、1的字符串 它是回文串 #长度=2,判断左右是否相同 #对于strs[i,j]而言它是否是回文串 取决于它内缩2位的字符串是否是回文串同时还要判断其边界是否相同,=2也可划归此类 @@ -264,8 +288,8 @@ def longestPalindrome(self, s: str) -> str: 遍历二叉树有深度和广度,但是由于要重建二叉树,我们普通的遍历结果是连在一起的,无法确定None节点在哪里, 所以如果想要用一次遍历的结果推导出其二叉树的构型 需要为叶节点的孩子打上标记 1.BFS 层序遍历实现 - - 1 序列化 层序遍历的二叉树 - ```angular2html + - 1 序列化 层序遍历的二叉树 + ```python def serialize(self, root):#层序遍历中使用deque是最简单的 #手写一个二叉树的层寻遍历 if not root: return [] @@ -281,7 +305,7 @@ def serialize(self, root):#层序遍历中使用deque是最简单的 return res ``` - 2 重建时,如果遍历到的元素是#,那我们就不对它进行处理 - ```angular2html + ```python def deserialize(self, data): if not data: return None data = data.split(',') @@ -303,8 +327,8 @@ def deserialize(self, data): ``` 2.前序遍历 递归解 - - 1 序列化 前序遍历 -```angular2html + - 1 序列化 前序遍历 +```python def serialize(self, root): #手写一个二叉树的层寻遍历 if root == None: return '#,' @@ -312,13 +336,13 @@ def serialize(self, root): rightserilized = self.serialize(root.right) return str(root.val) + ',' + leftserilized + rightserilized ``` - - 2 反序列化 -```angular2html + - 2 反序列化 +```python def deserialize(self, data): data = data.split(',') root = self.deserializeCore(data) return root - + def deserializeCore(self,data): root_val = data.pop(0) if root_val == '#': return None @@ -331,7 +355,7 @@ def deserializeCore(self,data): #### 二叉树的最近公共祖先 1.递归 class Solution: -```angular2html +```python #1.递归 分析出找到最近公共祖先节点的情形,如果p,q由同一祖先节点 则p、q要么位于某棵树的左右子树 #要么在同一棵树上,在同一棵树上又有 p或q为根 另外存在p或q在其左右子树中 res = None @@ -352,8 +376,8 @@ class Solution: #reverse states return root_left or root_right or(root.val==p.val or root.val==q.val) ``` -写的更简洁一点 -```angular2html +写的更简洁一点 +```python def lowestCommonAncestor(self, root, p, q): if not root or p==root or q==root: return root @@ -365,7 +389,7 @@ def lowestCommonAncestor(self, root, p, q): ``` 2.记录父节点 -```angular2html +```python class Solution: # ,然后我们就可以利用节点的父节点信息从p结点开始不断往上跳,并记录已经访问过的节点,再从q节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。 all_parents = {} @@ -396,9 +420,9 @@ class Solution: #### 根据二叉树的前中序列重建二叉树 手动模拟根据二叉树的前中序列生成二叉树的过程,不难发现每次都是先确定根节点,以根节点划分出左右子树 对应到两个序列,递归的进行确定根节点,左右子树序列 -所以我们在重建时,先确定根节点、然后为其分配左右子树, +所以我们在重建时,先确定根节点、然后为其分配左右子树, 处理左右子树时,先确定并对应其前中序列,进行相同的处理 -```angular2html +```python def buildTree(self, pre: List[int], inorder: List[int]) -> TreeNode: if not pre or not inorder: return None @@ -412,8 +436,8 @@ def buildTree(self, pre: List[int], inorder: List[int]) -> TreeNode: #### 删除未排序链表中的重复元素 1.使用set实现存储未重复元素,然后重建 (超时)尽管时间复杂度是O(N),但是相当于遍历了两次 -```angular2html -if head is None or head.next is None: return head +```python +if head is None or head.next is None: return head once = set() while head is not None: if head.val not in once: @@ -422,17 +446,17 @@ if head is None or head.next is None: return head head = pre = ListNode(None) while once: head.next = ListNode(once.pop()) - head = head.next + head = head.next return pre.next ``` 可以知道,如果当前元素已经出现过,那么如果遍历时记录了前一个指针,那么可以直接删除掉这个节点元素 -```angular2html +```python if not head: return head once = {head.val} pre = head while head.next:#如果有下一个节点 cur = head.next - if not cur.val in once: + if not cur.val in once: once.add(cur.val) head = head.next else:#如果这个元素已经出现,那就直接删除掉 @@ -443,7 +467,7 @@ if not head: return head #### 括号生成 1.因为括号类别已经确定,可以想象为左右括号最多N个 左括号出现次数小于N即可,右括号小于左括号个数 -```angular2html +```python def generateParenthesis(self,n): result = [] self._generate_parenthesis(0, 0, n, '',result) @@ -463,7 +487,7 @@ def _generate_parenthesis(self, left, right, n, res, result): # reverse state ``` 上面这种解法,由于最后要返回res,所以在递归时传入的参数较多,可以简化一下 -```angular2html +```python def generateParenthesis(self,n): result = [] def _generate_parenthesis( left, right, n, res): @@ -480,7 +504,7 @@ def generateParenthesis(self,n): #### 组合 碰到组合、全排列、括号生成这种打印类的题,一般都是 回溯算法,回溯算法有一个基本模板: -```angular2html +```python def backtracing(路径,可选路径): #触发结束条件 #for i in range(): @@ -491,7 +515,7 @@ def backtracing(路径,可选路径): ``` -```angular2html +```python def combine(self, n, k): def backtracing(first=1, tmp=[]): #触发结束条件 @@ -513,7 +537,7 @@ def combine(self, n, k): #### 组合II #### 全排列 -```angular2html +```python def permute(self, nums: List[int]) -> List[List[int]]: def backtrace(nums, tmp): #触发结束条件 @@ -531,7 +555,7 @@ def permute(self, nums: List[int]) -> List[List[int]]: ``` #### 全排列II -```angular2html +```python def permuteUnique(self, nums): """ :type nums: List[int] @@ -559,7 +583,7 @@ flag=False if n< 0 else True times,res = abs(n),1 while times>0: res *= x - times -= 1 + times -= 1 return res if flag else 1/res ``` 递归形式如下 但是都超出时间限制 @@ -580,7 +604,7 @@ return self.myPow(x*x, n // 2) if n%2==0 else x*self.myPow(x, n-1) #### 子集 1.递归 -```angular2html +```python def subsets(self, nums: List[int]) -> List[List[int]]: res = [[]] for num in nums: @@ -588,7 +612,7 @@ def subsets(self, nums: List[int]) -> List[List[int]]: return res ``` 2.回溯 -```angular2html +```python def subsets(self, nums: List[int]) -> List[List[int]]: def backtrack(first=0, tmp=[]): #处理结束条件 @@ -609,7 +633,7 @@ def subsets(self, nums: List[int]) -> List[List[int]]: ``` 3.位运算 -```angular2html +```python def subsets(self, nums: List[int]) -> List[List[int]]: size = len(nums) res = [] @@ -623,7 +647,7 @@ def subsets(self, nums: List[int]) -> List[List[int]]: #### 字符串相加 手动模拟数字进位加法,如果两个数长度不一致,就在将其作为0处理 -```angular2html +```python def addStrings(self, num1, num2): """ :type num1: str @@ -647,7 +671,7 @@ def addStrings(self, num1, num2): #### 长度最小的子数组 1.枚举出长度为1,2,3...的数组,查看其值是否大于s,如果大于则可以直接返回 此时的枚举长度 但是时间复杂度高 O(N^2) -```angular2html +```python def minSubArrayLen(self, s, nums): # 1. 穷举 超出时间限制 for i in range(1, len(nums) + 1): @@ -662,7 +686,7 @@ def minSubArrayLen(self, s, nums): 所以我们可以使用双指针 来界定是否是最短子数组 双指针开始时指向 数组头 如果当前窗口和 小于s,end右移 以达到期望的s,如果此时已经到达s,记录下当前的窗口值 将当前窗口往右移动 继续判断窗口值与s的关系,如果小了,就右移end;如果还是大于s,窗口继续右移 -```angular2html +```python def minSubArrayLen(self, s, nums): if not nums: return 0 size, res = len(nums), len(nums) + 1 diff --git "a/Week03/\345\233\236\346\272\257.md" "b/Week03/\345\233\236\346\272\257.md" index e69de29bb..3d21c65a5 100644 --- "a/Week03/\345\233\236\346\272\257.md" +++ "b/Week03/\345\233\236\346\272\257.md" @@ -0,0 +1,115 @@ +## 回溯习题整理 + +```python +result = [] +def backtrack(路径, 选择列表): + if 满足结束条件: + result.add(路径) + return + for 选择 in 选择列表: + 做选择 + backtrack(路径, 选择列表) + 撤销选择 +``` +#### 1.子集 +>给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 +说明:解集不能包含重复的子集。 +>例:nums = [1,2,3] +输出 +[ + [3], + [1], + [2], + [1,2,3], + [1,3], + [2,3], + [1,2], + [] +] + +首先要能想到用DFS, +DFS的模板是 +```python +def dfs(): + # recursive terminator + # process cur_layer + # drill_down + # reverse state +``` +其次待求是所有子集,必然涉及记录子集 +首先这一题我们能想到要用深度优先来做,但是待求是所有子集,子集中list的长度可以是0-3, +在深度优先过程中,明显会涉及到从叶节点到父节点的回溯过程 +使用tmp记录每个子集,由于子集内容是[]->[1]->[1,2]->[1,2,3]... +所以递归过程中需要将每个时刻的值加入到tmp传入下一层递归,对于长度到达最大后,自然需要回溯 +比如[1,2,3]->[1,3]->[2] +```python +class Solution: + def subSet(self,nums): + def backtrace(first=0,tmp=[]): + res.append(tmp[:]) + for i in range(first,size): + tmp.append(nums[i]) + backtrace(i + 1, tmp) + tmp.pop() + res, size = [], len(nums) + backtrace() + return res +``` + +#### 子集II +>给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 +说明:解集不能包含重复的子集。 +例如:[1,2,2] +输出: +[ + [2], + [1], + [1,2,2], + [2,2], + [1,2], + [] +] + +首先要清楚,重复解来自于哪里?明显是来自tmp.pop()之后继续for循环遍历,可以取到后边的元素,就会出现重复解 +所以,如果在for循环里面,pass掉nums[i]==numsp[i-1]的内容, +即可同时对这个i有一定的限定,不能仅仅是i>0,而是大于当前位置 +```python +class Solution: + def subSet(self,nums): + def backtrace(first=0,tmp=[]): + res.append(tmp[:]) + for i in range(first,size): + if i > first and nums[i]==nums[i-1]: continue + tmp.append(nums[i]) + backtrace(i + 1, tmp) + tmp.pop() + res, size = [], len(nums) + backtrace() + return res +``` + +#### 电话号码的字母组合 +时间复杂度是3^N*4^M M+N = len(digits) +```python +class Solution(object): + def letterCombinations(self, digits): + """ + :type digits: str + :rtype: List[str] + """ + hashmap = {'2':'abc','3':'def','4':'ghi','5':'jkl','6':'mno', + '7':'pqrs','8':'tuv','9':'wxyz'} + def backtrace(combinations,digits): + if digits == '': + res.append(combinations) + else: + for ch in hashmap[digits[0]]: + backtrace(combinations+ch,digits[1:]) + res = [] + if digits: + backtrace('',digits) + return res +``` + + + diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" index 5bd680df8..c0a5fb502 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_Pow(x,n).py" @@ -4,9 +4,21 @@ class Solution: def myPow(self, x: float, n: int) -> float: - if n == 0: return 1 - if n == 1: return x - if n < 0: - return 1 / self.myPow(x, -n) - # return self.myPow(x, n // 2) * self.myPow(x, n - n // 2) - return self.myPow(x*x,n//2) if n%2==0 else x*self.myPow(x,n-1) \ No newline at end of file + # if n == 0: return 1 + # if n == 1: return x + # if n < 0: + # return 1 / self.myPow(x, -n) + # return self.myPow(x*x,n//2) if n%2==0 else x*self.myPow(x,n-1) + flag = 1 + if n < 0: flag = 0 + n, res = abs(n), 1 + while n: + if n & 1: # 奇数时 + res = res * x + x = x * x + n = n >> 1 + return res if flag else 1 / res + +s = Solution() +res = s.myPow(2,4) +print(res) diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" index 1c34bdb41..7dfc749bf 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\255\220\351\233\206.py" @@ -5,33 +5,31 @@ def subsets(self, nums: List[int]) -> List[List[int]]: # for num in nums: # res += [tmp + [num] for tmp in res] # return res - # def backtrack(first=0, tmp=[]): - # #处理结束条件 - # if len(tmp) == k: - # res.append(tmp[:]) - # for i in range(first, size): - # #选择 - # tmp.append(nums[i]) - # # print(curr) - # #下一层决策 - # backtrack(i + 1, tmp) - # tmp.pop() - # - # res = [] - # size = len(nums) - # for k in range(size + 1): - # backtrack() - # return res + def backtrack(first=0, tmp=[],k=0): + #处理结束条件 + # if len(tmp) == k:#最后结果的长度是0-3 + # res.append(tmp[:]) + res.append(tmp[:]) + for i in range(first, size): + tmp.append(nums[i]) + backtrack(i + 1, tmp, k+1) + tmp.pop() - size = len(nums) res = [] - for i in range(2 ** size, 2 ** (size + 1)): - # generate bitmask, from 0..00 to 1..11 - bitmask = bin(i)[3:] - # append subset corresponding to that bitmask - res.append([nums[j] for j in range(size) if bitmask[j] == '1']) + size = len(nums) + # for k in range(size + 1): + backtrack() return res + # size = len(nums) + # res = [] + # for i in range(2 ** size, 2 ** (size + 1)): + # # generate bitmask, from 0..00 to 1..11 + # bitmask = bin(i)[3:] + # # append subset corresponding to that bitmask + # res.append([nums[j] for j in range(size) if bitmask[j] == '1']) + # return res + s = Solution() diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27\345\255\220\351\233\206II.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27\345\255\220\351\233\206II.py" index 2f3178bdc..ed765953b 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27\345\255\220\351\233\206II.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27\345\255\220\351\233\206II.py" @@ -1,3 +1,22 @@ # -*- coding:utf-8 -*- # Author : Ray -# Data : 2020/7/12 8:35 PM \ No newline at end of file +# Data : 2020/7/12 8:35 PM +from typing import List +class Solution: + def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: + def backtrace(first=0,tmp=[]): + res.append(tmp[:]) + for i in range(first,size): + if i > first and nums[i] == nums[i-1]: continue + tmp.append(nums[i]) + backtrace(i + 1, tmp) + tmp.pop() + res, size = [], len(nums) + nums.sort() + backtrace() + return res +s = Solution() +res = s.subsetsWithDup([4,4,4,1,4]) +print(res) +print(len(res)) + diff --git "a/Week03/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py" "b/Week03/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py" index d84a64da0..27c5c78ee 100644 --- "a/Week03/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py" +++ "b/Week03/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py" @@ -1,3 +1,30 @@ # -*- coding:utf-8 -*- # Author : Ray -# Data : 2020/7/12 11:01 PM \ No newline at end of file +# Data : 2020/7/12 11:01 PM + +from typing import List +class Solution: + def letterCombinations(self, digits: str) -> List[str]: + hashmap = {'2':'abc','3':'def','4':'ghi','5':'jkl','6':'mno', + '7':'pqrs','8':'tuv','9':'wxyz'} + # dfs + # def backtrace(combinations,digits):#'23' + # if digits == '': + # res.append(combinations) + # else: + # for cur_str in hashmap[digits[0]]:#'abc' + # backtrace(combinations + cur_str,digits[1:])#'abc'中挑一个,'3' + # res = [] + # # if digits: + # backtrace('',digits) + # return res + # bfs + if digits == '': return [] + combinations = [''] + for digit in digits: + combinations = [combination + cur for combination in combinations for cur in hashmap[digit]] + return combinations + +s = Solution() +res = s.letterCombinations('23') +print(res) \ No newline at end of file From a3918d478283bf50eadb88dad0b8f71034340cc7 Mon Sep 17 00:00:00 2001 From: mqray Date: Thu, 23 Jul 2020 00:29:25 +0800 Subject: [PATCH 087/105] =?UTF-8?q?markdown=E6=A0=BC=E5=BC=8F=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week02/NOTE.md | 80 +++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/Week02/NOTE.md b/Week02/NOTE.md index b443060f9..19d690bbd 100644 --- a/Week02/NOTE.md +++ b/Week02/NOTE.md @@ -8,7 +8,7 @@ return sorted(s) == sorted(t) ``` 2.根据两个字符串构建hash表,判断两个hash表是否一致 -```angular2html +```python dic1, dic2 = {}, {} for item in s: dic1[item] = dic1.get(item, 0) + 1 @@ -19,7 +19,7 @@ return dic1 == dic2 ``` 3.只需要使用一个hash表,前一次遍历增加值,后一次遍历减少值 最后判断hash表中的值是否为0 -```angular2html +```python if len(s) != len(t): return False hashmap = {} for substr in s: @@ -40,7 +40,7 @@ return True ``` 4.使用python内置的count函数,统计字符出现的个数 原理与方法2一致 -```angular2html +```python if len(s) != len(t): return False for i in set(s): @@ -49,7 +49,7 @@ for i in set(s): return True ``` 优化 -```angular2html +```python if len(s)!=len(t):return False tmp = set(s) @@ -65,7 +65,7 @@ return False 1.由于异位词都是由相同字母集组成的,可以在遍历列表时,根据其字母排序是否一致,作为异位词分组的根据 具体的 根据字母排序是否一致,构建hash表,以字母排序作为key(当然也可以使用字母的tuple序),以原字符串作为键 由于涉及到排序 所以时间复杂度为O(NKlogK),空间复杂度为O(NK) -```angular2html +```python dic = {} for item in strs: # key = tuple(sorted(item))#字母的键也可以用字母排序对应的tuple @@ -80,7 +80,7 @@ return [dic[x] for x in dic]#击败97% 这种写法很直观,但是判断当前字符是否存在hash表中,有简简洁写法 dict.get()获取不到时,返回[] 获取到时 + [item]可以直接在原list中拼接 -```angular2html +```python dic = {} for item in strs: key = ''.join((sorted(item))) @@ -98,7 +98,7 @@ return [dic[item] for item in dic] 2.根据字符串中字符出现的次数作为hash表的键 对于每次遍历到的字符串,都需要维护一个长度为26的list,并要将其转化为tuple 时间复杂度是O(NK),空间复杂度为O(NK) -```angular2html +```python dic = {} for item in strs: count = [0] * 26 @@ -109,7 +109,7 @@ for item in strs: return [dic[x] for x in dic] ``` 对应的defaultdict实现如下 -```angular2html +```python dic = collections.defaultdict(list) for item in strs: count = [0] * 26 @@ -121,11 +121,11 @@ return [dic[x] for x in dic] ### 二叉树的深度优先遍历 递归实现都比较简单,也比较容易理解,不赘述 - + #### 二叉树的前序遍历 根左右 1.递归实现 -```angular2html +```python def preorderTraversal(self, root: TreeNode) -> List[int]: res = [] if root: @@ -147,7 +147,7 @@ def preorder(self, root, res): # 前序遍历 根左右 然后判断其左右子节点是否存在,并对他们进行入栈操作 最后返回res -```angular2html +```python def preorderTraversal(self, root: TreeNode) -> List[int]: # 前序遍历的迭代实现 if root is None: return [] @@ -167,7 +167,7 @@ def preorderTraversal(self, root: TreeNode) -> List[int]: #### 二叉树的中序遍历 左根右 1.递归实现 -```angular2html +```python def inorderTraversal(self, root): """ #中序遍历 左根右 @@ -191,7 +191,7 @@ def inorder(self, root, res): 中序遍历的非递归实现就复杂一些了,因为每次并不是先将根节点的值输出,而是优先的找到树的最左子树 所以要确保能一直往最左节点找 同时入栈 如果已经找到最左节点, 那么首先应当将这个元素出栈存入res中 其次应判断当前栈顶元素是是否有右孩子 将cur指向栈顶元素的右孩子 -```angular2html +```python def inorderTraversal(self, root: TreeNode) -> List[int]: if root is None: return [] res, stack = [], [] @@ -208,7 +208,7 @@ def inorderTraversal(self, root: TreeNode) -> List[int]: #### 二叉树的后序遍历 左右根 1.递归实现 -```angular2html +```python def postorderTraversal(self,root): res = [] if root is not None: @@ -226,7 +226,7 @@ def postorder(self,root,res): 后续遍历的非递归方式应该是最难的,因为在入栈过程中还需要额外的指针标识是否已经访问过左子树的右孩子节点 这里取巧使用两个栈,根节点不用在一个单独的栈中出入并用指针记录访问元素 -```angular2html +```python def postorderTraversal(self, root): #用两个栈实现后序遍历的非递归实现 if root is None: @@ -244,7 +244,7 @@ def postorderTraversal(self, root): #### 二叉树的层序遍历 写着写着,才发现二叉树的层序遍历和我上面后序遍历是真的像 -```angular2html +```python class Solution(object): def levelTraversal(self,root): if root is None: @@ -264,7 +264,7 @@ class Solution(object): #### N叉树的层序遍历 刚开始是这么写的,看起来算法逻辑没什么问题,但是这里我相当于是将cur当做一个list在做 而实际上cur只是一个Node,哪怕它是root.children它也是个Node,所以没法将其进行迭代 -```angular2html +```python def levelOrder(self, root: 'Node') -> List[List[int]]: if root is None: return [] quene,res = [root],[] @@ -285,7 +285,7 @@ def levelOrder(self, root: 'Node') -> List[List[int]]: 每次都将quene所有元素记录到tmp中,将所有节点合并为list之后存入res 同时,在加入的过程中,用tmp_quene记录下一层的节点值, 在遍历完上层节点后,将下层节点赋给quene -```angular2html +```python def levelOrder(self,root): #击败55% if root is None: return [] @@ -305,7 +305,7 @@ def levelOrder(self,root): #### 数组中最小的k个数 1.暴力解法 对数组进行排序,返回前k个 -```angular2html +```python arr.sort() return arr[:k] ``` @@ -323,7 +323,7 @@ res = [-x for x in heap] return res ``` 3.快排思想 -```angular2html +```python def partition(self, nums, left, right): pivot = nums[left] while left < right: @@ -361,7 +361,7 @@ def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: 对于有节点值交换的情形 进一步考量它的下一层是否符合小根堆或大根堆的条件 建堆之后 堆顶的元素应该是最大的(大根堆),此时将它与末尾元素调换就会使得最大元素到最后位置,对现今的堆顶元素进行堆化 这个过程就完成了对一个元素的排序,目前堆中的最大元素已经到了末尾,下一次进行调整时就无须再处理此元素 -```angular2html +```python #时间复杂度为NlogN,logN为建立大根堆/小根堆的时间复杂度, #heapify的时间复杂度是O(logN)的因为,最坏情况下,每一层都需要判断 @@ -393,7 +393,7 @@ def heap_sort(self,nums): #### 判断是否是丑数 如果一个数是丑数那肯定满足这种定义num = 2^i*3^j*5^k -```angular2html +```python if num == 0: return False while num % 5 == 0: num /= 5 while num % 3 == 0: num /= 3 @@ -412,7 +412,7 @@ for item in [2,3,5]: #### 求第n个丑数 动态规划的题,解法分 动态转移方程和动态转移矩阵 后面整理一套解法 -```angular2html +```python # 1、2、3、5、4、6、8、9、10 if n==0: return 0 @@ -428,7 +428,7 @@ return res[-1] #### 验证字符串是否是回文串 1.翻转字符串 看是否相同 击败81% -```angular2html +```python tmp = "".join(char.lower() for char in s if ch.isalnum()) return tmp == tmp[::-1] ``` @@ -447,7 +447,7 @@ return True #### 正则表达式匹配 1.递归解法 是超出时间限制的,时间复杂度是O(3^N) -```angular2html +```python def isMatch(self, s: str, pattern: str) -> bool: # 特殊情况处理 if len(s) == 0 and len(pattern) == 0: return True @@ -470,7 +470,7 @@ def isMatch(self, s: str, pattern: str) -> bool: ``` python中有装饰器优化迭代过程@lru_cache 所以在函数前使用装饰器即可通过 -```angular2html +```python @lru_cache def isMatch(self, s: str, pattern: str) -> bool: pass @@ -485,7 +485,7 @@ else: return match_first and self.isMatch(s[1:], pattern[1:]) ``` 2.动态规划 -```angular2html +```python pass ``` @@ -493,7 +493,7 @@ pass #### 只出现一次的数字 时间复杂度为O(N),空间复杂度为O(N) 除一个数外,所有元素都出现了两次,求这个只出现一次的元素 1.两次hash表 遍历list,用hash表统计每个值出现的次数,根据出现次数返回key -```angular2html +```python # 1.hash表记录出现次数,以num为key,以出现次数为value 击败42% dic = {} for num in nums: @@ -503,7 +503,7 @@ for key, value in dic.items(): return key ``` 2.题目要求用常数级的空间复杂度实现,则不能用hash表实现 -```angular2html +```python #位运算,击败97% # 由于每个元素都出现了两次,根据异或运算可以消去这两个元素 #最后保留的就是带求值key和初始值1的异或 @@ -515,19 +515,19 @@ return res #### 只出现一次的数字II 1. 数学计算 -```angular2html +```python tmp = set(nums) return (3*sum(tmp) - sum(nums))//2 ``` 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。 1.python解法 使用count函数 但是count函数本身的时间复杂度就是O(N)的,导致算法时间复杂度是O(N^2) -```angular2html +```python for num in nums: if nums.count(num)==1: return num ``` 对应的优化是采用collections中的Counter模块 -```angular2html +```python from collections import Counter dic = Counter(nums) for key in dic.keys(): @@ -535,7 +535,7 @@ for key in dic.keys(): return key ``` 2.hash表法 通用解 -```angular2html +```python dic = {} for num in nums: dic[num] = dic.get(num,0)+1 @@ -547,7 +547,7 @@ for key, value in dic.items(): 1x1x1->1 1->0,这个数可以出现0次、1次、2次,需要两位来表示其状态 构造真值表 写出逻辑表达式 并化简 参考连接[电路逻辑通俗解](https://leetcode-cn.com/problems/single-number-ii/solution/luo-ji-dian-lu-jiao-du-xiang-xi-fen-xi-gai-ti-si-l/) -```angular2html +```python x,y = 0,0 for z in nums: tmp = ~x&(y^z) @@ -556,7 +556,7 @@ for z in nums: return y ``` 根据两个表达式同构的性质,可以优化更新x的逻辑表达式 -```angular2html +```python x, y = 0, 0 for num in nums:#num means input y = ~x & (y^num) @@ -566,14 +566,14 @@ return y #### 只出现一次的数字III 1.使用Counter -```angular2html +```python from collections import Counter #{'num':count} dic = Counter(nums) return [key for key in dic if dic[key]==1 ] ``` 给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。 2.hash表法 -```angular2html +```python dic,res = {}, [] for num in nums: dic[num] = dic.get(num,0) + 1 @@ -585,7 +585,7 @@ return res 3.接上一题的思路,如果对这些元素进行异或,得到的结果就是待求元素的异或值,如何从结果中分离这两个元素呢? 异或得到的结果不能直接分离出待求元素,但是我们可以根据这个异或值的第一个1将原数组分类, 由于其余元素都是出现两次的,所以对这两个数组分别求异或即可得到结果。 -```angular2html +```python tmp = 0 for num in nums: tmp ^= num @@ -612,7 +612,7 @@ return res ``` 上面的方式可以优化,其一,找第一位不同,第二,不需要用数组存放元素,直接根据此位是否为1,直接进行计算 -```angular2html +```python tmp= 0 for num in nums: tmp ^= num @@ -630,7 +630,7 @@ return [x, tmp^x]#tmp是两个数的异或值,一个值已经找到了 路径: 左->中->再上 左->中 左->中->右 -```angular2html +```python class TreeNode: def __init__(self, x): self.val = x From 53948032ef179ed00eb0a6b848814b494df85e37 Mon Sep 17 00:00:00 2001 From: mqray Date: Thu, 23 Jul 2020 00:30:58 +0800 Subject: [PATCH 088/105] =?UTF-8?q?markdown=E6=A0=BC=E5=BC=8F=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week01/.idea/workspace.xml | 414 ++++-------------- Week01/NOTE.md | 106 +++-- ...51\345\275\242\351\235\242\347\247\257.py" | 24 +- 3 files changed, 134 insertions(+), 410 deletions(-) diff --git a/Week01/.idea/workspace.xml b/Week01/.idea/workspace.xml index 893638ddb..0f8fff7a4 100644 --- a/Week01/.idea/workspace.xml +++ b/Week01/.idea/workspace.xml @@ -2,24 +2,12 @@ + - - - - - - - - - - - - - - - - + + + @@ -257,6 +247,7 @@ + @@ -268,7 +259,6 @@ + @@ -273,30 +287,8 @@ - - - - - + + - + - + - + - + - - - - - - + + + + + - - - - - + + + + + @@ -463,12 +454,12 @@ - + - + @@ -519,6 +510,108 @@ + + + file://$PROJECT_DIR$/组合.py + 9 + + + file://$PROJECT_DIR$/组合.py + 10 + + + file://$PROJECT_DIR$/组合.py + 14 + + + file://$PROJECT_DIR$/组合.py + 12 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 42 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 43 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 44 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 45 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 46 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 47 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 48 + + + file://$PROJECT_DIR$/每日一题6_27_全排列.py + 54 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 27 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 28 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 29 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 31 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 34 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 35 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 36 + + + file://$PROJECT_DIR$/每日一题6_27_全排列II.py + 39 + + @@ -661,20 +754,6 @@ - - - - - - - - - - - - - - @@ -690,13 +769,6 @@ - - - - - - - @@ -735,43 +807,16 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + @@ -786,7 +831,7 @@ - + @@ -797,15 +842,46 @@ - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -813,16 +889,72 @@ - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Week03/NOTE.md b/Week03/NOTE.md index 8ac6d1451..1d51e17be 100644 --- a/Week03/NOTE.md +++ b/Week03/NOTE.md @@ -556,6 +556,19 @@ def permute(self, nums: List[int]) -> List[List[int]]: #### 全排列II ```python +class SolutionII: + def permuteUnique(self, nums: List[int]) -> List[List[int]]: + def backtrace(nums,tmp): + if len(tmp) == size: + res.append(tmp[:]) + for i in range(len(nums)): + backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]]) + res, size = [], len(nums) + backtrace(nums,[]) + return res +``` +上面在判重的时候,是在写入res时手动遍历判重,其实可以直接用set记录中间结果 +```python def permuteUnique(self, nums): """ :type nums: List[int] diff --git "a/Week03/\344\273\205\344\273\205\346\230\257\347\277\273\350\275\254\345\255\227\347\254\246.py" "b/Week03/\344\273\205\344\273\205\346\230\257\347\277\273\350\275\254\345\255\227\347\254\246.py" new file mode 100644 index 000000000..150a698d5 --- /dev/null +++ "b/Week03/\344\273\205\344\273\205\346\230\257\347\277\273\350\275\254\345\255\227\347\254\246.py" @@ -0,0 +1,22 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/23 8:59 PM + +class Solution: + def reverseOnlyLetters(self, strs: str) -> str: + tmp = list(strs) + left, right = 0, len(strs) - 1 + while left <= right: + if not tmp[left].isalpha(): left = left + 1 + elif not tmp[right].isalpha(): right = right - 1 + else: + tmp[left], tmp[right] = tmp[right], tmp[left] + left, right = left + 1, right - 1 + return ''.join(tmp) + +s = Solution() +strs = "a-bC-dEf-ghIj" +# strs = "ab-cd" +# strs = "7_28]" +res = s.reverseOnlyLetters(strs) +print(res) \ No newline at end of file diff --git "a/Week03/\345\233\236\346\226\207\346\225\260.py" "b/Week03/\345\233\236\346\226\207\346\225\260.py" new file mode 100644 index 000000000..0494a788d --- /dev/null +++ "b/Week03/\345\233\236\346\226\207\346\225\260.py" @@ -0,0 +1,24 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/23 9:45 PM + +class Solution: + def isPalindrome(self, x: int) -> bool: + # if x < 0: return False + # tmp = str(x) + # left,right = 0, len(tmp)-1 + # while left <= right: + # if tmp[left] != tmp[right]: return False + # else: left,right = left+1,right-1 + # return True + + # return str(x) == str(x)[::-1] + res = x + tmp = 0 + while x > 0: + tmp = tmp*10 + x%10 + x = x//10 + return res == tmp +s = Solution() +res = s.isPalindrome(-1211) +print(res) diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" index e1a743e04..2fd060d22 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227.py" @@ -4,21 +4,6 @@ from typing import List class Solution(object): - # def permute(self, nums): - # def backtracing(first=0): - # if first == size: - # result.append(nums[:]) - # for i in range(first, size): - # nums[first], nums[i] = nums[i], nums[first] - # backtracing(first+1) - # nums[first], nums[i] = nums[i], nums[first] - - # size = len(nums) - # result = [] - # #l路径 - # #选择列表 就是除去已经被加入到cur中的其余元素 - # backtracing() - # return result # def permute(self,nums): # res = [] # self.backtracing(res,nums,[]) @@ -53,8 +38,19 @@ def backtrace(nums, tmp): +class SolutionII: + def permute(self, nums: List[int]) -> List[List[int]]: + def backtrace(nums,tmp): + if len(tmp) == size: + res.append(tmp[:]) + for i in range(len(nums)): + backtrace(nums[:i]+nums[i+1:],tmp + [nums[i]]) + res,size = [],len(nums) + backtrace(nums,[]) + return res + -s = Solution() +s = SolutionII() nums = [1,3,2] res = s.permute(nums) print(res) \ No newline at end of file diff --git "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" index 04a64d158..974b750f4 100644 --- "a/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" +++ "b/Week03/\346\257\217\346\227\245\344\270\200\351\242\2306_27_\345\205\250\346\216\222\345\210\227II.py" @@ -20,22 +20,22 @@ def backtrace(nums, tmp): res = [] backtrace(nums, []) return res - # res = [] - # self.backtracing(res,nums,[]) - # return res - # def backtracing(self,res,nums,tmp): - # #触发结束条件 - # if len(nums)==len(tmp): - # res.append(tmp[:]) - # for i in range(len(nums)): - # #排除不合法条件 - # if nums[i] in tmp: - # continue - # #做选择 - # tmp.append(nums[i]) - # #进入下一层决策 - # self.backtracing(res,nums,tmp) - # tmp.pop() -s = Solution() + + +from typing import List +class SolutionII: + def permuteUnique(self, nums: List[int]) -> List[List[int]]: + def backtrace(nums,tmp): + if len(tmp) == size: + res.append(tmp[:]) + visited = set()#同层去重,每一层只能选择这一层还没有被选过的元素 + for i in range(len(nums)): + if nums[i] in visited: continue + visited.add(nums[i]) + backtrace(nums[:i]+nums[i+1:],tmp+[nums[i]]) + res, size = [], len(nums) + backtrace(nums,[]) + return res +s = SolutionII() res = s.permuteUnique([1,1,2]) print(res) \ No newline at end of file diff --git "a/Week03/\347\273\204\345\220\210.py" "b/Week03/\347\273\204\345\220\210.py" new file mode 100644 index 000000000..1886fc3fd --- /dev/null +++ "b/Week03/\347\273\204\345\220\210.py" @@ -0,0 +1,24 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/23 8:26 PM + +#给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。 +from typing import List +class Solution: + def combine(self, n: int, k: int) -> List[List[int]]: + def backtrace(first=1, tmp=[]): + if len(tmp) == k: + res.append(tmp[:]) + return + for i in range(first,n+1): + tmp.append(i) + backtrace(i+1, tmp) + tmp.pop() + res = [] + backtrace() + return res + + +s = Solution() +res = s.combine(4,3) +print(res) \ No newline at end of file diff --git "a/Week03/\347\273\204\345\220\210\346\200\273\345\222\214.py" "b/Week03/\347\273\204\345\220\210\346\200\273\345\222\214.py" new file mode 100644 index 000000000..820d2f43f --- /dev/null +++ "b/Week03/\347\273\204\345\220\210\346\200\273\345\222\214.py" @@ -0,0 +1,26 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/23 11:53 PM + +from typing import List +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + def dfs(candidates, target, tmp, start): + if target<0: return + if target == 0: + res.append(tmp) + # for num in candidates: + # dfs(candidates, target-num, tmp+[num]) + for i in range(start, len(candidates)): + dfs(candidates, target-candidates[i], tmp+[candidates[i]], i) + res = [] + dfs(candidates, target, [], 0) + return res + # res = [sorted(nums) for nums in res] + # res = [nums for nums in res if nums not in res] + +s = Solution() +candidates = [2,3,6,7] +target = 7 +res = s.combinationSum(candidates,target) +print(res) \ No newline at end of file diff --git "a/Week03/\347\273\204\345\220\210\346\200\273\345\222\214II.py" "b/Week03/\347\273\204\345\220\210\346\200\273\345\222\214II.py" new file mode 100644 index 000000000..9a187ffca --- /dev/null +++ "b/Week03/\347\273\204\345\220\210\346\200\273\345\222\214II.py" @@ -0,0 +1,28 @@ +# -*- coding:utf-8 -*- +# Author : Ray +# Data : 2020/7/24 12:42 AM + +from typing import List +class Solution: + def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]: + def dfs(candidates, target, tmp, start): + if target < 0: return + if target == 0: res.append(tmp) + # visited = set() + for i in range(start, len(candidates)): + if i > 0 and candidates[i-1] == candidates[i]: continue + cur = candidates[i] + # if cur in visited: continue + # visited.add(cur) + dfs(candidates[:i]+candidates[i+1:],target-cur,tmp+[cur],i) + candidates.sort() + res = [] + dfs(candidates,target,[],0) + return res + +s = Solution() +# candidates = [10,1,2,7,6,1,5] +candidates = [1,1,2,5,6,7,10] +target = 8 +res = s.combinationSum2(candidates,target) +print(res) \ No newline at end of file From 2c269bdb4d9802b342ea1dfddcc383775342b464 Mon Sep 17 00:00:00 2001 From: mqray Date: Sat, 25 Jul 2020 00:32:45 +0800 Subject: [PATCH 091/105] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week07/.idea/leetcode/editor.xml | 25 ++ Week07/.idea/workspace.xml | 240 +++++++++++------- Week07/NOTE.md | 136 +++++++++- "Week07/Trie\346\240\221.py" | 65 ++--- ...5\350\257\215\346\220\234\347\264\242I.py" | 58 +++++ ...\350\257\215\346\220\234\347\264\242II.py" | 30 +++ 6 files changed, 415 insertions(+), 139 deletions(-) create mode 100644 Week07/.idea/leetcode/editor.xml create mode 100644 "Week07/\345\215\225\350\257\215\346\220\234\347\264\242I.py" diff --git a/Week07/.idea/leetcode/editor.xml b/Week07/.idea/leetcode/editor.xml new file mode 100644 index 000000000..0118ed9fc --- /dev/null +++ b/Week07/.idea/leetcode/editor.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/Week07/.idea/workspace.xml b/Week07/.idea/workspace.xml index 405b91e26..d941e37dd 100644 --- a/Week07/.idea/workspace.xml +++ b/Week07/.idea/workspace.xml @@ -2,22 +2,15 @@ - - - - - + + - - - - - - - + + + - + - - - - - + + + + + + + + + + + @@ -76,8 +81,29 @@ - - + + + + + + + + + + + + + + + + + + + + + + + @@ -85,7 +111,7 @@ - + @@ -100,11 +126,11 @@ - + - - + + @@ -112,8 +138,8 @@ - - + + @@ -121,8 +147,8 @@ - - + + @@ -142,13 +168,15 @@ @@ -169,6 +197,7 @@ + @@ -180,7 +209,6 @@