I think the writing is very clear, I hope there is no infringement of the author's copyright, the original address http://blog.csdn.net/hackbuteer1/article/details/6699642
To quickly find the two numbers in an array so that the sum of the two numbers equals a given value, for the sake of simplification, we assume that there must be at least one set of conforming solutions in this array.
If there are two arrays, the following:
5,6,1,4,7,9,8
Given sum= 10
1,5,6,7,8,9
Given sum= 10
Analysis and Solution
The subject is not difficult and easy to understand. But to get a high-efficiency solution, still need some thinking.
Solution One
A straightforward solution is to be exhaustive: remove two numbers from the array and calculate whether the sum of the two is a given number.
Obviously its time complexity is N (N-1)/2 i.e. O (n^2). The algorithm is simple and easy to write, but inefficient. Generally in the program design, to minimize the time and space complexity of the algorithm, so need to continue to find more efficient solution.
Solution Two
The sum of two numbers is assumed, given sums. A workaround is that each number in the array arr[i] is judged by whether Sum-arr[i] is in the arrays, so that it becomes a lookup algorithm.
The complexity of finding a number in an unordered array is O (N), for each number arr[i], it is necessary to find the corresponding sum-arr[i] in the array, it is easy to get the time complexity or O (n^2). This is not improved compared to the original method. However, if the efficiency of the search can be improved, the efficiency of the whole algorithm can be improved. How to improve the efficiency of the search?
People who have studied programming know that improving the search efficiency is usually done by sorting the array to be looked up, and then finding it by means of two-point lookup, which can shorten the original O (N) lookup time to O (log2n), so that for each arr[i], it takes O (log2n) to find the corresponding Sum-arr [i] in the absence of an array, the total time complexity is reduced to n log2n. It also takes an O (n*log2n) time to sort an array of length N, but it is enough to sort only once, so the total time complexity remains O (n*log2n). In this way, the most primitive method is improved.
Here, some readers may further think that sorting and binary search can shorten the time from O (n^2) to O (n*log2n), but there is a faster way to find it: the hash table. Because given a number, it takes only O (1) time to find whether another number is in the array based on the hash table mapping. In this case, the overall algorithm complexity can be reduced to O (n), but this method requires an additional o (n) hash table storage space. In some cases, it is also a good idea to use space to change time.
Solution Three
It is also possible to consider the problem in a different way, assuming that there is an ordered array of the sum of any two elements of this array (long as n^2). Then using the binary lookup method, only with O (2*log2n) can solve the problem. Of course it is not possible to calculate this ordered array because it requires O (n^2) time. But this thought still inspires us to direct a sequential traversal of two numbers, thus reducing the time complexity of the algorithm.
First the array is sorted, and the time complexity is (n*log2n).
Then i = 0,j = n-1, see arr[i] + arr[j] is equal to sum, and if so, the end. If it is less than sum, then i = i + 1; if it is greater than sum, j = j–1. This only needs to be traversed on a well-ordered array to get the final result, and the time complexity is O (N). Two steps add up the total time complexity O (n*log2n), the following program takes advantage of this idea, the code is as follows:
[CPP]View Plain Copy
- 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++;
- Else
- j--;
- }
- return (-1,-1);
- }
Its time complexity is O (N).
I couldn't understand it at first, so I'm sure we can find this. Don't miss out on the location. It can be understood that if the array after the sequence is 1,3,6,a,9,12,17,28,b,35,46, then I initially point to 1 position, J initially points to the position of 46, for example, the Sum=a+b,a<b,a and B in the array to a certain position. So I and J in the process of change, only consider I encountered a or J encountered B, there must be a first encounter, such as I encountered a, then J must not point to B, so then J refers to the value is larger than B, so J decreases until the B position. Similarly if J first points to B position, then I must not point to a (this is our premise), then I now refer to the value is smaller than a, so I increase, until a position.
Scaling Issues
1. What is your solution if you change the "two numbers" in this question to "three numbers" or "any number"?
Three numbers: First, the array is sorted, and then traversed from i=0 to n-1, traversing Arr[i], in the call to the function Getsumnum above (arr, sum-arr[i]).
An idea of any m number:
First, the array is sorted first, then from i=0 to n-1 element traversal, traversing arr[i], in the remaining n-1 elements called Getsumnum (Arr,sum-arr[i]), at this time for m-1 elements and Sum-arr[i]; Next, the same method , from j=0 to n-2 element traversal, traverse Arr[j], recursively call Getsumnum (Arr,sum-arr[i]-arr[j]) on arr, at this time for m-2 elements and sum-arr[i]-arr[j]; recursively, Until 2 elements are calculated and sum is-?-?-?... Until the time.
Whether it is to ask for 3 numbers is the m number, can always compare the poor lifting method less an order of N, than the first sort and then two-point find sum-arr[i] also fast.
Reference Link: http://blog.csdn.net/mimi9919/article/details/51335337
Quickly find two numbers in an array so that the sum of the two numbers equals a given value