classSolution: defstringSequence(self, target: str) -> List[str]: ans = ["a"] alphabet_list = [chr(i) for i inrange(ord('a'), ord('z') + 1)] for i, s inenumerate(target): length = int(ord(s) - ord('a')) lst_word = ans[-1] if i == 0and length == 0: continue if i == 0and length != 0: for i inrange(1, length+1): change_alpha = alphabet_list[i] ans.append(change_alpha) continue for i inrange(length+1): append_words = lst_word + alphabet_list[i] ans.append(append_words) return ans
看题解之后比较简洁的写法
1 2 3 4 5 6 7 8 9
classSolution: defstringSequence(self, target: str) -> List[str]: ans = [] s = [] for c in target: s.append('') for s[-1] in ascii_lowercase[:ord(c) - ord('a') + 1]: ans.append(''.join(s)) return ans
classSolution: deflengthOfLongestSubstring(self, s: str) -> int: n = len(s) if n == 0: return0 ans = 1 for i inrange(n): now_length = 1 seen = set() seen.add(s[i]) for j inrange(i+1, n): if s[j] notin seen: seen.add(s[j]) now_length += 1 ans = max(now_length, ans) else: break return ans
用滑动窗口的思想进行优化,一般来说,滑动窗口类型的题目可以模板化为这样的代码:
1 2 3 4 5 6 7
for i inrange(n): window = set() while right < n and (window notin valid): window.add(s[right]) right += 1 ans = max(ans, right - i) window.remove(s[i])
滑动窗口的时间复杂度是 O(n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: deflengthOfLongestSubstring(self, s: str) -> int: n = len(s) if n == 0: return0 if n == 1: return1 seen = set() right = 0 ans = 0 for i inrange(n-1): while right < n and s[right] notin seen: seen.add(s[right]) right += 1 ans = max(ans, right - i) seen.remove(s[i]) return ans
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
首先,最暴力的方法就是 O(n^3) 的时间复杂度,直接三重循环,找到所有的三元组,然后再去重。
但是在固定一个数之后,本质上又转化成了两数之和的问题,所以可以用双指针来优化一下。
这是一个复杂度为 O(n^2) 的算法,通过了 308/313 的测试用例。
1 2 3 4 5 6 7 8 9 10 11 12
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: ans = [] for i inrange(len(nums)): target = -nums[i] seen = {} for j inrange(i+1, len(nums)): target_list = sorted([-target, nums[j], target-nums[j]]) if target - nums[j] in seen and target_list notin ans: ans.append(target_list) seen[nums[j]] = j return ans
上面的算法在中间的去重操作上还需要遍历一次 ans 数组,所以可以用一个 set 来代替 ans 数组,这样就不需要再去重了。而且在python中,set 的查找操作 in 是 O(1) 的时间复杂度,所以这样的优化是可行的。
这种算法时间复杂度是 O(n^2),通过了 312/313 的测试用例。
1 2 3 4 5 6 7 8 9 10 11 12
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: ans = set() # 用集合去重 for i inrange(len(nums)): target = -nums[i] seen = {} for j inrange(i + 1, len(nums)): if target - nums[j] in seen: triplet = tuple(sorted([-target, nums[j], target - nums[j]])) ans.add(triplet) # 直接将结果加入集合 seen[nums[j]] = j return [list(triplet) for triplet in ans] # 将最终结果转为列表返回
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: sorted_list = sorted(nums) ans = set() for i inrange(len(sorted_list)): if i > 0and sorted_list[i] == sorted_list[i-1]: continue target = -sorted_list[i] left = i+1 right = len(sorted_list)-1 while left < right: if sorted_list[left] + sorted_list[right] > target: right -= 1 continue if sorted_list[left] + sorted_list[right] < target: left += 1 continue if sorted_list[left] + sorted_list[right] == target: triplet = tuple(sorted([-target, sorted_list[left], sorted_list[right]])) ans.add(triplet) right -= 1 continue return [list(triplet) for triplet in ans]
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
一开始想到的暴力O(n^2)的方法,遍历所有的组合,找到最大的面积。不过显然会TLE。
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defmaxArea(self, height: List[int]) -> int: ans = 0 for i inrange(len(height)-1): for j inrange(i+1, len(height)): bigger_height = min(height[i], height[j]) area = bigger_height * (j - i) # print(area) if area <= ans: continue else: ans = area return ans
假设我们有两个指针,指向数组的两个位置,分别对应着高度 x, y (x <= y),不妨假设他们之间的距离是 t 。那么这两个指针之间的面积就是 min(x, y) * t = x * t 。此时我们如果移动高的指针,得到新的 y_1。分两种情况讨论,如果 y_1 < y,那么新的面积就是 min(x, y_1) * (t-1) <= min(x, y) * t。如果 y_1 >= y,那么新的面积就是 min(x, y_1) * (t-1) = x * (t-1)。这样可以看出,如果我们移动高的指针,面积只会变小,所以我们应该移动矮的指针。
classSolution: deflongestConsecutive(self, nums: List[int]) -> int: if nums == []: return0 new_list = sorted(set(nums)) ans = 1 longest = 1 # print(new_list) for i inrange(0, len(new_list)-1): if new_list[i+1] == new_list[i] + 1: ans += 1 if ans >= longest: longest = ans continue ans = 1 return longest
classSolution: defgroupAnagrams(self, strs: List[str]) -> List[List[str]]: seen = {} for i, word inenumerate(strs): sorted_word = ''.join(sorted(word)) if sorted_word notin seen: seen[sorted_word] = [word] else: seen[sorted_word].append(word) # for key, value in seen.items(): # ans.append(value) returnlist(seen.values())