Leetcode Review
399. Evaluate Division
Problem Description:
You are given an array of variable pairs equations and an array of real numbers values, where equations[i] = [Ai, Bi] and values[i] represent the equation Ai / Bi = values[i]. Each Ai or Bi is a string that represents a single variable.
You are also given some queries, where queries[j] = [Cj, Dj] represents the jth query where you must find the answer for Cj / Dj = ?.
Return the answers to all queries. If a single answer cannot be determined, return -1.0.
Note: The input is always valid. You may assume that evaluating the queries will not result in division by zero and that there is no contradiction.
Note: The variables that do not occur in the list of equations are undefined, so the answer cannot be determined for them.
Example 1:
1 | Input: equations = [["a","b"],["b","c"]], values = [2.0,3.0], queries = [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]] |
Example 2:
1 | Input: equations = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]] |
Example 3:
1 | Input: equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]] |
This is a typical graph-related problem. The idea is to construct an adjacency matrix matrix, where matrix[i][j] represents the value of i / j. If there is no such value, it is set to 0.
After constructing the matrix, we can use DFS to recursively search for the relationship. For example, in Example 1, to compute a / c, we first find a / b through DFS, then continue to find b / c, and multiply them to obtain a / c.
The detailed implementation is as follows:
1 | class Solution { |
Time Complexity Analysis:
Building the map (mapping strings to matrix indices) takes
O(E), whereEis the number of equations.Constructing the adjacency matrix takes
O(E).In the worst case, the DFS method may traverse every value in the adjacency matrix. Suppose there are
ndistinct variables, so the matrix containsn^2values. The time complexity of DFS isO(n^2).When iterating through
queries, suppose there areQqueries. Each query calls DFS once, so the time complexity isO(Q * n^2).
Overall time complexity is O(E + Q * n^2).
Space Complexity Analysis:
The matrix contains
n^2entries, so the complexity isO(n^2).The map stores
nentries, so the complexity isO(n).The recursion depth of DFS may reach all nodes, so the complexity is
O(n).The set used in DFS may contain all nodes in the worst case, so the complexity is
O(n).The result array
rescontainsQentries, so the complexity isO(Q).
Overall space complexity is O(Q + n^2).
994. Rotting Oranges
Problem Description:

The idea is to first traverse the grid. If we find a rotten orange, we add it to a Queue. After the traversal is complete, we perform BFS on all rotten oranges in the queue and record the time for each BFS step, dynamically updating the maximum time. Finally, we scan the grid again. If there are still fresh oranges left, return -1; otherwise, return the maximum time.
The code is as follows:
1 | class Solution { |
Time Complexity Analysis:
- The two nested
forloops takeO(n*m), wherenandmare the number of rows and columns of the grid. - In the worst case, BFS traverses every cell once, so the time complexity is
O(n*m).
Overall time complexity: O(n*m)
Space Complexity Analysis:
- In the worst case, the queue may contain all cells, so the space complexity is
O(n*m).
Overall space complexity: O(n*m)
875. Koko Eating Bananas
Koko loves to eat bananas. There are n piles of bananas, and the ith pile has piles[i] bananas. The guards have gone and will come back in h hours.
Koko can decide her bananas-per-hour eating speed k. Each hour, she chooses one pile of bananas and eats k bananas from that pile. If the pile has fewer than k bananas, she eats all of them and will not eat any more bananas during that hour.
Koko likes to eat slowly but still wants to finish all the bananas before the guards return.
Return the minimum integer k such that she can eat all the bananas within h hours.
Example 1:
1 | Input: piles = [3,6,7,11], h = 8 |
Example 2:
1 | Input: piles = [30,11,23,4,20], h = 5 |
Example 3:
1 | Input: piles = [30,11,23,4,20], h = 6 |
We can use binary search to continuously narrow down the minimum valid eating speed until we find the smallest possible speed.
The code is as follows:
1 | class Solution { |
Since the maximum number of bananas in a single pile is 10^9, we can set the maximum possible speed to 10^9 and the minimum speed to 1. Then we apply binary search to continuously narrow the range.
It is important to note that in the check() method, the variable hours must be declared as long to avoid overflow.
Time Complexity Analysis:
- Let
nbe the length ofpiles. Each binary search step requires traversing thepilesarray once, which takesO(n). - The search range is from
1to10^9, and binary search runs inO(log 10^9)time. - Therefore, the overall time complexity is
O(n log 10^9).
Space Complexity:
O(1)
962. Maximum Width Ramp
A ramp in an integer array nums is a pair (i, j) for which i < j and nums[i] <= nums[j]. The width of such a ramp is j - i.
Given an integer array nums, return the maximum width of a ramp in nums. If there is no ramp in nums, return 0.
Example 1:
1 | Input: nums = [6,0,8,2,1,5] |
Example 2:
1 | Input: nums = [9,8,1,0,1,9,4,0,4,1] |
In simple terms, this problem asks us to find, for each element, the farthest element to its right that is greater than or equal to it, and then compute the maximum possible distance.
The specific approach is to maintain a monotonically decreasing stack while traversing from left to right. Then, traverse from right to left. If the value at the top index of the stack is less than or equal to the current element, pop it from the stack and update the maximum width. Continue this process until the stack becomes empty.
The code is as follows:
1 | class Solution { |
Time Complexity Analysis
- Maintaining the monotonic stack requires traversing each element once:
O(n). - The second traversal from right to left processes each element at most once in the worst case:
O(n).
Therefore, the overall time complexity is O(n).
Space Complexity Analysis
- In the worst case, the
stackstores all indices:O(n).
Therefore, the space complexity is O(n).
2406. Divide Intervals Into Minimum Number of Groups
You are given a 2D integer array intervals where intervals[i] = [lefti, righti] represents the inclusive interval [lefti, righti].
You have to divide the intervals into one or more groups such that each interval is in exactly one group, and no two intervals that are in the same group intersect each other.
Return the minimum number of groups you need to make.
Two intervals intersect if there is at least one common number between them. For example, the intervals [1, 5] and [5, 8] intersect.
Example 1:
1 | Input: intervals = [[5,10],[6,8],[1,5],[2,3],[1,10]] |
Example 2:
1 | Input: intervals = [[1,3],[5,6],[8,10],[11,13]] |
这道题可以用时间线和事件的思路去解决,不必拘泥于时间对,而是把每一个时间对拆开,将其视为开始时间和结束时间。
同时使用一个最小堆对时间进行排序,当存在开始时间和结束时间相同时先处理开始时间。维护一个变量记录同时存在的事件的最大数量,即为答案。
代码如下:
1 | class Solution { |
时间复杂度分析:
- 假设intervals有n个事件,那么一共有2n个时间点,插入堆的复杂度为
O(log2n),综合复杂度为O(2nlog(2n)) = O(nlogn)。
空间复杂度分析:
- 堆需要
O(2n) = O(n)的空间
632. Smallest Range Covering Elements from K Lists
You have k lists of sorted integers in non-decreasing order. Find the smallest range that includes at least one number from each of the k lists.
We define the range [a, b] is smaller than range [c, d] if b - a < d - c or a < c if b - a == d - c.
Example 1:
1 | Input: nums = [[4,10,15,24,26],[0,9,12,20],[5,18,22,30]] |
Example 2:
1 | Input: nums = [[1,2,3],[1,2,3],[1,2,3]] |
When a problem involves finding a “maximum” or “minimum”, it is often a good idea to consider using a heap, because we frequently need to retrieve the smallest or largest value efficiently. A heap allows us to get the minimum (or maximum) in O(1) time and update it in O(log k) time, which helps reduce the overall time complexity.
At each step, we put one element from each list into the heap. We remove the minimum element, dynamically maintain the current maximum value, compute the current range, and update the result if necessary. Then we push the next element from the same list as the removed element into the heap. We repeat this process until the heap size becomes smaller than k. The smallest recorded range is the final answer.
1 | class Solution { |
1 | The step-by-step process for Example 1 is as follows: |
Time Complexity Analysis
- Suppose there are
klists and a total ofNelements. - In the worst case, every element is pushed into and popped from the heap once.
- Each heap operation costs
O(log k).
Therefore, the total time complexity is O(N log k).
Space Complexity Analysis
- The heap always contains at most
kelements.
Therefore, the space complexity is O(k).
1942. The Number of the Smallest Unoccupied Chair
There is a party where n friends numbered from 0 to n - 1 are attending. There is an infinite number of chairs in this party that are numbered from 0 to infinity. When a friend arrives at the party, they sit on the unoccupied chair with the smallest number.
- For example, if chairs
0,1, and5are occupied when a friend comes, they will sit on chair number2.
When a friend leaves the party, their chair becomes unoccupied at the moment they leave. If another friend arrives at that same moment, they can sit in that chair.
You are given a 0-indexed 2D integer array times where times[i] = [arrivali, leavingi], indicating the arrival and leaving times of the ith friend respectively, and an integer targetFriend. All arrival times are distinct.
Return the chair number that the friend numbered targetFriend will sit on.
Example 1:
1 | Input: times = [[1,4],[2,3],[4,6]], targetFriend = 1 |
Example 2:
1 | Input: times = [[3,10],[1,5],[2,6]], targetFriend = 0 |
Approach
We can split each person’s time into two events: an arrival event and a leaving event.
Store them in a min-heap as arrays:arr[0]→ timearr[1]→ friend numberarr[2]→ event type (1 = arrival, 0 = leaving)
Sort primarily by time.
Use another priority queue
availableChairsto keep track of currently available chairs, so we can always obtain the smallest available chair.Use a
MapcalledoccupiedChairsto record which chair each friend is currently using.- Key → friend number
- Value → chair number
Process
Traverse all events in chronological order:
If it is an arrival event:
- Take the smallest chair from
availableChairs - If the friend is
targetFriend, return the chair immediately - Otherwise, record it in
occupiedChairs
- Take the smallest chair from
If it is a leaving event:
- Retrieve the chair from
occupiedChairs - Put the chair back into
availableChairs
- Retrieve the chair from
1 | class Solution { |
Time Complexity Analysis
- Suppose there are
nfriends. - We insert
2nevents into the heap. Each insertion costsO(log n), so this part costsO(n log n). - Adding all chairs into
availableChairscostsO(n log n). - Processing each event:
- Polling from
availableChairscostsO(log n) - Inserting into
occupiedChairscostsO(1) - Overall worst-case cost is
O(n log n)
- Polling from
Therefore, the total time complexity is:
1 | O(n log n) |
Space Complexity Analysis
eventsrequiresO(2n)availableChairsrequires up toO(n)occupiedChairsrequires up toO(n)
Therefore, the overall space complexity is:
1 | O(n) |
632. Smallest Range Covering Elements from K Lists
You have k lists of sorted integers in non-decreasing order. Find the smallest range that includes at least one number from each of the k lists.
We define the range [a, b] is smaller than range [c, d] if b - a < d - c or a < c if b - a == d - c.
Example 1:
1 | Input: nums = [[4,10,15,24,26],[0,9,12,20],[5,18,22,30]] |
Example 2:
1 | Input: nums = [[1,2,3],[1,2,3],[1,2,3]] |
Constraints:
nums.length == k1 <= k <= 35001 <= nums[i].length <= 50-10^5 <= nums[i][j] <= 10^5nums[i]is sorted in non-decreasing order.
Approach
The core of this problem is to ensure that the selected range always contains at least one element from each list.
To achieve this, we maintain a container that always holds exactly k elements (where k is the number of lists). During traversal, we must repeatedly obtain the current minimum and maximum values to determine the range, so using a min-heap is the natural choice.
Initialization:
Push the first element of each list into the heap and record the current maximum value.Traversal:
Use awhileloop. Each time:- Remove the smallest element from the heap.
- Update the current minimum.
- Compare and update the smallest range if needed.
After removing the smallest element, insert the next element from the same list (if it exists) into the heap, and update the maximum value.
When the loop ends, the recorded range is the answer.
1 | class Solution { |
Time Complexity Analysis
- Suppose there are
Ntotal elements across all lists. - In the worst case, we traverse all elements.
- Each element is pushed into and popped from the heap at most once.
- The heap size is always
k. - Insertion and heap maintenance cost
O(log k).
Therefore, the total time complexity is:
1 | O(N log k) |
Space Complexity Analysis
- The heap contains at most
kelements.
Therefore, the space complexity is:
1 | O(k) |
2406. Divide Intervals Into Minimum Number of Groups
You are given a 2D integer array intervals where intervals[i] = [lefti, righti] represents the inclusive interval [lefti, righti].
You have to divide the intervals into one or more groups such that each interval is in exactly one group, and no two intervals that are in the same group intersect each other.
Return the minimum number of groups you need to make.
Two intervals intersect if there is at least one common number between them. For example, the intervals [1, 5] and [5, 8] intersect.
Example 1:
1 | Input: intervals = [[5,10],[6,8],[1,5],[2,3],[1,10]] |
Example 2:
1 | Input: intervals = [[1,3],[5,6],[8,10],[11,13]] |
Constraints:
1 <= intervals.length <= 10^5intervals[i].length == 21 <= lefti <= righti <= 10^6
Approach
We can visualize a timeline and draw each interval as a segment on it.
The time point with the maximum number of overlapping intervals corresponds to the minimum number of groups required.
- Split each interval into a start event and an end event, and push them into a min-heap.
- Traverse all events in chronological order.
- While traversing, maintain the number of currently active intervals.
- The maximum number of simultaneously active intervals is the answer.
1 | class Solution { |
Time Complexity Analysis
- Suppose there are
Nintervals. - We insert
2Nelements into the heap and remove2Nelements. - Each heap operation costs
O(log(2N)).
Therefore, the total time complexity is:
1 | O(N log N) |
Space Complexity Analysis
- The heap contains at most
2Nelements.
Therefore, the space complexity is:
1 | O(N) |
962. Maximum Width Ramp
A ramp in an integer array nums is a pair (i, j) such that i < j and nums[i] <= nums[j]. The width of the ramp is j - i.
Given an integer array nums, return the maximum width of a ramp in nums. If there is no ramp in nums, return 0.
Example 1
1 | Input: nums = [6,0,8,2,1,5] |
Example 2
1 | Input: nums = [9,8,1,0,1,9,4,0,4,1] |
Constraints
2 <= nums.length <= 5 * 10^40 <= nums[i] <= 5 * 10^4
Method 1: Sorting
Idea
Bind each element with its index, then sort them in ascending order by value.
After sorting:
- If
nums[i] <= nums[j], then(nums[i], i)must appear before(nums[j], j)in the sorted array. - While traversing the sorted array, maintain the smallest index seen so far (
minIndex). - For each element:
- Update the maximum width using
index - minIndex. - Update
minIndex.
- Update the maximum width using
1 | class Solution { |
Time Complexity Analysis
- Sorting takes
O(N log N). - One traversal takes
O(N).
Overall time complexity:
1 | O(N log N) |
Method 2: Monotonic Stack (More Efficient)
Idea
Use a monotonic decreasing stack to store candidate left indices.
First Pass (Left to Right)
- If the current element is smaller than the element at the top of the stack, push its index.
- This ensures the stack maintains strictly decreasing values.
- If there are duplicate values, only the leftmost index is kept.
Second Pass (Right to Left)
- If
nums[i] >= nums[stack.peek()]:- A valid ramp is found.
- Update the maximum width.
- Pop the stack.
- Continue until the stack is empty or the condition no longer holds.
The stack effectively behaves like a reversed sorted “set” of candidate left endpoints, ensuring we always try the leftmost valid index to maximize width.
1 | class Solution { |
Time Complexity Analysis
- Building the monotonic stack:
O(N) - Reverse traversal:
O(N) - Each index is pushed and popped at most once.
Overall time complexity:
1 | O(N) |
3152. Special Array II
An array is considered special if every pair of adjacent elements contains two numbers with different parity.
You are given an integer array nums and a 2D integer matrix queries, where queries[i] = [fromi, toi].
Your task is to determine whether the subarray nums[fromi..toi] is special.
Return a boolean array answer such that answer[i] is true if nums[fromi..toi] is special.
Example 1
Input:
nums = [3,4,1,2,6], queries = [[0,4]]
Output:
[false]
Explanation:
The subarray is [3,4,1,2,6].
2 and 6 are both even, so it is not special.
Example 2
Input:
nums = [4,3,1,6], queries = [[0,2],[2,3]]
Output:
[false,true]
Explanation:
- The subarray
[4,3,1]: 3 and 1 are both odd → not special. - The subarray
[1,6]: the pair (1,6) has different parity → special.
Constraints
1 <= nums.length <= 10^51 <= nums[i] <= 10^51 <= queries.length <= 10^5queries[i].length == 20 <= queries[i][0] <= queries[i][1] <= nums.length - 1
Method 1: Binary Search on Invalid Adjacent Pairs
Idea
- Traverse the array once.
- If two adjacent elements have the same parity, store the smaller index
iin a list. - For each query
[left, right]:- We need to check whether there exists an index
iin the range[left, right - 1] - Use binary search to check if such an index exists in the list.
- If found → the subarray is NOT special.
- Otherwise → it is special.
- We need to check whether there exists an index
1 | class Solution { |
Time Complexity
- Traverse array:
O(N) - Binary search for each query:
O(Q log N)
Overall:
1 | O(N + Q log N) |
Space Complexity
- Store invalid adjacent indices:
O(N)
Method 2: Prefix Sum (More Efficient)
Idea
Instead of binary search, we can preprocess prefix sums.
Define:
prefixSum[i]= number of adjacent same-parity pairs in range[0, i]
If two adjacent elements have the same parity:
1 | prefixSum[i] = prefixSum[i - 1] + 1 |
Otherwise:
1 | prefixSum[i] = prefixSum[i - 1] |
For a query [from, to]:
- If
prefixSum[to] - prefixSum[from] == 0
→ no same-parity adjacent pair exists
→ subarray is special.
1 | class Solution { |
Time Complexity
- Build prefix sum:
O(N) - Process queries:
O(Q)
Overall:
1 | O(N + Q) |
Space Complexity
1 | O(N) |
Summary
| Method | Time Complexity | Space Complexity | Recommended |
|---|---|---|---|
| Binary Search | O(N + Q log N) | O(N) | ⭐⭐ |
| Prefix Sum | O(N + Q) | O(N) | ⭐⭐⭐⭐ |
The prefix sum solution is cleaner and optimal for large inputs.
2779. Maximum Beauty of an Array After Applying Operation
You are given a 0-indexed array nums and a non-negative integer k.
In one operation, you can:
- Choose an index
ithat has not been chosen before. - Replace
nums[i]with any integer in the range[nums[i] - k, nums[i] + k].
The beauty of the array is defined as the length of the longest subsequence consisting of equal elements.
Return the maximum possible beauty of the array after applying the operation any number of times.
Each index can be chosen at most once.
A subsequence is formed by deleting some elements (possibly none) without changing the order of the remaining elements.
Example 1
1 | Input: nums = [4,6,1,2], k = 2 |
Example 2
1 | Input: nums = [1,1,1,1], k = 10 |
Constraints
1 <= nums.length <= 10^50 <= nums[i], k <= 10^5
Key Insight
Each number nums[i] can be transformed into any value in the interval:
1 | [nums[i] - k, nums[i] + k] |
So the problem becomes:
Find the maximum number of intervals that overlap at some point.
This is essentially an interval overlap problem.
Although the problem mentions subsequences, the actual goal is to find the largest group of numbers whose intervals intersect at some common value.
Approach: Sorting + Binary Search
Idea
- Sort the array.
- Fix a left index
i. - Use binary search to find the furthest index
midsuch that:
1 | nums[mid] - k <= nums[i] + k |
This ensures that the intervals overlap.
- Update the maximum length.
1 | class Solution { |
Time Complexity
- Sorting:
O(N log N) - Outer loop:
O(N) - Binary search inside:
O(log N)
Overall:
1 | O(N log N) |
Space Complexity
1 | O(1) |
(ignoring sorting’s internal stack space)
Intuition Summary
Even though the problem mentions subsequences, the core idea is:
- Each element defines a transformable interval.
- We want the maximum number of intervals that overlap.
- Sorting enables efficient binary search to compute overlap size.
This is fundamentally an interval overlap maximization problem.
2981. Find Longest Special Substring That Occurs Thrice I
You are given a string s consisting of lowercase English letters.
A string is called special if it contains only a single repeated character.
For example:
"abc"is NOT special"ddd","zz", and"f"are special
Return the length of the longest special substring that occurs at least three times, or -1 if no such substring exists.
A substring is a contiguous non-empty sequence of characters.
Example 1
1 | Input: s = "aaaa" |
Example 2
1 | Input: s = "abcdef" |
Example 3
1 | Input: s = "abcaba" |
Constraints
3 <= s.length <= 50sconsists only of lowercase English letters.
Key Idea
A brute-force approach would try all substrings of all possible lengths for each character — but that would be inefficient.
Instead, observe:
For each character, we only need to track:
- The longest consecutive segment
- The second longest consecutive segment
- Their counts
For a character:
Let:
longestcountLongestsecondLongestcountSecondLongest
Then:
If
countLongest >= 3
→ answer can belongestIf
countLongest == 2
→ answer can belongest - 1If
countLongest == 1:- If
secondLongest == longest - 1
→ answer can belongest - 1 - Otherwise
→ answer can belongest - 2
- If
Additionally, if total occurrences across segments ≥ 3, length 1 is always possible.
Implementation
1 | class Solution { |
Time Complexity
- Traverse string:
O(N) - Update operation:
O(1) - Traverse 26 letters:
O(1)
Overall:
1 | O(N) |
Space Complexity
1 | O(1) |
(Only 26 × 4 fixed-size storage)
Final Insight
The trick is recognizing that:
- Only the top two segment lengths per character matter.
- We don’t need to examine all substrings.
- Careful case analysis reduces the problem to simple arithmetic comparisons.
This makes the solution linear and efficient.
3381. Maximum Subarray Sum With Length Divisible by K
You are given an integer array nums and an integer k.
Return the maximum sum of a subarray whose length is divisible by k.
Example 1
Input:
nums = [1,2], k = 1
Output:
3
Explanation:
The subarray [1, 2] has length 2, which is divisible by 1.
Example 2
Input:
nums = [-1,-2,-3,-4,-5], k = 4
Output:
-10
Explanation:
The subarray [-1, -2, -3, -4] has length 4, which is divisible by 4.
Example 3
Input:
nums = [-5,1,2,-3,4], k = 2
Output:
4
Explanation:
The subarray [1, 2, -3, 4] has length 4, which is divisible by 2.
Constraints
1 <= k <= nums.length <= 2 * 10^5-10^9 <= nums[i] <= 10^9
Key Idea
If k = 1, the problem reduces to the classic maximum subarray sum, which can be solved using Kadane’s algorithm in O(N) time.
If k > 1, observe:
A valid subarray must have length:
1 | k, 2k, 3k, ... |
For each possible starting remainder i in [0, k - 1], we can:
Group elements into blocks of size
k:1
[i, i+k), [i+k, i+2k), ...
Treat each block sum as a single element.
Then apply Kadane’s algorithm on that transformed array.
This converts the problem into multiple standard maximum subarray problems.
Implementation
1 | class Solution { |
Time Complexity
- Prefix sum computation:
O(N) - Outer loop:
O(K) - Inner grouping:
O(N / K) - Kadane per group:
O(N / K)
Total:
1 | O(K × (N/K + N/K)) = O(N) |
Space Complexity
- Prefix array:
O(N) - Temporary block array: up to
O(N/K)
Overall:
1 | O(N) |
Final Insight
This problem cleverly reduces a “length divisible by k” constraint into grouping elements into blocks of size k, allowing reuse of Kadane’s algorithm.
The key realization is:
Any valid subarray can be decomposed into consecutive full blocks of size
k.
Once that’s recognized, the problem becomes linear-time solvable.
3376. Minimum Time to Break Locks I
Bob needs to break n locks, each requiring a certain amount of energy given by the array strength, where strength[i] represents the energy needed to break the i-th lock.
The rules are:
- The sword’s initial energy is
0. - The initial growth factor
X = 1. - Every minute, the sword’s energy increases by the current factor
X. - To break the
i-th lock, the energy must be at leaststrength[i]. - After breaking a lock:
- The energy resets to
0. - The factor increases by
K(i.e.,X += K).
- The energy resets to
Your task is to compute the minimum time (in minutes) required to break all locks.
Approach
Since n ≤ 8, we can use backtracking (DFS) to try all possible orders of breaking the locks.
At each step:
Choose an unvisited lock.
Compute the time needed to accumulate enough energy:
1
2time = ceil(strength[i] / X)
= (strength[i] + X - 1) / XRecurse with:
- Updated factor
X + K - Increased total time
- Marked lock as visited
- Updated factor
Keep track of the minimum total time across all permutations.
Code
1 | class Solution { |
Time Complexity
Since we try all possible orders of breaking the locks:
1 | O(N!) |
Given that N ≤ 8, this is acceptable.
Space Complexity
- Recursion stack depth:
O(N) - Visited array:
O(N)
Overall:
1 | O(N) |
2762. Continuous Subarrays
You are given a 0-indexed integer array nums. A subarray of nums is called continuous if:
For indices i to j in the subarray, for every pair i ≤ i1, i2 ≤ j:
1 | 0 ≤ |nums[i1] - nums[i2]| ≤ 2 |
Return the total number of continuous subarrays.
A subarray is a contiguous non-empty sequence of elements within an array.
Key Insight
For a subarray to be valid:
1 | max(subarray) - min(subarray) ≤ 2 |
So this becomes a classic sliding window problem where we must maintain:
- The maximum value in the window
- The minimum value in the window
Whenever:
1 | max - min > 2 |
we shrink the window from the left.
To efficiently maintain max and min, we can use:
- Two heaps (min heap + max heap) →
O(N log N) - Two monotonic deques →
O(N)(optimal)
Heap Version
1 | class Solution { |
Time Complexity
- Each element enters and leaves the heap at most once
- Heap operations cost
O(log N)
1 | O(N log N) |
Space Complexity
1 | O(N) |
Monotonic Deque Version (Optimal)
1 | class Solution { |
Time Complexity
Each element:
- Enters deque once
- Leaves deque once
1 | O(N) |
Space Complexity
1 | O(N) |
Final Takeaway
This is a standard sliding window problem with a bounded range constraint:
1 | max - min ≤ 2 |
Maintaining both the maximum and minimum dynamically is the key.
Using two monotonic deques reduces the complexity from O(N log N) to O(N).
1734. Decode XORed Permutation
There is an integer array perm that is a permutation of the first n positive integers, where n is always odd.
It was encoded into another array encoded of length n - 1, such that:
1 | encoded[i] = perm[i] XOR perm[i + 1] |
Given encoded, return the original array perm.
It is guaranteed that the answer exists and is unique.
Key Insight
Since:
1 | encoded[i] = perm[i] XOR perm[i+1] |
If we know any one value in perm, we can recover the entire permutation using XOR.
The idea is to compute perm[0].
Derivation
Because perm is a permutation of [1, 2, ..., n]:
1 | perm[0] ^ perm[1] ^ ... ^ perm[n-1] = 1 ^ 2 ^ ... ^ n |
Let:
1 | total = 1 ^ 2 ^ ... ^ n |
Now observe:
1 | encoded[1] = perm[1] ^ perm[2] |
If we XOR all encoded elements at odd indices:
1 | encoded[1] ^ encoded[3] ^ ... ^ encoded[n-2] |
We get:
1 | perm[1] ^ perm[2] ^ |
Since n is odd, this covers:
1 | perm[1] ^ perm[2] ^ ... ^ perm[n-1] |
Call this value partial.
Then:
1 | perm[0] = total ^ partial |
Once perm[0] is known, the rest can be reconstructed using:
1 | perm[i] = perm[i-1] ^ encoded[i-1] |
Code
1 | class Solution { |
Time Complexity
1 | O(n) |
- One pass to compute total XOR
- One pass over half of
encoded - One pass to reconstruct the permutation
Space Complexity
1 | O(1) |
Only constant extra variables are used (excluding output array).
Final Insight
The key trick is using the property that:
1 | a ^ a = 0 |
and leveraging the fact that n is odd, which guarantees we can isolate perm[0].
Once the first element is determined, the entire permutation follows naturally.
1930. Unique Length-3 Palindromic Subsequences
Given a string s, return the number of unique palindromes of length 3 that are a subsequence of s.
A palindrome reads the same forward and backward.
A subsequence is formed by deleting some (possibly zero) characters without changing the relative order.
Key Idea
Since the required palindrome length is 3, its structure must be:
1 | a b a |
So for every character a, we:
- Find its first occurrence
- Find its last occurrence
- Count how many distinct characters appear between them
Each distinct middle character b forms a unique palindrome:
1 | a b a |
The main challenge is avoiding duplicates.
Approach
We use:
first[26]to record the first occurrence of each character- A prefix frequency array
map[i][26]:map[i][c]stores how many times charactercappears ins[0..i]
- A boolean matrix
exists[26][26]to prevent duplicate counting
When processing index i as a potential right boundary:
- Let
curbe the character - Check if the distance from its first occurrence is at least 2
- For every character
k:- If it appears between
first[cur]andi - And hasn’t been counted before
- Then increment result
- If it appears between
Code
1 | class Solution { |
Time Complexity
1 | O(n) |
- One pass to build prefix frequency
- One pass to count valid palindromes
- Inner loop runs over 26 characters (constant)
Space Complexity
1 | O(n) |
- Prefix frequency array requires
O(n * 26) - Auxiliary arrays are constant size
Core Insight
Because the palindrome length is fixed at 3, we reduce the problem to:
For each character
a, count distinct characters between its first and last occurrence.
The constraint of lowercase English letters (26 characters) makes this efficient and manageable.
2381. Shifting Letters II
You are given a string s and a list of shift operations shifts, where:
1 | shifts[i] = [start, end, direction] |
- If
direction == 1, shift characters in[start, end]forward - If
direction == 0, shift characters in[start, end]backward
Shifting forward:
1 | 'z' → 'a' |
Shifting backward:
1 | 'a' → 'z' |
Return the final string after applying all shifts.
Key Idea
If we simulate each shift directly, the worst-case time complexity becomes:
1 | O(n * m) |
where n is the string length and m is the number of shifts — this will TLE.
Instead, we use a difference array (prefix sum technique).
Why it works
For each shift operation:
- If forward (
direction == 1):1
2diff[start] += 1
diff[end + 1] -= 1 - If backward (
direction == 0):1
2diff[start] -= 1
diff[end + 1] += 1
After processing all operations, we compute the prefix sum of diff.
Then diff[i] tells us how many times index i should be shifted.
Finally, apply the shift with modulo 26.
Code
1 | class Solution { |
Time Complexity
1 | O(n + m) |
- Process all shift operations
- One prefix sum pass
- One pass to build result
Space Complexity
1 | O(n) |
- Difference array of size
n + 1
Core Insight
This is a classic range update problem.
Instead of applying each shift directly, we:
- Convert range updates into point updates using a difference array
- Use prefix sum to recover final shifts
- Apply modulo arithmetic for circular alphabet shifts
This reduces the problem to linear time.
983. Minimum Cost For Tickets
You are given a list of travel days days and ticket costs:
- 1-day pass →
costs[0] - 7-day pass →
costs[1] - 30-day pass →
costs[2]
Each pass covers consecutive days starting from the purchase day.
Return the minimum total cost to cover all travel days.
Key Idea — Dynamic Programming
This is a classic DP problem.
Let:
1 | dp[d] = minimum cost to cover travel starting from day d |
We compute it backwards from the last travel day.
For a travel day d, we have three choices:
1 | dp[d] = min( |
If a day is not a travel day, its cost equals the next day’s cost.
To simplify indexing beyond the last day, we extend the DP array by 30 extra days.
Code
1 | class Solution { |
Time Complexity
1 | O(n) |
Each travel day is processed once, and non-travel days are filled in once.
Space Complexity
1 | O(365) |
The DP array size is bounded by the maximum possible day (≤ 365 + 30).
Core Insight
At every travel day, we decide:
Should we buy a 1-day, 7-day, or 30-day pass?
Since each decision only depends on future days, backward DP works naturally.
This is essentially a minimum cost coverage problem with fixed interval options.









