diff --git "a/Week_01/1.\344\270\244\346\225\260\344\271\213\345\222\214.py" "b/Week_01/1.\344\270\244\346\225\260\344\271\213\345\222\214.py" new file mode 100644 index 00000000..24ab4a10 --- /dev/null +++ "b/Week_01/1.\344\270\244\346\225\260\344\271\213\345\222\214.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=1 lang=python +# +# [1] 两数之和 +# + +# @lc code=start +class Solution(object): + def twoSum(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + dic = {} + for i in range(len(nums)): + if target - nums[i] not in dic: + dic[nums[i]] = i + else: + return [dic[target - nums[i]], i] + +# @lc code=end + diff --git "a/Week_01/11.\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250.py" "b/Week_01/11.\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250.py" new file mode 100644 index 00000000..d4d24e23 --- /dev/null +++ "b/Week_01/11.\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250.py" @@ -0,0 +1,20 @@ +# +# @lc app=leetcode.cn id=11 lang=python3 +# +# [11] 盛最多水的容器 +# + +# @lc code=start +class Solution: + def maxArea(self, height: List[int]) -> int: + left, right = 0, len(height) - 1 + area = (right - left) * min(height[left], height[right]) + while left < right: + if height[left] > height[right]: + right -= 1 + else: + left += 1 + area = max(area, (right - left) * min(height[left], height[right])) + return area +# @lc code=end + diff --git "a/Week_01/141.\347\216\257\345\275\242\351\223\276\350\241\250.py" "b/Week_01/141.\347\216\257\345\275\242\351\223\276\350\241\250.py" new file mode 100644 index 00000000..cdabaa48 --- /dev/null +++ "b/Week_01/141.\347\216\257\345\275\242\351\223\276\350\241\250.py" @@ -0,0 +1,26 @@ +# +# @lc app=leetcode.cn id=141 lang=python3 +# +# [141] 环形链表 +# + +# @lc code=start +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: ListNode) -> bool: + # 快慢指针 + slow = ListNode(-1) + slow.next = fast = head + while fast and fast.next: + if fast == slow:return True + fast = fast.next.next + slow = slow.next + return False + +# @lc code=end + diff --git "a/Week_01/142.\347\216\257\345\275\242\351\223\276\350\241\250-ii.py" "b/Week_01/142.\347\216\257\345\275\242\351\223\276\350\241\250-ii.py" new file mode 100644 index 00000000..865a4345 --- /dev/null +++ "b/Week_01/142.\347\216\257\345\275\242\351\223\276\350\241\250-ii.py" @@ -0,0 +1,29 @@ +# +# @lc app=leetcode.cn id=142 lang=python3 +# +# [142] 环形链表 II +# + +# @lc code=start +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def detectCycle(self, head: ListNode) -> ListNode: + fast = slow = head + while True: + if not (fast and fast.next): return + fast, slow = fast.next.next, slow.next + if fast == slow: + break + fast = head + while fast != slow: + fast, slow = fast.next, slow.next + return fast + + +# @lc code=end + diff --git "a/Week_01/15.\344\270\211\346\225\260\344\271\213\345\222\214.py" "b/Week_01/15.\344\270\211\346\225\260\344\271\213\345\222\214.py" new file mode 100644 index 00000000..cd6c94db --- /dev/null +++ "b/Week_01/15.\344\270\211\346\225\260\344\271\213\345\222\214.py" @@ -0,0 +1,35 @@ +# +# @lc app=leetcode.cn id=15 lang=python3 +# +# [15] 三数之和 +# + +# @lc code=start +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + nums.sort() + res = [] + if len(nums) < 3:return [] + for i in range(len(nums) - 2): + if i > 0 and nums[i] == nums[i - 1]: continue + j = i + 1 + k = len(nums) - 1 + while j < k: + sum_3 = nums[i] + nums[j] + nums[k] + if sum_3 == 0: + res.append([nums[i], nums[j], nums[k]]) + j += 1 + k -= 1 + if sum_3 > 0: + k -= 1 + if sum_3 < 0: + j += 1 + # 判重 + while j < k and j - 1 > i and nums[j] == nums[j - 1]: + j += 1 + while j < k and k + 1 < len(nums) and nums[k] == nums[k + 1]: + k -= 1 + return res + +# @lc code=end + diff --git "a/Week_01/155.\346\234\200\345\260\217\346\240\210.py" "b/Week_01/155.\346\234\200\345\260\217\346\240\210.py" new file mode 100644 index 00000000..478efc3a --- /dev/null +++ "b/Week_01/155.\346\234\200\345\260\217\346\240\210.py" @@ -0,0 +1,40 @@ +# +# @lc app=leetcode.cn id=155 lang=python3 +# +# [155] 最小栈 +# + +# @lc code=start +class MinStack: + + def __init__(self): + """ + initialize your data structure here. + """ + self.stack = [] + self.min_stack = [float('inf')] + + def push(self, x: int) -> None: + self.stack.append(x) + self.min_stack.append(min(x, self.min_stack[-1])) + + def pop(self) -> None: + self.stack.pop() + 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() +# @lc code=end + diff --git "a/Week_01/18.\345\233\233\346\225\260\344\271\213\345\222\214.py" "b/Week_01/18.\345\233\233\346\225\260\344\271\213\345\222\214.py" new file mode 100644 index 00000000..81de0b9d --- /dev/null +++ "b/Week_01/18.\345\233\233\346\225\260\344\271\213\345\222\214.py" @@ -0,0 +1,11 @@ +# +# @lc app=leetcode.cn id=18 lang=python3 +# +# [18] 四数之和 +# + +# @lc code=start +class Solution: + def fourSum(self, nums: List[int], target: int) -> List[List[int]]: +# @lc code=end + diff --git "a/Week_01/189.\346\227\213\350\275\254\346\225\260\347\273\204.py" "b/Week_01/189.\346\227\213\350\275\254\346\225\260\347\273\204.py" new file mode 100644 index 00000000..86f9f99c --- /dev/null +++ "b/Week_01/189.\346\227\213\350\275\254\346\225\260\347\273\204.py" @@ -0,0 +1,20 @@ +# +# @lc app=leetcode.cn id=189 lang=python3 +# +# [189] 旋转数组 +# + +# @lc code=start +class Solution: + def rotate(self, nums: List[int], k: int) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + n = len(nums) + k %= n + nums[:] = nums[::-1] + nums[:k] = nums[:k][::-1] + nums[k:] = nums[k:][::-1] + +# @lc code=end + diff --git "a/Week_01/20.\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267.py" "b/Week_01/20.\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267.py" new file mode 100644 index 00000000..43514247 --- /dev/null +++ "b/Week_01/20.\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267.py" @@ -0,0 +1,19 @@ +# +# @lc app=leetcode.cn id=20 lang=python3 +# +# [20] 有效的括号 +# + +# @lc code=start +class Solution: + def isValid(self, s: str) -> bool: + dic = {'(':')', '[':']','{':'}'} + stack = [] + for i in s: + if stack and i == dic.get(stack[-1],0): + stack.pop() + else : + stack.append(i) + return not stack +# @lc code=end + diff --git "a/Week_01/206.\345\217\215\350\275\254\351\223\276\350\241\250.py" "b/Week_01/206.\345\217\215\350\275\254\351\223\276\350\241\250.py" new file mode 100644 index 00000000..d4952da6 --- /dev/null +++ "b/Week_01/206.\345\217\215\350\275\254\351\223\276\350\241\250.py" @@ -0,0 +1,36 @@ +# +# @lc app=leetcode.cn id=206 lang=python3 +# +# [206] 反转链表 +# + +# @lc code=start +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def reverseList(self, head: ListNode) -> ListNode: + # 迭代法 + pre = None + cur = head + while cur: + # tmp = cur.next + # cur.next = pre + # pre = cur + # cur = tmp + cur.next,pre,cur = pre,cur,cur.next + return pre + + # # 递归法(有点难理解) + # if not head or not head.next: + # return head + # cur = self.reverseList(head.next) # 这里返回的是反序的链表, cur指向表头 + # head.next.next = head + # head.next = None + # return cur + +# @lc code=end + diff --git "a/Week_01/21.\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.py" "b/Week_01/21.\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.py" new file mode 100644 index 00000000..061d7478 --- /dev/null +++ "b/Week_01/21.\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.py" @@ -0,0 +1,33 @@ +# +# @lc app=leetcode.cn id=21 lang=python3 +# +# [21] 合并两个有序链表 +# + +# @lc code=start +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: + dummp = tmp = ListNode(0) + while l1 and l2: + if l1.val < l2.val: + tmp.next = l1 + l1 = l1.next + else: + tmp.next = l2 + l2 = l2.next + tmp = tmp.next + if l1: + tmp.next = l1 + else: + tmp.next = l2 + return dummp.next + + + +# @lc code=end + diff --git "a/Week_01/239.\346\273\221\345\212\250\347\252\227\345\217\243\346\234\200\345\244\247\345\200\274.py" "b/Week_01/239.\346\273\221\345\212\250\347\252\227\345\217\243\346\234\200\345\244\247\345\200\274.py" new file mode 100644 index 00000000..2834711c --- /dev/null +++ "b/Week_01/239.\346\273\221\345\212\250\347\252\227\345\217\243\346\234\200\345\244\247\345\200\274.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=239 lang=python3 +# +# [239] 滑动窗口最大值 +# + +# @lc code=start +class Solution: + def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: + # 双端队列 + deq = collections.deque() # 存放下标 + ans = [] + for i in range(len(nums)): + # 当deq的第一个数字下标越界,则清除deq的第一个数 + if deq and deq[0] + k <= i: + deq.popleft() + # 当deq[-1]的数字小于当前i的数字,则直接去掉deq[-1] + while deq and nums[deq[-1]] < nums[i]: + deq.pop() + # 清除掉所有不满足的数字后,就可以添加新的元素了 + # 注意:这里加入的是下标,而不是nums的元素 + deq.append(i) + # 当i>k的时候就可以更新答案了 + if i >= k - 1: + ans.append(nums[deq[0]]) + return ans +# @lc code=end + diff --git "a/Week_01/24.\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271.py" "b/Week_01/24.\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271.py" new file mode 100644 index 00000000..c24e8ebe --- /dev/null +++ "b/Week_01/24.\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271.py" @@ -0,0 +1,37 @@ +# +# @lc app=leetcode.cn id=24 lang=python3 +# +# [24] 两两交换链表中的节点 +# + +# @lc code=start +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def swapPairs(self, head: ListNode) -> ListNode: + # 迭代 + dummyHead = ListNode(0) + dummyHead.next = head + tmp = dummyHead + while tmp.next and tmp.next.next: + pre = tmp.next + cur = tmp.next.next + tmp.next = cur + pre.next = cur.next + cur.next = pre + tmp = pre + return dummyHead.next + + # # 递归 + # if not head or not head.next:return head + + # tmp = head.next + # head.next = self.swapPairs(head.next.next) + # tmp.next = head + # return tmp + +# @lc code=end + diff --git "a/Week_01/242.\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" "b/Week_01/242.\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" new file mode 100644 index 00000000..73cb7c35 --- /dev/null +++ "b/Week_01/242.\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" @@ -0,0 +1,24 @@ +# +# @lc app=leetcode.cn id=242 lang=python3 +# +# [242] 有效的字母异位词 +# + +# @lc code=start +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + # 自定义字典 + dic_s = defaultdict(int) + dic_t = defaultdict(int) + for i in s: + dic_s[i] += 1 + for j in t: + dic_t[j] += 1 + return dic_s == dic_t + + # 用库定义字典 + dic_s = collections.Counter(s) + dic_t = collections.Counter(t) + return dic_s == dic_t +# @lc code=end + diff --git "a/Week_01/25.k-\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250.py" "b/Week_01/25.k-\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250.py" new file mode 100644 index 00000000..5fb8c8c2 --- /dev/null +++ "b/Week_01/25.k-\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250.py" @@ -0,0 +1,57 @@ +# +# @lc app=leetcode.cn id=25 lang=python3 +# +# [25] K 个一组翻转链表 +# + +# @lc code=start +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def reverse(self, head ,tail): + """ + 这一段完全类似反转链表的代码,可以照抄逻辑 + """ + pre = None + cur = head + # 这里和反转链表少许不同 + # 结束条件是反转到该段链表的结束 + while pre != tail: + tmp = cur.next + cur.next = pre + pre = cur + cur = tmp + return tail, head + + + def reverseKGroup(self, head: ListNode, k: int) -> ListNode: + dummy = ListNode(0) + pre = dummy + pre.next = head + + while True: + tail = pre # 前一段链表的结尾 + # 判断下面是否还有k个节点 + # 如果没有了,说明不需要反转了,直接返回整个链表 + # 如果还有,那么tail刚好走k步到了当前这段链表的结尾 + for _ in range(k): + tail = tail.next + if not tail: + return dummy.next + + nex = tail.next # 记录一下结尾的下一个节点,方面后面连接 + head, tail = self.reverse(head, tail) # 反转链表 + # 反转完成后开始连接链表 + pre.next = head + tail.next = nex + + # 初始化下一个链表的初始值 + pre = tail + head = nex + return dummy.next + +# @lc code=end + diff --git "a/Week_01/258.\345\220\204\344\275\215\347\233\270\345\212\240.py" "b/Week_01/258.\345\220\204\344\275\215\347\233\270\345\212\240.py" new file mode 100644 index 00000000..0e3150b4 --- /dev/null +++ "b/Week_01/258.\345\220\204\344\275\215\347\233\270\345\212\240.py" @@ -0,0 +1,11 @@ +# +# @lc app=leetcode.cn id=258 lang=python3 +# +# [258] 各位相加 +# + +# @lc code=start +class Solution: + def addDigits(self, num: int) -> int: +# @lc code=end + diff --git "a/Week_01/26.\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271.py" "b/Week_01/26.\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271.py" new file mode 100644 index 00000000..4a6b7ac3 --- /dev/null +++ "b/Week_01/26.\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271.py" @@ -0,0 +1,20 @@ +# +# @lc app=leetcode.cn id=26 lang=python3 +# +# [26] 删除排序数组中的重复项 +# + +# @lc code=start +class Solution: + def removeDuplicates(self, nums: List[int]) -> int: + if len(nums)<2:return len(nums) + slow = 0 + fast = 1 + while fast < len(nums): + if nums[fast] != nums[slow]: + slow += 1 + nums[slow] = nums[fast] + fast += 1 + return slow + 1 +# @lc code=end + diff --git "a/Week_01/283.\347\247\273\345\212\250\351\233\266.py" "b/Week_01/283.\347\247\273\345\212\250\351\233\266.py" new file mode 100644 index 00000000..08ebd50f --- /dev/null +++ "b/Week_01/283.\347\247\273\345\212\250\351\233\266.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=283 lang=python +# +# [283] 移动零 +# + +# @lc code=start +class Solution(object): + def moveZeroes(self, nums): + """ + :type nums: List[int] + :rtype: None Do not return anything, modify nums in-place instead. + """ + index = 0 # 记录非零元素改填入的位置 + for i in range(len(nums)): + if nums[i] != 0: + # 答案提供的思路 + # nums[index] = nums[i] + # if i != index: + # nums[i] = 0 + # index += 1 + + # 自己思考后的答案(本质上是双指针) + nums[index], nums[i]= nums[i], nums[index] + index += 1 + return nums +# @lc code=end + diff --git "a/Week_01/33.\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/Week_01/33.\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 00000000..efa8cc83 --- /dev/null +++ "b/Week_01/33.\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,16 @@ +# +# @lc app=leetcode.cn id=33 lang=python +# +# [33] 搜索旋转排序数组 +# + +# @lc code=start +class Solution(object): + def search(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: int + """ +# @lc code=end + diff --git "a/Week_01/42.\346\216\245\351\233\250\346\260\264.py" "b/Week_01/42.\346\216\245\351\233\250\346\260\264.py" new file mode 100644 index 00000000..b1db3204 --- /dev/null +++ "b/Week_01/42.\346\216\245\351\233\250\346\260\264.py" @@ -0,0 +1,24 @@ +# +# @lc app=leetcode.cn id=42 lang=python3 +# +# [42] 接雨水 +# + +# @lc code=start +class Solution: + def trap(self, height: List[int]) -> int: + # 方法一:韦恩图思想, 思想简单, 代码简单, 过目难忘 + s1 = s2 = 0 + max1 = max2 = 0 + n = len(height) + for i in range(n): + if max1 < height[i]: + max1 = height[i] + if max2 < height[n - 1 - i]: + max2 = height[n - 1 - i] + s1 += max1 + s2 += max2 + ans = s1 + s2 - n * max1 - sum(height) + return ans +# @lc code=end + diff --git "a/Week_01/641.\350\256\276\350\256\241\345\276\252\347\216\257\345\217\214\347\253\257\351\230\237\345\210\227.py" "b/Week_01/641.\350\256\276\350\256\241\345\276\252\347\216\257\345\217\214\347\253\257\351\230\237\345\210\227.py" new file mode 100644 index 00000000..3f78ecfb --- /dev/null +++ "b/Week_01/641.\350\256\276\350\256\241\345\276\252\347\216\257\345\217\214\347\253\257\351\230\237\345\210\227.py" @@ -0,0 +1,112 @@ +# +# @lc app=leetcode.cn id=641 lang=python3 +# +# [641] 设计循环双端队列 +# + +# @lc code=start +class MyCircularDeque: + + def __init__(self, k): + """ + Initialize your data structure here. Set the size of the deque to be k. + :type k: int + """ + self.front = 0 # 指向当前起始数据 + self.rear = 0 # 指向当前结束数据的后一个位置 + self.capacity = k + 1 # 多出的一个是为了 避免“队列为空”和“队列为满”的判别条件冲突 + self.arr = [0 for _ in range(self.capacity)] + + def insertFront(self, value): + """ + Adds an item at the front of Deque. Return true if the operation is successful. + :type value: int + :rtype: bool + """ + if self.isFull(): + return False + self.front = (self.front - 1 + self.capacity) % self.capacity + self.arr[self.front] = value + return True + + def insertLast(self, value): + """ + Adds an item at the rear of Deque. Return true if the operation is successful. + :type value: int + :rtype: bool + """ + if self.isFull(): + return False + self.arr[self.rear] = value + self.rear = (self.rear + 1) % self.capacity + return True + + def deleteFront(self): + """ + Deletes an item from the front of Deque. Return true if the operation is successful. + :rtype: bool + """ + if self.isEmpty(): + return False + self.front = (self.front + 1) % self.capacity + return True + + + def deleteLast(self): + """ + Deletes an item from the rear of Deque. Return true if the operation is successful. + :rtype: bool + """ + if self.isEmpty(): + return False + self.rear = (self.rear - 1 + self.capacity) % self.capacity + return True + + def getFront(self): + """ + Get the front item from the deque. + :rtype: int + """ + if self.isEmpty(): + return -1 + return self.arr[self.front] + + + def getRear(self): + """ + Get the last item from the deque. + :rtype: int + """ + if self.isEmpty(): + return -1 + return self.arr[(self.rear - 1 + self.capacity) % self.capacity] + + def isEmpty(self): + """ + Checks whether the circular deque is empty or not. + :rtype: bool + """ + return self.rear == self.front + + + def isFull(self): + """ + Checks whether the circular deque is full or not. + :rtype: bool + """ + return (self.rear + 1) % self.capacity == self.front + + + +# Your MyCircularDeque object will be instantiated and called as such: +# obj = MyCircularDeque(k) +# param_1 = obj.insertFront(value) +# param_2 = obj.insertLast(value) +# param_3 = obj.deleteFront() +# param_4 = obj.deleteLast() +# param_5 = obj.getFront() +# param_6 = obj.getRear() +# param_7 = obj.isEmpty() +# param_8 = obj.isFull() +# @lc code=end + diff --git "a/Week_01/66.\345\212\240\344\270\200.py" "b/Week_01/66.\345\212\240\344\270\200.py" new file mode 100644 index 00000000..97768786 --- /dev/null +++ "b/Week_01/66.\345\212\240\344\270\200.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=66 lang=python3 +# +# [66] 加一 +# + +# @lc code=start +class Solution: + def plusOne(self, digits: List[int]) -> List[int]: + tail = [] + # 满9进一 + while digits and digits[-1] == 9: + digits.pop() + tail.append(0) + # 加上尾部的0 + if digits == []: + return [1] + tail + else: + digits[-1] += 1 + return digits + tail + +# @lc code=end + diff --git "a/Week_01/70.\347\210\254\346\245\274\346\242\257.py" "b/Week_01/70.\347\210\254\346\245\274\346\242\257.py" new file mode 100644 index 00000000..13e08b69 --- /dev/null +++ "b/Week_01/70.\347\210\254\346\245\274\346\242\257.py" @@ -0,0 +1,31 @@ +# +# @lc app=leetcode.cn id=70 lang=python +# +# [70] 爬楼梯 +# + +# @lc code=start +class Solution(object): + def climbStairs(self, n): + """ + :type n: int + :rtype: int + """ + # # 动态规划 + # # dp[i] 爬第i层楼梯有多少中方法 + # if n < 2: return 1 + # dp = [1]*(n + 1) + # dp[1] = 1 + # for i in range(2,n + 1): + # dp[i] = dp[i - 1] + dp[i - 2] + # return dp[-1] + + # 降低空间复杂度 + if n < 2: return 1 + dp0, dp1 = 1, 1 + for i in range(2,n + 1): + dp2 = dp0 + dp1 + dp0, dp1 = dp1, dp2 + return dp2 +# @lc code=end + diff --git "a/Week_01/84.\346\237\261\347\212\266\345\233\276\344\270\255\346\234\200\345\244\247\347\232\204\347\237\251\345\275\242.py" "b/Week_01/84.\346\237\261\347\212\266\345\233\276\344\270\255\346\234\200\345\244\247\347\232\204\347\237\251\345\275\242.py" new file mode 100644 index 00000000..937b46ea --- /dev/null +++ "b/Week_01/84.\346\237\261\347\212\266\345\233\276\344\270\255\346\234\200\345\244\247\347\232\204\347\237\251\345\275\242.py" @@ -0,0 +1,44 @@ +# +# @lc app=leetcode.cn id=84 lang=python3 +# +# [84] 柱状图中最大的矩形 +# + +# @lc code=start +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + # # 官方解 + # n = len(heights) + # stack = [] # 存放柱的下标 + # left = [0] * n # 每根柱子的左边界 + # right = [n] * n # 每根柱子的右边界 + + # for i in range(n): + # while stack and heights[stack[-1]] > heights[i]: + # right[stack[-1]] = i # 找到了stack[-1]的柱字的右边界 + # stack.pop() + # left[i] = stack[-1] if stack else -1 # 找到左边界 + # stack.append(i) + + # ans = 0 + # for i in range(n): + # ans = max(ans, (right[i] - left[i] - 1) * heights[i]) + # return ans + + # 另一种解 + heights = [0] + heights + [0] # 这一步处理的很妙,甚至有点觉得似懂非懂 + n = len(heights) + stack = [] + ans = 0 + + for i in range(n): + while stack and heights[stack[-1]] > heights[i]: + tmp = stack.pop() + # 这里计算的是i前面的那个柱子的面积 + ans = max(ans, (i - stack[-1] - 1) * heights[tmp]) + stack.append(i) + return ans + + +# @lc code=end + diff --git "a/Week_01/88.\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.py" "b/Week_01/88.\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.py" new file mode 100644 index 00000000..731df32c --- /dev/null +++ "b/Week_01/88.\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.py" @@ -0,0 +1,30 @@ +# +# @lc app=leetcode.cn id=88 lang=python3 +# +# [88] 合并两个有序数组 +# + +# @lc code=start +class Solution: + def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: + """ + Do not return anything, modify nums1 in-place instead. + """ + # 从后往前 + index = m + n - 1 + index1 = m - 1 + index2 = n - 1 + while (index1>=0 and index2>=0): + if nums1[index1] < nums2[index2]: + nums1[index] = nums2[index2] + index2 -= 1 + else: + nums1[index] = nums1[index1] + index1 -= 1 + index -= 1 + # 补尾 + if index2>=0: + nums1[:index2 + 1] = nums2[:index2 + 1] + +# @lc code=end + diff --git "a/Week_01/94.\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py" "b/Week_01/94.\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py" new file mode 100644 index 00000000..e11b5e4b --- /dev/null +++ "b/Week_01/94.\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=94 lang=python3 +# +# [94] 二叉树的中序遍历 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def inorderTraversal(self, root: TreeNode) -> List[int]: + # 递归 + ans = [] + def dfs(root): + if root: + dfs(root.left) + ans.append(root.val) + dfs(root.right) + dfs(root) + return ans + +# @lc code=end + diff --git a/Week_01/README.md b/Week_01/README.md index 50de3041..c928e5b4 100644 --- a/Week_01/README.md +++ b/Week_01/README.md @@ -1 +1,4 @@ -学习笔记 \ No newline at end of file +学习总结 +1 对于链表反转和两两交换链表中的节点这两道题进行了反复练习,三次手敲代码后,发现对于其中的转换思路有了清晰的认识。 +2 同时清除的认识到从顶层开始向下设计代码的好处,对于一个复杂的问题,先建立主框架,在详细写子函数,思路会清晰很多。以K个一组反转链表为例,本来思路很混乱,但是把问题分解成,先按K个一组分组,然后把反转链表写成一个子函数的问题,思路就很清晰了。在有了反转链表的多次敲代码的基础上,这道题也变得不那么思路混乱了。 +3 本周学习中的一个难点:单调栈的思路,这个思路看起来很简单,但是遇到实际问题往往无法立刻想到,看完答案能理解答案的思路同时自己敲出来,但是依旧无法自己独利完成。个人总结其中的难点在于,入栈和出栈的条件,这往往的问题的难点。其中典型的问题是柱状图中最大的矩阵,还有上周日自己参加的leetcode周赛第二题,找出最具竞争力的子序列,利用单调栈很容易写出来,但是自己似乎仍然没有独立的思路,还需要继续努力。 \ No newline at end of file diff --git "a/Week_02/1.\344\270\244\346\225\260\344\271\213\345\222\214.py" "b/Week_02/1.\344\270\244\346\225\260\344\271\213\345\222\214.py" new file mode 100644 index 00000000..3d3aa225 --- /dev/null +++ "b/Week_02/1.\344\270\244\346\225\260\344\271\213\345\222\214.py" @@ -0,0 +1,29 @@ +# +# @lc app=leetcode.cn id=1 lang=python +# +# [1] 两数之和 +# + +# @lc code=start +class Solution(object): + def twoSum(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + # dic = {} + # for i in range(len(nums)): + # if target - nums[i] not in dic: + # dic[nums[i]] = i + # else: + # return [dic[target - nums[i]], i] + + dic = {} + for i in range(len(nums)): + if target - nums[i] in dic: + return [dic[target - nums[i]], i] + dic[nums[i]] = i + +# @lc code=end + diff --git "a/Week_02/1021.\345\210\240\351\231\244\346\234\200\345\244\226\345\261\202\347\232\204\346\213\254\345\217\267.py" "b/Week_02/1021.\345\210\240\351\231\244\346\234\200\345\244\226\345\261\202\347\232\204\346\213\254\345\217\267.py" new file mode 100644 index 00000000..f935e86c --- /dev/null +++ "b/Week_02/1021.\345\210\240\351\231\244\346\234\200\345\244\226\345\261\202\347\232\204\346\213\254\345\217\267.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=1021 lang=python +# +# [1021] 删除最外层的括号 +# + +# @lc code=start +class Solution(object): + def removeOuterParentheses(self, S): + """ + :type S: str + :rtype: str + """ + ans = '' + stack = [] + for c in S: + if c == "(": + if stack: + ans += c + stack.append(c) + else: + stack.pop() + if stack: + ans += c + return ans + +# @lc code=end + diff --git "a/Week_02/144.\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" "b/Week_02/144.\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" new file mode 100644 index 00000000..186bb3d8 --- /dev/null +++ "b/Week_02/144.\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" @@ -0,0 +1,41 @@ +# +# @lc app=leetcode.cn id=144 lang=python3 +# +# [144] 二叉树的前序遍历 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def preorderTraversal(self, root: TreeNode) -> List[int]: + # # 迭代 + # if not root:return [] + # stack = [root] + # ans = [] + # while stack: + # root = stack.pop() + # if isinstance(root, int): + # ans.append(root) + # elif root: + # stack.append(root.right) + # stack.append(root.left) + # stack.append(root.val) + # return ans + + # 递归 + ans = [] + def dfs(root): + if not root:return + ans.append(root.val) + dfs(root.left) + dfs(root.right) + dfs(root) + return ans + +# @lc code=end + diff --git "a/Week_02/264.\344\270\221\346\225\260-ii.py" "b/Week_02/264.\344\270\221\346\225\260-ii.py" new file mode 100644 index 00000000..0c5492e3 --- /dev/null +++ "b/Week_02/264.\344\270\221\346\225\260-ii.py" @@ -0,0 +1,29 @@ +# +# @lc app=leetcode.cn id=264 lang=python +# +# [264] 丑数 II +# + +# @lc code=start +class Solution(object): + def nthUglyNumber(self, n): + """ + :type n: int + :rtype: int + """ + if n == 1:return 1 + isexsit = {1} + hp = [1] + ans = [] + for _ in range(1690): + cur = heappop(hp) + ans.append(cur) + for i in [2, 3, 5]: + new = i * cur + if new not in isexsit: + heappush(hp, new) + isexsit.add(new) + return ans[n - 1] + +# @lc code=end + diff --git "a/Week_02/347.\345\211\215-k-\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.py" "b/Week_02/347.\345\211\215-k-\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.py" new file mode 100644 index 00000000..0106a100 --- /dev/null +++ "b/Week_02/347.\345\211\215-k-\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.py" @@ -0,0 +1,31 @@ +# +# @lc app=leetcode.cn id=347 lang=python +# +# [347] 前 K 个高频元素 +# + +# @lc code=start +class Solution(object): + def topKFrequent(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: List[int] + """ + # 小根堆可以得出前k个最大的数字 + count = Counter(nums) + count_value = count.values() + hp = count_value[:k] + heapq.heapify(hp) + for i in count_value[k:]: + if i > hp[0]: + heappop(hp) + heappush(hp, i) + ans = [] + for key, value in count.items(): + if value >= hp[0]: + ans.append(key) + return ans + +# @lc code=end + diff --git "a/Week_02/350.\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206-ii.py" "b/Week_02/350.\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206-ii.py" new file mode 100644 index 00000000..38098e06 --- /dev/null +++ "b/Week_02/350.\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206-ii.py" @@ -0,0 +1,25 @@ +# +# @lc app=leetcode.cn id=350 lang=python +# +# [350] 两个数组的交集 II +# + +# @lc code=start +class Solution(object): + def intersect(self, nums1, nums2): + """ + :type nums1: List[int] + :type nums2: List[int] + :rtype: List[int] + """ + if len(nums1) > len(nums2): + return self.intersect(nums2, nums1) + count = Counter(nums1) + ans = [] + for i in range(len(nums2)): + if count.get(nums2[i], 0) > 0: + count[nums2[i]] -= 1 + ans.append(nums2[i]) + return ans +# @lc code=end + diff --git "a/Week_02/429.n-\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" "b/Week_02/429.n-\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" new file mode 100644 index 00000000..20acf01b --- /dev/null +++ "b/Week_02/429.n-\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" @@ -0,0 +1,50 @@ +# +# @lc app=leetcode.cn id=429 lang=python +# +# [429] N 叉树的层序遍历 +# + +# @lc code=start +""" +# Definition for a Node. +class Node(object): + def __init__(self, val=None, children=None): + self.val = val + self.children = children +""" + +class Solution(object): + def levelOrder(self, root): + """ + :type root: Node + :rtype: List[List[int]] + """ + # 递归 + ans = [] + def dfs(root, index): + if not root:return + if len(ans) <= index: + ans.append([]) + ans[index].append(root.val) + for child in root.children: + dfs(child, index + 1) + dfs(root, 0) + return ans + + # 迭代 + # import collections + if not root:return [] + ans = [] + deq = deque([root]) + while deq: + tmp = [] + for _ in range(len(deq)): + root = deq.popleft() + if root: + tmp.append(root.val) + deq.extend(root.children) + ans.append(tmp) + return list(ans) + +# @lc code=end + diff --git "a/Week_02/49.\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py" "b/Week_02/49.\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py" new file mode 100644 index 00000000..9015e361 --- /dev/null +++ "b/Week_02/49.\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=49 lang=python +# +# [49] 字母异位词分组 +# + +# @lc code=start +class Solution(object): + def groupAnagrams(self, strs): + """ + :type strs: List[str] + :rtype: List[List[str]] + """ + dic = defaultdict(list) + for s in strs: + count = [0] * 26 + for c in s: + count[ord(c) - ord('a')] += 1 + dic[tuple(count)].append(s) + return dic.values() + + # @lc code=end + diff --git "a/Week_02/589.n\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" "b/Week_02/589.n\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" new file mode 100644 index 00000000..1040d3ff --- /dev/null +++ "b/Week_02/589.n\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206.py" @@ -0,0 +1,52 @@ +# +# @lc app=leetcode.cn id=589 lang=python3 +# +# [589] N叉树的前序遍历 +# + +# @lc code=start +""" +# Definition for a Node. +class Node: + def __init__(self, val=None, children=None): + self.val = val + self.children = children +""" + +class Solution: + def preorder(self, root: 'Node') -> List[int]: + # # 迭代1 + # if not root:return [] + # ans = [] + # stack = [root] + # while stack: + # root = stack.pop() + # if isinstance(root, int): + # ans.append(root) + # elif root: + # stack.extend(root.children[::-1]) + # stack.append(root.val) + # return ans + # # 迭代2 + # if not root:return [] + # ans = [] + # stack = [root] + # while stack: + # root = stack.pop() + # if root: + # ans.append(root.val) + # stack.extend(root.children[::-1]) + # return ans + + # 递归 + ans = [] + def dfs(root): + if not root:return + ans.append(root.val) + for child in root.children: + dfs(child) + dfs(root) + return ans + +# @lc code=end + diff --git "a/Week_02/590.n\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py" "b/Week_02/590.n\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py" new file mode 100644 index 00000000..37861f73 --- /dev/null +++ "b/Week_02/590.n\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206.py" @@ -0,0 +1,52 @@ +# +# @lc app=leetcode.cn id=590 lang=python3 +# +# [590] N叉树的后序遍历 +# + +# @lc code=start +""" +# Definition for a Node. +class Node: + def __init__(self, val=None, children=None): + self.val = val + self.children = children +""" + +class Solution: + def postorder(self, root: 'Node'): + # 递归 + ans = [] + def dfs(root): + if not root:return + for child in root.children: + dfs(child) + ans.append(root.val) + dfs(root) + return ans + + # # 迭代1 + # if not root:return [] + # ans = [] + # stack = [root] + # while stack: + # root = stack.pop() + # if isinstance(root, int): + # ans.append(root) + # elif root: + # stack.append(root.val) + # stack.extend(root.children[::-1]) + # return ans + + # # 迭代2 + # if not root:return [] + # ans = [] + # stack = [root] + # while stack: + # root = stack.pop() + # if root: + # ans.append(root.val) + # stack.extend(root.children) + # return ans[::-1] +# @lc code=end + diff --git "a/Week_02/94.\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py" "b/Week_02/94.\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py" new file mode 100644 index 00000000..36a686ad --- /dev/null +++ "b/Week_02/94.\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206.py" @@ -0,0 +1,43 @@ +# +# @lc app=leetcode.cn id=94 lang=python3 +# +# [94] 二叉树的中序遍历 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def inorderTraversal(self, root: TreeNode) -> List[int]: + # # 递归 + # ans = [] + # def dfs(root): + # if root: + # dfs(root.left) + # ans.append(root.val) + # dfs(root.right) + # dfs(root) + # return ans + + # # 迭代 + # if not root: return [] + # stack = [root] + # ans = [] + # while stack: + # root = stack.pop() + # if isinstance(root, int): + # ans.append(root) + # elif root: + # stack.append(root.right) + # stack.append(root.val) + # stack.append(root.left) + # return ans + + + +# @lc code=end + diff --git a/Week_02/README.md b/Week_02/README.md index 50de3041..fcbb2c91 100644 --- a/Week_02/README.md +++ b/Week_02/README.md @@ -1 +1,26 @@ -学习笔记 \ No newline at end of file +# 第二周总结 +## 1.哈希表、映射、集合 +哈希表、集合:查找O(1), 插入O(1), 删除O(1) +哈希碰撞解决方法:使用链表 + +## 2.树、二叉树、二叉搜索树 +1 需要掌握二叉树的四种遍历方式:前、中、后、层序遍历(迭代法、递归法) + +2 二叉搜索树:根节点的数值大于所有左子树节点的值,小于所有右子树节点的值(注:不是左子节点和右子节点) + +3 需要掌握搜索二叉树的删除和插入 + +## 3.堆和二叉堆 +1 堆:分为大根堆和小根堆,大根堆的根节点值大于所有子树节点值,小根堆相反。 + +2 结构属性 +* 根节点(顶堆节点) : [0] +* 索引为i的左孩子的索引是(2*i+1) +* 索引为i的右孩子的索引是(2*i+2) +* 索引为i的父节点的索引是(i-1)/2 + +3 插入删除操作方式 +* 插入操作:在堆尾插入新元素 -> 向上调整 +* 删除操作:用堆尾元素替代堆顶元素 -> 向下调整 + +4 应用场景:求最大的第K个数:小根堆;求最小的第K个数:大根堆 \ No newline at end of file diff --git "a/Week_03/104.\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py" "b/Week_03/104.\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py" new file mode 100644 index 00000000..3969de8e --- /dev/null +++ "b/Week_03/104.\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=104 lang=python +# +# [104] 二叉树的最大深度 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution(object): + def maxDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: return 0 + return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) +# @lc code=end + diff --git "a/Week_03/105.\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221.py" "b/Week_03/105.\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221.py" new file mode 100644 index 00000000..7f7cb058 --- /dev/null +++ "b/Week_03/105.\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221.py" @@ -0,0 +1,34 @@ +# +# @lc app=leetcode.cn id=105 lang=python +# +# [105] 从前序与中序遍历序列构造二叉树 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def buildTree(self, preorder, inorder): + """ + :type preorder: List[int] + :type inorder: List[int] + :rtype: TreeNode + """ + def recur(root, left, right): # root:preorder;left,right:inorder + if left > right: return + node = TreeNode(preorder[root]) + i = dic[preorder[root]] + node.left = recur(root + 1, left, i - 1) + node.right = recur(root + i - left + 1, i + 1, right) + return node + dic = {} + for i in range(len(inorder)): + dic[inorder[i]] = i + return recur(0, 0, len(inorder) - 1) +# @lc code=end + diff --git "a/Week_03/111.\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py" "b/Week_03/111.\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py" new file mode 100644 index 00000000..a8cbc246 --- /dev/null +++ "b/Week_03/111.\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246.py" @@ -0,0 +1,26 @@ +# +# @lc app=leetcode.cn id=111 lang=python +# +# [111] 二叉树的最小深度 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution(object): + def minDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: return 0 + if not root.left and not root.right: return 1 + left = self.minDepth(root.left) if root.left else float('inf') + right = self.minDepth(root.right) if root.right else float('inf') + return min(left, right) + 1 +# @lc code=end + diff --git "a/Week_03/169.\345\244\232\346\225\260\345\205\203\347\264\240.py" "b/Week_03/169.\345\244\232\346\225\260\345\205\203\347\264\240.py" new file mode 100644 index 00000000..3e8d25aa --- /dev/null +++ "b/Week_03/169.\345\244\232\346\225\260\345\205\203\347\264\240.py" @@ -0,0 +1,18 @@ +# +# @lc app=leetcode.cn id=169 lang=python +# +# [169] 多数元素 +# + +# @lc code=start +class Solution(object): + def majorityElement(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + count = Counter(nums) + return max(count.keys(), key=count.get) + # 高级用法:max(可迭代对象, key=函数名) +# @lc code=end + diff --git "a/Week_03/17.\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/Week_03/17.\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py" new file mode 100644 index 00000000..8c92b28a --- /dev/null +++ "b/Week_03/17.\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210.py" @@ -0,0 +1,36 @@ +# +# @lc app=leetcode.cn id=17 lang=python +# +# [17] 电话号码的字母组合 +# + +# @lc code=start +class Solution(object): + def letterCombinations(self, digits): + """ + :type digits: str + :rtype: List[str] + """ + dic = {'2': ['a', 'b', 'c'], + '3': ['d', 'e', 'f'], + '4': ['g', 'h', 'i'], + '5': ['j', 'k', 'l'], + '6': ['m', 'n', 'o'], + '7': ['p', 'q', 'r', 's'], + '8': ['t', 'u', 'v'], + '9': ['w', 'x', 'y', 'z']} + + def backtrack(tmp, index): + if len(tmp) == n: + ans.append(tmp) + return + for i in range(index, n): + for j in dic[digits[i]]: + backtrack(tmp + j, i + 1) + if digits == '': return [] + ans = [] + n = len(digits) + backtrack('', 0) + return ans +# @lc code=end + diff --git "a/Week_03/22.\346\213\254\345\217\267\347\224\237\346\210\220.py" "b/Week_03/22.\346\213\254\345\217\267\347\224\237\346\210\220.py" new file mode 100644 index 00000000..4467db5b --- /dev/null +++ "b/Week_03/22.\346\213\254\345\217\267\347\224\237\346\210\220.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=22 lang=python +# +# [22] 括号生成 +# + +# @lc code=start +class Solution(object): + def generateParenthesis(self, n): + """ + :type n: int + :rtype: List[str] + """ + def backtrack(left, right, tmp): + if left == n and right == n: + ans.append(tmp) + if left < n: backtrack(left + 1, right, tmp + "(") + if right < left: backtrack(left, right + 1, tmp + ")") + ans = [] + backtrack(0, 0, '') + return ans +# @lc code=end + diff --git "a/Week_03/226.\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py" "b/Week_03/226.\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py" new file mode 100644 index 00000000..9203bdbe --- /dev/null +++ "b/Week_03/226.\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.py" @@ -0,0 +1,25 @@ +# +# @lc app=leetcode.cn id=226 lang=python +# +# [226] 翻转二叉树 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def invertTree(self, root): + """ + :type root: TreeNode + :rtype: TreeNode + """ + if not root:return + root.left, root.right = self.invertTree(root.right), self.invertTree(root.left) + return root +# @lc code=end + diff --git "a/Week_03/236.\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/Week_03/236.\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 00000000..7167b602 --- /dev/null +++ "b/Week_03/236.\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,36 @@ +# +# @lc app=leetcode.cn id=236 lang=python +# +# [236] 二叉树的最近公共祖先 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + """ + :type root: TreeNode + :type p: TreeNode + :type q: TreeNode + :rtype: TreeNode + """ + if not root or root == p or root == q:return root + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + # # 以下是四种情况(全列出来更容易理解) + # if not left and not right: return None + # if not left: return right + # if not right: return left + # if left and right: return root + # 以上四种情况可以合并简写如下 + if not left: return right + if not right: return left + return root +# @lc code=end + diff --git "a/Week_03/297.\344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\344\270\216\345\217\215\345\272\217\345\210\227\345\214\226.py" "b/Week_03/297.\344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\344\270\216\345\217\215\345\272\217\345\210\227\345\214\226.py" new file mode 100644 index 00000000..8c936a3e --- /dev/null +++ "b/Week_03/297.\344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\344\270\216\345\217\215\345\272\217\345\210\227\345\214\226.py" @@ -0,0 +1,64 @@ +# +# @lc app=leetcode.cn id=297 lang=python +# +# [297] 二叉树的序列化与反序列化 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Codec: + + def serialize(self, root): + """Encodes a tree to a single string. + :type root: TreeNode + :rtype: str + """ + if not root: return '[]' + ans = [] + deq = deque([root]) + while deq: + node = deq.popleft() + if node: + ans.append(str(node.val)) + deq.extend([node.left, node.right]) + else: + ans.append('null') + # print(ans) + return '[{}]'.format(','.join(ans)) + + + def deserialize(self, data): + """Decodes your encoded data to tree. + :type data: str + :rtype: TreeNode + """ + if data == '[]': return [] + data = data[1:-1].split(',') + root = TreeNode(int(data[0])) + deq = deque([root]) + i = 1 + while deq: + node = deq.popleft() + if data[i] != 'null': + node.left = TreeNode(int(data[i])) + deq.append(node.left) + i += 1 + if data[i] != 'null': + node.right = TreeNode(int(data[i])) + deq.append(node.right) + i += 1 + return root + + +# Your Codec object will be instantiated and called as such: +# ser = Codec() +# deser = Codec() +# ans = deser.deserialize(ser.serialize(root)) +# @lc code=end + diff --git "a/Week_03/46.\345\205\250\346\216\222\345\210\227.py" "b/Week_03/46.\345\205\250\346\216\222\345\210\227.py" new file mode 100644 index 00000000..cfbcaf3d --- /dev/null +++ "b/Week_03/46.\345\205\250\346\216\222\345\210\227.py" @@ -0,0 +1,26 @@ +# +# @lc app=leetcode.cn id=46 lang=python +# +# [46] 全排列 +# + +# @lc code=start +class Solution(object): + def permute(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + def backtrack(tmp, nums): + if len(tmp) == n: + ans.append(tmp) + return + for i in range(len(nums)): + backtrack(tmp + [nums[i]], nums[:i] + nums[i + 1:]) + + n = len(nums) + ans = [] + backtrack([], nums) + return ans +# @lc code=end + diff --git "a/Week_03/47.\345\205\250\346\216\222\345\210\227-ii.py" "b/Week_03/47.\345\205\250\346\216\222\345\210\227-ii.py" new file mode 100644 index 00000000..dcdd3ce6 --- /dev/null +++ "b/Week_03/47.\345\205\250\346\216\222\345\210\227-ii.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=47 lang=python +# +# [47] 全排列 II +# + +# @lc code=start +class Solution(object): + def permuteUnique(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + def backtrack(tmp, nums): + if len(tmp) == n: + ans.append(tmp) + return + for i in range(len(nums)): + if i > 0 and nums[i] == nums[i - 1]:continue + backtrack(tmp + [nums[i]], nums[:i] + nums[i + 1:]) + + n = len(nums) + ans = [] + nums.sort() + backtrack([], nums) + return ans +# @lc code=end + diff --git a/Week_03/50.pow-x-n.py b/Week_03/50.pow-x-n.py new file mode 100644 index 00000000..9f4584fc --- /dev/null +++ b/Week_03/50.pow-x-n.py @@ -0,0 +1,29 @@ +# +# @lc app=leetcode.cn id=50 lang=python +# +# [50] Pow(x, n) +# + +# @lc code=start +class Solution(object): + def myPow(self, x, n): + """ + :type x: float + :type n: int + :rtype: float + """ + # 分治 + if n == 0: return 1 + if x == 0: return 0 + if n < 0: x, n = 1 / x, -n + def recur(x, n): + if n == 1:return x + half = recur(x, n // 2) + if n % 2 == 1: + return half * half * x + else: + return half * half + return recur(x, n) + +# @lc code=end + diff --git "a/Week_03/51.n-\347\232\207\345\220\216.py" "b/Week_03/51.n-\347\232\207\345\220\216.py" new file mode 100644 index 00000000..489e5795 --- /dev/null +++ "b/Week_03/51.n-\347\232\207\345\220\216.py" @@ -0,0 +1,43 @@ +# +# @lc app=leetcode.cn id=51 lang=python +# +# [51] N 皇后 +# + +# @lc code=start +class Solution(object): + def solveNQueens(self, n): + """ + :type n: int + :rtype: List[List[str]] + """ + # 判断是否冲突 + def nonconflict(index, ans): + for i in range(len(ans)): + # 当前棋子和前面几行处在一条直线上 + if index == int(ans[i]): return False + # 当前棋子和前面几行处在一条斜线上 + if abs(int(ans[i]) - index) == len(ans) - i: return False + return True + + # 主程序 + def backtrack(ans): + if len(ans) == n: + res.append(ans) + return + for i in range(n): + if nonconflict(i, ans): backtrack(ans + str(i)) + res = [] + backtrack('') + + # 打印 + for ans_i,ans in enumerate(res): + tmp = [['.']*n for _ in range(n)] + for i in range(n): + tmp[i][int(ans[i])] = 'Q' + res[ans_i] = [''.join(x) for x in tmp] + return res + + +# @lc code=end + diff --git "a/Week_03/77.\347\273\204\345\220\210.py" "b/Week_03/77.\347\273\204\345\220\210.py" new file mode 100644 index 00000000..055101b1 --- /dev/null +++ "b/Week_03/77.\347\273\204\345\220\210.py" @@ -0,0 +1,25 @@ +# +# @lc app=leetcode.cn id=77 lang=python +# +# [77] 组合 +# + +# @lc code=start +class Solution(object): + def combine(self, n, k): + """ + :type n: int + :type k: int + :rtype: List[List[int]] + """ + def backtrack(tmp, index): + if len(tmp) == k: + ans.append(tmp) + return + for i in range(index, n): + backtrack(tmp + [i + 1], i + 1) + ans = [] + backtrack([], 0) + return ans +# @lc code=end + diff --git "a/Week_03/78.\345\255\220\351\233\206.py" "b/Week_03/78.\345\255\220\351\233\206.py" new file mode 100644 index 00000000..744b14b0 --- /dev/null +++ "b/Week_03/78.\345\255\220\351\233\206.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=78 lang=python +# +# [78] 子集 +# + +# @lc code=start +class Solution(object): + def subsets(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + def backtrack(tmp, index): + ans.append(tmp) + for i in range(index, n): + backtrack(tmp + [nums[i]], i + 1) + ans = [] + n = len(nums) + backtrack([], 0) + return ans +# @lc code=end + diff --git "a/Week_03/98.\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.py" "b/Week_03/98.\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 00000000..4b0ad939 --- /dev/null +++ "b/Week_03/98.\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,29 @@ +# +# @lc app=leetcode.cn id=98 lang=python +# +# [98] 验证二叉搜索树 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution(object): + def isValidBST(self, root): + """ + :type root: TreeNode + :rtype: bool + """ + # 分治 + def valid(root, low, up): + if not root: return True + if root.val >= up or root.val <= low: return False + if not valid(root.left, low, root.val): return False + if not valid(root.right, root.val, up): return False + return True + return valid(root, float('-inf'), float('inf')) +# @lc code=end + diff --git a/Week_03/README.md b/Week_03/README.md index 50de3041..42ad81b0 100644 --- a/Week_03/README.md +++ b/Week_03/README.md @@ -1 +1,68 @@ -学习笔记 \ No newline at end of file +# 第三周总结 +## 递归 +* 递归要点 +终止条件;处理当前层;进入下一层;清除当前变量(可选) +* 递归代码模板 +``` +Python +def recursion(level, param1, param2, ...): + 1 recursion terminator + if level > MAX_LEVEL: + process_result + return + 2 process logic in current level + process(level, data...) + 3 drill down + self.recursion(level + 1, p1, ...) + 4 reverse the current level status if needed +``` + +## 回溯 +* 回溯要点 +终止条件;选择、下一步、撤销选择;清除当前变量(可选) +* 回溯代码模板 +``` +result = [] +def backtrack(路径, 选择列表): + if 满足结束条件: + result.add(路径) + return + + for 选择 in 选择列表: + 做选择 + backtrack(路径, 选择列表) + 撤销选择 +``` + +## 分治 +* 分治要点 +终止条件;分解子问题、处理子问题、合并结果;清除当前变量(可选) +* 分治代码模板 +``` +Python +def divide_conquer(problem, param1, param2, ...): + 1 recursion terminator + if problem is None: + print_result + return + + 2 prepare data + data = prepare_data(problem) + subproblems = split_problem(problem, data) + + 3 conquer subproblems + subresult1 = self.divide_conquer(subproblems[0], p1, ...) + subresult2 = self.divide_conquer(subproblems[1], p1, ...) + subresult3 = self.divide_conquer(subproblems[2], p1, ...) + … + + 4 process and generate the final result + result = process_result(subresult1, subresult2, subresult3, …) + + revert the current level states +``` + +## 个人理解 +分治和回溯是递归的特殊表现形式,都存在终止条件判断,变化点在于如何处理当前层和进入下一层。 +回溯先进行选择后进入下一层,最后撤回选择;分治是先分解子问题,再进入下一层,最后合并结果。 +本质上并没有什么不同,只是处理当前层的方式有些不同。 \ No newline at end of file diff --git "a/Week_04/102.\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" "b/Week_04/102.\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" new file mode 100644 index 00000000..f8a9f504 --- /dev/null +++ "b/Week_04/102.\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.py" @@ -0,0 +1,47 @@ +# +# @lc app=leetcode.cn id=102 lang=python +# +# [102] 二叉树的层序遍历 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def levelOrder(self, root): + """ + :type root: TreeNode + :rtype: List[List[int]] + """ + # BFS + if not root: return [] + deq = deque([root]) + ans = [] + while deq: + tmp = [] + for _ in range(len(deq)): + node = deq.popleft() + tmp.append(node.val) + if node.left: deq.append(node.left) + if node.right: deq.append(node.right) + ans.append(tmp) + return ans + + # DFS + def dfs(root, index): + if len(ans) - 1 < index: + ans.append([]) + ans[index].append(root.val) + if root.left: dfs(root.left, index + 1) + if root.right: dfs(root.right, index + 1) + if not root: return [] + ans = [] + dfs(root, 0) + return ans +# @lc code=end + diff --git "a/Week_04/122.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-ii.py" "b/Week_04/122.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-ii.py" new file mode 100644 index 00000000..0ded2b85 --- /dev/null +++ "b/Week_04/122.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-ii.py" @@ -0,0 +1,22 @@ +# +# @lc app=leetcode.cn id=122 lang=python +# +# [122] 买卖股票的最佳时机 II +# + +# @lc code=start +class Solution(object): + def maxProfit(self, prices): + """ + :type prices: List[int] + :rtype: int + """ + # 贪心 + incomes = 0 + if len(prices) <= 1:return 0 + for i in range(len(prices) - 1): + if prices[i] < prices[i + 1]: + incomes += prices[i + 1] - prices[i] + return incomes +# @lc code=end + diff --git "a/Week_04/126.\345\215\225\350\257\215\346\216\245\351\276\231-ii.py" "b/Week_04/126.\345\215\225\350\257\215\346\216\245\351\276\231-ii.py" new file mode 100644 index 00000000..fb9d203a --- /dev/null +++ "b/Week_04/126.\345\215\225\350\257\215\346\216\245\351\276\231-ii.py" @@ -0,0 +1,46 @@ +# +# @lc app=leetcode.cn id=126 lang=python +# +# [126] 单词接龙 II +# + +# @lc code=start +class Solution(object): + def findLadders(self, beginWord, endWord, wordList): + """ + :type beginWord: str + :type endWord: str + :type wordList: List[str] + :rtype: List[List[str]] + """ + wordList = set(wordList) + deq = deque([beginWord]) + visited = set([beginWord]) # 记录本层和之前层出现过的单词 + # 生成图 + graph = defaultdict(set) + while deq: + next_visited = set() # 记录下一层出现的单词 + for _ in range(len(deq)): + word = deq.popleft() + for i in range(len(beginWord)): + for p in range(26): + tmp = word[:i] + chr(97 + p) + word[i + 1:] + if tmp in wordList and tmp not in visited: + graph[word].add(tmp) + if tmp not in next_visited: + next_visited.add(tmp) + deq.append(tmp) # 在这里只需要加一遍 + visited = visited | next_visited + + # DFS调用所有路径 + ans = [] + def dfs(tmp, route): + if tmp == endWord: + ans.append(route) + return + for word in graph[tmp]: + dfs(word, route + [word]) + dfs(beginWord, [beginWord]) + return ans +# @lc code=end + diff --git "a/Week_04/127.\345\215\225\350\257\215\346\216\245\351\276\231.py" "b/Week_04/127.\345\215\225\350\257\215\346\216\245\351\276\231.py" new file mode 100644 index 00000000..da10b11a --- /dev/null +++ "b/Week_04/127.\345\215\225\350\257\215\346\216\245\351\276\231.py" @@ -0,0 +1,31 @@ +# +# @lc app=leetcode.cn id=127 lang=python +# +# [127] 单词接龙 +# + +# @lc code=start +class Solution(object): + def ladderLength(self, beginWord, endWord, wordList): + """ + :type beginWord: str + :type endWord: str + :type wordList: List[str] + :rtype: int + """ + wordList = set(wordList) + deq = deque([(beginWord, 1)]) + exist = set([beginWord]) + while deq: + word, step = deq.popleft() + if word == endWord: return step + for i in range(len(beginWord)): + for p in range(26): + tmp = word[:i] + chr(97 + p) + word[i + 1:] + if tmp in wordList and tmp not in exist: + # 这里是和接龙2本质区别的地方,这里的操作只能找到一条路径 + exist.add(tmp) + deq.append((tmp, step + 1)) + return 0 +# @lc code=end + diff --git "a/Week_04/153.\345\257\273\346\211\276\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\346\234\200\345\260\217\345\200\274.py" "b/Week_04/153.\345\257\273\346\211\276\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\346\234\200\345\260\217\345\200\274.py" new file mode 100644 index 00000000..65a1d7ea --- /dev/null +++ "b/Week_04/153.\345\257\273\346\211\276\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\346\234\200\345\260\217\345\200\274.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=153 lang=python +# +# [153] 寻找旋转排序数组中的最小值 +# + +# @lc code=start +class Solution(object): + def findMin(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + left, right = 0, len(nums) - 1 + while left < right: + mid = left + (right - left) // 2 + # 这是循环前升序排列的数,左边的数小,右边的数大, + # 而且我们要找的是最小值,要偏向左找,目标值右边的情况会比较简单 + # 目的就是让最终停留的点是最小值点 + if nums[mid] < nums[right]: + right = mid + elif nums[mid] > nums[right]: + left = mid + 1 + return nums[left] + +# @lc code=end + diff --git "a/Week_04/200.\345\262\233\345\261\277\346\225\260\351\207\217.py" "b/Week_04/200.\345\262\233\345\261\277\346\225\260\351\207\217.py" new file mode 100644 index 00000000..0b397774 --- /dev/null +++ "b/Week_04/200.\345\262\233\345\261\277\346\225\260\351\207\217.py" @@ -0,0 +1,46 @@ +# +# @lc app=leetcode.cn id=200 lang=python +# +# [200] 岛屿数量 +# + +# @lc code=start +class Solution(object): + def numIslands(self, grid): + """ + :type grid: List[List[str]] + :rtype: int + """ + # DFS + def dfs(i, j): + if not (0 <= i < len(grid) and 0 <= j < len(grid[0])) or grid[i][j] == '0':return + grid[i][j] = '0' + dfs(i, j + 1) + dfs(i, j - 1) + dfs(i - 1, j) + dfs(i + 1, j) + count = 0 + for i in range(len(grid)): + for j in range(len(grid[0])): + if grid[i][j] == '1': + dfs(i, j) # 把i,j的岛屿归零,同时把周围的岛屿归零 + count += 1 + return count + + # BFS + def bfs(i, j): + deq = deque([(i, j)]) + while deq: + i, j = deq.popleft() + if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == '1': + grid[i][j] = '0' + deq.extend([(i + 1, j), (i - 1, j), (i, j - 1), (i, j + 1)]) + count = 0 + for i in range(len(grid)): + for j in range(len(grid[0])): + if grid[i][j] == '1': + bfs(i, j) + count += 1 + return count +# @lc code=end + diff --git "a/Week_04/33.\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/Week_04/33.\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 00000000..54129108 --- /dev/null +++ "b/Week_04/33.\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,34 @@ +# +# @lc app=leetcode.cn id=33 lang=python +# +# [33] 搜索旋转排序数组 +# + +# @lc code=start +class Solution(object): + def search(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: int + """ + left, right = 0, len(nums) - 1 + while left < right: + mid = left + (right - left) // 2 + if nums[mid] == target: return mid + # 左边有序 + if nums[left] <= nums[mid]: + # 由于前面判断了nums[mid] == target,所以这里target < nums[mid],不需要等号 + if nums[left] <= target < nums[mid]: + right = mid + else: + left = mid + 1 + else: + if nums[mid] < target <= nums[right]: + left = mid + 1 + else: + right = mid + return left if nums[left] == target else -1 + +# @lc code=end + diff --git "a/Week_04/367.\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/Week_04/367.\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 00000000..9f97f64a --- /dev/null +++ "b/Week_04/367.\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,35 @@ +# +# @lc app=leetcode.cn id=367 lang=python +# +# [367] 有效的完全平方数 +# + +# @lc code=start +class Solution(object): + def isPerfectSquare(self, num): + """ + :type num: int + :rtype: bool + """ + # 方法一、这道题本质上和69.x的平方根没什么区别,用其思路可以写成如下 + left, right = 0, num + while left < right: + mid = left + (right - left + 1) // 2 + if mid * mid <= num: + left = mid + else: + right = mid - 1 + return left * left == num + + # 方法二、由于这道题有提前返回条件mid * mid == num,所以可以写成如下 + left, right = 0, num + while left < right: + mid = left + (right - left + 1) // 2 + if mid * mid == num: return True + if mid * mid < num: + left = mid + else: + right = mid - 1 + return False +# @lc code=end + diff --git "a/Week_04/433.\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py" "b/Week_04/433.\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py" new file mode 100644 index 00000000..64991617 --- /dev/null +++ "b/Week_04/433.\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py" @@ -0,0 +1,32 @@ +# +# @lc app=leetcode.cn id=433 lang=python +# +# [433] 最小基因变化 +# + +# @lc code=start +class Solution(object): + def minMutation(self, start, end, bank): + """ + :type start: str + :type end: str + :type bank: List[str] + :rtype: int + """ + possible = ['A', 'G', 'C', 'T'] + bank = set(bank) + deq = deque([(start, 0)]) + exist = set([start]) + while deq: + word, step = deq.popleft() + if word == end: return step + for i in range(len(start)): + for p in possible: + tmp = word[:i] + p + word[i + 1:] + if tmp in bank and tmp not in exist: + exist.add(tmp) + deq.append((tmp, step + 1)) + return -1 + +# @lc code=end + diff --git "a/Week_04/45.\350\267\263\350\267\203\346\270\270\346\210\217-ii.py" "b/Week_04/45.\350\267\263\350\267\203\346\270\270\346\210\217-ii.py" new file mode 100644 index 00000000..8408e616 --- /dev/null +++ "b/Week_04/45.\350\267\263\350\267\203\346\270\270\346\210\217-ii.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=45 lang=python +# +# [45] 跳跃游戏 II +# + +# @lc code=start +class Solution(object): + def jump(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + most = 0 # 每一个数字最远可到达的地方 + step_most = 0 # 每一步最远可到达的地方 + count = 0 # 记录步数 + # 如果访问最后一个元素,在边界正好为最后一个位置的情况下, + # 我们会增加一次「不必要的跳跃次数」,因此我们不必访问最后一个元素。 + for i in range(len(nums) - 1): + if i <= most: + most = max(nums[i] + i, most) + if i == step_most: + step_most = most + count += 1 + return count +# @lc code=end + diff --git "a/Week_04/455.\345\210\206\345\217\221\351\245\274\345\271\262.py" "b/Week_04/455.\345\210\206\345\217\221\351\245\274\345\271\262.py" new file mode 100644 index 00000000..8a89f0a4 --- /dev/null +++ "b/Week_04/455.\345\210\206\345\217\221\351\245\274\345\271\262.py" @@ -0,0 +1,29 @@ +# +# @lc app=leetcode.cn id=455 lang=python +# +# [455] 分发饼干 +# + +# @lc code=start +class Solution(object): + def findContentChildren(self, g, s): + """ + :type g: List[int] + :type s: List[int] + :rtype: int + """ + # 贪心 + g.sort() + s.sort() + i = j = 0 + count = 0 + while i < len(g) and j < len(s): + if s[j] >= g[i]: + count += 1 + i += 1 + j += 1 + else: + j += 1 + return count +# @lc code=end + diff --git "a/Week_04/515.\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274.py" "b/Week_04/515.\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274.py" new file mode 100644 index 00000000..0984b836 --- /dev/null +++ "b/Week_04/515.\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274.py" @@ -0,0 +1,34 @@ +# +# @lc app=leetcode.cn id=515 lang=python +# +# [515] 在每个树行中找最大值 +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution(object): + def largestValues(self, root): + """ + :type root: TreeNode + :rtype: List[int] + """ + # BFS + if not root: return [] + deq = deque([root]) + ans = [] + while deq: + tmp = [] + for _ in range(len(deq)): + node = deq.popleft() + tmp.append(node.val) + if node.left: deq.append(node.left) + if node.right: deq.append(node.right) + ans.append(max(tmp)) + return ans +# @lc code=end + diff --git "a/Week_04/529.\346\211\253\351\233\267\346\270\270\346\210\217.py" "b/Week_04/529.\346\211\253\351\233\267\346\270\270\346\210\217.py" new file mode 100644 index 00000000..36c1cabe --- /dev/null +++ "b/Week_04/529.\346\211\253\351\233\267\346\270\270\346\210\217.py" @@ -0,0 +1,44 @@ +# +# @lc app=leetcode.cn id=529 lang=python +# +# [529] 扫雷游戏 +# + +# @lc code=start +class Solution(object): + def updateBoard(self, board, click): + """ + :type board: List[List[str]] + :type click: List[int] + :rtype: List[List[str]] + """ + direction = ((1, 1), (1, 0), (1, -1), (0, 1), + (0, -1), (-1, 1), (-1, 0), (-1, -1)) + i, j = click + # 判断当前点击点是否有雷 + if board[i][j] == 'M': + board[i][j] = 'X' + return board + m, n = len(board), len(board[0]) + def check(i, j): + count = 0 + for x, y in direction: + if (0 <= x + i <= m - 1 and 0 <= y + j <= n - 1 and + board[i + x][j + y] == 'M'): + count += 1 + return count + def dfs(i, j): + # 检查周围有几颗雷 + count = check(i, j) + if count == 0: + board[i][j] = 'B' + for x, y in direction: + if (0 <= x + i <= m - 1 and 0 <= y + j <= n - 1 and + board[i + x][j + y] == 'E'): + dfs(x + i, y + j) + else: + board[i][j] = str(count) + dfs(i, j) # 递归的揭露 + return board +# @lc code=end + diff --git "a/Week_04/55.\350\267\263\350\267\203\346\270\270\346\210\217.py" "b/Week_04/55.\350\267\263\350\267\203\346\270\270\346\210\217.py" new file mode 100644 index 00000000..5ba3a5f1 --- /dev/null +++ "b/Week_04/55.\350\267\263\350\267\203\346\270\270\346\210\217.py" @@ -0,0 +1,22 @@ +# +# @lc app=leetcode.cn id=55 lang=python +# +# [55] 跳跃游戏 +# + +# @lc code=start +class Solution(object): + def canJump(self, nums): + """ + :type nums: List[int] + :rtype: bool + """ + most = 0 # 最远可到达的地方 + for i in range(len(nums)): + if i <= most: + most = max(nums[i] + i, most) + if most >= len(nums) - 1: return True + return False + +# @lc code=end + diff --git "a/Week_04/69.x-\347\232\204\345\271\263\346\226\271\346\240\271.py" "b/Week_04/69.x-\347\232\204\345\271\263\346\226\271\346\240\271.py" new file mode 100644 index 00000000..3f8353fd --- /dev/null +++ "b/Week_04/69.x-\347\232\204\345\271\263\346\226\271\346\240\271.py" @@ -0,0 +1,35 @@ +# +# @lc app=leetcode.cn id=69 lang=python +# +# [69] x 的平方根 +# + +# @lc code=start +class Solution(object): + def mySqrt(self, x): + """ + :type x: int + :rtype: int + """ + # 方法一(套模板的写法如下) + left, right = 0, x + while left < right: + mid = left + (right - left + 1) // 2 + if mid * mid == x: return mid + if mid * mid < x: + left = mid + else: + right = mid - 1 + return left + + # 方法二(对于上面的判断可以合并成如下) + left, right = 0, x + while left < right: + mid = left + (right - left + 1) // 2 + if mid * mid <= x: + left = mid + else: + right = mid - 1 + return left +# @lc code=end + diff --git "a/Week_04/74.\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py" "b/Week_04/74.\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py" new file mode 100644 index 00000000..6c5e76e6 --- /dev/null +++ "b/Week_04/74.\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265.py" @@ -0,0 +1,26 @@ +# +# @lc app=leetcode.cn id=74 lang=python +# +# [74] 搜索二维矩阵 +# + +# @lc code=start +class Solution(object): + def searchMatrix(self, matrix, target): + """ + :type matrix: List[List[int]] + :type target: int + :rtype: bool + """ + m, n = len(matrix), len(matrix[0]) + left, right = 0, m * n - 1 + while left < right: + mid = left + (right - left) // 2 + if matrix[mid // n][mid % n] == target:return True + if matrix[mid // n][mid % n] < target: + left = mid + 1 + else: + right = mid + return matrix[left // n][left % n] == target +# @lc code=end + diff --git "a/Week_04/860.\346\237\240\346\252\254\346\260\264\346\211\276\351\233\266.py" "b/Week_04/860.\346\237\240\346\252\254\346\260\264\346\211\276\351\233\266.py" new file mode 100644 index 00000000..e3dd9f96 --- /dev/null +++ "b/Week_04/860.\346\237\240\346\252\254\346\260\264\346\211\276\351\233\266.py" @@ -0,0 +1,32 @@ +# +# @lc app=leetcode.cn id=860 lang=python +# +# [860] 柠檬水找零 +# + +# @lc code=start +class Solution(object): + def lemonadeChange(self, bills): + """ + :type bills: List[int] + :rtype: bool + """ + count = [0] * 2 # 记录收入5、10圆的数量 + for c in bills: + if c == 5: + count[0] += 1 + if c == 10: + if count[0] == 0: return False + count[0] -= 1 + count[1] += 1 + if c == 20: + if count[1] > 0 and count[0] > 0: + count[1] -= 1 + count[0] -= 1 + elif count[0] > 2: + count[0] -= 3 + else: + return False + return True +# @lc code=end + diff --git "a/Week_04/874.\346\250\241\346\213\237\350\241\214\350\265\260\346\234\272\345\231\250\344\272\272.py" "b/Week_04/874.\346\250\241\346\213\237\350\241\214\350\265\260\346\234\272\345\231\250\344\272\272.py" new file mode 100644 index 00000000..6841b04a --- /dev/null +++ "b/Week_04/874.\346\250\241\346\213\237\350\241\214\350\265\260\346\234\272\345\231\250\344\272\272.py" @@ -0,0 +1,36 @@ +# +# @lc app=leetcode.cn id=874 lang=python +# +# [874] 模拟行走机器人 +# + +# @lc code=start +class Solution(object): + def robotSim(self, commands, obstacles): + """ + :type commands: List[int] + :type obstacles: List[List[int]] + :rtype: int + """ + # 记录当前方向 + di = 0 + dx = [0, 1, 0, -1] + dy = [1, 0, -1, 0] + # 变为集合,方便查找 + obstacles = set(map(tuple, obstacles)) + ans = 0 + x = y = 0 + for cmd in commands: + if cmd == -2: + di = (di - 1) % 4 + elif cmd == -1: + di = (di + 1) % 4 + else: + for _ in range(cmd): + if (x + dx[di], y + dy[di]) not in obstacles: + x += dx[di] + y += dy[di] + ans = max(ans, x**2 + y**2) + return ans +# @lc code=end + diff --git a/Week_04/README.md b/Week_04/README.md index 50de3041..f2f34c15 100644 --- a/Week_04/README.md +++ b/Week_04/README.md @@ -1 +1,98 @@ -学习笔记 \ No newline at end of file +# 第四周总结 +## 1.深度优先遍历与广度优先遍历 +广度优先更多的是利用双端队列来实现,深度优先更多的是利用递归来实现,也可以利用栈来实现。 +``` +#Python递归写法 +visited = set() +def dfs(node, visited): + if node in visited: # terminator + # already visited + return + + visited.add(node) + + # process current node here. + ... + for next_node in node.children(): + if next_node not in visited: + dfs(next_node, visited) +``` +``` +#Python非递归写法 +def DFS(self, tree): + if tree.root is None: + return [] + visited, stack = [], [tree.root] + while stack: + node = stack.pop() + visited.add(node) + process (node) + nodes = generate_related_nodes(node) + stack.push(nodes) + # other processing work + ... + +``` +``` +# Python +def BFS(graph, start, end): + visited = set() + queue = [] + queue.append([start]) + while queue: + node = queue.pop() + visited.add(node) + process(node) + nodes = generate_related_nodes(node) + queue.push(nodes) + # other processing work + ... +``` +## 2.贪心算法 +贪心方法就是每次通过局部最优来获得全局最优,思想很简单,但是往往证明寻找局部最优能找到全局最优比较困难。 + +## 3.二分查找 +直接给出二分查找的三种模板 +``` +# Python模板一 +left, right = 0, len(array) - 1 +while left <= right: + mid = left + (right - left) // 2 + if array[mid] == target: + # find the target!! + break or return result + elif array[mid] < target: + left = mid + 1 + else: + right = mid - 1 +``` +``` +# Python模板二 +left, right = 0, len(array) - 1 +while left < right: + mid = left + (right - left) // 2 + if array[mid] == target: + # find the target!! + break or return result + elif array[mid] < target: + left = mid + 1 + else: + right = mid +return left +``` +``` +# Python模板三 +left, right = 0, len(array) - 1 +while left < right: + mid = left + (right - left + 1) // 2 + if array[mid] == target: + # find the target!! + break or return result + elif array[mid] < target: + left = mid + else: + right = mid - 1 +return left +``` +从以上三种模板,可以看出一点套路, ``` mid = left + (right - left) // 2 ``` 与 ```left = mid + 1, right = mid``` 搭配; ``` mid = left + (right - left + 1) // 2 ``` 应该与 ```left = mid, right = mid - 1``` 搭配。而 ```left = mid + 1, right = mid - 1``` 容易使得 right < left ,所以不便与 ```while (left < right)``` 搭配。 +其次```while left <= right```这种形式,结束后right < left,由于```mid = left + (right - left) // 2```使得mid是偏向left的,但是```right = mid - 1```其实并不太好,这里面会有重复部分,容易死循环。 \ No newline at end of file diff --git "a/Week_06/1143.\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" "b/Week_06/1143.\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" new file mode 100644 index 00000000..ab2c445d --- /dev/null +++ "b/Week_06/1143.\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=1143 lang=python +# +# [1143] 最长公共子序列 +# + +# @lc code=start +class Solution(object): + def longestCommonSubsequence(self, text1, text2): + """ + :type text1: str + :type text2: str + :rtype: int + """ + # dp[i][j] : text1的前i个字串和text2的前j个字串的最长公共子序列 + m = len(text1) + 1 + n = len(text2) + 1 + dp = [[0]*n for _ in range(m)] + for i in range(1, m): + for j in range(1, n): + 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] + +# @lc code=end + diff --git "a/Week_06/120.\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" "b/Week_06/120.\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" new file mode 100644 index 00000000..acf01ee1 --- /dev/null +++ "b/Week_06/120.\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" @@ -0,0 +1,21 @@ +# +# @lc app=leetcode.cn id=120 lang=python +# +# [120] 三角形最小路径和 +# + +# @lc code=start +class Solution(object): + def minimumTotal(self, triangle): + """ + :type triangle: List[List[int]] + :rtype: int + """ + # dp[i][j] 从下到上(i,j)的最小路径和 + dp = triangle + for i in range(len(dp) - 2, -1, -1): + for j in range(i + 1): + dp[i][j] += min(dp[i + 1][j], dp[i + 1][j + 1]) + return dp[0][0] +# @lc code=end + diff --git "a/Week_06/121.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.py" "b/Week_06/121.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.py" new file mode 100644 index 00000000..0d47f6ac --- /dev/null +++ "b/Week_06/121.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.py" @@ -0,0 +1,24 @@ +# +# @lc app=leetcode.cn id=121 lang=python +# +# [121] 买卖股票的最佳时机 +# + +# @lc code=start +class Solution(object): + def maxProfit(self, prices): + """ + :type prices: List[int] + :rtype: int + """ + # dp[i]第i天的历史最低价 + if len(prices) < 2: return 0 + n = len(prices) + dp = [prices[0]] * n + max_profit = 0 + for i, price in enumerate(prices[1:]): + dp[i] = min(dp[i - 1], price) + max_profit = max(max_profit, price - dp[i]) + return max_profit +# @lc code=end + diff --git "a/Week_06/122.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-ii.py" "b/Week_06/122.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-ii.py" new file mode 100644 index 00000000..c0f09fad --- /dev/null +++ "b/Week_06/122.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-ii.py" @@ -0,0 +1,34 @@ +# +# @lc app=leetcode.cn id=122 lang=python +# +# [122] 买卖股票的最佳时机 II +# + +# @lc code=start +class Solution(object): + def maxProfit(self, prices): + """ + :type prices: List[int] + :rtype: int + """ + # # 贪心 + # incomes = 0 + # if len(prices) <= 1:return 0 + # for i in range(len(prices) - 1): + # if prices[i] < prices[i + 1]: + # incomes += prices[i + 1] - prices[i] + # return incomes + + # 动态规划 + # dp[i][0] 第i天手里持有股票的最大收益 + # dp[i][1] 第i天手里没有股票的最大收益 + n = len(prices) + dp = [[0] * 2 for _ in range(n)] + dp[0][0] = -prices[0] + dp[0][1] = 0 + for i in range(1, n): + dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]) + dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]) + return dp[-1][1] +# @lc code=end + diff --git "a/Week_06/123.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-iii.py" "b/Week_06/123.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-iii.py" new file mode 100644 index 00000000..7ead9849 --- /dev/null +++ "b/Week_06/123.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-iii.py" @@ -0,0 +1,51 @@ +# +# @lc app=leetcode.cn id=123 lang=python +# +# [123] 买卖股票的最佳时机 III +# + +# @lc code=start +class Solution(object): + def maxProfit(self, prices): + """ + :type prices: List[int] + :rtype: int + """ + # # 动态规划 + # # dp[i][0] 第i天初始化状态股票的最大收益 + # # dp[i][1] 第i天第一次持有(含买入)股票的最大收益 + # # dp[i][0] 第i天第一次不持有(含卖出)股票的最大收益 + # # dp[i][1] 第i天第二次持有(含买入)股票的最大收益 + # # dp[i][0] 第i天第二次不持有(含卖出)股票的最大收益 + # n = len(prices) + # dp = [[0] * 5 for _ in range(n)] + # dp[0][0] = 0 + # dp[0][1] = -prices[0] + # dp[0][2] = 0 + # dp[0][3] = -prices[0] + # dp[0][4] = 0 + # for i in range(1, n): + # dp[i][0] = 0 + # dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]) + # dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i]) + # dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]) + # dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]) + # return max(dp[-1]) + + # 可优化 + n = len(prices) + dp = [[0] * 5 for _ in range(n)] + dp0 = 0 + dp1= -prices[0] + dp2 = 0 + dp3 = -prices[0] + dp4 = 0 + for i in range(1, n): + dp0 = 0 + dp1 = max(dp1, dp0 - prices[i]) + dp2 = max(dp2, dp1 + prices[i]) + dp3 = max(dp3, dp2 - prices[i]) + dp4 = max(dp4, dp3 + prices[i]) + return max(dp1,dp2,dp3,dp4) +# @lc code=end + diff --git "a/Week_06/152.\344\271\230\347\247\257\346\234\200\345\244\247\345\255\220\346\225\260\347\273\204.py" "b/Week_06/152.\344\271\230\347\247\257\346\234\200\345\244\247\345\255\220\346\225\260\347\273\204.py" new file mode 100644 index 00000000..a759b820 --- /dev/null +++ "b/Week_06/152.\344\271\230\347\247\257\346\234\200\345\244\247\345\255\220\346\225\260\347\273\204.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=152 lang=python +# +# [152] 乘积最大子数组 +# + +# @lc code=start +class Solution(object): + def maxProduct(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + # dp[i][0] 前i个子数组中的最大连续子数组乘积 + # dp[i][1] 前i个子数组中的最小连续子数组乘积 + n = len(nums) + dp = [[nums[0]] * 2 for _ in range(n)] + for i in range(1, n): + dp[i][0] = max(dp[i - 1][0] * nums[i], dp[i - 1][1] * nums[i], nums[i]) + dp[i][1] = min(dp[i - 1][0] * nums[i], dp[i - 1][1] * nums[i], nums[i]) + return max(map(lambda x:x[0], dp)) +# @lc code=end + diff --git "a/Week_06/188.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-iv.py" "b/Week_06/188.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-iv.py" new file mode 100644 index 00000000..ce184ee2 --- /dev/null +++ "b/Week_06/188.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272-iv.py" @@ -0,0 +1,48 @@ +# +# @lc app=leetcode.cn id=188 lang=python +# +# [188] 买卖股票的最佳时机 IV +# + +# @lc code=start +class Solution(object): + def maxProfit(self, k, prices): + """ + :type k: int + :type prices: List[int] + :rtype: int + """ + # 动态规划 + # dp[i][0] 第i天初始化状态股票的最大收益 + # dp[i][2 * j + 1] 第i天第j + 1次持有股票的最大收益 + # dp[i][2 * j + 1] 第i天第j + 1次没有股票的最大收益 + # n = len(prices) + # if n < 2: return 0 + # dp = [[0] * (2 * k + 1) for _ in range(n)] + # dp[0][0] = 0 + # for j in range(k): + # dp[0][2 * j + 1] = -prices[0] + # dp[0][2 * j + 2] = 0 + # for i in range(1, n): + # dp[i][0] = 0 + # for j in range(k): + # dp[i][2 * j + 1] = max(dp[i - 1][2 * j + 1], dp[i - 1][2 * j] - prices[i]) + # dp[i][2 * j + 2] = max(dp[i - 1][2 * j + 2], dp[i - 1][2 * j + 1] + prices[i]) + # return max(dp[-1]) + + # 同样用类似购买股票3的方式优化空间(用一维数组,但是我已经快看不懂了) + n = len(prices) + if n < 2: return 0 + dp = [0] * (2 * k + 1) + dp[0] = 0 + for j in range(k): + dp[2 * j + 1] = -prices[0] + dp[2 * j + 2] = 0 + for i in range(1, n): + dp[0] = 0 + for j in range(k): + dp[2 * j + 1] = max(dp[2 * j + 1], dp[2 * j] - prices[i]) + dp[2 * j + 2] = max(dp[2 * j + 2], dp[2 * j + 1] + prices[i]) + return max(dp) +# @lc code=end + diff --git "a/Week_06/198.\346\211\223\345\256\266\345\212\253\350\210\215.py" "b/Week_06/198.\346\211\223\345\256\266\345\212\253\350\210\215.py" new file mode 100644 index 00000000..16a58947 --- /dev/null +++ "b/Week_06/198.\346\211\223\345\256\266\345\212\253\350\210\215.py" @@ -0,0 +1,25 @@ +# +# @lc app=leetcode.cn id=198 lang=python +# +# [198] 打家劫舍 +# + +# @lc code=start +class Solution(object): + def rob(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + # dp[i] 偷了前i家房屋的最大收益 + n = len(nums) + if n == 0: return 0 + if len(nums) <= 2: return max(nums) + dp = nums + dp[1] = max(dp[:2]) + for i in range(2, n): + dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]) + return dp[-1] + +# @lc code=end + diff --git "a/Week_06/213.\346\211\223\345\256\266\345\212\253\350\210\215-ii.py" "b/Week_06/213.\346\211\223\345\256\266\345\212\253\350\210\215-ii.py" new file mode 100644 index 00000000..c71fcf33 --- /dev/null +++ "b/Week_06/213.\346\211\223\345\256\266\345\212\253\350\210\215-ii.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=213 lang=python +# +# [213] 打家劫舍 II +# + +# @lc code=start +class Solution(object): + def rob(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + # 把问题分成偷nums[:-1]和nums[1:] + def sub_rob(nums): + # dp[i] 偷了前i家房屋的最大收益 + n = len(nums) + if n == 0: return 0 + if len(nums) <= 2: return max(nums) + dp = nums + dp[1] = max(dp[:2]) + for i in range(2, n): + dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]) + return dp[-1] + return max(sub_rob(nums[:-1]), sub_rob(nums[1:])) if len(nums) > 1 else nums[0] +# @lc code=end + diff --git "a/Week_06/221.\346\234\200\345\244\247\346\255\243\346\226\271\345\275\242.py" "b/Week_06/221.\346\234\200\345\244\247\346\255\243\346\226\271\345\275\242.py" new file mode 100644 index 00000000..28c2c80d --- /dev/null +++ "b/Week_06/221.\346\234\200\345\244\247\346\255\243\346\226\271\345\275\242.py" @@ -0,0 +1,29 @@ +# +# @lc app=leetcode.cn id=221 lang=python +# +# [221] 最大正方形 +# + +# @lc code=start +class Solution(object): + def maximalSquare(self, matrix): + """ + :type matrix: List[List[str]] + :rtype: int + """ + # dp[i][j]表示以(i,j)为右下角的最大正方形边长 + m, n = len(matrix), len(matrix[0]) + dp = matrix + for i in range(m): + dp[i][0] = int(dp[i][0]) + for j in range(n): + dp[0][j] = int(dp[0][j]) + for i in range(1, m): + for j in range(1, n): + if matrix[i][j] == '1': + dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 + else: + dp[i][j] = 0 + return max(map(max, dp))**2 +# @lc code=end + diff --git "a/Week_06/279.\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py" "b/Week_06/279.\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py" new file mode 100644 index 00000000..e431984d --- /dev/null +++ "b/Week_06/279.\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260.py" @@ -0,0 +1,22 @@ +# +# @lc app=leetcode.cn id=279 lang=python +# +# [279] 完全平方数 +# + +# @lc code=start +class Solution(object): + def numSquares(self, n): + """ + :type n: int + :rtype: int + """ + # dp[j] 代表组合成正整数j需要的最小完全平方数个数 + dp = [i for i in range(n + 1)] + for j in range(2, n + 1): + for i in range(int(sqrt(j) + 1)): + dp[j] = min(dp[j], dp[j - i*i] + 1) + return dp[-1] + +# @lc code=end + diff --git "a/Week_06/309.\346\234\200\344\275\263\344\271\260\345\215\226\350\202\241\347\245\250\346\227\266\346\234\272\345\220\253\345\206\267\345\206\273\346\234\237.py" "b/Week_06/309.\346\234\200\344\275\263\344\271\260\345\215\226\350\202\241\347\245\250\346\227\266\346\234\272\345\220\253\345\206\267\345\206\273\346\234\237.py" new file mode 100644 index 00000000..513eb7ca --- /dev/null +++ "b/Week_06/309.\346\234\200\344\275\263\344\271\260\345\215\226\350\202\241\347\245\250\346\227\266\346\234\272\345\220\253\345\206\267\345\206\273\346\234\237.py" @@ -0,0 +1,31 @@ +# +# @lc app=leetcode.cn id=309 lang=python +# +# [309] 最佳买卖股票时机含冷冻期 +# + +# @lc code=start +class Solution(object): + def maxProfit(self, prices): + """ + :type prices: List[int] + :rtype: int + """ + # 动态规划 + # dp[i][0] 第i天(非卖出日)不持有股票的最大收益 + # dp[i][1] 第i天持有股票的最大收益 + # dp[i][2] 第i天卖出股票的最大收益 + if len(prices) < 2: return 0 + n = len(prices) + dp = [[0]*3 for _ in range(n)] + dp[0][0] = 0 + dp[0][1] = -prices[0] + dp[0][2] = 0 + for i in range(1, n): + dp[i][0] = max(dp[i - 1][0], dp[i - 1][2]) + dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]) + dp[i][2] = dp[i - 1][1] + prices[i] + return max(dp[-1]) + +# @lc code=end + diff --git "a/Week_06/312.\346\210\263\346\260\224\347\220\203.py" "b/Week_06/312.\346\210\263\346\260\224\347\220\203.py" new file mode 100644 index 00000000..4e74f4cd --- /dev/null +++ "b/Week_06/312.\346\210\263\346\260\224\347\220\203.py" @@ -0,0 +1,24 @@ +# +# @lc app=leetcode.cn id=312 lang=python +# +# [312] 戳气球 +# + +# @lc code=start +class Solution(object): + def maxCoins(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + # dp[i][j] 从第i个气球到第j个气球(i,j不戳破)全部戳破能获得的最大硬币 + nums = [1] + nums + [1] + n = len(nums) + dp = [[0]*n for _ in range(n)] + for j in range(2, n): + for i in range(j - 2, -1, -1): + for k in range(i + 1, j): + dp[i][j] = max(dp[i][k] + dp[k][j] + nums[i]*nums[j]*nums[k], dp[i][j]) + return dp[0][-1] +# @lc code=end + diff --git "a/Week_06/32.\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267.py" "b/Week_06/32.\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267.py" new file mode 100644 index 00000000..07761b7f --- /dev/null +++ "b/Week_06/32.\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=32 lang=python +# +# [32] 最长有效括号 +# + +# @lc code=start +class Solution(object): + def longestValidParentheses(self, s): + """ + :type s: str + :rtype: int + """ + # dp[i] 代表以第i个字符结尾的字符串最长有效括号长度 + n = len(s) + dp = [0] * n + for i in range(n): + if i > 0 and s[i] == ')': + if s[i - 1] == '(': + dp[i] = dp[i - 2] + 2 + else: + if i - dp[i - 1] - 1 >= 0 and s[i - dp[i - 1] - 1] == '(': + dp[i] = dp[i - dp[i - 1] - 2] + dp[i - 1] + 2 + dp.append(0) + return max(dp) +# @lc code=end + diff --git "a/Week_06/322.\351\233\266\351\222\261\345\205\221\346\215\242.py" "b/Week_06/322.\351\233\266\351\222\261\345\205\221\346\215\242.py" new file mode 100644 index 00000000..8c64d4bf --- /dev/null +++ "b/Week_06/322.\351\233\266\351\222\261\345\205\221\346\215\242.py" @@ -0,0 +1,25 @@ +# +# @lc app=leetcode.cn id=322 lang=python +# +# [322] 零钱兑换 +# + +# @lc code=start +class Solution(object): + def coinChange(self, coins, amount): + """ + :type coins: List[int] + :type amount: int + :rtype: int + """ + # dp[i] 总金额为i需要凑齐的最小硬币数 + dp = [amount + 1] * (amount + 1) + dp[0] = 0 + for coin in coins: + for i in range(1, amount + 1): + if i - coin >= 0: + dp[i] = min(dp[i], dp[i - coin] + 1) + return dp[-1] if dp[-1] < amount + 1 else -1 + +# @lc code=end + diff --git "a/Week_06/337.\346\211\223\345\256\266\345\212\253\350\210\215-iii.py" "b/Week_06/337.\346\211\223\345\256\266\345\212\253\350\210\215-iii.py" new file mode 100644 index 00000000..1a09abc8 --- /dev/null +++ "b/Week_06/337.\346\211\223\345\256\266\345\212\253\350\210\215-iii.py" @@ -0,0 +1,30 @@ +# +# @lc app=leetcode.cn id=337 lang=python +# +# [337] 打家劫舍 III +# + +# @lc code=start +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def rob(self, root): + """ + :type root: TreeNode + :rtype: int + """ + def dfs(root): + if not root: return 0, 0 # 偷和不偷的最大金额 + left = dfs(root.left) + right = dfs(root.right) + do = root.val + left[1] + right[1] + undo = max(left) + max(right) + return do, undo + return max(dfs(root)) +# @lc code=end + diff --git "a/Week_06/363.\347\237\251\345\275\242\345\214\272\345\237\237\344\270\215\350\266\205\350\277\207-k-\347\232\204\346\234\200\345\244\247\346\225\260\345\200\274\345\222\214.py" "b/Week_06/363.\347\237\251\345\275\242\345\214\272\345\237\237\344\270\215\350\266\205\350\277\207-k-\347\232\204\346\234\200\345\244\247\346\225\260\345\200\274\345\222\214.py" new file mode 100644 index 00000000..01732928 --- /dev/null +++ "b/Week_06/363.\347\237\251\345\275\242\345\214\272\345\237\237\344\270\215\350\266\205\350\277\207-k-\347\232\204\346\234\200\345\244\247\346\225\260\345\200\274\345\222\214.py" @@ -0,0 +1,33 @@ +# +# @lc app=leetcode.cn id=363 lang=python +# +# [363] 矩形区域不超过 K 的最大数值和 +# + +# @lc code=start +class Solution(object): + def maxSumSubmatrix(self, matrix, k): + """ + :type matrix: List[List[int]] + :type k: int + :rtype: int + """ + m, n = len(matrix), len(matrix[0]) + res = float('-inf') + for left in range(n): + nums = [0] * m + for right in range(left, n): + for i in range(m): + nums[i] += matrix[i][right] + arr = [0] # 只能初始化0,没有想通为什么 + cum = 0 + for num in nums: + cum += num + loc = bisect.bisect_left(arr, cum - k) + if loc < len(arr): + res = max(cum - arr[loc], res) + bisect.insort(arr, cum) + return res + +# @lc code=end + diff --git "a/Week_06/403.\351\235\222\350\233\231\350\277\207\346\262\263.py" "b/Week_06/403.\351\235\222\350\233\231\350\277\207\346\262\263.py" new file mode 100644 index 00000000..f768958d --- /dev/null +++ "b/Week_06/403.\351\235\222\350\233\231\350\277\207\346\262\263.py" @@ -0,0 +1,26 @@ +# +# @lc app=leetcode.cn id=403 lang=python +# +# [403] 青蛙过河 +# + +# @lc code=start +class Solution(object): + def canCross(self, stones): + """ + :type stones: List[int] + :rtype: bool + """ + n = len(stones) + # dp[i] 表示:跳到第 i 个石头的最后一步距离是 need 时能否成功。need是dp[i]里面的数字 + dp = [set() for _ in range(n)] + dp[0].add(0) + for i in range(1, n): + for j in range(i): + need = stones[i] - stones[j] + # if need in dp[j] or need + 1 in dp[j] or need - 1 in dp[j]: + if (set((need, need + 1, need - 1)) & dp[j]) != set(): + dp[i].add(need) + return dp[-1] != set() +# @lc code=end + diff --git "a/Week_06/410.\345\210\206\345\211\262\346\225\260\347\273\204\347\232\204\346\234\200\345\244\247\345\200\274.py" "b/Week_06/410.\345\210\206\345\211\262\346\225\260\347\273\204\347\232\204\346\234\200\345\244\247\345\200\274.py" new file mode 100644 index 00000000..b9b40ec9 --- /dev/null +++ "b/Week_06/410.\345\210\206\345\211\262\346\225\260\347\273\204\347\232\204\346\234\200\345\244\247\345\200\274.py" @@ -0,0 +1,59 @@ +# +# @lc app=leetcode.cn id=410 lang=python +# +# [410] 分割数组的最大值 +# + +# @lc code=start +class Solution(object): + def splitArray(self, nums, m): + """ + :type nums: List[int] + :type m: int + :rtype: int + """ + # 这道题用动态规划超时 + # # 动态规划 + # n = len(nums) + # # f[i][j] 表示将数组的前 i 个数分割为 j 段所能得到的最大连续子数组和的最小值。 + # f = [[float('inf')] * (m + 1) for _ in range(n + 1)] + # sub = [0] + # for elem in nums: + # sub.append(sub[-1] + elem) + # # print(sub) + # f[0][0] = 0 + # for i in range(1, n + 1): + # for j in range(1, min(i, m) + 1): + # for k in range(j - 1,i): + # f[i][j] = min(f[i][j], max(f[k][j - 1], sub[i] - sub[k])) + # return f[n][m] + + # 二分法 + def split(mid): + # 计算以mid为数组和上界,划分数组的个数 + cnt = 1 # 划分数组个数 + s = 0 + for num in nums: + if s + num > mid: + s = num + cnt += 1 + else: + s += num + return cnt + # mid表示 m 个子数组各自和的最大值最小值 + left = max(nums) + right = sum(nums) + while left < right: + # 这道题的关键是要找最小值,因此需要把right向left偏移,mid = left + (right - left) // 2 + # 可以与69题x的平方根对比,这道题是求平方数不超过x的最大数,需要让left向right便宜,mid = left + (right - left + 1) // 2 + # 这两道题竟然结合在了一起,值得思考 + mid = left + (right - left) // 2 + cnt = split(mid) + # 如果cnt>m,说明mid太小了,划分的数组太少了 + if cnt > m: + left = mid + 1 + else: + right = mid + return left +# @lc code=end + diff --git "a/Week_06/518.\351\233\266\351\222\261\345\205\221\346\215\242-ii.py" "b/Week_06/518.\351\233\266\351\222\261\345\205\221\346\215\242-ii.py" new file mode 100644 index 00000000..e30d2a67 --- /dev/null +++ "b/Week_06/518.\351\233\266\351\222\261\345\205\221\346\215\242-ii.py" @@ -0,0 +1,25 @@ +# +# @lc app=leetcode.cn id=518 lang=python +# +# [518] 零钱兑换 II +# + +# @lc code=start +class Solution(object): + def change(self, amount, coins): + """ + :type amount: int + :type coins: List[int] + :rtype: int + """ + # dp[i] 总金额为i需要凑齐的硬币组合数 + dp = [0] * (amount + 1) + dp[0] = 1 + for coin in coins: + for i in range(1, amount + 1): + if i - coin >= 0: + dp[i] = dp[i] + dp[i - coin] + return dp[-1] + +# @lc code=end + diff --git "a/Week_06/53.\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py" "b/Week_06/53.\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py" new file mode 100644 index 00000000..e1a25046 --- /dev/null +++ "b/Week_06/53.\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214.py" @@ -0,0 +1,22 @@ +# +# @lc app=leetcode.cn id=53 lang=python +# +# [53] 最大子序和 +# + +# @lc code=start +class Solution(object): + def maxSubArray(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + # dp[i] 表示第i个字符结尾的最大连续子数组和 + n = len(nums) + if n == 0: return 0 + dp = [nums[0]] * n + for i in range(1, n): + dp[i] = max(dp[i - 1] + nums[i], nums[i]) + return max(dp) +# @lc code=end + diff --git "a/Week_06/552.\345\255\246\347\224\237\345\207\272\345\213\244\350\256\260\345\275\225-ii.py" "b/Week_06/552.\345\255\246\347\224\237\345\207\272\345\213\244\350\256\260\345\275\225-ii.py" new file mode 100644 index 00000000..25f4f0ef --- /dev/null +++ "b/Week_06/552.\345\255\246\347\224\237\345\207\272\345\213\244\350\256\260\345\275\225-ii.py" @@ -0,0 +1,32 @@ +# +# @lc app=leetcode.cn id=552 lang=python +# +# [552] 学生出勤记录 II +# + +# @lc code=start +class Solution(object): + def checkRecord(self, n): + """ + :type n: int + :rtype: int + """ + # dp[i] 代表不考虑A的情况下,可被奖励的的记录数 + # dp[i - 1] 代表以P为最后一个数字 + # dp[i - 2] 代表以PL为最后两个数字 + # dp[i - 3] 代表以PLL为最后三个数字 + dp = [0] * max(n + 1, 3) # 考虑了n = 0,1,2的情况 + mod = 10**9+7 + dp[0] = 1 + dp[1] = 2 + dp[2] = 4 + for i in range(3, n + 1): + dp[i] = (dp[i - 1] + dp[i - 2] + dp[i - 3]) % mod + res = dp[n] + # A可以替换1-n个数字中的任意一个,所以从1遍历到n + for i in range(1, n + 1): + res += (dp[i - 1] * dp[n - i]) % mod + return res % mod + +# @lc code=end + diff --git "a/Week_06/62.\344\270\215\345\220\214\350\267\257\345\276\204.py" "b/Week_06/62.\344\270\215\345\220\214\350\267\257\345\276\204.py" new file mode 100644 index 00000000..77ac6976 --- /dev/null +++ "b/Week_06/62.\344\270\215\345\220\214\350\267\257\345\276\204.py" @@ -0,0 +1,22 @@ +# +# @lc app=leetcode.cn id=62 lang=python +# +# [62] 不同路径 +# + +# @lc code=start +class Solution(object): + def uniquePaths(self, m, n): + """ + :type m: int + :type n: int + :rtype: int + """ + # dp[j] 从(0,0)到(i,j)的不同路径数 + dp = [1] * n + for i in range(1, m): + for j in range(1, n): + dp[j] = dp[j - 1] + dp[j] + return dp[-1] +# @lc code=end + diff --git "a/Week_06/621.\344\273\273\345\212\241\350\260\203\345\272\246\345\231\250.py" "b/Week_06/621.\344\273\273\345\212\241\350\260\203\345\272\246\345\231\250.py" new file mode 100644 index 00000000..ce5472e1 --- /dev/null +++ "b/Week_06/621.\344\273\273\345\212\241\350\260\203\345\272\246\345\231\250.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=621 lang=python +# +# [621] 任务调度器 +# + +# @lc code=start +class Solution(object): + def leastInterval(self, tasks, n): + """ + :type tasks: List[str] + :type n: int + :rtype: int + """ + # 这似乎和动态规划没什么关系? + cnt = Counter(tasks) + max_cnt = max(cnt.values()) + ans = (max_cnt - 1) * (n + 1) + for i in cnt.values(): + if i == max_cnt: ans += 1 + return max(ans, len(tasks)) +# @lc code=end + diff --git "a/Week_06/63.\344\270\215\345\220\214\350\267\257\345\276\204-ii.py" "b/Week_06/63.\344\270\215\345\220\214\350\267\257\345\276\204-ii.py" new file mode 100644 index 00000000..c4f884ba --- /dev/null +++ "b/Week_06/63.\344\270\215\345\220\214\350\267\257\345\276\204-ii.py" @@ -0,0 +1,32 @@ +# +# @lc app=leetcode.cn id=63 lang=python +# +# [63] 不同路径 II +# + +# @lc code=start +class Solution(object): + def uniquePathsWithObstacles(self, obstacleGrid): + """ + :type obstacleGrid: List[List[int]] + :rtype: int + """ + # dp[i][j] 从(0,0)到(i,j)的不同路径数 + if obstacleGrid[0][0] == 1:return 0 + m, n = len(obstacleGrid), len(obstacleGrid[0]) + dp = [[0] * n for _ in range(m)] + dp[0][0] = 1 + for i in range(1, m): + dp[i][0] = dp[i - 1][0] if obstacleGrid[i][0] == 0 else 0 + for j in range(1, n): + dp[0][j] = dp[0][j - 1] if obstacleGrid[0][j] == 0 else 0 + for i in range(1, m): + 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[-1][-1] + +# @lc code=end + diff --git "a/Week_06/64.\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" "b/Week_06/64.\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" new file mode 100644 index 00000000..22d054c5 --- /dev/null +++ "b/Week_06/64.\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=64 lang=python +# +# [64] 最小路径和 +# + +# @lc code=start +class Solution(object): + def minPathSum(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + # dp[i][j] 从(0,0)-(i,j)的最小路径和 + m, n = len(grid), len(grid[0]) + dp = [[grid[0][0]] * n for _ in range(m)] + for i in range(1, m): + dp[i][0] = dp[i - 1][0] + grid[i][0] + for j in range(1, n): + dp[0][j] = dp[0][j - 1] + grid[0][j] + for i in range(1, m): + for j in range(1, n): + dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j] + return dp[-1][-1] + +# @lc code=end + diff --git "a/Week_06/647.\345\233\236\346\226\207\345\255\220\344\270\262.py" "b/Week_06/647.\345\233\236\346\226\207\345\255\220\344\270\262.py" new file mode 100644 index 00000000..633a66da --- /dev/null +++ "b/Week_06/647.\345\233\236\346\226\207\345\255\220\344\270\262.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=647 lang=python +# +# [647] 回文子串 +# + +# @lc code=start +class Solution(object): + def countSubstrings(self, s): + """ + :type s: str + :rtype: int + """ + # dp[i][j] 表示从第i到第j个字符是否是回文子串,是返回1 + dp = [[0] * len(s) for _ in range(len(s))] + for j in range(len(s)): + for i in range(j + 1): + if i == j: + dp[i][j] = 1 + elif j - i == 1 and s[i] == s[j]: + dp[i][j] = 1 + elif s[i] == s[j] and dp[i + 1][j - 1] == 1: + dp[i][j] = 1 + return sum(map(sum, dp)) + +# @lc code=end + diff --git "a/Week_06/714.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272\345\220\253\346\211\213\347\273\255\350\264\271.py" "b/Week_06/714.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272\345\220\253\346\211\213\347\273\255\350\264\271.py" new file mode 100644 index 00000000..a327034f --- /dev/null +++ "b/Week_06/714.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272\345\220\253\346\211\213\347\273\255\350\264\271.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=714 lang=python +# +# [714] 买卖股票的最佳时机含手续费 +# + +# @lc code=start +class Solution(object): + def maxProfit(self, prices, fee): + """ + :type prices: List[int] + :type fee: int + :rtype: int + """ + # 动态规划 + # dp[i][0] 第i天手里持有股票的最大收益 + # dp[i][1] 第i天手里没有股票的最大收益 + # 和买卖股票2唯一的区别就是卖出减去个手续费就行了,其他一样 + n = len(prices) + dp = [[0] * 2 for _ in range(n)] + dp[0][0] = -prices[0] + dp[0][1] = 0 + for i in range(1, n): + dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]) + dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee) + return dp[-1][1] +# @lc code=end + diff --git "a/Week_06/72.\347\274\226\350\276\221\350\267\235\347\246\273.py" "b/Week_06/72.\347\274\226\350\276\221\350\267\235\347\246\273.py" new file mode 100644 index 00000000..4f2fb3fa --- /dev/null +++ "b/Week_06/72.\347\274\226\350\276\221\350\267\235\347\246\273.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=72 lang=python +# +# [72] 编辑距离 +# + +# @lc code=start +class Solution(object): + def minDistance(self, word1, word2): + """ + :type word1: str + :type word2: str + :rtype: int + """ + # dp[i][j] 表示从word1的前i个字符变成word2的前j个字符需要的最少操作数 + m, n = len(word1) + 1, len(word2) + 1 + dp = [[0] * n for _ in range(m)] + for i in range(m): + for j in range(n): + if 0 in (i, j): + dp[i][j] = i + j + elif word1[i - 1] == word2[j - 1]: + dp[i][j] = dp[i - 1][j - 1] + else: + dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 + return dp[-1][-1] +# @lc code=end + diff --git "a/Week_06/76.\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262.py" "b/Week_06/76.\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262.py" new file mode 100644 index 00000000..c64c5e1a --- /dev/null +++ "b/Week_06/76.\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262.py" @@ -0,0 +1,41 @@ +# +# @lc app=leetcode.cn id=76 lang=python +# +# [76] 最小覆盖子串 +# + +# @lc code=start +class Solution(object): + def minWindow(self, s, t): + """ + :type s: str + :type t: str + :rtype: str + """ + # 这道题似乎没有用到动态规划? + find = defaultdict(int) + for c in t: + find[c] += 1 + min_len = float('inf') + right = left = 0 + cnt = len(t) # 记录[left:right]区间内的涵盖t字符的数量 + ans = '' + while right < len(s): + if find[s[right]] > 0: + cnt -= 1 + find[s[right]] -= 1 + right += 1 + # 当cnt == 0,说明找到了全部的t + while cnt == 0: + if right - left < min_len: + min_len = right - left + ans = s[left:right] + if find[s[left]] == 0: + cnt += 1 + find[s[left]] += 1 + left += 1 + return ans + + +# @lc code=end + diff --git "a/Week_06/91.\350\247\243\347\240\201\346\226\271\346\263\225.py" "b/Week_06/91.\350\247\243\347\240\201\346\226\271\346\263\225.py" new file mode 100644 index 00000000..f0372418 --- /dev/null +++ "b/Week_06/91.\350\247\243\347\240\201\346\226\271\346\263\225.py" @@ -0,0 +1,30 @@ +# +# @lc app=leetcode.cn id=91 lang=python +# +# [91] 解码方法 +# + +# @lc code=start +class Solution(object): + def numDecodings(self, s): + """ + :type s: str + :rtype: int + """ + # dp[i] 第i个数字前的解码方法 + if s[0] == '0': return 0 + n = len(s) + 1 + dp = [1] * n + for i in range(2, n): + if s[i - 1] == '0' and s[i - 2] not in '12': + return 0 + elif s[i - 1] == '0' and s[i - 2] in '12': + dp[i] = dp[i - 2] + elif '10' < s[i - 2:i] <= '26': + dp[i] = dp[i - 1] + dp[i - 2] + else: + dp[i] = dp[i - 1] + return dp[-1] + +# @lc code=end + diff --git "a/Week_06/980.\344\270\215\345\220\214\350\267\257\345\276\204-iii.py" "b/Week_06/980.\344\270\215\345\220\214\350\267\257\345\276\204-iii.py" new file mode 100644 index 00000000..d0cd950e --- /dev/null +++ "b/Week_06/980.\344\270\215\345\220\214\350\267\257\345\276\204-iii.py" @@ -0,0 +1,46 @@ +# +# @lc app=leetcode.cn id=980 lang=python +# +# [980] 不同路径 III +# + +# @lc code=start +class Solution(object): + def uniquePathsIII(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + # 本来想用动态规划的,但无奈官方题解以及有动态规划解析的答案都含有位运算,暂时还没学会 + # 等学会了再来看吧 + # 回溯方法 + direction = ((1,0),(-1,0),(0,1),(0,-1)) + def dfs(i, j, index): + if grid[i][j] == 2: + if index == cnt: + self.ans += 1 + return + for x, y in direction: + x += i + y += j + if 0<= x < m and 0 <= y < n: + if grid[x][y] == 0: + grid[x][y] = 1 + dfs(x, y, index + 1) + grid[x][y] = 0 + elif grid[x][y] == 2: + dfs(x, y, index) + self.ans = 0 # 记录路径数 + cnt = 0 # 统计所有需要走的格子数 + m, n = len(grid), len(grid[0]) + for i in range(m): + for j in range(n): + if grid[i][j] == 0: + cnt += 1 + for i in range(m): + for j in range(n): + if grid[i][j] == 1: + dfs(i ,j, 0) # 坐标及已经经过的格子 + return self.ans +# @lc code=end + diff --git a/Week_06/README.md b/Week_06/README.md index 50de3041..86a2ac99 100644 --- a/Week_06/README.md +++ b/Week_06/README.md @@ -1 +1,8 @@ -学习笔记 \ No newline at end of file +# 第六周学习感悟 +两周反复刷了三十多道动态规划题之后,感受就是动态规划博大精深,我还是没有深入,遇到新题依旧处于不知所措状态。 +动态规划,要点都很清楚,寻找最优子结构。其实这句话要贯彻落实并不简单。 +写点自己感悟,或者说我认为的重点吧。主要包括三点: +* 1 准确定义dp数组含义 +* 2 准确列出状态转移方程 +* 3 准确写出初始化条件 +能清除给出以上三个答案,可以说动态规划问题就解决了。准确定义dp数组直接决定了能否写出合理的状态转移方程。其实往往最难的就是我们不知道如何去定义这个数组。做完30道题个人感觉还是远远不够,遇到简单的动态规划可以应对,稍微复杂一点就完全无法克服了, \ No newline at end of file diff --git "a/Week_07/1091.\344\272\214\350\277\233\345\210\266\347\237\251\351\230\265\344\270\255\347\232\204\346\234\200\347\237\255\350\267\257\345\276\204.py" "b/Week_07/1091.\344\272\214\350\277\233\345\210\266\347\237\251\351\230\265\344\270\255\347\232\204\346\234\200\347\237\255\350\267\257\345\276\204.py" new file mode 100644 index 00000000..66b8a96a --- /dev/null +++ "b/Week_07/1091.\344\272\214\350\277\233\345\210\266\347\237\251\351\230\265\344\270\255\347\232\204\346\234\200\347\237\255\350\267\257\345\276\204.py" @@ -0,0 +1,86 @@ +# +# @lc app=leetcode.cn id=1091 lang=python +# +# [1091] 二进制矩阵中的最短路径 +# + +# @lc code=start +class Solution(object): + def shortestPathBinaryMatrix(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + # 双向BFS + direction = ((1,0),(1,-1),(1,1),(0,1),(0,-1),(-1,1),(-1,0),(-1,-1)) + if not grid or grid[0][0] == 1 or grid[-1][-1] == 1:return -1 + n = len(grid) + if n == 1:return 1 + front = {(0,0)} + back = {(n - 1,n - 1)} + grid[0][0] = 1 + step = 0 + while front: + step += 1 + front_next = set() + for i,j in front: + for x,y in direction: + x,y=x+i,y+j + # 注意:下面两句话只能写在这部分,不能往下也不能往上。 + # 往上往下都不可能让(x,y)在back里,因此下面的grid[x][y] = 1去重了 + if (x,y) in back: + return step + 1 + if 0 <= x < n and 0 <= y < n and grid[x][y] == 0: + front_next.add((x,y)) + grid[x][y] = 1 + front = front_next + if len(back) < len(front): + front,back=back,front + return -1 + + # 双向BFS + # direction = ((1,0),(1,-1),(1,1),(0,1),(0,-1),(-1,1),(-1,0),(-1,-1)) + # if not grid or grid[0][0] == 1 or grid[-1][-1] == 1:return -1 + # n = len(grid) + # front = {(0,0)} + # back = {(n - 1,n - 1)} + # visited = front | back + # grid[0][0] = 1 + # step = 1 + # while front: + # front_next = set() + # for i,j in front: + # if (i,j) in back: + # return step + # for x,y in direction: + # x,y=x+i,y+j + # if (x,y) in back: + # return step + 1 + # if 0 <= x < n and 0 <= y < n and grid[x][y] == 0 and (x,y) not in visited: + # front_next.add((x,y)) + # visited.add((x,y)) + # # grid[x][y] = 1 + # front = front_next + # if len(back) < len(front): + # front,back=back,front + # step += 1 + # return -1 + + # # BFS + # direction = ((1,0),(1,-1),(1,1),(0,1),(0,-1),(-1,1),(-1,0),(-1,-1)) + # if not grid or grid[0][0] == 1 or grid[-1][-1] == 1:return -1 + # deq = deque([(0,0,1)]) + # grid[0][0] = 1 + # n = len(grid) + # while deq: + # for _ in range(len(deq)): + # i,j,step = deq.popleft() + # if (i,j) == (n-1,n-1):return step + # for x,y in direction: + # x,y=x+i,y+j + # if 0 <= x < n and 0 <= y < n and grid[x][y] == 0: + # deq.append((x,y,step + 1)) + # grid[x][y] = 1 + # return -1 +# @lc code=end + diff --git "a/Week_07/127.\345\215\225\350\257\215\346\216\245\351\276\231.py" "b/Week_07/127.\345\215\225\350\257\215\346\216\245\351\276\231.py" new file mode 100644 index 00000000..60afae2c --- /dev/null +++ "b/Week_07/127.\345\215\225\350\257\215\346\216\245\351\276\231.py" @@ -0,0 +1,56 @@ +# +# @lc app=leetcode.cn id=127 lang=python +# +# [127] 单词接龙 +# + +# @lc code=start +class Solution(object): + def ladderLength(self, beginWord, endWord, wordList): + """ + :type beginWord: str + :type endWord: str + :type wordList: List[str] + :rtype: int + """ + # 双向BFS + wordList = set(wordList) + if endWord not in wordList: return 0 + front = {beginWord} + back = {endWord} + n = len(beginWord) + step = 1 + while front: + step += 1 + front_next = set() + for word in front: + for i in range(n): + for j in range(26): + neww = word[:i] + chr(97 + j) + word[i + 1:] + if neww in back: + return step + if neww in wordList: + front_next.add(neww) + wordList.remove(neww) + front = front_next + if len(front) > len(back): + front,back = back,front + return 0 + + # 单向BFS + # wordList = set(wordList) + # deq = deque([(beginWord, 1)]) + # exist = set([beginWord]) + # while deq: + # word, step = deq.popleft() + # if word == endWord: return step + # for i in range(len(beginWord)): + # for p in range(26): + # tmp = word[:i] + chr(97 + p) + word[i + 1:] + # if tmp in wordList and tmp not in exist: + # # 这里是和接龙2本质区别的地方,这里的操作只能找到一条路径 + # exist.add(tmp) + # deq.append((tmp, step + 1)) + # return 0 +# @lc code=end + diff --git "a/Week_07/130.\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237.py" "b/Week_07/130.\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237.py" new file mode 100644 index 00000000..75315f6b --- /dev/null +++ "b/Week_07/130.\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237.py" @@ -0,0 +1,46 @@ +# +# @lc app=leetcode.cn id=130 lang=python +# +# [130] 被围绕的区域 +# + +# @lc code=start +class UF(object): + def __init__(self,size): + self.p = [i for i in range(size + 1)] + def union(self, x, y): + self.p[self.parent(x)] = self.parent(y) + def parent(self, x): + root = x + while self.p[root] != root: + root = self.p[root] + while self.p[x] != root: + self.p[x],x=root,self.p[x] + return root +class Solution(object): + def solve(self, board): + """ + :type board: List[List[str]] + :rtype: None Do not return anything, modify board in-place instead. + """ + if not board or not board[0]:return + direction = ((1,0),(-1,0),(0,1),(0,-1)) + m, n = len(board),len(board[0]) + dummy = m*n + uf = UF(dummy) + for i in range(m): + for j in range(n): + if board[i][j] == 'O': + if i in (0,m-1) or j in (0,n-1): + uf.union(i*n+j,dummy) + else: + for x,y in direction: + x,y=x+i,y+j + if 0 <= x < m and 0 <= y < n and board[x][y] == 'O': + uf.union(i*n+j,x*n+y) + for i in range(m): + for j in range(n): + if board[i][j] == 'O' and uf.parent(i*n+j) != uf.parent(dummy): + board[i][j] = 'X' +# @lc code=end + diff --git "a/Week_07/200.\345\262\233\345\261\277\346\225\260\351\207\217.py" "b/Week_07/200.\345\262\233\345\261\277\346\225\260\351\207\217.py" new file mode 100644 index 00000000..c35fcd0e --- /dev/null +++ "b/Week_07/200.\345\262\233\345\261\277\346\225\260\351\207\217.py" @@ -0,0 +1,70 @@ +# +# @lc app=leetcode.cn id=200 lang=python +# +# [200] 岛屿数量 +# + +# @lc code=start + + +class Solution(object): + def numIslands(self, grid): + """ + :type grid: List[List[str]] + :rtype: int + """ + # # DFS + # def dfs(i, j): + # if not (0 <= i < len(grid) and 0 <= j < len(grid[0])) or grid[i][j] == '0':return + # grid[i][j] = '0' + # dfs(i, j + 1) + # dfs(i, j - 1) + # dfs(i - 1, j) + # dfs(i + 1, j) + # count = 0 + # for i in range(len(grid)): + # for j in range(len(grid[0])): + # if grid[i][j] == '1': + # dfs(i, j) # 把i,j的岛屿归零,同时把周围的岛屿归零 + # count += 1 + # return count + + # # BFS + # def bfs(i, j): + # deq = deque([(i, j)]) + # while deq: + # i, j = deq.popleft() + # if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == '1': + # grid[i][j] = '0' + # deq.extend([(i + 1, j), (i - 1, j), (i, j - 1), (i, j + 1)]) + # count = 0 + # for i in range(len(grid)): + # for j in range(len(grid[0])): + # if grid[i][j] == '1': + # bfs(i, j) + # count += 1 + # return count + + # 并查集 + def union(x,y): + p[parent(x)] = parent(y) + def parent(i): + root = i + while root != p[root]: + root = p[root] + while p[i] != root: + p[i], i = root, p[i] + return root + m,n = len(grid), len(grid[0]) + p = [i for i in range(m*n)] + direction = ((0,-1),(-1,0)) + for i in range(m): + for j in range(n): + if grid[i][j] == '1': + for x,y in direction: + x,y=x+i,y+j + if 0 <= x < m and 0 <= y < n and grid[x][y] == '1': + union(i*n+j,x*n+y) + return len({parent(i*n+j) for i in range(m) for j in range(n) if grid[i][j] == '1'}) +# @lc code=end + diff --git "a/Week_07/208.\345\256\236\347\216\260-trie-\345\211\215\347\274\200\346\240\221.py" "b/Week_07/208.\345\256\236\347\216\260-trie-\345\211\215\347\274\200\346\240\221.py" new file mode 100644 index 00000000..46f6c1c0 --- /dev/null +++ "b/Week_07/208.\345\256\236\347\216\260-trie-\345\211\215\347\274\200\346\240\221.py" @@ -0,0 +1,60 @@ +# +# @lc app=leetcode.cn id=208 lang=python +# +# [208] 实现 Trie (前缀树) +# + +# @lc code=start +class Trie(object): + + def __init__(self): + """ + Initialize your data structure here. + """ + self.root = {} # 初始化根节点 + + def insert(self, word): + """ + Inserts a word into the trie. + :type word: str + :rtype: None + """ + node = self.root + for char in word: + node = node.setdefault(char, {}) + node['#'] = '#' + + def search(self, word): + """ + Returns if the word is in the trie. + :type word: str + :rtype: bool + """ + node = self.root + for char in word: + if char not in node: + return False + node = node[char] + return '#' in node + + def startsWith(self, prefix): + """ + Returns if there is any word in the trie that starts with the given prefix. + :type prefix: str + :rtype: bool + """ + node = self.root + for char in prefix: + if char not in node: + return False + node = node[char] + 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) +# @lc code=end + diff --git "a/Week_07/212.\345\215\225\350\257\215\346\220\234\347\264\242-ii.py" "b/Week_07/212.\345\215\225\350\257\215\346\220\234\347\264\242-ii.py" new file mode 100644 index 00000000..c9c26cd4 --- /dev/null +++ "b/Week_07/212.\345\215\225\350\257\215\346\220\234\347\264\242-ii.py" @@ -0,0 +1,44 @@ +# +# @lc app=leetcode.cn id=212 lang=python +# +# [212] 单词搜索 II +# + +# @lc code=start +class Solution(object): + def findWords(self, board, words): + """ + :type board: List[List[str]] + :type words: List[str] + :rtype: List[str] + """ + # dfs搜索 + def dfs(i,j,word,root): + if '#' in root: + ans.add(word) + tmp = board[i][j] # 备份 + board[i][j] = 0 # 标记走过的路径 + for x,y in direction: + x,y=x+i,y+j + if 0 <= x < m and 0 <= y < n and board[x][y] in root: + dfs(x,y,word + board[x][y], root[board[x][y]]) + board[i][j] = tmp + # 生成Trie + root = {} + for word in words: + node = root + for char in word: + node = node.setdefault(char, {}) + node['#'] = '#' + + m,n = len(board), len(board[0]) + direction = ((1,0),(-1,0),(0,1),(0,-1)) + ans = set() + for i in range(m): + for j in range(n): + if board[i][j] in root: + dfs(i,j,board[i][j],root[board[i][j]]) + return list(ans) + +# @lc code=end + diff --git "a/Week_07/36.\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" "b/Week_07/36.\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" new file mode 100644 index 00000000..a4358bd0 --- /dev/null +++ "b/Week_07/36.\346\234\211\346\225\210\347\232\204\346\225\260\347\213\254.py" @@ -0,0 +1,30 @@ +# +# @lc app=leetcode.cn id=36 lang=python +# +# [36] 有效的数独 +# + +# @lc code=start +class Solution(object): + def isValidSudoku(self, board): + """ + :type board: List[List[str]] + :rtype: bool + """ + row = [defaultdict(int) for _ in range(9)] + col = [defaultdict(int) for _ in range(9)] + box = [defaultdict(int) for _ in range(9)] + for i in range(9): + for j in range(9): + index = i // 3 * 3 + j // 3 + if board[i][j] != '.': + row[i][int(board[i][j])] += 1 + col[j][int(board[i][j])] += 1 + box[index][int(board[i][j])] += 1 + if row[i][int(board[i][j])] > 1 or col[j][int(board[i][j])] > 1 or box[index][int(board[i][j])] > 1: + return False + return True + + +# @lc code=end + diff --git "a/Week_07/37.\350\247\243\346\225\260\347\213\254.py" "b/Week_07/37.\350\247\243\346\225\260\347\213\254.py" new file mode 100644 index 00000000..f5e47c27 --- /dev/null +++ "b/Week_07/37.\350\247\243\346\225\260\347\213\254.py" @@ -0,0 +1,50 @@ +# +# @lc app=leetcode.cn id=37 lang=python +# +# [37] 解数独 +# + +# @lc code=start +class Solution(object): + def solveSudoku(self, board): + """ + :type board: List[List[str]] + :rtype: None Do not return anything, modify board in-place instead. + """ + row = [set() for _ in range(9)] + col = [set() for _ in range(9)] + box = [set() for _ in range(9)] + nums = set('123456789') + blank = [] + for i in range(9): + for j in range(9): + if board[i][j] == '.': + blank.append((i,j)) + else: + row[i].add(board[i][j]) + col[j].add(board[i][j]) + box[i // 3 * 3 + j // 3].add(board[i][j]) + + def dfs(n): + if n == len(blank): + return True + i,j = blank[n] + rest = nums - row[i] - col[j] - box[i // 3 * 3 + j // 3] # 还剩的可以填的数字 + if not rest: + return False + + for num in rest: + board[i][j] = num + row[i].add(board[i][j]) + col[j].add(board[i][j]) + box[i // 3 * 3 + j // 3].add(board[i][j]) + if dfs(n + 1): + return True + row[i].remove(board[i][j]) + col[j].remove(board[i][j]) + box[i // 3 * 3 + j // 3].remove(board[i][j]) + board[i][j] = '.' + + dfs(0) +# @lc code=end + diff --git "a/Week_07/433.\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py" "b/Week_07/433.\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py" new file mode 100644 index 00000000..1adb637c --- /dev/null +++ "b/Week_07/433.\346\234\200\345\260\217\345\237\272\345\233\240\345\217\230\345\214\226.py" @@ -0,0 +1,57 @@ +# +# @lc app=leetcode.cn id=433 lang=python +# +# [433] 最小基因变化 +# + +# @lc code=start +class Solution(object): + def minMutation(self, start, end, bank): + """ + :type start: str + :type end: str + :type bank: List[str] + :rtype: int + """ + # 双向BFS + bank = set(bank) + if end not in bank: return -1 + front = {start} + back = {end} + n = len(start) + step = 0 + while front: + step += 1 + front_next = set() + for word in front: + for i in range(n): + for j in 'AGCT': + neww = word[:i] + j + word[i + 1:] + if neww in back: + return step + if neww in bank: + front_next.add(neww) + bank.remove(neww) + front = front_next + if len(front) > len(back): + front,back = back,front + return -1 + + # 单向BFS + # possible = ['A', 'G', 'C', 'T'] + # bank = set(bank) + # deq = deque([(start, 0)]) + # exist = set([start]) + # while deq: + # word, step = deq.popleft() + # if word == end: return step + # for i in range(len(start)): + # for p in possible: + # tmp = word[:i] + p + word[i + 1:] + # if tmp in bank and tmp not in exist: + # exist.add(tmp) + # deq.append((tmp, step + 1)) + # return -1 + +# @lc code=end + diff --git "a/Week_07/51.n-\347\232\207\345\220\216.py" "b/Week_07/51.n-\347\232\207\345\220\216.py" new file mode 100644 index 00000000..6b735f0c --- /dev/null +++ "b/Week_07/51.n-\347\232\207\345\220\216.py" @@ -0,0 +1,43 @@ +# +# @lc app=leetcode.cn id=51 lang=python +# +# [51] N 皇后 +# + +# @lc code=start +class Solution(object): + def solveNQueens(self, n): + """ + :type n: int + :rtype: List[List[str]] + """ + # 判断是否冲突 + def nonconflict(index, ans): + for i in range(len(ans)): + # 当前棋子和前面几行处在一条直线上 + if index == int(ans[i]): return False + # 当前棋子和前面几行处在一条斜线上 + if abs(int(ans[i]) - index) == len(ans) - i: return False + return True + + # 回溯 + def backtrack(ans): + if len(ans) == n: + res.append(ans) + return + for i in range(n): + if nonconflict(i, ans): backtrack(ans + str(i)) + res = [] + backtrack('') + + # 打印 + for ans_i,ans in enumerate(res): + tmp = [['.']*n for _ in range(n)] + for i in range(n): + tmp[i][int(ans[i])] = 'Q' + res[ans_i] = [''.join(x) for x in tmp] + return res + + +# @lc code=end + diff --git "a/Week_07/547.\347\234\201\344\273\275\346\225\260\351\207\217.py" "b/Week_07/547.\347\234\201\344\273\275\346\225\260\351\207\217.py" new file mode 100644 index 00000000..8fbfd519 --- /dev/null +++ "b/Week_07/547.\347\234\201\344\273\275\346\225\260\351\207\217.py" @@ -0,0 +1,39 @@ +# +# @lc app=leetcode.cn id=547 lang=python +# +# [547] 省份数量 +# + +# @lc code=start +class UF(object): + def __init__(self,size): + self.p = [i for i in range(size)] + + def union(self, x, y): + self.p[self.parent(x)] = self.parent(y) + + def parent(self, x): + root = x + while self.p[root] != root: + root = self.p[root] + while self.p[x] != root: + self.p[x],x=root,self.p[x] + return root + + +class Solution(object): + def findCircleNum(self, isConnected): + """ + :type isConnected: List[List[int]] + :rtype: int + """ + n = len(isConnected) + uf = UF(n) + for i in range(n): + for j in range(n): + if isConnected[i][j] == 1: + uf.union(i,j) + return len({uf.parent(x) for x in uf.p}) + +# @lc code=end + diff --git "a/Week_07/773.\346\273\221\345\212\250\350\260\234\351\242\230.py" "b/Week_07/773.\346\273\221\345\212\250\350\260\234\351\242\230.py" new file mode 100644 index 00000000..96a2b0fd --- /dev/null +++ "b/Week_07/773.\346\273\221\345\212\250\350\260\234\351\242\230.py" @@ -0,0 +1,61 @@ +# +# @lc app=leetcode.cn id=773 lang=python +# +# [773] 滑动谜题 +# + +# @lc code=start +class Solution(object): + def slidingPuzzle(self, board): + """ + :type board: List[List[int]] + :rtype: int + """ + # 双向BFS + dic = {0:(1,3),1:(0,2,4),2:(1,5),3:(0,4),4:(1,3,5),5:(2,4)} + board = tuple(board[0] + board[1]) + if board == (1,2,3,4,5,0):return 0 + front = {board} + back = {(1,2,3,4,5,0)} + step = 0 + visited = front | back + while front: + step += 1 + next_front = set() + for board in front: + zero = board.index(0) + for zero_next in dic[zero]: + next_board = list(board) + next_board[zero_next],next_board[zero] = next_board[zero],next_board[zero_next] + next_board = tuple(next_board) + if next_board in back: + return step + if next_board not in visited: + visited.add(next_board) + next_front.add(next_board) + front = next_front + if len(front) > len(back): + front, back = back, front + return -1 + + + # # BFS + # dic = {0:(1,3),1:(0,2,4),2:(1,5),3:(0,4),4:(1,3,5),5:(2,4)} + # board = tuple(board[0] + board[1]) + # deq = deque([(board, board.index(0), 0)]) + # visited = set() + # visited.add(board) + # while deq: + # board, zero, step = deq.popleft() + # if board == (1,2,3,4,5,0): + # return step + # for next_zero in dic[zero]: + # next_board = list(board) + # next_board[zero],next_board[next_zero] = next_board[next_zero],next_board[zero] + # next_board = tuple(next_board) + # if next_board not in visited: + # deq.append((next_board, next_zero, step + 1)) + # visited.add(next_board) + # return -1 +# @lc code=end + diff --git a/Week_07/README.md b/Week_07/README.md index 50de3041..c42dea5f 100644 --- a/Week_07/README.md +++ b/Week_07/README.md @@ -1 +1,190 @@ -学习笔记 \ No newline at end of file +# 第七周学习笔记 +## Trie树(字典树) +字典树是以字典的形式存放,是一种树形结构,是一种哈希树的变种。 +典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 +它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 +三个基本性质: +* 根节点不包含字符,除根节点外每一个节点都只包含一个字符; +* 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; +* 每个节点的所有子节点包含的字符都不相同。 +Python模板 +``` +class Trie(object): + + def __init__(self): + """ + Initialize your data structure here. + """ + self.root = {} + self.end = '#' + + def insert(self, word): + """ + Inserts a word into the trie. + :type word: str + :rtype: None + """ + node = self.root # 注意:这里下面虽然是对node进行改变,但是字典是可变类型,所以self.root也会跟着改变 + for char in word: + node = node.setdefault(char, {}) # 如果含有char,则node进入char,也就是进入下一层。否则以char为键创建空字典 + node[self.end] = self.end + # node[self.end] = node.get(self.end, 0) + 1 # 叶子节点可以计算频次 + + def search(self, word): + """ + Returns if the word is in the trie. + :type word: str + :rtype: bool + """ + node = self.root + for char in word: + if char not in node: + return False + node = node[char] # 不断进入下一个子节点 + return self.end in node + + def startsWith(self, prefix): + """ + Returns if there is any word in the trie that starts with the given prefix. + :type prefix: str + :rtype: bool + """ + node = self.root + for char in prefix: + if char not in node: + return False + node = node[char] + return True +``` +## 并查集 +并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。 +并查集的初始化定义用数组有两种方式,一种```p = [i for i in range(size)] ```,另一种```p = [i for -1 in range(size)] ``` +当然也可以用字典来定义,一种```p = {i:i for i in range(size)} ```,另一种```p = {i:-1 for i in range(size)} ```,当然,其中的-1也可以替换成None或者其他形式,只要能和下标区别开就行,下标一般是从0开始的正整数,也就是除了从0开始的正整数其他形式的符号数字都能替换-1. +字典形式的优势是可以不从0开始初始化,可以从任意值初始化。而数组形式必须从0开始初始化,且连续,因为数组是以下标作为索引的,不连续的话无法正确索引到根节点。所以综合来看还是用字典形式的更加方便。 +``` + +class UnionFind: + def __init__(self,size): + + self.p = {i:None for i in range(size)} + + def find(self,x): + root = x + while self.p[root] != None: + root = self.p[root] + + while self.p[x] != root: + x, self.p[x] = self.p[x], root + return root + + def merge(self,x,y): + if not self.is_connected(x,y): + self.p[self.find(x)] = self.find(y) + + def is_connected(self,x,y): + return self.find(x) == self.find(y) + + +class UnionFind: + def __init__(self,size): + + self.p = {i:i for i in range(size)} + + def find(self,x): + root = x + while self.p[root] != root: + root = self.p[root] + # 路径压缩 + while self.p[x] != root: + x, self.p[x] = self.p[x], root + return root + + def merge(self,x,y): + if not self.is_connected(x,y): + self.p[self.find(x)] = self.find(y) + + def is_connected(self,x,y): + return self.find(x) == self.find(y) +``` +上面讲的两种方式,都是初始化的时候就事先准备好了size长度的字典(或数组),其实还可以初始化空字典,然后需要的时候再加入,只要新添加一个add()函数即可,这种方式不需要提前知道当前集合的大小,可以随意调整,更加方便。模板如下: +``` +class UnionFind: + def __init__(self,size): + + self.p = {} + + def find(self,x): + root = x + while self.p[root] != root: + root = self.p[root] + # 路径压缩 + while self.p[x] != root: + x, self.p[x] = self.p[x], root + return root + + def merge(self,x,y): + if not self.is_connected(x,y): + self.p[self.find(x)] = self.find(y) + + def is_connected(self,x,y): + return self.find(x) == self.find(y) + + def add(self,x): + if x not in self.p: + self.p[x] = x +``` +## 剪枝 +个人觉得剪枝是一项经验活,剪枝一般用在回溯、递归、DFS里面去掉多余不需要的计算。但是很难用什么话语总结,一般是先写好递归代码,然后再思考如何剪枝降低时间复杂度。 +## 双向BFS +双向BFS和单向BFS大同小异,只是从两边同时开始往中间查找。 +Python模板如下 +``` +def BFS(graph, start, end): +    visited = set() + front = {start} + back = {end} + + while front: + front_next = {} + for node in front: + visited.add(node) + process(node) + nodes = generate_related_nodes(node)  + if nodes in back: + return ... + front_next.add(nodes) + + front = front_next + if len(front) > len(back): + front, back = back, front + + # other processing work  + ... +``` +## A* search(启发式搜索) +以后再学吧 + +## AVL树 +AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。 +AVL树的删除、插入、查找和普通搜索二叉树没什么区别。唯一有区别的是当删除、插入之后,AVL树变得不平衡之后,如何通过旋转重新变得平衡。 +旋转有四种操作,需要牢记: +* 左左:上部右旋一次 +* 右右:上部左旋一次 +* 左右:下部左旋一次,上部右旋一次 +* 右左:下部右旋一次,上部左旋一次 +同时如果旋转的过程中还有子树,子树也要跟着调整 +不足:结点需要额外的存储空间、且调整次数频繁,维护成本高 + +## 红黑树 +近似平衡二叉树,能够确保任何结点的左右子树的高度差小于两倍。 +红黑树满足条件如下: +* 根结点是黑色 +* 每个结点要么是红色要么是黑色 +* 每个叶结点(null结点,空结点)是黑色 +* 不能有相邻的两个红色结点 +* 从任何一个结点到其叶子结点的所有路径都包含相同数目的黑色结点 + +### 红黑树对比 +* 如果读操作远大于写,那么选择AVL树(微博、数据库);如果写操作和读操作五五开,那么选择红黑树(map,set) +* AVL树查找会比红黑树快,写入、删除操作会慢。 +* AVL树需要的存储空间比红黑树大,因为需要记录heights和factors(平衡因子),红黑树只要1bit来存储红黑(01)信息。 diff --git "a/Week_08/1122.\346\225\260\347\273\204\347\232\204\347\233\270\345\257\271\346\216\222\345\272\217.py" "b/Week_08/1122.\346\225\260\347\273\204\347\232\204\347\233\270\345\257\271\346\216\222\345\272\217.py" new file mode 100644 index 00000000..3c065602 --- /dev/null +++ "b/Week_08/1122.\346\225\260\347\273\204\347\232\204\347\233\270\345\257\271\346\216\222\345\272\217.py" @@ -0,0 +1,29 @@ +# +# @lc app=leetcode.cn id=1122 lang=python +# +# [1122] 数组的相对排序 +# + +# @lc code=start +class Solution(object): + def relativeSortArray(self, arr1, arr2): + """ + :type arr1: List[int] + :type arr2: List[int] + :rtype: List[int] + """ + # 计数排序 + upper = max(arr1) + 1 + freq = [0]*upper + for x in arr1: + freq[x] +=1 + arr = [] + for x in arr2: + arr.extend([x]*freq[x]) + freq[x] = 0 + for x in range(upper): + arr.extend([x]*freq[x]) + return arr + +# @lc code=end + diff --git "a/Week_08/146.lru-\347\274\223\345\255\230\346\234\272\345\210\266.py" "b/Week_08/146.lru-\347\274\223\345\255\230\346\234\272\345\210\266.py" new file mode 100644 index 00000000..53c55023 --- /dev/null +++ "b/Week_08/146.lru-\347\274\223\345\255\230\346\234\272\345\210\266.py" @@ -0,0 +1,84 @@ +# +# @lc app=leetcode.cn id=146 lang=python +# +# [146] LRU 缓存机制 +# + +# @lc code=start +class DLinkNode(): + def __init__(self,key=0,value=0): + self.key = key + self.value = value + self.next = None + self.prev = None + +class LRUCache(object): + + def __init__(self, capacity): + """ + :type capacity: int + """ + self.cache = dict() + self.head = DLinkNode() + self.tail = DLinkNode() + self.head.next = self.tail + self.tail.prev = self.head + self.capacity = capacity + self.size = 0 + + def get(self, key): + """ + :type key: int + :rtype: int + """ + if key not in self.cache: + return -1 + node = self.cache[key] + self.movetohead(node) + return node.value + + def put(self, key, value): + """ + :type key: int + :type value: int + :rtype: None + """ + if key not in self.cache: + node = DLinkNode(key,value) + self.addtohead(node) + self.cache[key] = node + self.size += 1 + if self.size > self.capacity: + removed = self.removetail() + self.cache.pop(removed.key) + self.size -= 1 + else: + node = self.cache[key] + self.movetohead(node) + node.value = value + + def addtohead(self, node): + node.next = self.head.next + node.prev = self.head + self.head.next.prev = node + self.head.next = node + + def removenode(self, node): + node.next.prev = node.prev + node.prev.next = node.next + + def removetail(self): + node = self.tail.prev + self.removenode(node) + return node + + def movetohead(self, node): + self.removenode(node) + self.addtohead(node) + +# Your LRUCache object will be instantiated and called as such: +# obj = LRUCache(capacity) +# param_1 = obj.get(key) +# obj.put(key,value) +# @lc code=end + diff --git "a/Week_08/190.\351\242\240\345\200\222\344\272\214\350\277\233\345\210\266\344\275\215.py" "b/Week_08/190.\351\242\240\345\200\222\344\272\214\350\277\233\345\210\266\344\275\215.py" new file mode 100644 index 00000000..812f4759 --- /dev/null +++ "b/Week_08/190.\351\242\240\345\200\222\344\272\214\350\277\233\345\210\266\344\275\215.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=190 lang=python +# +# [190] 颠倒二进制位 +# + +# @lc code=start + + +class Solution: + # @param n, an integer + # @return an integer + def reverseBits(self, n): + ans = 0 + cnt = 31 + while n: + ans += (n&1)<>=1 + return ans + +# @lc code=end + diff --git "a/Week_08/191.\344\275\215-1-\347\232\204\344\270\252\346\225\260.py" "b/Week_08/191.\344\275\215-1-\347\232\204\344\270\252\346\225\260.py" new file mode 100644 index 00000000..de1988bc --- /dev/null +++ "b/Week_08/191.\344\275\215-1-\347\232\204\344\270\252\346\225\260.py" @@ -0,0 +1,21 @@ +# +# @lc app=leetcode.cn id=191 lang=python +# +# [191] 位1的个数 +# + +# @lc code=start +class Solution(object): + def hammingWeight(self, n): + """ + :type n: int + :rtype: int + """ + cnt = 0 + while n > 0: + n &= n-1 + cnt+=1 + return cnt + +# @lc code=end + diff --git "a/Week_08/231.2-\347\232\204\345\271\202.py" "b/Week_08/231.2-\347\232\204\345\271\202.py" new file mode 100644 index 00000000..925eb96c --- /dev/null +++ "b/Week_08/231.2-\347\232\204\345\271\202.py" @@ -0,0 +1,16 @@ +# +# @lc app=leetcode.cn id=231 lang=python +# +# [231] 2的幂 +# + +# @lc code=start +class Solution(object): + def isPowerOfTwo(self, n): + """ + :type n: int + :rtype: bool + """ + return n > 0 and n&(n-1) == 0 +# @lc code=end + diff --git "a/Week_08/338.\346\257\224\347\211\271\344\275\215\350\256\241\346\225\260.py" "b/Week_08/338.\346\257\224\347\211\271\344\275\215\350\256\241\346\225\260.py" new file mode 100644 index 00000000..ba8922c6 --- /dev/null +++ "b/Week_08/338.\346\257\224\347\211\271\344\275\215\350\256\241\346\225\260.py" @@ -0,0 +1,20 @@ +# +# @lc app=leetcode.cn id=338 lang=python +# +# [338] 比特位计数 +# + +# @lc code=start +class Solution(object): + def countBits(self, num): + """ + :type num: int + :rtype: List[int] + """ + dp = [0] * (num+1) + for i in range(1,num+1): + dp[i] = dp[i&(i-1)] + 1 + return dp + +# @lc code=end + diff --git "a/Week_08/493.\347\277\273\350\275\254\345\257\271.py" "b/Week_08/493.\347\277\273\350\275\254\345\257\271.py" new file mode 100644 index 00000000..0e163632 --- /dev/null +++ "b/Week_08/493.\347\277\273\350\275\254\345\257\271.py" @@ -0,0 +1,49 @@ +# +# @lc app=leetcode.cn id=493 lang=python +# +# [493] 翻转对 +# + +# @lc code=start +class Solution(object): + def reversePairs(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + def merge(nums,left,mid,right): + i, j = left, mid+1 + while i <= mid and j <= right: + if nums[i] > 2*nums[j]: + self.cnt += mid-i+1 + j += 1 + else: + i += 1 + + i, j = left, mid+1 + tmp=[] + while i <= mid and j <= right: + if nums[i] <= nums[j]: + tmp.append(nums[i]) + i += 1 + else: + tmp.append(nums[j]) + j += 1 + if i > mid: + tmp += nums[j:right+1] + else: + tmp += nums[i:mid+1] + nums[left:right+1] = tmp + + def merge_sort(nums,left,right): + if left >= right:return + mid = (left + right) >> 1 + merge_sort(nums, left, mid) + merge_sort(nums, mid+1, right) + merge(nums, left, mid, right) + + self.cnt = 0 + merge_sort(nums,0,len(nums)-1) + return self.cnt +# @lc code=end + diff --git "a/Week_08/51.n-\347\232\207\345\220\216.py" "b/Week_08/51.n-\347\232\207\345\220\216.py" new file mode 100644 index 00000000..0fc635a9 --- /dev/null +++ "b/Week_08/51.n-\347\232\207\345\220\216.py" @@ -0,0 +1,75 @@ +# +# @lc app=leetcode.cn id=51 lang=python +# +# [51] N 皇后 +# + +# @lc code=start +class Solution(object): + def solveNQueens(self, n): + """ + :type n: int + :rtype: List[List[str]] + """ + + # 方法一:位运算 + def dfs(i,j,pie,na,queen): + if i == n: + ans.append(queen) + return + bit = (~(j|pie|na)&((1<>1,queen+[int(math.log(p, 2))]) + if n < 1:return [] + ans = [] + dfs(0,0,0,0,[]) + return [["."*i + "Q" + "."*(n-i-1) for i in res] for res in ans] + + # # 方法二:最简单的方法 + # def dfs(queen, pie, na): + # row = len(queen) + # if row == n: + # ans.append(queen) + # return + # for col in range(n): + # if col not in queen and row+col not in pie and row-col not in na: + # dfs(queen + [col], pie + [row+col], na + [row-col]) + # ans = [] + # dfs([],[],[]) + # return [['.'*i+'Q'+'.'*(n-i-1) for i in res] for res in ans] + + # 方法一:最基础的方法 + # # 判断是否冲突 + # def nonconflict(index, ans): + # for i in range(len(ans)): + # # 当前棋子和前面几行处在一条直线上 + # if index == int(ans[i]): return False + # # 当前棋子和前面几行处在一条斜线上 + # if abs(int(ans[i]) - index) == len(ans) - i: return False + # return True + + # # 回溯 + # def backtrack(ans): + # if len(ans) == n: + # res.append(ans) + # return + # for i in range(n): + # if nonconflict(i, ans): backtrack(ans + str(i)) + # res = [] + # backtrack('') + + # # 打印 + # for ans_i,ans in enumerate(res): + # tmp = [['.']*n for _ in range(n)] + # for i in range(n): + # tmp[i][int(ans[i])] = 'Q' + # res[ans_i] = [''.join(x) for x in tmp] + # return res + + +# @lc code=end + diff --git "a/Week_08/52.n\347\232\207\345\220\216-ii.py" "b/Week_08/52.n\347\232\207\345\220\216-ii.py" new file mode 100644 index 00000000..360b2549 --- /dev/null +++ "b/Week_08/52.n\347\232\207\345\220\216-ii.py" @@ -0,0 +1,33 @@ +# +# @lc app=leetcode.cn id=52 lang=python +# +# [52] N皇后 II +# + +# @lc code=start +class Solution(object): + def totalNQueens(self, n): + """ + :type n: int + :rtype: int + """ + # 位运算法 + def dfs(i,j,pie,na): + if i == n: + self.ans += 1 + return + + bit = (~(j|pie|na)&((1<>1) + + if n < 1:return [] + self.ans = 0 + dfs(0,0,0,0) + return self.ans +# @lc code=end + diff --git "a/Week_08/56.\345\220\210\345\271\266\345\214\272\351\227\264.py" "b/Week_08/56.\345\220\210\345\271\266\345\214\272\351\227\264.py" new file mode 100644 index 00000000..1927aa40 --- /dev/null +++ "b/Week_08/56.\345\220\210\345\271\266\345\214\272\351\227\264.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=56 lang=python +# +# [56] 合并区间 +# + +# @lc code=start +class Solution(object): + def merge(self, intervals): + """ + :type intervals: List[List[int]] + :rtype: List[List[int]] + """ + intervals.sort(key=lambda x:x[0]) + ans = [] + for interval in intervals: + if not ans or ans[-1][1] < interval[0]: + ans.append(interval) + else: + ans[-1][1] = max(ans[-1][1], interval[1]) + return ans +# @lc code=end + diff --git a/Week_08/README.md b/Week_08/README.md index 50de3041..8aab1a66 100644 --- a/Week_08/README.md +++ b/Week_08/README.md @@ -1 +1,107 @@ -学习笔记 \ No newline at end of file +# 第八周学习笔记 +## 位运算 +主要掌握一些位运算技巧。目前用的比较多的有以下几个: +* ```x&-x``` 取最小位1 +* ```x&(x-1)``` 打掉最小位1 +* ```>>n``` 左移n位 +* ```< 0: + self.remain -= 1 + else: + self.dic.popitem(last=False) + self.dic[key] = value +``` +## 排序算法 +### 快速排序 +``` +def quick_sort(A,left,right): # 这个本质思想就是确定中间一个值的位置,并把小于中间值的放到中间值前面,大于的放到后面 + if left < right: + mid = partition(A,left,right) + quick_sort_c(A, left, mid-1) + quick_sort_c(A, mid+1, right) + +def partition(A,left,right): # 把小于pivot的值放前面,大于q的值放后面 + pivot = A[right] # 确定中间值的位置,一般是第一个、中间一个和最后一个数字 + i = left + for j in range(left,right): + if A[j] < pivot: + A[j],A[i] = A[i],A[j] + i+=1 + A[right],A[i] = A[i],A[right] + return i +``` +### 归并排序 +``` +def merge(nums,left,mid,right): + i, j = left, mid+1 + tmp=[] + while i <= mid and j <= right: + if nums[i] <= nums[j]: + tmp.append(nums[i]) + i += 1 + else: + tmp.append(nums[j]) + j += 1 + if i > mid: + tmp += nums[j:right+1] + else: + tmp += nums[i:mid+1] + nums[left:right+1] = tmp + +def merge_sort(nums,left,right): + if left >= right:return + mid = (left + right) >> 1 + merge_sort(nums, left, mid) + merge_sort(nums, mid+1, right) + merge(nums, left, mid, right) +``` + diff --git "a/Week_09/10.\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\345\214\271\351\205\215.py" "b/Week_09/10.\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 00000000..a9571316 --- /dev/null +++ "b/Week_09/10.\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,28 @@ +# +# @lc app=leetcode.cn id=10 lang=python +# +# [10] 正则表达式匹配 +# + +# @lc code=start +class Solution(object): + def isMatch(self, s, p): + """ + :type s: str + :type p: str + :rtype: bool + """ + memo = {} + def dp(i, j): + if (i,j) in memo: return memo[(i,j)] + if len(p) == j:return len(s) == i + ismatch = i < len(s) and (p[j] in {'.', s[i]}) + if j+1 nums[j]: + # dp[i] = max(dp[i], dp[j] + 1) + # return max(dp) + + # # 二分查找(使用库函数) + # dp = [] + # for num in nums: + # pos = bisect.bisect_left(dp, num) + # if pos == len(dp): + # dp.append(num) + # else: + # dp[pos] = num + # return len(dp) + + # 二分查找(基于上述库函数思路) + dp = [float('-inf')] + for num in nums: + left = 0 + right = len(dp) + while left < right: + mid = (left+right)>>1 + if dp[mid] >= num: + right = mid + else: + left = mid + 1 + if right == len(dp): + dp.append(num) + else: + dp[right] = num + return len(dp) - 1 + +# @lc code=end + diff --git "a/Week_09/344.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262.py" "b/Week_09/344.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262.py" new file mode 100644 index 00000000..0398b2ef --- /dev/null +++ "b/Week_09/344.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262.py" @@ -0,0 +1,18 @@ +# +# @lc app=leetcode.cn id=344 lang=python +# +# [344] 反转字符串 +# + +# @lc code=start +class Solution(object): + def reverseString(self, s): + """ + :type s: List[str] + :rtype: None Do not return anything, modify s in-place instead. + """ + n = len(s) + for i in range(len(s)//2): + s[i],s[n-i-1] = s[n-i-1],s[i] +# @lc code=end + diff --git "a/Week_09/387.\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\224\257\344\270\200\345\255\227\347\254\246.py" "b/Week_09/387.\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\224\257\344\270\200\345\255\227\347\254\246.py" new file mode 100644 index 00000000..f953cd05 --- /dev/null +++ "b/Week_09/387.\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\224\257\344\270\200\345\255\227\347\254\246.py" @@ -0,0 +1,20 @@ +# +# @lc app=leetcode.cn id=387 lang=python +# +# [387] 字符串中的第一个唯一字符 +# + +# @lc code=start +class Solution(object): + def firstUniqChar(self, s): + """ + :type s: str + :rtype: int + """ + cnt = Counter(s) + for i in range(len(s)): + if cnt[s[i]] == 1: + return i + return -1 +# @lc code=end + diff --git "a/Week_09/541.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262-ii.py" "b/Week_09/541.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262-ii.py" new file mode 100644 index 00000000..31a19873 --- /dev/null +++ "b/Week_09/541.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262-ii.py" @@ -0,0 +1,23 @@ +# +# @lc app=leetcode.cn id=541 lang=python +# +# [541] 反转字符串 II +# + +# @lc code=start +class Solution(object): + def reverseStr(self, s, k): + """ + :type s: str + :type k: int + :rtype: str + """ + flag = True + res = '' + for i in range(0, len(s), k): + res += s[i:i+k][::-1] if flag else s[i:i+k] + flag = not flag + return res + +# @lc code=end + diff --git "a/Week_09/557.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\215\225\350\257\215-iii.py" "b/Week_09/557.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\215\225\350\257\215-iii.py" new file mode 100644 index 00000000..4c3e751a --- /dev/null +++ "b/Week_09/557.\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\215\225\350\257\215-iii.py" @@ -0,0 +1,21 @@ +# +# @lc app=leetcode.cn id=557 lang=python +# +# [557] 反转字符串中的单词 III +# + +# @lc code=start +class Solution(object): + def reverseWords(self, s): + """ + :type s: str + :rtype: str + """ + # s = s.strip().split(' ') + # for i in range(len(s)): + # s[i] = s[i][::-1] + # return ' '.join(s) + + return ' '.join(s[::-1].split(' ')[::-1]) +# @lc code=end + diff --git "a/Week_09/680.\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262-\342\205\261.py" "b/Week_09/680.\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262-\342\205\261.py" new file mode 100644 index 00000000..de6e25f0 --- /dev/null +++ "b/Week_09/680.\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262-\342\205\261.py" @@ -0,0 +1,24 @@ +# +# @lc app=leetcode.cn id=680 lang=python +# +# [680] 验证回文字符串 Ⅱ +# + +# @lc code=start +class Solution(object): + def validPalindrome(self, s): + """ + :type s: str + :rtype: bool + """ + isPalindrome = lambda x:x == x[::-1] + left, right = 0, len(s) - 1 + while left <= right: + if s[left] == s[right]: + left += 1 + right -= 1 + else: + return isPalindrome(s[left:right]) or isPalindrome(s[left+1:right+1]) + return True +# @lc code=end + diff --git "a/Week_09/746.\344\275\277\347\224\250\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257.py" "b/Week_09/746.\344\275\277\347\224\250\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257.py" new file mode 100644 index 00000000..ec6c476d --- /dev/null +++ "b/Week_09/746.\344\275\277\347\224\250\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257.py" @@ -0,0 +1,25 @@ +# +# @lc app=leetcode.cn id=746 lang=python +# +# [746] 使用最小花费爬楼梯 +# + +# @lc code=start +class Solution(object): + def minCostClimbingStairs(self, cost): + """ + :type cost: List[int] + :rtype: int + """ + # dp[i]:代表第i个楼梯的最低花费 + # dp[i] = min(dp[i - 1] + cost[i], dp[i - 2] + cost[i]) + if len(cost) < 2: return 0 + dp = [0] * len(cost) + dp[0] = cost[0] + dp[1] = cost[1] + for i in range(2, len(cost)): + dp[i] = min(dp[i - 1] + cost[i], dp[i - 2] + cost[i]) + return min(dp[-1], dp[-2]) + +# @lc code=end + diff --git "a/Week_09/8.\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\225\264\346\225\260-atoi.py" "b/Week_09/8.\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\225\264\346\225\260-atoi.py" new file mode 100644 index 00000000..68457989 --- /dev/null +++ "b/Week_09/8.\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\225\264\346\225\260-atoi.py" @@ -0,0 +1,27 @@ +# +# @lc app=leetcode.cn id=8 lang=python +# +# [8] 字符串转换整数 (atoi) +# + +# @lc code=start +class Solution(object): + def myAtoi(self, s): + """ + :type s: str + :rtype: int + """ + s = list(s.strip()) + if len(s)==0:return 0 + sign = -1 if s[0] == '-' else 1 + if s[0] in '-+': + s.pop(0) + ans = 0 + for c in s: + if c.isdigit(): + ans = ans * 10 + int(c) + else: + break + return max(min(sign*ans, 2**31-1), -2**31) +# @lc code=end + diff --git "a/Week_09/917.\344\273\205\344\273\205\345\217\215\350\275\254\345\255\227\346\257\215.py" "b/Week_09/917.\344\273\205\344\273\205\345\217\215\350\275\254\345\255\227\346\257\215.py" new file mode 100644 index 00000000..c3d62407 --- /dev/null +++ "b/Week_09/917.\344\273\205\344\273\205\345\217\215\350\275\254\345\255\227\346\257\215.py" @@ -0,0 +1,28 @@ +# +# @lc app=leetcode.cn id=917 lang=python +# +# [917] 仅仅反转字母 +# + +# @lc code=start +class Solution(object): + def reverseOnlyLetters(self, S): + """ + :type S: str + :rtype: str + """ + s = [] + for c in S: + if c.isalpha(): + s.append(c) + ans = [] + for c in S: + if c.isalpha(): + ans.append(s.pop()) + else: + ans.append(c) + return ''.join(ans) + + +# @lc code=end + diff --git a/Week_09/README.md b/Week_09/README.md index 50de3041..fed5af8d 100644 --- a/Week_09/README.md +++ b/Week_09/README.md @@ -1 +1,3 @@ -学习笔记 \ No newline at end of file +# 学习笔记 +本周其实没什么特别多的新内容,基本全都是复习内容。 +所以好好刷题吧,坚持五毒神掌过遍数。 \ No newline at end of file diff --git "a/Week_\346\257\225\344\270\232\346\200\273\347\273\223/README.md" "b/Week_\346\257\225\344\270\232\346\200\273\347\273\223/README.md" index 50de3041..778f0d9e 100644 --- "a/Week_\346\257\225\344\270\232\346\200\273\347\273\223/README.md" +++ "b/Week_\346\257\225\344\270\232\346\200\273\347\273\223/README.md" @@ -1 +1,10 @@ -学习笔记 \ No newline at end of file +# 毕业总结 +从进入训练营到结束,只有两个半月时间,这段时间让我学到了很多。 + +作为一名打算转行进入计算机领域的研二学生,一直听说数据结构和算法是入行的必经之路,其他东西可以会的少一点,但是数据结构和算法必须熟练。刚开始刷题像个无头苍蝇,不知道从何下手。因为选择加入了训练营。 + +加入训练营的这段时间,系统的掌握了数据结构和算法基础知识。五毒神掌理念是训练营带来的最重要的改变。算法最重要的是坚持刷题,做老题,在质不在量。 + +目前,我还处在找工作阶段,会一直坚持刷题,坚持五毒,遇到不会的敢于看答案,贯彻五毒,而不是死磕。 + +课程的结束并不代表学习的结束,而是学习的新开始。和同学们一起刷题的日子是快乐的,坚持是一件很酷的事情,从来没想过自己会坚持这么久,相信以后还会一直坚持下去。 \ No newline at end of file