diff --git a/Week_04/id_36/LeetCode_169_36.py b/Week_04/id_36/LeetCode_169_36.py new file mode 100644 index 00000000..2ef99fdb --- /dev/null +++ b/Week_04/id_36/LeetCode_169_36.py @@ -0,0 +1,129 @@ +# +# @lc app=leetcode.cn id=169 lang=python3 +# +# [169] 求众数 +# +# https://leetcode-cn.com/problems/majority-element/description/ +# +# algorithms +# Easy (59.73%) +# Likes: 259 +# Dislikes: 0 +# Total Accepted: 49.1K +# Total Submissions: 82.1K +# Testcase Example: '[3,2,3]' +# +# 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 +# +# 你可以假设数组是非空的,并且给定的数组总是存在众数。 +# +# 示例 1: +# +# 输入: [3,2,3] +# 输出: 3 +# +# 示例 2: +# +# 输入: [2,2,1,1,1,2,2] +# 输出: 2 +# +# + +# # 暴力法 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# majority_num = len(nums)//2 + +# for num in nums: +# count = 0 +# for n in nums: +# if n == num: +# count += 1 + +# if count > majority_num: +# return num + +# return -1 + +# # 哈希表-1 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# if not nums or len(nums) < 1: +# return 0 + +# counts = {} + +# for num in nums: +# if not counts.get(num): +# counts[num] = 1 +# else: +# counts[num] += 1 + +# max_value = 0 +# majority = 0 + +# for key, value in counts.items(): +# if value > max_value: +# max_value = value +# majority = key + +# return majority + +# # 哈希表-2 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# import collections +# counts = collections.Counter(nums) +# return max(counts.keys(), key = counts.get) + +# # 排序 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# nums_len = len(nums) +# if not nums or nums_len < 1: +# return 0 + +# nums.sort() +# return nums[nums_len // 2] + +# # 分治 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# def majority_element_rec(low, high): +# if low == high: +# return nums[low] + +# middle = low + (high - low) // 2 +# left = majority_element_rec(low, middle) +# right = majority_element_rec(middle + 1, high) + +# if left == right: +# return left + +# # left_count = sum(1 for i in range(low, high + 1) if nums[i] == left) +# # right_count = sum(1 for i in range(low, high + 1) if nums[i] == right) +# left_count = 0 +# right_count = 0 +# for i in range(low, high + 1): +# if nums[i] == left: +# left_count += 1 +# elif nums[i] == right: +# right_count += 1 + +# return left if left_count > right_count else right + +# return majority_element_rec(0, len(nums) - 1) + +# Boyer-Moore 投票算法 +class Solution: + def majorityElement(self, nums: List[int]) -> int: + count = 0 + candidate = None + + for num in nums: + if count == 0: + candidate = num + count += (1 if num == candidate else -1) + + return candidate + diff --git a/Week_04/id_36/LeetCode_455_36.py b/Week_04/id_36/LeetCode_455_36.py new file mode 100644 index 00000000..4b7b0edf --- /dev/null +++ b/Week_04/id_36/LeetCode_455_36.py @@ -0,0 +1,89 @@ +# +# @lc app=leetcode.cn id=455 lang=python3 +# +# [455] 分发饼干 +# +# https://leetcode-cn.com/problems/assign-cookies/description/ +# +# algorithms +# Easy (49.91%) +# Likes: 91 +# Dislikes: 0 +# Total Accepted: 10.7K +# Total Submissions: 21.4K +# Testcase Example: '[1,2,3]\n[1,1]' +# +# 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi +# ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i +# ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 +# +# 注意: +# +# 你可以假设胃口值为正。 +# 一个小朋友最多只能拥有一块饼干。 +# +# 示例 1: +# +# +# 输入: [1,2,3], [1,1] +# +# 输出: 1 +# +# 解释: +# 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 +# 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 +# 所以你应该输出1。 +# +# +# 示例 2: +# +# +# 输入: [1,2], [1,2,3] +# +# 输出: 2 +# +# 解释: +# 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 +# 你拥有的饼干数量和尺寸都足以让所有孩子满足。 +# 所以你应该输出2. +# +# +# +# class Solution: +# def findContentChildren(self, g: List[int], s: List[int]) -> int: +# g.sort() +# s.sort() + +# gi = 0 +# si = 0 +# res = 0 + +# while gi < len(g) and si < len(s): +# if s[si] >= g[gi]: +# si += 1 +# gi += 1 +# res += 1 +# else: +# si += 1 + +# return res + +class Solution: + def findContentChildren(self, g: List[int], s: List[int]) -> int: + import heapq + + heapq.heapify(g) + heapq.heapify(s) + + res = 0 + + while g and s: + if s[0] >= g[0]: + heapq.heappop(g) + heapq.heappop(s) + res += 1 + else: + heapq.heappop(s) + + return res + diff --git a/Week_04/id_36/LeetCode_46_36.py b/Week_04/id_36/LeetCode_46_36.py new file mode 100644 index 00000000..7c864673 --- /dev/null +++ b/Week_04/id_36/LeetCode_46_36.py @@ -0,0 +1,48 @@ +# +# @lc app=leetcode.cn id=46 lang=python3 +# +# [46] 全排列 +# +# https://leetcode-cn.com/problems/permutations/description/ +# +# algorithms +# Medium (69.78%) +# Likes: 294 +# Dislikes: 0 +# Total Accepted: 29.2K +# Total Submissions: 41.9K +# Testcase Example: '[1,2,3]' +# +# 给定一个没有重复数字的序列,返回其所有可能的全排列。 +# +# 示例: +# +# 输入: [1,2,3] +# 输出: +# [ +# ⁠ [1,2,3], +# ⁠ [1,3,2], +# ⁠ [2,1,3], +# ⁠ [2,3,1], +# ⁠ [3,1,2], +# ⁠ [3,2,1] +# ] +# +# +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + def backtrack(first = 0): + if first == n: + output.append(nums[:]) + + for i in range(first, n): + nums[first], nums[i] = nums[i], nums[first] + backtrack(first + 1) + nums[first], nums[i] = nums[i], nums[first] + + n = len(nums) + output = [] + backtrack() + + return output + diff --git a/Week_04/id_36/LeetCode_53_36.py b/Week_04/id_36/LeetCode_53_36.py new file mode 100644 index 00000000..6bc83058 --- /dev/null +++ b/Week_04/id_36/LeetCode_53_36.py @@ -0,0 +1,88 @@ +# +# @lc app=leetcode.cn id=53 lang=python3 +# +# [53] 最大子序和 +# +# https://leetcode-cn.com/problems/maximum-subarray/description/ +# +# algorithms +# Easy (45.55%) +# Likes: 1009 +# Dislikes: 0 +# Total Accepted: 65.3K +# Total Submissions: 142.9K +# Testcase Example: '[-2,1,-3,4,-1,2,1,-5,4]' +# +# 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 +# +# 示例: +# +# 输入: [-2,1,-3,4,-1,2,1,-5,4], +# 输出: 6 +# 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 +# +# +# 进阶: +# +# 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 +# +# # 暴力法 +# class Solution: +# def maxSubArray(self, nums: List[int]) -> int: +# n = len(nums) +# if n <= 0: +# return 0 + +# tmp = nums[0] +# max_value = tmp + +# for i in range(1, n): +# tmp = tmp + nums[i] if tmp > 0 else nums[i] +# max_value = max(max_value, tmp) + +# return max_value + +# class Solution: +# def maxSubArray(self, nums: List[int]) -> int: +# n = len(nums) +# if n <= 0: +# return 0 +# elif n == 1: +# return nums[0] + +# max_value = nums[0] +# tmp = 0 + +# for num in nums: +# tmp = tmp + num if tmp > 0 else num +# max_value = max(max_value, tmp) + +# return max_value + +# 分治法 +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + if n <= 0: + return 0 + elif n == 1: + return nums[0] + + middle = n // 2 + max_left = self.maxSubArray(nums[0 : middle]) + max_right = self.maxSubArray(nums[middle : n]) + + tmp = 0 + max_le = nums[middle - 1] + for i in range(middle - 1, -1, -1): + tmp += nums[i] + max_le = max(max_le, tmp) + + max_ri = nums[middle] + tmp = 0 + for i in range(middle, n): + tmp += nums[i] + max_ri = max(max_ri, tmp) + + return max(max_left, max_right, max_le + max_ri) + diff --git a/Week_04/id_36/LeetCode_70_36.py b/Week_04/id_36/LeetCode_70_36.py new file mode 100644 index 00000000..25c3ec37 --- /dev/null +++ b/Week_04/id_36/LeetCode_70_36.py @@ -0,0 +1,56 @@ +# +# @lc app=leetcode.cn id=70 lang=python3 +# +# [70] 爬楼梯 +# +# https://leetcode-cn.com/problems/climbing-stairs/description/ +# +# algorithms +# Easy (45.72%) +# Likes: 518 +# Dislikes: 0 +# Total Accepted: 55.5K +# Total Submissions: 121.4K +# Testcase Example: '2' +# +# 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 +# +# 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? +# +# 注意:给定 n 是一个正整数。 +# +# 示例 1: +# +# 输入: 2 +# 输出: 2 +# 解释: 有两种方法可以爬到楼顶。 +# 1. 1 阶 + 1 阶 +# 2. 2 阶 +# +# 示例 2: +# +# 输入: 3 +# 输出: 3 +# 解释: 有三种方法可以爬到楼顶。 +# 1. 1 阶 + 1 阶 + 1 阶 +# 2. 1 阶 + 2 阶 +# 3. 2 阶 + 1 阶 +# +# +# +class Solution: + def climbStairs(self, n: int) -> int: + def climb_stairs(i, n, m_dict): + if i > n: + return 0 + elif i == n: + return 1 + + if m_dict.get(i) and m_dict.get(i) > 0: + return m_dict.get(i) + + m_dict[i] = climb_stairs(i + 1, n, m_dict) + climb_stairs(i + 2, n, m_dict) + return m_dict[i] + + return climb_stairs(0, n, {}) + diff --git a/Week_04/id_36/LeetCode_720_36.py b/Week_04/id_36/LeetCode_720_36.py new file mode 100644 index 00000000..401b8cc8 --- /dev/null +++ b/Week_04/id_36/LeetCode_720_36.py @@ -0,0 +1,73 @@ +# +# @lc app=leetcode.cn id=720 lang=python3 +# +# [720] 词典中最长的单词 +# +# https://leetcode-cn.com/problems/longest-word-in-dictionary/description/ +# +# algorithms +# Easy (42.64%) +# Likes: 36 +# Dislikes: 0 +# Total Accepted: 2.6K +# Total Submissions: 6.2K +# Testcase Example: '["w","wo","wor","worl","world"]' +# +# +# 给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。 +# +# 若无答案,则返回空字符串。 +# +# 示例 1: +# +# +# 输入: +# words = ["w","wo","wor","worl", "world"] +# 输出: "world" +# 解释: +# 单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。 +# +# +# 示例 2: +# +# +# 输入: +# words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] +# 输出: "apple" +# 解释: +# "apply"和"apple"都能由词典中的单词组成。但是"apple"得字典序小于"apply"。 +# +# +# 注意: +# +# +# 所有输入的字符串都只包含小写字母。 +# words数组长度范围为[1,1000]。 +# words[i]的长度范围为[1,30]。 +# +# +# +# class Solution: +# def longestWord(self, words: List[str]) -> str: +# ans = "" +# word_set = set(words) +# for word in words: +# word_len = len(word) +# ans_len = len(ans) +# if word_len > ans_len or word_len == ans_len and word < ans: +# if all(word[:k] in word_set for k in range(1, word_len)): +# ans = word + +# return ans + +class Solution: + def longestWord(self, words: List[str]) -> str: + ans = "" + word_set = set(words) + words.sort(key = lambda c : (-(len(c)), c)) + for word in words: + if all(word[:k] in word_set for k in range(1, len(word))): + return word + + return "" + diff --git a/Week_04/id_36/LeetCode_77_36.py b/Week_04/id_36/LeetCode_77_36.py new file mode 100644 index 00000000..a500827e --- /dev/null +++ b/Week_04/id_36/LeetCode_77_36.py @@ -0,0 +1,46 @@ +# +# @lc app=leetcode.cn id=77 lang=python3 +# +# [77] 组合 +# +# https://leetcode-cn.com/problems/combinations/description/ +# +# algorithms +# Medium (68.76%) +# Likes: 129 +# Dislikes: 0 +# Total Accepted: 13.2K +# Total Submissions: 19.1K +# Testcase Example: '4\n2' +# +# 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。 +# +# 示例: +# +# 输入: n = 4, k = 2 +# 输出: +# [ +# ⁠ [2,4], +# ⁠ [3,4], +# ⁠ [2,3], +# ⁠ [1,2], +# ⁠ [1,3], +# ⁠ [1,4], +# ] +# +# +class Solution: + def combine(self, n: int, k: int) -> List[List[int]]: + def backtrack(first = 1, curr = []): + if len(curr) == k: + output.append(curr[:]) + + for i in range(first, n + 1): + curr.append(i) + backtrack(i + 1, curr) + curr.pop() + + output = [] + backtrack() + return output + diff --git a/Week_04/id_36/LeetCode_78_36.py b/Week_04/id_36/LeetCode_78_36.py new file mode 100644 index 00000000..9b116983 --- /dev/null +++ b/Week_04/id_36/LeetCode_78_36.py @@ -0,0 +1,51 @@ +# +# @lc app=leetcode.cn id=78 lang=python3 +# +# [78] 子集 +# +# https://leetcode-cn.com/problems/subsets/description/ +# +# algorithms +# Medium (73.91%) +# Likes: 268 +# Dislikes: 0 +# Total Accepted: 23.5K +# Total Submissions: 31.8K +# Testcase Example: '[1,2,3]' +# +# 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 +# +# 说明:解集不能包含重复的子集。 +# +# 示例: +# +# 输入: nums = [1,2,3] +# 输出: +# [ +# ⁠ [3], +# [1], +# [2], +# [1,2,3], +# [1,3], +# [2,3], +# [1,2], +# [] +# ] +# +# +class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + n = len(nums) + if n == 0: + return [] + + res = [] + + def backtrack(i, tmp): + res.append(tmp) + for j in range(i, n): + backtrack(j + 1, tmp + [nums[j]]) + + backtrack(0, []) + return res +