Array Part2
Two pointers
| 977 |
We can use two pointers to read the positive and negative parts of the array - one pointer
j in the positive direction, and another i in the negative direction.
Now that we are reading two increasing arrays (the squares of the elements), we can merge these arrays together using a two-pointer technique.
O(N) time and O(1) space, since better candidadates must use the taller line of l and r
therefore we can use two pointer keep moving towards each other until they meet. Always
abandon the shorter line while moving.
tail = 0;
for (int i = 0; i < nums.size(); i++)
if (i < 2 || nums[i] > nums[tail - 2]) // not included twice yet
nums[tail++] = nums[i];
return tail
Please note, we are comparing nums[i] with nums[tail - 2] not nums[i - 2]
Improved on 1, instead of brute force emuerate every pair for j, k we could first sort the array in ascending order. And let j = i + 1, and k = n - 1. and check each pair of i,j,k has closer sum. If so update the result. When we find a sum that is less than target we move j forward by 1. When we find a sum that is larger or equal to target we move k backward by 1 until j < k no longer holds, we still could get the same result as in the brute force solution. But now the time complexity is only O(N^2) and space is O(1)
Similar to 16, except we could have duplicates.
for i from 0 to n - 2
Set target = -nums[i]
triples = {nums[i], nums[j], nums[k]}
while (j < k)
sum = nums[j] + nums[k]
if (sum < target)
j++;
else if (sum > target)
k--;
else
while (j < n - 1 && triples[1] == nums[j]) j++; // go to next non triples[1] value
while (k >= 0 && triples[2] == nums[k]) k--; // go to next non triples[2] value
result.insert(triples);
while (i < n -2 && nums[i] == nums[i+1]) i++; // go to next non duplicate nums[i]
O(N^2) time and O(N^2) space, O(1) extra space.
Similar to 15 3Sum. Only difference is one more level loop. And you can do some early exit checks to make it faster. Like if first 4 elements already > target early exit. If first 1 and last three elements sum < target, continue next loop.
Please note, we are comparing nums[i] with nums[tail - 2] not nums[i - 2]
| 16 |
| 15 |
for i from 0 to n - 2
Set target = -nums[i]
triples = {nums[i], nums[j], nums[k]}
while (j < k)
sum = nums[j] + nums[k]
if (sum < target)
j++;
else if (sum > target)
k--;
else
while (j < n - 1 && triples[1] == nums[j]) j++; // go to next non triples[1] value
while (k >= 0 && triples[2] == nums[k]) k--; // go to next non triples[2] value
result.insert(triples);
while (i < n -2 && nums[i] == nums[i+1]) i++; // go to next non duplicate nums[i]
O(N^2) time and O(N^2) space, O(1) extra space.
| 18 |
O(N^3) time and O(N^3) space, O(1) extra space.
| 229 |
(1) First pass, find the two candidate majority number.
(2) Second pass, recounter that voting times
(3) Check both voting times if greater than n / 3, put in the result array
2*N time and O(1) space.
Greedy
| 55 |
int leftMostReachableIdx = n - 1;
for (int i = n - 2; i >= 0; i--)
if (i + nums[i] >= leftMostReachableIdx)
leftMostReachableIdx = i;
return leftMostReachableIdx == 0;
Prefix Sum / product
| 238 |
Initialize the result array to all 1's
Use fromBegin and fromEnd to save the prefix/postfix product until element i
Update each res[i] with res[i] * prefixProduct and res[n - 1 -i] with res[n - 1 - i] * postfixProduct in one loop.
visited[i] = true;
| 560 |
DNF (Dutch National Flag) problem
| 75 |
It’s actually Dutch national flag problem (DNF).
[, i): 0
[i, j]: 1
(k, ...]: 2
Once j goes over k, the sorting is complete
Before that, check the value of nums[j]:
(a) If nums[j] == 0, swap with nums[i] and increase both i,j
(b) If nums[j] == 1, no swap needed, just increase j
(c) If nums[j] == 2, swap with nums[k], and increase j and decrease k.
j <= k, not j < k. We need equal, otherwise 2, 0, 1 won't work. Because when j == k, it is possible
that the number is 0, we still need to swap it with 1.
[i, j]: 1
(k, ...]: 2
Once j goes over k, the sorting is complete
Before that, check the value of nums[j]:
(a) If nums[j] == 0, swap with nums[i] and increase both i,j
(b) If nums[j] == 1, no swap needed, just increase j
(c) If nums[j] == 2, swap with nums[k], and increase j and decrease k.
j <= k, not j < k. We need equal, otherwise 2, 0, 1 won't work. Because when j == k, it is possible
that the number is 0, we still need to swap it with 1.
| 75 |
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
| 922 |
while i < N and j >= 0 repeat the following stetps
find the first even number that is on a odd position, let i point to it
find the first odd number that is on a even position, let j point to it
swap these two numbers,
Priority Queue
| 621 |
The idea is to create a priority queue. First use hash map to count each chars frequency and put the frequency inside the priority queue so that the most frequent number is in front of the queue. Since each
cycle we could schedule at most n + 1 task. We
always try round robin between the most popular tasks at any time. Get a task from each category task and put it in a temp array. Then iterate the array, decrease the frequency by 1, if still >= 0, then push it back to the priority queue. If after iteration, the queue is not empty, that means the full cycle is filled or we have to insert some idle slot. if the queue is empty, then we add count to the total time.Backtracking
(1) Sort the array
(2) For every element from begin (starting from 0 to array.size() - 1, try backtracking, get combination with the current element, decrease target by current element, recursively call the backtracking helper function still with the current position to allow duplicated value. After coming back from the recursion, try without the current element.
(1) Sort the array
(2) For every element from begin (starting from 0 to array.size() - 1, try backtracking, get combination with the current element, decrease target by current element, recursively call the backtracking helper function still with the current position plus one to avoid duplicated value. After coming back from the recursion, try without the current element.
DP:
| 120 |
Base case: minVal[j] = triangle[row - 1][j] for j = 0,1, ... row - 1
Transition formula: minVal[j] = triangle[i][j] + min(minVal[j], minVal[j + 1])
the min path value will be minVal[0] finally
O(N) space and O(N^2) time
// DP O(N), greedy O(N) time and O(1) space. Base on the fact that maxProduct[i] could only be max({nums[i], maxProduct[i - 1] * nums[i], minProduct[i - 1] * nums[i]})
| 152 |
vector<vector<int> > dp(sizeA + 1, vector<int>(sizeB + 1, 0));
if A[i] == B[j]
dp[i][j] = dp[i + 1][j + 1] + 1;
dp[i][j] = dp[i + 1][j + 1] + 1;
res = max(res, dp[i][j]);
O(N) time and O(N) space DP, use an array to save the minimum price encountered so far in the second loop, calculate the max diff between prices array and the minimum price array.
A further improved version, would be do this in one loop. Use a variable to save the minPrice encountered so far and get the maximum diff between each price and the the minPrice. O(N) time and O(1) space.
A further improved version, would be do this in one loop. Use a variable to save the minPrice encountered so far and get the maximum diff between each price and the the minPrice. O(N) time and O(1) space.
| 714 |
for (int i = 0; i < prices.size(); i++)
cash = max(cash, hold + prices[i] - fee); // Max possible profit without stock at day i end
hold = max(hold, hold - prices[i]); // Max possible profit with stock at day i end
return cash
| 55 |
Can save these trial errors, do not make the same mistake again.
Must calcuate this backward from right to left.
Top-down to bottom-up conversion is done by eliminating recursion. In practice, this achieves better performance as we no longer have the method stack overhead and might even benefit from some caching. More importantly, this step opens up possibilities for future optimization. The recursion is usually eliminated by trying to reverse the order of the steps from the top-down approach.
Base case:
memo[n - 1] = GOOD;
Transition Formula:
for pos : [startPos + 1 farthestPos]
if (memo[pos] == GOOD)
memo[startPos] = GOOD;
return memo[0] == GOOD
| 53 |
Base case: dp[0] = numes[0], maxSlice = nums[0];
Transition Formula:
dp[i+1] = max(dp[i - 1] + nums[i], nums[i]);
maxSlice = max(dp[i], maxSlice); i = 1, 2, ... n - 1
| 769 |
Binary Search
| 162 |
int mid = l + (r - l) / 2;
if (nums[mid] > nums[mid + 1])
r = mid;
else
l = mid + 1;
}
return l;
Sort the array
For every pair (i,j) i=0,1, ... n - 2, j = i+1. Binary Search value x = nums[i] + nums[j] to find the first index that is greater or equal to x. all The elements between j + 1 and k - 1 i.e: (k-1) - (j+1) + 1= k -j - 1 can construct triangle.
Indexing + Binary Search, O(S) + O(W * L * log(S)), space O(S)
Map S to {char : [indices]}
"acbca" ==> pos = {
'a' : [0, 4]
'b' : [2]
'c' : [1, 3]
prev = -1
index = lower_bound(pos[c], prev)
if (index == len(pos[c])) return false
prev = pos[c][index];
Use equal_range(nums.begin(), nums.end(), target) to find the the upper and lower bounds.
If upper bound and lower bound are both NULL, then return {-1, -1}. Otherwise, return
{bounds.first - nums.begin(), bounds.second - nums.begin() - 1}
You can also implement your own version of equal_range using lower_bound and upper_bound.
Solution 1:
O(lgN) time and O(1) space, two passes
Use helper function findPivot() to binary search and find the minimum value index, which is the pivot index. ( i.e: 153 Find Minimum in Rotated Sorted Array). And then do rotated binary search (i.e. realMid = (mid + pivot) % n).
NOTE in step 2 binary search exit condition less than or equal, but in step 1, finding a pivot index, strict less than is sufficient.
Solution 2:
O(lgN) time and O(1) space, One pass
A[mid] = target, return mid,otherwise
(1) A[mid] < A[end]: A[mid+1 : end] sorted
A[mid] < target <= A[end] right half,otherwise left half
(2) A[mid] > A[end] : A[start : mid-1] sorted
A[start] <= target < A[mid] left half, otherwise right half
| 792 |
Map S to {char : [indices]}
"acbca" ==> pos = {
'a' : [0, 4]
'b' : [2]
'c' : [1, 3]
prev = -1
index = lower_bound(pos[c], prev)
if (index == len(pos[c])) return false
prev = pos[c][index];
| 34 |
If upper bound and lower bound are both NULL, then return {-1, -1}. Otherwise, return
{bounds.first - nums.begin(), bounds.second - nums.begin() - 1}
You can also implement your own version of equal_range using lower_bound and upper_bound.
| 33 |
O(lgN) time and O(1) space, two passes
Use helper function findPivot() to binary search and find the minimum value index, which is the pivot index. ( i.e: 153 Find Minimum in Rotated Sorted Array). And then do rotated binary search (i.e. realMid = (mid + pivot) % n).
NOTE in step 2 binary search exit condition less than or equal, but in step 1, finding a pivot index, strict less than is sufficient.
Solution 2:
O(lgN) time and O(1) space, One pass
A[mid] = target, return mid,otherwise
(1) A[mid] < A[end]: A[mid+1 : end] sorted
A[mid] < target <= A[end] right half,otherwise left half
(2) A[mid] > A[end] : A[start : mid-1] sorted
A[start] <= target < A[mid] left half, otherwise right half
| 81 |
Same two 33 Search in Rotated Sorted Array, solution 2. But add two more lines two skip duplicate elements. O(lgN) average time and O(1) space, worst case O(N) time (all duplicate numbers)
while (l < r && nums[l] == nums[l + 1]) l++; // skip duplicates from the left
while (r > l && nums[r] == nums[r - 1]) r--; // skip duplicates from the right
while (l < r && nums[l] == nums[l + 1]) l++; // skip duplicates from the left
while (r > l && nums[r] == nums[r - 1]) r--; // skip duplicates from the right
Backtracking
DFS + backtracking. O(2^n)
Use a DFS helper function to pass over the result array and the candidate array and the current number with starting value 1, the total target and the total split parts k.
Exit condition:
when (0 == k && 0 == target) push the candidate into the result.
when (k <= 0 || n <= 0 || cur > 9) early exit
Otherwise:
DFS try to split the target with/without current value:
without current value:
DFS(res, candidate, n, k, cur + 1);
backtracking with current value
DFS(res, candidate, n - cur, k - 1, cur +1)
In the end, return res.
Sliding window
Calculate the total sum of the first window (size k from left side to right side). And initialize the largest average value with first sum / k. Then move the window right by 1 each time and add the new value entered the window and subtract the element leaving the window. Keep doing this until the last window. Get the maximum sum / k among them.
| 219 |
| 713 |
Our loop invariant is that
left is the smallest value so that the product in the window prod = nums[left] * nums[left + 1] * ... * nums[right] is less than k.
For every right, we update
left and prod to maintain this invariant. Then, the number of intervals with subarray product less than k and with right-most coordinate right, is right - left + 1. We'll count all of these for each value of right.Hash Map/Set
| 414 |
result set size is greater or equal than 3, return the first element ( the third largest number), otherwise return the last element (rbegin()), the largest element.
| 380 |
unordered_map<int, int> mp
+
vector<int> nums
insert:
emplace_back(val)
mp[val] = nums.size() - 1
Delete:
idea: copy the last to overwrite the one to be deleted and update the map accordingly.
int last = nums.back();
mp[last] = mp[val];
nums[mp[val]] = last;
nums.pop_back();
mp.erase(val);
getRandom():
return nums[rand() % nums.size()];
next_permutation
Find the first decreasing number backward
Find the first number that is slightly larger than nums[i]
Swap nums[i] and nums[j]
reverse nums[i + 1] to end
Matrix Layer traversal
| 48 |
for layer = 0,1,2 ... n /2
int first = layer;
int last = layer + n - 1;
for i = first, first + 1, ... last
int offset = i - first;
int top = matrix[first][i];
matrix[first][i] = matrix[last - offset][first]; // left, bottom --> left, top
matrix[last - offset][first] = matrix[last][last - offset]; // right, bottom --> left, bottom
matrix[last][last - offset] = matrix[i][last]; // right, top --> right, bottom
matrix[i][last] = top; // left, top --> right, top
Here
| 59 |
| 54 |
Others
| 766 |
| 448 |
of abs(number) - 1 to negative and collect the index + 1 which has value nums[index] > 0 in the end
| 442 |
| 88 |
| 665 |
(2) Better O(N) time and O(1) space. Loop each element and find the first reverse point. i.e: nums[j] > nums[j + 1]. Try remove nums[j] and nums[j+1] from the array (pseudo remove, save the nums[j] to a temp and overwrite nums[j] with nums[j+1] first. and then later overwrite both with temp). If after remove either of them the remaining is_sorted, return true, otherwise return false.
For each time Series element in the array, if its poison duration doesn't overlap with previous one. Add the whole duration to the total poison time. If it overlaps with the previous one, add the non-overlap time duration to the total time, which is duration - overlap time = duration - (end time of last poison duration - current duration start time)
Iteratively generate the super set in a double loop. O(2^N)
like for [1,2,3]
step 1: [], [1]
step 2: [], [1], [2], [1,2]
step 3: [], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]
Brute force, O(N^2), O(1) space. For loop each element, keep calculating nums[nums[i]] and increase the count. Get the maximum of all the count value.
O(N) time and O(N) space improved on brute force. Use visited flag array to record these numbers that have visited, to avoid repeated calculation.
Similar to 62 Unique Paths. Except we need to guard the transition formula with condition:
if (!obstacleGrid[i][j])
memo[i][j] = memo[i - 1][j] + memo[i][j - 1];
Also for base cases, the first row and column is not necessarily always 1. It is zero if there is obstacle (and all the elements following zero is also zero in the first row and column)
There are 3 buckets which numbers in can be placed into:
less than L
less than or equal to R
greater than R
Bucket 1 is a subset of Bucket 2. Return the ongoing count of bucket 2 numbers minus the ongoing count of bucket 1 numbers. Completely ignore bucket 3. The ongoing count of bucket 1 and 2 is reset back to 0 when a number no longer meets the ongoing count criteria ( “less than L” for bucket 1 and “less than or equal to R” for bucket 2 ).
Keep a vector<pair<int,int>> for all calendar events, and vector<pair<int,int>> for double booked overlapping part events with start = max(start, cal.first), end = min(end, cal.second).
For checking overlapping. if s1 >= e2 || s2 >= e1 there is no overlapping, so there is conflicts when
(!(s1 >= e2 || s2 >= e1)), i.e: (s1 < e2 && s2 < e1)
The key here is how to do this in-place. You can add 2 to the current status if you know the next status is going to be live, you could still use board[i][j] & 1 to get the current status while counting. After scanning the array and updating the status. We just need one extra shift right 1 bit all elements, then we have all the latest cell status.
Sort the arry first. Then in the loop, keep a maxEnd for starting from the current group, if the next interval start is less or equal to maxEnd then it is mergeable with the current group. After find all the mergeable interval for current group, the merged interval will be Interval(intervals[first].start, maxEnd).
The answer will be all the elements in clockwise order from the first-outer layer, followed by the elements from the second-outer layer, and so on.
Simple, just loop twice the array one time reverse each row (i.e flip each row) and then loop the array again to invert each element.
| 495 |
| 667 |
if you have
if
This can be done by picking numbers interleavingly from head and tail,
n number, the maximum k can be n - 1;if
n is 9, max k is 8.This can be done by picking numbers interleavingly from head and tail,
// start from i = 1, j = n;
// i++, j--, i++, j--, i++, j--
1 2 3 4 5
9 8 7 6
out: 1 9 2 8 3 7 6 4 5
dif: 8 7 6 5 4 3 2 1
Above is a case where
When k is less than that, simply lay out the rest
order(all diff is 1). Say if k is 5:
k is exactly n - 1When k is less than that, simply lay out the rest
(i, j) in incrementalorder(all diff is 1). Say if k is 5:
i++ j-- i++ j-- i++ i++ i++ ...
out: 1 9 2 8 3 4 5 6 7
dif: 8 7 6 5 1 1 1 1
| 78 |
like for [1,2,3]
step 1: [], [1]
step 2: [], [1], [2], [1,2]
step 3: [], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]
| 565 |
O(N) time and O(N) space improved on brute force. Use visited flag array to record these numbers that have visited, to avoid repeated calculation.
| 63 |
if (!obstacleGrid[i][j])
memo[i][j] = memo[i - 1][j] + memo[i][j - 1];
Also for base cases, the first row and column is not necessarily always 1. It is zero if there is obstacle (and all the elements following zero is also zero in the first row and column)
| 795 |
less than L
less than or equal to R
greater than R
Bucket 1 is a subset of Bucket 2. Return the ongoing count of bucket 2 numbers minus the ongoing count of bucket 1 numbers. Completely ignore bucket 3. The ongoing count of bucket 1 and 2 is reset back to 0 when a number no longer meets the ongoing count criteria ( “less than L” for bucket 1 and “less than or equal to R” for bucket 2 ).
| 731 |
For checking overlapping. if s1 >= e2 || s2 >= e1 there is no overlapping, so there is conflicts when
(!(s1 >= e2 || s2 >= e1)), i.e: (s1 < e2 && s2 < e1)
| 289 |
| 56 |
The answer will be all the elements in clockwise order from the first-outer layer, followed by the elements from the second-outer layer, and so on.
| 832 |
If you want to do this in one pass. You can easily combine the two loops as well.
Loop every element in the array from i = 0 to len(arr) - 1
if arr[i] == 0, insert 0 at the index i, increase i by 1
increase 1 always unconditionally
(1) Sort the array and save the result to a new array called sortedHeight
(2) For loop each element from begin to end and check if the sorted array and the original array value match, if match skip, if not add 1 to the total result
(3) return the result after loop.
| 1089 |
if arr[i] == 0, insert 0 at the index i, increase i by 1
increase 1 always unconditionally
| 1051 |
(2) For loop each element from begin to end and check if the sorted array and the original array value match, if match skip, if not add 1 to the total result
(3) return the result after loop.
Comments
Post a Comment