Prelude
I hope this programming Art series will bring you one way, one way of creativity, and one way of doing it. This chapter is still the same as in Chapter 4. We hope you can have a pleasant journey by choosing simple interview questions. If you have any questions, please do not confirm them. Thank you.
Section 1: find two numbers that meet the conditions
14th questions (array ):
Question: enter an array and a number, and search for two numbers in the array so that the sum of them is exactly the number entered.
The time complexity is O (n ). If there are multiple pairs of numbers and the sum is equal to the input number, output any one.
For example, input arrays 1, 2, 4, 7, 11, 15, and numbers 15. Because 4 + 11 = 15, 4 and 11 are output.
Analysis:
Let's try to solve this problem step by step (pay attention to the difference between the sequential disorder in the elaboration ):
Directly select two numbers from the array to determine whether their sum is the input number. The complexity is O (N ^ 2 ). Obviously, we need to find more efficient solutions.
The question is equivalent to finding and judging whether sum-a [I] is also in the original sequence for each a [I, the time required for each query is O (N). In this way, the complexity of O (N ^ 2) is found. So how can we increase the speed of column search and judgment? By the way, binary search increases the search time of the original O (N) to O (logN), so that for N a [I], it takes logN time to find the corresponding sum-a [I] in the original sequence. The total time complexity has been reduced to O (N * logN ), the space complexity is O (1 ). (If ordered, binary O (N * logN) is directly used. If unordered, binary is sorted first and then binary. The complexity is also O (N * logN + N * logN) = O (N * logN), total space is O (1 )).
Is there a better way to columns? Based on the above idea 2, if a [I] is in the sequence, if a [I] + a [k] = sum, then sum-a [I] (a [k]) must also be in the sequence. For example:
Original sequence: values 1, 2, 4, 7, 11, and 15 are reduced by the input number 15:
Corresponding sequence: 14, 13, 11, 8, 4, 0
The first array starts scanning right from the leftmost end of the array with a pointer I, and the second array starts scanning left from the rightmost end of the array with a pointer j, if the number shown below is the same as that shown above, that is, a [* I] = a [* j], we can find the two numbers. As above, I, j finally finds the same number 4 and 11 in the first, and the second sequence, so the two numbers that meet the condition are 4 + 11 = 15. How can this problem be solved? The time complexity is instantly reduced to O (N), but at the same time the space of O (N) is required to store the second array (@ fei yu: to reach O (N) complexity, the first array starts scanning right from the leftmost end of the array with a pointer I, and the second array starts scanning left from the rightmost end of the array with a pointer j, first, I points to element 1, j points to element 0, who points to the small element, who first moves, because 1 (I)> 0 (j), So I does not move, j moves to the left. Then j moves to element 4 and finds that it is greater than element 1. Therefore, stop moving j and start moving I until I points to 4. At this time, the element I points to is equal to the element j points, therefore, "4" is the first number that meets the condition. Then, I is moved and j is judged until they reach the boundary ).
Of course, you can also construct a hash table. As described in the beauty of programming, given a number, you only need to use O (1) to find whether another number is in the Array Based on the hash ing) in this way, the overall algorithm can also be reduced to O (N), but there is a defect that the construction of hash increases the space of O (N, this is the same as the above idea 3. However, changing the Time of the space is still a good method with strict time requirements.
If the array is unordered, first sort (n * logn), and then use two pointers, I, j, respectively, to point to the beginning and end of the array, so that I = 0, j = n-1, then I ++, j --, successively judge a [I] + a [j]? = Sum. If a [I] + a [j]> sum at a moment, we need to reduce the value of sum. So I will not move at the moment, j --, if a [I] + a [j] <sum at a moment, you need to increase the value of sum. Therefore, when the array is unordered, the time complexity is O (n * logn + n) = O (n * logn). If the original array is ordered, no prior sorting is required, with O (n), and the space complexity is still O (1), this idea is an improvement over all the above ideas. (If ordered, scan at both ends of the two pointers at O (N). If unordered, first sort and then scan at both ends. Time O (N * logN + N) = O (N * logN), the space is always O (1 )). (Compared with idea 2 above, the time overhead after sorting is reduced from the n * logn of the previous binary to the O (N) of the scanning )).
Summary:
Whether the original sequence is ordered or unordered, there are three solutions to this problem: 1. 2. (If the sequence is unordered, 2: 2). The total time complexity is O (n * logn ), the spatial complexity is O (1); 2. Scan the X-S [I] To map to an array or construct a hash table, the time complexity is O (n ), space complexity: O (n); 3. Scanning at both ends of two pointers (if unordered, first sorted and then scanned); time complexity: ordered O (n ), unordered O (n * logn + n) = O (n * logn), the space complexity is O (1 ).
Therefore, to achieve the objective of time O (N) and space O (1), unless the original array is ordered (pointer scanning), otherwise, when the array is unordered, only sorting can be performed first, and then the pointer scanning method or binary (time n * logn, space O (1), or ing or hash (time O (n ), space O (n )). Time or space must be sacrificed at the same time.
In summary, if the array is ordered, the scanning methods at both ends of the two pointers are given priority to achieve the optimal (O (N), null (O (1) effect. Otherwise, if you want to sort data, the fastest time complexity is of course only N * logN, and the Space O (1) is nothing else.
Code:
OK. Before entering section 2, let's first implement idea 5 (assuming that the array is already ordered). The code can be written as follows (two sections of code are implemented ):
View plaincopy to clipboardprint?
// Code 1
// O (N)
Pair findSum (int * s, int n, int x)
{
// Sort (s, s + n); If the array is not ordered, sort O (N * logN) in advance)
Int * begin = s;
Int * end = s + n-1;
While (begin <end) // The two headers are forced, or the scanning methods at both ends of the two pointers are called. The classic method is O (N)
{
If (* begin + * end> x)
{
-- End;
}
Else if (* begin + * end <x)
{
++ Begin;
}
Else
{
Return Pair (* begin, * end );
}
}
Return Pair (-1,-1 );
}
// Or write the following code,
// Code 2
// Copyright @ zhedahht & yansha
// July, updated, and 2011.05.14.
Bool find_num (int data [], unsigned int length, int sum, int & first_num, int & second_num)
{
If (length <1)
Return true;
Int begin = 0;
Int end = length-1;
While (end> begin)
{
Long current_sum = data [begin] + data [end];
If (current_sum = sum)
{
First_num = data [begin];
Second_num = data [end];
Return true;
}
Else if (current_sum> sum)
End --;
Else
Begin ++;
}
Return false;
}
Extension:
1. If you want to return the two numbers at the same time, you are also required to return the position columns of the two numbers?
2. If you change the two numbers you are looking for in the question to "multiple numbers" or any number series? (See section 2 below)
3. for Binary Search: left <= right, right = middle-1; left <right, right = middle;
// The interval operated by the algorithm,