Lintcode has most of the topics from Leetcode, but leetcode comparison card, the following Lintcode as a platform, a brief introduction of my AC several topics, and this leads to some algorithmic basis.
1) The sum of two numbers (Two-sum)
Topic ID: 56, Link: http://www.lintcode.com/zh-cn/problem/two-sum/
Title Description:
Given an array of integers, find two numbers so that they are equal to a given number of target.
The function you need to implement twoSum
needs to return the subscript for these two numbers, and the first subscript is less than the second subscript. Note that the range of subscripts here is 1 to N, not with the 0
beginning.
Note: You can assume that there is only one set of solutions.
Example: given numbers = [2, 7, 11, 15]
, target = 9
, return[1, 2],即数字2,7
Code interface:
Class Solution {public: / * * @param numbers:an array of Integer * @param target:target = numbers[index1] + NUMBERS[INDEX2] * @return: [Index1+1, Index2+1] (Index1 < INDEX2) */ vector twosum (vector &nums, int Target) { //write your code here }};
The common idea is that the two-layer for loop, any two-digit combination, will determine whether it is equal to the given target. But this is too slow and requires an O (n^2) of Time , O (1) of extra space. It can be thought that if a number a is currently selected, another number B must satisfy the criteria to satisfy the condition:b=targe-a, which is to look for the existence of B in the array.
How to quickly find out if there is a number B in the array? If the array is ordered, the binary lookup method can be used to find the time complexity of O (Logn). However, the topic is not given this condition. If an array is sorted, first O (Nlogn) is sorted, and the original subscript of the number is saved , obviously the time required for O (NLOGN) and the Space of O (n) are not the best method.
How do I quickly find an element for an array? The algorithm provides a method- hash (hash), that is, each element in an array computes its "unique" value ID (called a hash value) in a method (hash function) , stored in a new array a (commonly called a hash array). And its subscript is the "unique" value. If access A[id] exists, then this element exists, otherwise the element does not exist in the original array. Because arrays are sequential stored support for random access, it takes only O (1) time to find an element in an array, but when initializing a hash array, O (n) time and O (n) space are required . A hash array is a good way to use fast time for some specific applications, while not demanding space requirements. In order to satisfy a variety of application scenarios, but also derived from the size of the dynamic growth of the hash set (hash set), hash map (hashed map), the STL provides two classes on the hash: Unordered_set and Unordered_map, The former only stores elements, which can add additional flag information. For more details, please add your own.
Because of the structure of the hash array, the subscript of its elements has changed, so the additional storage element of the original subscript, so the problem uses UNORDERED_MAP<INT,INT>, the content is stored in < element value, the element original subscript; Detailed code:
class Solution {public:/* * @param numbers:an array of Integer * @param target:tar get = Numbers[index1] + numbers[index2] * @return: [Index1+1, Index2+1] (Index1 < INDEX2) *//* Tips:find any pair is OK not all pairs. * Using hash map to store the NUM value and index * notice:if the target is 4 and the answer expection Num 2 + 2, * Only the one num 2 are stored in hash map and also work ok! * Because must has the other NUM 2 are not in hash map! * */vector twosum (vector &nums, int target) {//write your code Herevector V (2,0);unordered_map<int,int> hash;// val+id//we can search num and insert it to hash map at same time//and current NUM must is not in hash mapfor (int i=nums . Size (); i--; Hash[nums[i]]=i) {if (Hash.find (target-nums[i]) = = Hash.end ()) continue;v[0] = 1 + i;//the index from 1 to n does 0 to n-1v [1] = 1 + hash[target-nums[i]];return v;} Return v;//no answer return {0,0}}};
It is important to note that the hash cannot store the same element because the same element has the same hash value. If the array {2,5,6} is evaluated for target=4, there is no solution, and the array {2,2,5,6},target=4 has a solution. How do I deal with this situation? It can be reversed, the initial hash is empty, and the elements that have been traversed are gradually added to the hash.
2) Three number and (3 sum)
Topic ID: 57, Link: http://www.lintcode.com/zh-cn/problem/3sum/
Title Description: Give an array of n integers, find three integers a, B, C in S, find all triples that make A + B + c = 0. In triples (A, B, c), a <= b <= c is required. The result cannot contain duplicate triples.
Example: such as S = {-1 0 1 2-1-4}, you need to return the triples set of: ( -1,0, 1),( -1,-1, 2)
The difficulty of this topic increases a lot, first becomes 3 number of the and, then asks to find all results, and cannot repeat. However, the return is only ternary, not the original subscript, if you use the hash, then three number, you need to know two number, that is, to two-layer for loop, then the time Complexity O (n^2), and the auxiliary space also O (n^2). Is there a better way to do it? In the sum of two numbers, a sort was considered, and then two points were found. Three numbers and do not return the original subscript, then the sorting + binary search can be?
The first is sorted in ascending order, then the subscript variable i,j,k is defined, because it is ternary, so three variables are needed. If the simple traversal, then is not related to order, its time complexity will reach O (n^3). Think about it: if you currently select a, B, and C three numbers, if they are smaller than the target targets, you need to replace one of them with a larger number, and vice versa. But what exactly is the number of the three digits replaced? You cannot be sure that you can only fix two variables first, and let them change the third one (replace). One approach is to fix the first two numbers i,j, then let K change in a range (binary search idea), the core code is as follows:
for (int i=0; i<n; ++i) {for (Int. j=i+1; j<n; ++j) {for (int left=j+1, right=n-1;left!=right;) {int k = (right+left)/2; int sum = a[i]+a[j]+a[k];if (sum>target) right = K;else if (sum<target) left=k;else {Insert (a[i],a[j],a[k]); }}}
Aside from some details, the time complexity of this method is still very large, which is O (N^2logn). Careful observation found that the K value is not continuous change, but on both sides of the jump. Then you can just fix one variable i and let J and K change. When the current value is less than target, j can be increased; otherwise, k decreases. The complete code is as follows:
class Solution {public:/** * @param numbers:give An array numbers of n integer * @return: Find all unique triplets in the array * which gives the sum of zero. * Each triplet in non-descending order */vector<vector > threesum (vector &a) {//write your code Herev Ector<vector > Vs;int target = 0;sort (A.begin (), A.end ()); Sort A in ascending orderfor (int i=0; i<a.size (); ++i) {if (i>0 && a[i-1]==a[i]) continue;//Skip Duplicat ionfor (int j=i+1, k=a.size ()-1; j<k;) {if (j>i+1 && a[j-1]==a[j]) {++j;continue;//Skip duplication}if (k <a.size ()-1 && a[k]==a[k+1]) {--k;continue; Skip Duplication}int sum = a[i]+a[j]+a[k];if (Sum > Target)--k;else if (sum < target) ++j;else{// Find a Tripletvector V (3,a[i]); v[1] = a[j++];v[2] = A[k--];vs.push_back (v);}}} return vs;}};
Be careful to remove duplicate results. Set up a ternary group <a,b,c> that satisfies the condition, if there are duplicate triples with the same, then the value of at least one element in A,b,c appears at least two times in the array. If the value of a is 2, which appears multiple times in the array, it must be contiguous (the array is already sorted), so you can use the method above to remove the duplicate triples. The method time complexity O (NLOGN) +o (n^2), the spatial complexity of O (1).
3) The nearest three and (3sum closest)
Topic Number: 59, Topic Link: http://www.lintcode.com/zh-cn/problem/3sum-closest/
Title Description: For an array containing n integers, find and the ternary group closest to the given integer target , returning the number of the three numbers. Simply return the nearest three and no three numbers required.
Example: S = [-1, 2, 1, -4]
and target = 1
. And the ternary group closest to 1 is-1 + 2 + 1 = 2.
Just look for three numbers and, without removing duplicates, obviously, this problem is much simpler than 2). You can use a similar approach, and update the closest three numbers in real time, and here is no longer detailed, an implementation code:
Class Solution {public: /** * @param numbers:give An array numbers of n integer * @param target:an integer * @return : Return the sum of the three integers * the sum closest target. */int threesumclosest (vector nums, int tar) {//write Your code Heresort (Nums.begin (), Nums.end ()), int ans = int_max;for (int i=0; i<nums.size (); ++i) {for (int j=i+1, k=nums. Size ()-1; j<k;) {int sum = nums[i]+nums[j]+nums[k];//update the closest Answerans = (ABS (tar-sum) <abs (Tar-ans)? sum:ans); if ( Sum > Tar)--k;else if (Sum < tar) ++j;else return sum;//sum equal to target}}return ans;};
4) Four number and (4 sum)
Topic Number: 58, Topic Link: http://www.lintcode.com/zh-cn/problem/4sum/
Title Description: Give an array of integers with n numbers, and find all four tuples (A, B, C, D) in s that make and are the target of the given integer. In four tuples (A, B, C, D), a <= b <= c <= D needs to be met, and the answer cannot contain duplicate four-tuple.
Example: For a given array of integers s=[1, 0,-1, 0,-2, 2] and target=0. The four-tuple collection that meets the requirements is:
( -1, 0, 0, 1), ( -2,-1, 1, 2), ( -2, 0, 0, 2)
Obviously, the difficulty of this problem is greatly improved. If you follow the idea of 2), the time complexity of O (n^3) is required , but the space is of constant magnitude. Try it first:
Class Solution {public:/** * @param numbers:give an array numbersbers of n integers * @param target:you need to the find four Elements that's sum of target * @return: Find all unique quadruplets in the array which gives the sum of * zero . *//* * Time O (n^3), Space O (1) * */vector<vector > foursum (vector A, int tar) {//write your code Herevector<ve ctor > Vs;sort (A.begin (), A.end ());//ascending orderfor (int i=0; i<a.size (); ++i) {if (i>0 && a[i-1]==a[ I]) continue;//duplicationfor (int j=i+1; j<a.size (); ++j) {if (j>i+1 && a[j-1]==a[j]) continue;// duplicationfor (int k=j+1, l=a.size ()-1; k<l;) {if (k>j+1 && a[k-1]==a[k]) {++k;//duplicationcontinue;} if (L<a.size ()-1 && a[l]==a[l+1]) {--l;//duplicationcontinue;} int sum = a[i]+a[j]+a[k]+a[l];if (Sum > Tar)--l;else if (Sum < tar) ++k;else {vector v (4,a[i]); V[1]=a[j], v[2]=a[k+ +], V[3]=a[l--];vs.push_back (v);}}} return vs;}};
It is clear that four subscript variables need to be defined: i,j,k,l, where the fixed i,j, let K and l a self-increment, a self-subtraction. You also need to be careful to repeat, and make sure that each four-tuple is sorted in ascending order.
If you use 1) , first combine any two elements, calculate their two number and deposit the hash, and then select the two number, a, B, and then go to the Hudson to find out if there is target-a-b. However, it is important to note that having the same and two tuples may not be unique and therefore requires an array to store all and the same two tuples, so use unordered_map<int,vector<pair<int,int> > > Twosum; As a hash map store, its type key represents a value of two and the array stores all two tuples with that value,pair<int,int> the element value for the specific two-tuple. Therefore, the time and space complexity of building the hash map is O (n^2).
Then once again define the two subscript variable i,j, when the I,j is selected, in the hash map shot may exist more than two tuples and all are target-a-b, set up with K and the same two-tuple, the overall time complexity is O (k*n^2).
How do I go about repeating? There is no good solution at the moment. Recall that the hash cannot store the same element, so we use a hash store candidate four-tuple (candidates), and for any one of the four-tuple that satisfies the body test instructions, the test is done directly to the SID to see if it exists, thereby repeating. Here is an implementation code:
Class Solution {public://hash functional for hashing the Vectorstruct hashvec{size_t operator () (const vector &v) const {string s;for (int i=0; i<v.size (); s+= "" +v[i++]); return hash () (s);}}; vector<vector> foursum (vector A, int tar) {//write your Codesort (A.begin (), A.end ());//ascending order//using hash Map to store the sum of a[i]+a[j] and index i,junordered_map<int,vector<pair<int,int> > > twosum;for (i NT I=0; I<a.size (); ++i) {if (i>0 && a[i-1]==a[i]) continue;//skip duplicationfor (int j=i+1; j<a.size (); ++j) {if (j>i+1 &am p;& A[j-1]==a[j]) continue;//Skip Duplicationtwosum[a[i]+a[j]].push_back (Make_pair (I,j));}} Unordered_set<vector,hashvec> cans; Test duplicationvector<vector > res;//resultsunordered_map<int,vector<pair<int,int> >;:: Iterator ts;vector<pair<int,int> >::iterator it;for (int i=2; i<a.size (); ++i) {for (int j=i+1; j<a.siz E (); ++J) {ts = Twosum.find (Tar-a[i]-A[J]); if (ts = = Twosum.end ()) continue; Can ' t find Sumfor (It=ts->second.begin (); It!=ts->second.end (); ++it) {if (It->second >= i) continue;//ski P Duplicationvector V (4, A[it->first]); V[1]=a[it->second], v[2]=a[i], v[3]=a[j];//Add the V to both cans and res if Cans has no vif (Cans.find (v) = = Cans.end ()) {Cans.insert (v); Res.push_back (v);}}} return res;}};
Wherestruct Hashvec is a hash-functor function . The so-called functor, whose essence is not a function, is just like a function. The function is to calculate the hash value. Because the unordered_map provided by the STL can only compute the hash value for the base data type, the hash value is the "unique" identifier of the element and is quoted because there is no hash function that can compute a unique identifier for any one element, when there are two different elements, after the hash function is computed , with the same hash value, there is a need to resolve the conflict (usually with a linear probe and a cross-linked list approach, which is not described in detail here). A good hash function that can improve the lookup speed of the hash. For any four-tuple, the STL does not have a corresponding hash function for the calculation, but the STL provides a simple hash function for the string, so you can use this to convert the four-tuple into a string to take advantage of the STL's own hash function hash<string> () perform calculations such as the above code 3~9 line.
Therefore, this method, while occupying an additional space of O (n^2), is significantly reduced in time and is O (k*n^2), so it is useful for some applications.
Note: Although hash map cans can be used to de-duplicate, it is best to make two numbers and de-duplication when generating a hash map of two and twosum, otherwise the hash map is too large to affect performance.
Note: The code involved in this article: the Sum:https://git.oschina.net/eudiwffe/lintcode/blob/master/c++/two-sum.cpp
3 Sum:https://git.oschina.net/eudiwffe/lintcode/blob/master/c++/3sum.cpp
3 Sum Closest:https://git.oschina.net/eudiwffe/lintcode/blob/master/c++/3sum-closest.cpp
4 Sum:https://git.oschina.net/eudiwffe/lintcode/blob/master/c++/4sum.cpp
[lintcode/leetcode]--two-and, three-and, four-number and