Two to K Sum
Last updated
Last updated
Given an array of integers, return indices of the two numbers such that they add up to the target.
Assume that each input would have exactly one solution.
The most naive approach is to try all possible combinations (for i from 0 to n-1, for j from i+1 to n -1)
If two numbers add up to the target, return those two indices.
O(n^2) runtime O(1) space
We can use an in-place sorting alg to sort the array first. Preferably quick sort because although merge sort is also O(nlogn) but recursion uses system stack which is O(n) space. Arrays.sort() uses a Dual-Pivot Quicksort.
Use left/right pointers. If nums[L] + nums[R] < target, move left to the right. If nums [L] + nums[R] > target, move R to the left. while loop L < R. if they collide return null.
Since sorting is done in-place, we have O(nlogn) run time and O(1) space.
Note: Sorting is worth it when the polynomial degree is high. If you want a linear time algorithm, don't use sorting.
Note2: This solution doesn't really return what the questions is asking. It returns the actual elements instead of their indices. If we want get the indices, then we have to create a new array (O(n) space) sort it, two pointers, then find the indices in the original array.
Now we are talking about how to solve this in linear time. We will use a data structure called hash table and its awesome property - O(1) look up.
We dump the array to a hashtbl first. Then for each element check if the complement (target - nums[i]) exists in the hashtbl. If so, return {i, hashtbl.get(target - nums[i])}.
Now we finally have O(n) time but also have O(n) space because of the HashMap.
Return all pairs of indices that sum to target. The input might have duplicate elements.
We have relaxed our original assumption of only one solution. Notice: we want indices not values.
Two pointers won't work by itself because we don't know whether we should move L or R when we find an answer. Then we can try hashing. The key is how do we construct our hash structure? Same as above, values as keys and indices as a list of values.
Here is the general idea to K sum problems - reduction. We want to reduce this problem to the non-duplicate version of two sum. Now we transform the key set into a non-duplicate sorted array. Now we can safely use the two pointer method on the new array. When we find a working pair, simply do L++ and R-- because we don't have duplicates.
Consider the case nums = [1, 1, 1, 1, 1], target = 2
, we have 4+3+2+1=10 pairs. The worst case is unfortunately O(n^2) same as the brute force solution. But enumerating all the position combinations will have an average case of O(n^2). Hashing offers a much better average case runtime.
This question tests candidate's ability to write loops, understanding sorting, and taking advantage of the property of the sorted array with two pointers. Hashing is also an option. The candidate should realize the time and space trade off. Especially this case, we trade O(n) extra space to bring down runtime from O(n^2) to O(n). In short, getting value we want two pointers. Getting indices we want to use hashing.
Given an array of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
We are finding triplets of elements (not indices). There might be duplicate elements. The solution set cannot contain duplicate triplets.
Brute force will be O(n^3). Again we can have three loops to enumerate all the possible combinations. We want to reduce this to the original two sum. Sorting is worth when bringing O(n^3) to O(n^2). Two pointer method is the better approach because of its constant space.
In terms of avoiding duplicates, the brute force way is to use a HashSet. But in the spirit of constant space, we want to something else that's more elegant.
The two pointer gimme duplicate answers?! Wut just happened ʕ •ₒ• ʔ Read the question plz read the question... The solution set may not contain duplicates. Since we can sort the array, duplicate elements are adjacent to each other.
This solution gives O(n^2) time and O(1) space.
HashMap approach will require a HashSet to eliminate the duplicate triplets. It's sort of like a brute force / wasting space O(n^2) solution.
Given an array of n integers, find three integers in the array such that the sum is closest to the target.
Return the sum of the three integers. Assume exactly one solution.
The brute force approach will be enumerating all the possible combinations using three loops. Return the trisum with the least distance to the target. We can obviously do better with the two pointer approach from 3 sum. We want to minimize epsilon and keep track of the closest sum.
Approach: 1. sort nums 2. for i from 0 to n-1 3. use two pointers L and R 4. try to get closer to the target update epsilon and closestSum
And we are closer to finish. Hang in there. First ACE!
Given an array nums and a target, find all possible triplets such that nums[i] + nums[j] + nums[k] < target.
Return the number of triplets. Assume no duplicate element.
A variation from 3 sum. Simple question but can trip people up on finding all possible triplets.
Extension from two sum. They all ask getting values instead of indices. So two pointers approach for all of them.
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
The array may contain duplicate elements. The solution set must not contain duplicate quadruplets.
Reduce 4sum to 3sum to sorted 2sum.
Approach: 1. sort nums 2. for i = 0 to n-1 //skip dup 3. for j from i + 1 to n-1 // now is 3sum skip dup 4. Two pointers L/R
2/11/2017 update: Is this it O(n^3)? Can you do even better?
Split this question into two sums then check the answer
Time Complexity Avg O(n^2) Worst Case O(n^3)
Can we write a function to solve 2, 3, 4, 5, ..., K sum? Here we go ʕ; •`ᴥ•´ʔ
Given n unique integers, a number k (sum) and a target. Find all possible k integers where their sum is target.
This question is testing searching recursively. We don't have to add another layer of complexity such as input might contain duplicate elements.
We want to enumerate all possible tuples that sum to target. The brute force approach is using DFS to create a DFS tree and put all the leaves that match with the target. We have (n^k) possible tuples. So the runtime will be . But as we learned from 2, 3, 4 sum, we can bring down the runtime from to using the two pointer method with sorting. Let's investigate both approaches here.
The simplest way to understand this kind of recursive search is to visualize it as a DFS tree. And how you choose and pick which "leaf" to join your collection. This is like a follow up question for subsets.
We realized a few potential enhancements. k <= 0 can cut out the extra level. we can use a for loop instead of doubling the stack frames with another recursive call. index > A.length - 1 is already included in the for loop. if (k == 0) then check target == 0 is so elegant (but we still want target < 0 to cut down some bad paths).
Something like this. ʕ – ᴥ – ʔ
Look at 4sum and design this recursive algorithm. Say we need to solve 8sum. We don't want to write out all the for loops explicitly. We need to solve this recursively.
Thought process:
What do we need for in the recursive call?
(results, A, k, target, startIndex yes, tuple yea it's the potential solution)
startIndex is for getting the subarray
Backtracking
Only reset the tuple from the top level? nope it doesn't work that way.
you gotta do the same thing at each level. use backtracking instead
This won't pass LC.90 because the base is 2sum (the test cases include 1sum). Nonetheless, a test case [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,5235,23634], 8, 87
works fine. We don't have to write 7 loops explicitly solve this 8sum problem. And we have generalized the idea of k sum that we can solve this in with sorting and two pointers.
Given n distinct positive integers, integer k (sum) and a target. Find k numbers where sum is target.
Return the number of solutions. You don't have to return all the possible solutions only the number of them.
Well this certainly looks similar to KSum II. We can enumerate all the possible combinations then return the count. Ez-pez right?
Ok. How can we do better than ?
Not that easy to see. It turns out this is really similar to the two-dimensional knapsack problem. We'll come back and finish off then.
It is a pretty obvious dp question once we get the essence of dynamic programming. We only need to store the number of solutions instead of the actual solutions. So creating states to keep track of them should not be hard. We have target value (integer) and number of items that we can put in the knapsack (discrete). By the nature of this kind of problem, the subproblems will overlap (ex. a set of items that contribute to a specific target value).
by Sigmainfy
by Welkin Lan
by ButterCola
Let's end with some .