正确性:维护 value -> index,当前元素只负责匹配之前出现过的补数。 只要每次更新后不变量仍成立,最终保留下来的状态就对应题目要求的结果。
解法:哈希表一次遍历
维护 value -> index,当前元素只负责匹配之前出现过的补数。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
seen = {}
for i, x in enumerate(nums):
need = target - x
if need in seen:
return [seen[need], i]
# 先查再存,避免同一个元素被用两次
seen[x] = i
return []
from collections import defaultdict
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
groups = defaultdict(list)
for s in strs:
cnt = [0] * 26
for ch in s:
cnt[ord(ch) - ord('a')] += 1
groups[tuple(cnt)].append(s)
return list(groups.values())
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
values = set(nums)
best = 0
for x in values:
if x - 1 in values:
continue
y = x
while y in values:
y += 1
best = max(best, y - x)
return best
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
slow = 0
for fast, x in enumerate(nums):
if x != 0:
nums[slow], nums[fast] = nums[fast], nums[slow]
slow += 1
class Solution:
def maxArea(self, height: List[int]) -> int:
left, right = 0, len(height) - 1
best = 0
while left < right:
h = min(height[left], height[right])
best = max(best, h * (right - left))
if height[left] < height[right]:
left += 1
else:
right -= 1
return best
正确性:固定 i,left/right 根据 sum 与 0 的关系移动。 只要每次更新后不变量仍成立,最终保留下来的状态就对应题目要求的结果。
解法:排序 + 固定一位 + 双指针
固定 i,left/right 根据 sum 与 0 的关系移动。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
ans = []
n = len(nums)
for i in range(n - 2):
if i > 0 and nums[i] == nums[i - 1]:
continue
if nums[i] > 0:
break
left, right = i + 1, n - 1
while left < right:
s = nums[i] + nums[left] + nums[right]
if s == 0:
ans.append([nums[i], nums[left], nums[right]])
left += 1
right -= 1
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
elif s < 0:
left += 1
else:
right -= 1
return ans
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
last = {}
left = 0
best = 0
for right, ch in enumerate(s):
if ch in last and last[ch] >= left:
left = last[ch] + 1
last[ch] = right
best = max(best, right - left + 1)
return best
from collections import Counter
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
need = Counter(p)
window = Counter()
ans = []
m = len(p)
for right, ch in enumerate(s):
window[ch] += 1
if right >= m:
left_ch = s[right - m]
window[left_ch] -= 1
if window[left_ch] == 0:
del window[left_ch]
if window == need:
ans.append(right - m + 1)
return ans
from collections import defaultdict
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = defaultdict(int)
count[0] = 1
prefix = 0
ans = 0
for x in nums:
prefix += x
ans += count[prefix - k]
count[prefix] += 1
return ans
from collections import deque
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
dq = deque()
ans = []
for i, x in enumerate(nums):
while dq and nums[dq[-1]] <= x:
dq.pop()
dq.append(i)
if dq[0] <= i - k:
dq.popleft()
if i >= k - 1:
ans.append(nums[dq[0]])
return ans
复杂度:时间 O(n),空间 O(k)。
复杂度分析
解法:单调递减队列:时间 O(n),主循环中每个元素或节点只进入核心结构常数次。 空间 O(k),主要来自大小受 k 控制的堆、窗口或候选集合。
from collections import Counter, defaultdict
class Solution:
def minWindow(self, s: str, t: str) -> str:
need = Counter(t)
window = defaultdict(int)
required = len(need)
formed = 0
left = 0
best_len = float('inf')
best = (0, 0)
for right, ch in enumerate(s):
window[ch] += 1
if ch in need and window[ch] == need[ch]:
formed += 1
while formed == required:
if right - left + 1 < best_len:
best_len = right - left + 1
best = (left, right + 1)
out = s[left]
window[out] -= 1
if out in need and window[out] < need[out]:
formed -= 1
left += 1
return '' if best_len == float('inf') else s[best[0]:best[1]]
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
local = best = nums[0]
for x in nums[1:]:
local = max(x, local + x)
best = max(best, local)
return best
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key=lambda x: x[0])
ans = []
for start, end in intervals:
if not ans or start > ans[-1][1]:
ans.append([start, end])
else:
ans[-1][1] = max(ans[-1][1], end)
return ans
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
n = len(nums)
k %= n
def reverse(l: int, r: int) -> None:
while l < r:
nums[l], nums[r] = nums[r], nums[l]
l += 1
r -= 1
reverse(0, n - 1)
reverse(0, k - 1)
reverse(k, n - 1)
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [1] * n
prefix = 1
for i in range(n):
ans[i] = prefix
prefix *= nums[i]
suffix = 1
for i in range(n - 1, -1, -1):
ans[i] *= suffix
suffix *= nums[i]
return ans
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums)
for i in range(n):
while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
j = nums[i] - 1
nums[i], nums[j] = nums[j], nums[i]
for i, x in enumerate(nums):
if x != i + 1:
return i + 1
return n + 1
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
m, n = len(matrix), len(matrix[0])
first_col_zero = any(matrix[i][0] == 0 for i in range(m))
first_row_zero = any(matrix[0][j] == 0 for j in range(n))
for i in range(1, m):
for j in range(1, n):
if matrix[i][j] == 0:
matrix[i][0] = matrix[0][j] = 0
for i in range(1, m):
for j in range(1, n):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
if first_row_zero:
for j in range(n):
matrix[0][j] = 0
if first_col_zero:
for i in range(m):
matrix[i][0] = 0
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
top, bottom = 0, len(matrix) - 1
left, right = 0, len(matrix[0]) - 1
ans = []
while top <= bottom and left <= right:
for j in range(left, right + 1):
ans.append(matrix[top][j])
top += 1
for i in range(top, bottom + 1):
ans.append(matrix[i][right])
right -= 1
if top <= bottom:
for j in range(right, left - 1, -1):
ans.append(matrix[bottom][j])
bottom -= 1
if left <= right:
for i in range(bottom, top - 1, -1):
ans.append(matrix[i][left])
left += 1
return ans
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
for i in range(n):
for j in range(i + 1, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
for row in matrix:
row.reverse()
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
row, col = 0, len(matrix[0]) - 1
while row < len(matrix) and col >= 0:
x = matrix[row][col]
if x == target:
return True
if x > target:
col -= 1
else:
row += 1
return False
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
p, q = headA, headB
while p is not q:
p = p.next if p else headB
q = q.next if q else headA
return p
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev, cur = None, head
while cur:
nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
return prev
复杂度:时间 O(n),空间 O(1)。
解法2:递归反转
递归返回新头,再把当前节点挂到后继节点之后。
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return head
new_head = self.reverseList(head.next)
head.next.next = head
head.next = None
return new_head
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
prev, cur = None, slow
while cur:
nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
left, right = head, prev
while right:
if left.val != right.val:
return False
left = left.next
right = right.next
return True
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
return False
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
p = head
while p is not slow:
p = p.next
slow = slow.next
return p
return None
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0, head)
prev = dummy
while prev.next and prev.next.next:
a = prev.next
b = a.next
a.next = b.next
b.next = a
prev.next = b
prev = a
return dummy.next
class Solution:
def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
if not head:
return None
mp = {}
cur = head
while cur:
mp[cur] = Node(cur.val)
cur = cur.next
cur = head
while cur:
mp[cur].next = mp.get(cur.next)
mp[cur].random = mp.get(cur.random)
cur = cur.next
return mp[head]
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return head
slow, fast = head, head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
mid = slow.next
slow.next = None
left = self.sortList(head)
right = self.sortList(mid)
return self.merge(left, right)
def merge(self, a: Optional[ListNode], b: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0)
tail = dummy
while a and b:
if a.val <= b.val:
tail.next = a
a = a.next
else:
tail.next = b
b = b.next
tail = tail.next
tail.next = a or b
return dummy.next
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ans, stack = [], []
cur = root
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
cur = stack.pop()
ans.append(cur.val)
cur = cur.right
return ans
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
def mirror(a, b):
if not a or not b:
return a is b
return a.val == b.val and mirror(a.left, b.right) and mirror(a.right, b.left)
return mirror(root.left, root.right) if root else True
class Solution:
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
best = 0
def depth(node):
nonlocal best
if not node:
return 0
left = depth(node.left)
right = depth(node.right)
best = max(best, left + right)
return 1 + max(left, right)
depth(root)
return best
from collections import deque
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
q = deque([root])
ans = []
while q:
level = []
for _ in range(len(q)):
node = q.popleft()
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
ans.append(level)
return ans
正确性:不必遍历完整棵树,数到第 k 个即可返回。 只要每次更新后不变量仍成立,最终保留下来的状态就对应题目要求的结果。
解法:中序遍历提前停止
不必遍历完整棵树,数到第 k 个即可返回。
class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
stack = []
cur = root
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
cur = stack.pop()
k -= 1
if k == 0:
return cur.val
cur = cur.right
from collections import deque
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
q = deque([root])
ans = []
while q:
size = len(q)
for i in range(size):
node = q.popleft()
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
if i == size - 1:
ans.append(node.val)
return ans
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root or root is p or root is q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if left and right:
return root
return left or right
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
best = float('-inf')
def gain(node):
nonlocal best
if not node:
return 0
left = max(gain(node.left), 0)
right = max(gain(node.right), 0)
best = max(best, node.val + left + right)
return node.val + max(left, right)
gain(root)
return best
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
m, n = len(grid), len(grid[0])
def dfs(i, j):
if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] != '1':
return
grid[i][j] = '0'
dfs(i + 1, j); dfs(i - 1, j)
dfs(i, j + 1); dfs(i, j - 1)
ans = 0
for i in range(m):
for j in range(n):
if grid[i][j] == '1':
ans += 1
dfs(i, j)
return ans
from collections import deque
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
q = deque()
fresh = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 2:
q.append((i, j))
elif grid[i][j] == 1:
fresh += 1
minutes = 0
dirs = [(1,0), (-1,0), (0,1), (0,-1)]
while q and fresh:
for _ in range(len(q)):
i, j = q.popleft()
for di, dj in dirs:
ni, nj = i + di, j + dj
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == 1:
grid[ni][nj] = 2
fresh -= 1
q.append((ni, nj))
minutes += 1
return minutes if fresh == 0 else -1
from collections import deque
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = [[] for _ in range(numCourses)]
indeg = [0] * numCourses
for a, b in prerequisites:
graph[b].append(a)
indeg[a] += 1
q = deque(i for i in range(numCourses) if indeg[i] == 0)
learned = 0
while q:
cur = q.popleft()
learned += 1
for nxt in graph[cur]:
indeg[nxt] -= 1
if indeg[nxt] == 0:
q.append(nxt)
return learned == numCourses
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
ans, path = [], []
used = [False] * len(nums)
def dfs():
if len(path) == len(nums):
ans.append(path[:])
return
for i, x in enumerate(nums):
if used[i]:
continue
used[i] = True
path.append(x)
dfs()
path.pop()
used[i] = False
dfs()
return ans
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
ans, path = [], []
def dfs(start):
ans.append(path[:])
for i in range(start, len(nums)):
path.append(nums[i])
dfs(i + 1)
path.pop()
dfs(0)
return ans
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
ans, path = [], []
def dfs(start, remain):
if remain == 0:
ans.append(path[:])
return
for i in range(start, len(candidates)):
x = candidates[i]
if x > remain:
break
path.append(x)
dfs(i, remain - x)
path.pop()
dfs(0, target)
return ans
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
m, n = len(board), len(board[0])
def dfs(i, j, idx):
if idx == len(word):
return True
if i < 0 or i >= m or j < 0 or j >= n or board[i][j] != word[idx]:
return False
tmp = board[i][j]
board[i][j] = '#'
ok = (dfs(i + 1, j, idx + 1) or dfs(i - 1, j, idx + 1) or
dfs(i, j + 1, idx + 1) or dfs(i, j - 1, idx + 1))
board[i][j] = tmp
return ok
return any(dfs(i, j, 0) for i in range(m) for j in range(n))
class Solution:
def partition(self, s: str) -> List[List[str]]:
n = len(s)
is_pal = [[False] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
for j in range(i, n):
is_pal[i][j] = s[i] == s[j] and (j - i < 2 or is_pal[i + 1][j - 1])
ans, path = [], []
def dfs(start):
if start == n:
ans.append(path[:])
return
for end in range(start, n):
if is_pal[start][end]:
path.append(s[start:end + 1])
dfs(end + 1)
path.pop()
dfs(0)
return ans
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
ans = []
cols, diag1, diag2 = set(), set(), set()
board = [['.'] * n for _ in range(n)]
def dfs(r):
if r == n:
ans.append([''.join(row) for row in board])
return
for c in range(n):
if c in cols or r - c in diag1 or r + c in diag2:
continue
cols.add(c); diag1.add(r - c); diag2.add(r + c)
board[r][c] = 'Q'
dfs(r + 1)
board[r][c] = '.'
cols.remove(c); diag1.remove(r - c); diag2.remove(r + c)
dfs(0)
return ans
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
m, n = len(matrix), len(matrix[0])
left, right = 0, m * n - 1
while left <= right:
mid = (left + right) // 2
x = matrix[mid // n][mid % n]
if x == target:
return True
if x < target:
left = mid + 1
else:
right = mid - 1
return False
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
m, n = len(nums1), len(nums2)
half = (m + n + 1) // 2
left, right = 0, m
while left <= right:
i = (left + right) // 2
j = half - i
a_left = float('-inf') if i == 0 else nums1[i - 1]
a_right = float('inf') if i == m else nums1[i]
b_left = float('-inf') if j == 0 else nums2[j - 1]
b_right = float('inf') if j == n else nums2[j]
if a_left <= b_right and b_left <= a_right:
if (m + n) % 2:
return max(a_left, b_left)
return (max(a_left, b_left) + min(a_right, b_right)) / 2
if a_left > b_right:
right = i - 1
else:
left = i + 1
class Solution:
def isValid(self, s: str) -> bool:
match = {')': '(', ']': '[', '}': '{'}
stack = []
for ch in s:
if ch in match.values():
stack.append(ch)
else:
if not stack or stack.pop() != match[ch]:
return False
return not stack
class Solution:
def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
ans = [0] * len(temperatures)
stack = []
for i, t in enumerate(temperatures):
while stack and temperatures[stack[-1]] < t:
j = stack.pop()
ans[j] = i - j
stack.append(i)
return ans
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
stack = []
best = 0
for i, h in enumerate(heights + [0]):
while stack and heights[stack[-1]] > h:
height = heights[stack.pop()]
left = stack[-1] if stack else -1
best = max(best, height * (i - left - 1))
stack.append(i)
return best
正确性:堆元素为 (freq, value),超出 k 时弹出最低频。 只要每次更新后不变量仍成立,最终保留下来的状态就对应题目要求的结果。
解法:计数 + 小根堆
堆元素为 (freq, value),超出 k 时弹出最低频。
from collections import Counter
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
heap = []
for x, freq in Counter(nums).items():
heapq.heappush(heap, (freq, x))
if len(heap) > k:
heapq.heappop(heap)
return [x for _, x in heap]
复杂度:时间 O(n log k),空间 O(n)。
复杂度分析
解法:计数 + 小根堆:时间 O(n log k),每个元素最多触发一次堆插入/弹出,堆大小受 k 控制。 空间 O(n),主要来自显式栈、单调栈或堆中保存的候选元素。
class Solution:
def maxProfit(self, prices: List[int]) -> int:
min_price = float('inf')
best = 0
for price in prices:
min_price = min(min_price, price)
best = max(best, price - min_price)
return best
class Solution:
def canJump(self, nums: List[int]) -> bool:
farthest = 0
for i, jump in enumerate(nums):
if i > farthest:
return False
farthest = max(farthest, i + jump)
if farthest >= len(nums) - 1:
return True
return True
class Solution:
def jump(self, nums: List[int]) -> int:
steps = 0
end = farthest = 0
for i in range(len(nums) - 1):
farthest = max(farthest, i + nums[i])
if i == end:
steps += 1
end = farthest
return steps
class Solution:
def partitionLabels(self, s: str) -> List[int]:
last = {ch: i for i, ch in enumerate(s)}
ans = []
start = end = 0
for i, ch in enumerate(s):
end = max(end, last[ch])
if i == end:
ans.append(end - start + 1)
start = i + 1
return ans
正确性:第 i 行只依赖第 i-1 行。 只要每次更新后不变量仍成立,最终保留下来的状态就对应题目要求的结果。
解法:逐行递推
第 i 行只依赖第 i-1 行。
class Solution:
def generate(self, numRows: int) -> List[List[int]]:
ans = []
for i in range(numRows):
row = [1] * (i + 1)
for j in range(1, i):
row[j] = ans[i - 1][j - 1] + ans[i - 1][j]
ans.append(row)
return ans
class Solution:
def numSquares(self, n: int) -> int:
dp = [0] + [float('inf')] * n
squares = [i * i for i in range(1, int(n ** 0.5) + 1)]
for i in range(1, n + 1):
for sq in squares:
if sq > i:
break
dp[i] = min(dp[i], dp[i - sq] + 1)
return dp[n]
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
words = set(wordDict)
dp = [False] * (len(s) + 1)
dp[0] = True
for i in range(1, len(s) + 1):
for j in range(i):
if dp[j] and s[j:i] in words:
dp[i] = True
break
return dp[-1]
from bisect import bisect_left
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
tails = []
for x in nums:
i = bisect_left(tails, x)
if i == len(tails):
tails.append(x)
else:
tails[i] = x
return len(tails)
class Solution:
def maxProduct(self, nums: List[int]) -> int:
cur_max = cur_min = best = nums[0]
for x in nums[1:]:
a, b = cur_max * x, cur_min * x
cur_max = max(x, a, b)
cur_min = min(x, a, b)
best = max(best, cur_max)
return best
class Solution:
def canPartition(self, nums: List[int]) -> bool:
total = sum(nums)
if total % 2:
return False
target = total // 2
dp = [False] * (target + 1)
dp[0] = True
for x in nums:
for s in range(target, x - 1, -1):
dp[s] = dp[s] or dp[s - x]
return dp[target]
class Solution:
def longestValidParentheses(self, s: str) -> int:
stack = [-1]
best = 0
for i, ch in enumerate(s):
if ch == '(':
stack.append(i)
else:
stack.pop()
if not stack:
stack.append(i)
else:
best = max(best, i - stack[-1])
return best
class Solution:
def longestPalindrome(self, s: str) -> str:
best_l = best_r = 0
def expand(l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return l + 1, r - 1
for i in range(len(s)):
for l, r in (expand(i, i), expand(i, i + 1)):
if r - l > best_r - best_l:
best_l, best_r = l, r
return s[best_l:best_r + 1]
class Solution:
def majorityElement(self, nums: List[int]) -> int:
candidate = None
count = 0
for x in nums:
if count == 0:
candidate = x
count += 1 if x == candidate else -1
return candidate
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
i = len(nums) - 2
while i >= 0 and nums[i] >= nums[i + 1]:
i -= 1
if i >= 0:
j = len(nums) - 1
while nums[j] <= nums[i]:
j -= 1
nums[i], nums[j] = nums[j], nums[i]
left, right = i + 1, len(nums) - 1
while left < right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1