Can we quickly find two numbers in an array so that the sum of these two numbers is equal to a given value? To simplify the process, we assume that there must be at least one set of compliant solutions in this array.
Assume there are two arrays as follows ,:
, 8
Given sum = 10
1, 5, 6, 7, 8, 9
Given sum = 10
Analysis and Solution
This question is not very difficult and easy to understand. However, it is still necessary to think about an efficient solution.
Solution 1
A direct solution is to extract two numbers from an array and calculate whether the sum of the two numbers is a given number.
Obviously, the time complexity is n (N-1)/2, that is, O (N ^ 2 ). This algorithm is simple and easy to write, but inefficient. Generally, in programming, we need to reduce the time and space complexity of the algorithm as much as possible, so we need to continue to look for more efficient solutions.
Solution 2
Calculates the sum of the two numbers, assuming that the given sum is sum. A work und is to determine whether sum-Arr [I] is in the array for each number in the array. In this way, it becomes a search algorithm.
The complexity of finding a number in an unordered array is O (n). For each number arr [I], the corresponding sum-Arr [I] needs to be searched, it is easy to get the time complexity O (N ^ 2 ). This is not improved compared with the original method. However, if the search efficiency can be improved, the efficiency of the entire algorithm can be improved. How can we improve the search efficiency?
Anyone who has learned programming knows that to improve search efficiency, you can sort the array to be searched first, and then use the binary search method to find the original O (n) the query time of is reduced to O (log2n), so that for each arr [I], it takes O (log2n) to find the corresponding sum-Arr [I] which is not in the array, the total time complexity is reduced to N * log2n. It also takes O (N * log2n) Time to sort arrays with N length. Fortunately, only one sorting is enough, therefore, the total time complexity is O (n * log2n ). In this way, the original method is improved.
At this point, some readers may think that sorting and then binary search can shorten the time from O (N ^ 2) to O (N * log2n ), however, there is a faster search method: hash table. Given a number, it only takes O (1) Time to find whether another number is in the Array Based on the hash table ing. In this way, the overall algorithm complexity can be reduced to O (N), but this method requires an additional increase in the O (n) hash table storage space. In some cases, changing the space for time is also a good method.
Solution 3
You can also consider the problem from another angle. Assume that an ordered array (N ^ 2 in length) has the sum of any two elements in this array ). The binary search method can solve this problem by using O (2 * log2n. Of course, it is unlikely to calculate this ordered array because it requires O (N ^ 2) time. However, this thinking still inspires us to directly traverse the sum of two numbers, thus reducing the time complexity of the algorithm.
First, sort the array. the time complexity is (N * log2n ).
Then set I = 0, j = n-1 to check whether arr [I] + arr [J] is equal to sum. If yes, it ends. If it is less than sum, I = I + 1; if it is greater than sum, j = J-1. In this way, you only need to traverse the sorted array once to get the final result. The time complexity is O (n ). The two steps add up the total time complexity O (N * log2n). The following code uses this idea:
Int getsumnum (INT [] arr, int sum), // arr is an array, sum is and {int I, j; for (I = 0, j = n-1; I <j;) {If (ARR [I] + arr [J] = sum) Return (I, j ); else if (ARR [I] + arr [J] <sum) I ++; elsej --;} return (-1,-1 );}
Its time complexity is O (n ).
At the beginning, I was unable to understand. Can I find this sum? Won't you miss the location you know. It can be understood that, if the sorted array is 1, 3, 6, A, 9, 12, 17, 28, B, 35, 46, then I initially points to the position of 1, J initially points to the position of 46, for example, sum = a + B, a <B, A, and B are obtained at a certain position in the array. Then, when I and j are changing, when I encounter a or J encounters B, there must be a first problem. For example, if I encounters, at this time, J must have not pointed to B. Therefore, J indicates that the value is greater than B, and J decreases until B. Similarly, if J points to B first, then I must not point to a (this is our premise). Then I points to a smaller value than a, so I increases, until Position.
Scaling Problems
1. If you change "two numbers" in this question to "three numbers" or "any number", what is your solution?
Three numbers: first, sort the array, and then traverse from I = 0 to n-1. When traversing arr [I], call the above function getsumnum (ARR, sum-Arr [I.
The idea of any M number:
First, sort the array, and traverse the array from I = 0 to n-1 elements. When traversing arr [I], call getsumnum (ARR, sum-Arr [I]), this is to calculate the sum of the -1 elements and sum-Arr [I]; next, the same method, from J = 0 to N-2 element traversal, recursively call getsumnum (ARR, Sum-Arr [I]-Arr [J]) on arr when traversing arr [J], in this case, Sum-Arr [I]-Arr [J] for the elements of the m-2, and recursion in turn until the sum of the two elements is sum -? -? -?... .
Whether you want to calculate three numbers or M numbers, you can always calculate an order of n less than the limit, which is faster than sorting first and then finding sum-Arr [I] in binary search.