Given a string s, remove duplicate letters so that every
letter appears once and only once. You must make sure your result is the
smallest in lexicographical order among all possible results.
classSolution: defremoveDuplicateLetters(self, s: str) -> str: stack = [] seen = set() last_occ = {c: i for i, c inenumerate(s)}
for i, c inenumerate(s): if c notin seen: while stack and c < stack[-1] and i < last_occ[stack[-1]]: seen -= {stack.pop()} seen.add(c) stack.append(c) return''.join(stack)
You are given an integer array nums. You are initially
positioned at the array's first index, and each element
in the array represents your maximum jump length at that position.
Return true if you can reach the last index, or
false otherwise.
1 2 3 4 5 6 7 8 9
Example 1: Input: nums = [2,3,1,1,4] Output: true Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2: Input: nums = [3,2,1,0,4] Output: false Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index.
dp
第一感觉是dp, 也确实ac了, 但是时间复杂度太高了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defcanJump(self, nums: List[int]) -> bool: dp = [Falsefor i inrange(len(nums))] dp[-1] = True n = len(nums) if n == 1: returnTrue for i inrange(n-2, -1, -1): v = nums[i] for j inrange(v+1): if i+j < n: if dp[i+j] == Trueand dp[i]==False: dp[i] = True break return dp[0]
classSolution: defcanJump(self, nums: List[int]) -> bool: count = 0 for i in nums: if count < 0: returnFalse elif i > count: count = i count -= 1 returnTrue
45. Jump Game II
You are given a 0-indexed array of integers
nums of length n. You are initially positioned
at nums[0].
Each element nums[i] represents the maximum length of a
forward jump from index i. In other words, if you are at
nums[i], you can jump to any nums[i + j]
where:
0 <= j <= nums[i] and
i + j < n
Return the minimum number of jumps to reach nums[n - 1].
The test cases are generated such that you can reach
nums[n - 1].
1 2 3 4 5 6 7 8
Example 1: Input: nums = [2,3,1,1,4] Output: 2 Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2: Input: nums = [2,3,0,1,4] Output: 2
greedy
每次跳的区间都划分出来, 实际时间复杂度O(n), 空间复杂度O(1).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defjump(self, nums: List[int]) -> int: prev = None curr = 0 furthest = 0 n = len(nums) ans = 0 while furthest < n - 1: ans += 1 if prev isNone: furthest = nums[curr] else: for i inrange(prev+1, curr+1): furthest = max(furthest, i + nums[i]) prev = curr curr = furthest return ans
409. Longest Palindrome
打卡题
Given a string s which consists of lowercase or
uppercase letters, return the length of the longest
palindrome that can be built with those letters.
Letters are case sensitive, for example, "Aa" is not considered a
palindrome.
1 2 3 4 5 6 7 8 9
Example 1: Input: s = "abccccdd" Output: 7 Explanation: One longest palindrome that can be built is "dccaccd", whose length is 7.
Example 2: Input: s = "a" Output: 1 Explanation: The longest palindrome that can be built is "a", whose length is 1.
偶数全加,奇数-1然后全加, 最后如果存在奇数就+1
1 2 3 4 5 6 7 8 9 10 11 12
classSolution: deflongestPalindrome(self, s: str) -> int: ctr = Counter(s) ans = 0 exist = 0 for k, v in ctr.items(): if v%2: ans += v - 1 exist = 1 else: ans += v return ans + exist
122. Best Time to Buy and
Sell Stock II
You are given an integer array prices where prices[i] is the price of
a given stock on the ith day.
On each day, you may decide to buy and/or sell the stock. You can
only hold at most one share of the stock at any time. However, you can
buy it then immediately sell it on the same day.
Find and return the maximum profit you can
achieve.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Example 1: Input: prices = [7,1,5,3,6,4] Output: 7 Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. Total profit is 4 + 3 = 7.
Example 2: Input: prices = [1,2,3,4,5] Output: 4 Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. Total profit is 4.
Example 3: Input: prices = [7,6,4,3,1] Output: 0 Explanation: There is no way to make a positive profit, so we never buy the stock to achieve the maximum profit of 0.
从a到b再从b到c相当于从a到c,所以我们只需要捕捉所有局部增量即可
1 2 3 4 5 6 7 8 9 10
classSolution: defmaxProfit(self, prices: List[int]) -> int: ans = 0 iflen(prices) == 1: return0 for i inrange(len(prices)-1): v = prices[i+1] - prices[i] if v > 0: ans += v return ans
134. Gas Station
There are n gas stations along a circular route, where
the amount of gas at the ith station is
gas[i].
You have a car with an unlimited gas tank and it costs
cost[i] of gas to travel from the ith station
to its next (i + 1)th station. You begin the journey with
an empty tank at one of the gas stations.
Given two integer arrays gas and cost,
return the starting gas station's index if you can travel around the
circuit once in the clockwise direction, otherwise return
-1. If there exists a solution, it is guaranteed to be
unique.
Example 1: Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2] Output: 3 Explanation: Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4 Travel to station 4. Your tank = 4 - 1 + 5 = 8 Travel to station 0. Your tank = 8 - 2 + 1 = 7 Travel to station 1. Your tank = 7 - 3 + 2 = 6 Travel to station 2. Your tank = 6 - 4 + 3 = 5 Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3. Therefore, return 3 as the starting index.
Example 2: Input: gas = [2,3,4], cost = [3,4,3] Output: -1 Explanation: You can't start at station 0 or 1, as there is not enough gas to travel to the next station. Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4 Travel to station 0. Your tank = 4 - 3 + 2 = 3 Travel to station 1. Your tank = 3 - 3 + 3 = 3 You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3. Therefore, you can't travel around the circuit once no matter where you start.
最经典的贪心
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defcanCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: n = len(gas) tank = 0 ifsum(gas) - sum(cost) < 0: return -1 ans = 0 for i inrange(n): tank += gas[i] - cost[i] if tank > 0and ans isNone: ans = i if tank < 0: tank = 0 ans = None return ans
135. Candy
There are n children standing in a line. Each child is
assigned a rating value given in the integer array ratings.
You are giving candies to these children subjected to the following
requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their
neighbors.
Return the minimum number of candies you need to have to distribute
the candies to the children.
1 2 3 4 5 6 7 8 9 10
Example 1: Input: ratings = [1,0,2] Output: 5 Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2: Input: ratings = [1,2,2] Output: 4 Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively. The third child gets 1 candy because it satisfies the above two conditions.
from functools import cmp_to_key classSolution: deflargestNumber(self, nums: List[int]) -> str: defmycmp(x, y): if x+y > y+x: return -1 elif x == y: return0 else: return1 return''.join(sorted(map(str,nums), key=cmp_to_key(mycmp))).lstrip('0') or'0'
321. Create Maximum Number
You are given two integer arrays nums1 and
nums2 of lengths m and n
respectively. nums1 and nums2 represent the
digits of two numbers. You are also given an integer k.
Create the maximum number of length k <= m + n from
digits of the two numbers. The relative order of the digits from the
same array must be preserved.
Return an array of the k digits representing the
answer.
1 2 3 4 5 6 7 8 9 10 11
Example 1: Input: nums1 = [3,4,6,5], nums2 = [9,1,2,5,8,3], k = 5 Output: [9,8,6,5,3]
Example 2: Input: nums1 = [6,7], nums2 = [6,0,4], k = 5 Output: [6,7,6,0,4]
Example 3: Input: nums1 = [3,9], nums2 = [8,9], k = 3 Output: [9,8,9]
classSolution: defmaxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]: defmerge(l1, l2): ret = [] while l1 or l2: if l1 > l2: ret.append(l1.pop(0)) else: ret.append(l2.pop(0)) return ret defmonostack(lst, length): ret = [] preserve = len(lst) - length for i inrange(len(lst)): while preserve and ret and lst[i] > ret[-1]: ret.pop() preserve -= 1 ret.append(lst[i]) return ret[:length] n1 = len(nums1) n2 = len(nums2) res = [] for i inrange(k+1): j = k-i if i <= n1 and j <= n2: lst1 = monostack(nums1, i) lst2 = monostack(nums2, j) res = max(res, merge(lst1, lst2)) return res
846. Hand of Straights
Alice has some number of cards and she wants to rearrange the cards
into groups so that each group is of size groupSize, and
consists of groupSize consecutive cards.
Given an integer array hand where hand[i]
is the value written on the ith card and an integer
groupSize, return true if she can rearrange
the cards, or false otherwise.
1 2 3 4 5 6 7 8 9
Example 1: Input: hand = [1,2,3,6,2,3,4,7,8], groupSize = 3 Output: true Explanation: Alice's hand can be rearranged as [1,2,3],[2,3,4],[6,7,8]
Example 2: Input: hand = [1,2,3,4,5], groupSize = 4 Output: false Explanation: Alice's hand can not be rearranged into groups of 4.
classSolution: defisNStraightHand(self, hand: List[int], groupSize: int) -> bool: iflen(hand) % groupSize: returnFalse hand = sorted(hand) lst = [] for i in hand: if lst and lst[-1][0] == i: lst[-1][1] += 1 else: lst.append([i, 1]) whilelen(lst)>=groupSize: k, v = lst.pop(0) if v > 0: prev = k for j inrange(groupSize-1): if lst[j][0] != prev + 1: returnFalse prev = prev+1 lst[j][1] -= v if lst[j][1] < 0: returnFalse
while lst: k, v = lst.pop(0) if v > 0: returnFalse returnTrue
Given a sorted integer array nums and an integer
n, add/patch elements to the array such that any number in
the range [1, n] inclusive can be formed by the sum of some
elements in the array.
Return the minimum number of patches required.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Example 1: Input: nums = [1,3], n = 6 Output: 1 Explanation: Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4. Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3]. Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6]. So we only need 1 patch.
Example 2: Input: nums = [1,5,10], n = 20 Output: 2 Explanation: The two patches can be [2, 4].
classSolution: defminPatches(self, nums: List[int], n: int) -> int: i = 0 bound = 0 ans = 0 while bound < n: if i < len(nums) and nums[i] <= bound + 1: bound += nums[i] i += 1 else: ans += 1 bound += bound + 1
return ans
334. Increasing Triplet
Subsequence
Given an integer array nums, return true if there exists a triple of
indices (i, j, k) such that i < j < k
and nums[i] < nums[j] < nums[k]. If no such indices
exists, return false.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Example 1: Input: nums = [1,2,3,4,5] Output: true Explanation: Any triplet where i < j < k is valid.
Example 2: Input: nums = [5,4,3,2,1] Output: false Explanation: No triplet exists.
Example 3: Input: nums = [2,1,5,0,4,6] Output: true Explanation: The triplet (3, 4, 5) is valid because nums[3] == 0 < nums[4] == 4 < nums[5] = 6.
最长递增子串, 做过一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defincreasingTriplet(self, nums: List[int]) -> bool: stack = [] for i in nums: ifnot stack: stack.append(i) else: if i > stack[-1]: stack.append(i) iflen(stack) == 3: returnTrue else: stack[bisect.bisect_left(stack, i)] = i returnlen(stack) >= 3
存在优化, 因为只需要三个元素, 逻辑并不需要二分, 直接判断即可.
1 2 3 4 5 6 7 8 9 10 11
classSolution: defincreasingTriplet(self, nums: List[int]) -> bool: first = second = math.inf for i in nums: if i <= first: first = i elif i <= second: second = i else: returnTrue returnFalse
376. Wiggle Subsequence
A wiggle sequence is a sequence where the
differences between successive numbers strictly alternate between
positive and negative. The first difference (if one exists) may be
either positive or negative. A sequence with one element and a sequence
with two non-equal elements are trivially wiggle sequences.
For example, [1, 7, 4, 9, 2, 5] is a wiggle sequence
because the differences (6, -3, 5, -7, 3) alternate between
positive and negative. In contrast, [1, 4, 7, 2, 5] and
[1, 7, 4, 5, 5] are not wiggle sequences. The first is not
because its first two differences are positive, and the second is not
because its last difference is zero. A subsequence is obtained by
deleting some elements (possibly zero) from the original sequence,
leaving the remaining elements in their original order.
Given an integer array nums, return the length of the
longest wiggle subsequence of nums.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Example 1: Input: nums = [1,7,4,9,2,5] Output: 6 Explanation: The entire sequence is a wiggle sequence with differences (6, -3, 5, -7, 3).
Example 2: Input: nums = [1,17,5,10,13,15,10,5,16,8] Output: 7 Explanation: There are several subsequences that achieve this length. One is [1, 17, 10, 13, 10, 16, 8] with differences (16, -7, 3, -3, 6, -8).
Example 3: Input: nums = [1,2,3,4,5,6,7,8,9] Output: 2
classSolution: defwiggleMaxLength(self, nums: List[int]) -> int: stack = [] state = None for i in nums: ifnot stack: stack.append(i) else: if i == stack[-1]: continue elif (state isNoneor state isTrue) and i < stack[-1]: stack.append(i) state = False elif (state isNoneor state isFalse) and i > stack[-1]: stack.append(i) state = True else: stack.pop() stack.append(i) returnlen(stack)
实际中间变量可以无视, 贪心思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defwiggleMaxLength(self, nums: List[int]) -> int: n = len(nums) if n < 2: return n ans = 1 prev = None for i inrange(1, n): diff = nums[i] - nums[i-1] if (diff > 0and prev != 1) or (diff < 0and prev != -1): ans += 1 prev = 1if diff > 0else -1 return ans
397. Integer Replacement
Given a positive integer n, you can apply one of the following
operations:
If n is even, replace n with n / 2.
If n is odd, replace n with either n + 1 or
n - 1.
Return the minimum number of operations needed for n to become 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Example 1: Input: n = 8 Output: 3 Explanation: 8 -> 4 -> 2 -> 1
Example 2: Input: n = 7 Output: 4 Explanation: 7 -> 8 -> 4 -> 2 -> 1 or 7 -> 6 -> 3 -> 2 -> 1
Example 3: Input: n = 4 Output: 2
看二进制末两位, 最后俩二进制位为11且数字大于3我们选择加,
其他时候选择减
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: defintegerReplacement(self, n: int) -> int: ans = 0 while n != 1: if n & 1: if n & 2and n > 3: n += 1 n >>= 2 ans += 3 else: n -= 1 n >>= 1 ans += 2 else: n >>= 1 ans += 1 return ans
402. Remove K Digits
Given string num representing a non-negative integer
num, and an integer k, return the smallest
possible integer after removing k digits from
num.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Example 1: Input: num = "1432219", k = 3 Output: "1219" Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.
Example 2: Input: num = "10200", k = 1 Output: "200" Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.
Example 3: Input: num = "10", k = 2 Output: "0" Explanation: Remove all the digits from the number and it is left with nothing which is 0.
monostack, stack存数值, 一旦检测更小值就pop然后k-=1,
直到符合要求.
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defremoveKdigits(self, num: str, k: int) -> str: n = len(num) if num.count('0') >= n-k: return'0' stack = [] for i in num: while k and stack and stack[-1] > i: stack.pop() k -= 1 stack.append(i)
Example 1: Input: k = 2, w = 0, profits = [1,2,3], capital = [0,1,1] Output: 4 Explanation: Since your initial capital is 0, you can only start the project indexed 0. After finishing it you will obtain profit 1 and your capital becomes 1. With capital 1, you can either start the project indexed 1 or the project indexed 2. Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital. Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.
Example 2: Input: k = 3, w = 0, profits = [1,2,3], capital = [0,1,2] Output: 6
classSolution: deffindMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int: sorted_data = sorted(zip(capital, profits)) queue = [] i = 0 n = len(profits) while k: while i < n and sorted_data[i][0] <= w: heapq.heappush(queue, -sorted_data[i][1]) i += 1 ifnot queue: break w -= heapq.heappop(queue) k -= 1 return w
2193. Minimum Number
of Moves to Make Palindrome
You are given a string s consisting only of lowercase
English letters.
In one move, you can select any two
adjacent characters of s and swap them.
Return the minimum number of moves needed to make
s a palindrome.
Note that the input will be generated such that s can
always be converted to a palindrome.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Example 1: Input: s = "aabb" Output: 2 Explanation: We can obtain two palindromes from s, "abba" and "baab". - We can obtain "abba" from s in 2 moves: "aabb" -> "abab" -> "abba". - We can obtain "baab" from s in 2 moves: "aabb" -> "abab" -> "baab". Thus, the minimum number of moves needed to make s a palindrome is 2.
Example 2: Input: s = "letelt" Output: 2 Explanation: One of the palindromes we can obtain from s in 2 moves is "lettel". One of the ways we can obtain it is "letelt" -> "letetl" -> "lettel". Other palindromes such as "tleelt" can also be obtained in 2 moves. It can be shown that it is not possible to obtain a palindrome in less than 2 moves.
classSolution: defminMovesToMakePalindrome(self, s: str) -> int: ans = 0 whilelen(s) > 2: lo = s.find(s[-1]) hi = s.rfind(s[0]) if lo < len(s)-hi-1: ans += lo s = s[:lo] + s[lo+1:-1] else: ans += len(s)-hi-1 s = s[1:hi] + s[hi+1:] return ans