Type: hash, binary search
Original question:
Given S, a set of integers, find the largest d such that a + B + c = d where a, B, c, and d are distinct elements of S.
Input
Several S, each consisting of a line containing an integer 1 <= n <= 1000 indicating the number of elements in S, followed by the elements of S, one per line. each element of S is a distinct integer between-536870912 and + 536870911 intrusive. the last line of input contains 0.
Output
For each S, a single line containing d, or a single line containing "no solution ".
Sample Input
5
2
3
5
7
12
5
2
16
64
256
1024
0
Output for Sample Input
12
No solution
General topic;
Returns an integer set S between-536870912 and 536870911, and returns the output of a + B + c = d, the largest d. Where a, B, c, and d belong to the set S, and they are different.
Analysis and Summary:
The simplest method is a three-layer for loop with the complexity O (n ^ 3), while n is 1000 at the maximum, which is bound to time out. Therefore, we need to convert a + B + c = d to d-c = a + B.
Where a + B can be obtained first, then we can use a two-layer for loop to enumerate d and c, and the complexity is changed to O (n ^ 2 ).
The key to this question is to judge whether a, B, c, and d are different numbers. Therefore, when calculating a + B's and, you can also mark a and B in the S of the set to store them with a structure question. Consider the set a + B As Sum, and then enumerate t = d-c to determine whether t is in Sum. If t is in, Judge d, whether the coordinate of c conflicts with the subscript of elements with the Sum value equal to t.
The first method is to sort Sum first and then directly perform binary search. Running time: 0.112 s, 250 MS (poj)
[Cpp]
/*
* Ultraviolet A 10125-Sumsets
* Binary Search version
* Time: 0.112 s (ultraviolet A), 250 MS (poj)
* Author: D_Double
*
*/
# Include <iostream>
# Include <cstring>
# Include <cstdio>
# Include <algorithm>
Const int MAXN = 1003;
Using namespace std;
Int S [MAXN], n, ans;
Struct Node {
Int sum;
Int a, B;
Friend bool operator <(const Node & a, const Node & B ){
Return a. sum <B. sum;
}
};
Node sum [MAXN * MAXN];
Int rear;
Bool solve (){
Node tmp;
Ans =-2147483646;
For (int I = n-1; I> = 0; -- I ){
For (int j = 0; j <n; ++ j) if (I! = J ){
Int t = S [I]-S [j];
Tmp. sum = t; tmp. a = I; tmp. B = j;
Node * p = lower_bound (sum, sum + rear, tmp );
If (p-> sum = t & S [I]> ans ){
While (p-> sum = t ){
If (p->! = I & p->! = J & p-> B! = I & p-> B! = J ){
Ans = S [I]; // because S [I] is an enumeration from large to small, once found, it must be the largest
Return true;
}
++ P;
}
}
}
}
Return false;
}
Int main (){
While (scanf ("% d", & n), n ){
For (int I = 0; I <n; ++ I) scanf ("% d", & S [I]);
Sort (S, S + n );
Rear = 0;
For (int I = 0; I <n; ++ I ){
For (int j = 0; j <n; ++ j) if (I! = J ){
Sum [rear]. sum = S [I] + S [j];
Sum [rear]. a = I, sum [rear ++]. B = j;
}
}
Sort (sum, sum + rear );
If (solve () printf ("% d \ n", ans );
Else printf ("no solution \ n ");
}
Return 0;
}
The second method is to use hash to search.
Note that the data range is-536870912 ~ 536870911, there is a negative number, so to add 536870912 to each value and convert it to a non-negative number, then the data range is changed to 0 ~ 536870912 + 536870911, and then perform hash transcoding. It is obvious that the sum of the two numbers may exceed the 32-bit int range, so long
Running time: 0.080 s, 219 MS (poj)
[Cpp]
/*
* Ultraviolet A 10125-Sumsets
* Hash version
* Time: 0.080 s (ultraviolet A), 219 MS (poj)
* Author: D_Double
*
*/
# Include <iostream>
# Include <cstring>
# Include <cstdio>
# Include <algorithm>
Const int MAXN = 1003;
Const long ADD = 536870912;
Using namespace std;
Int n, S [MAXN], ans;
Struct Node {
Long sum; // use long
Int a, B;
};
Node sum [MAXN * MAXN];
Int rear;
Const int HashSize = MAXN * MAXN;
Int head [HashSize], next [MAXN * MAXN];
Inline void init_lookup_table (){
Rear = 1;
Memset (head, 0, sizeof (head ));
}
Inline int hash (long key ){
Return (int) (key & 0x7FFFFFFF) % HashSize );
}
Inline bool try_to_insert (int s ){
Int h = hash (sum [s]. sum );
Int u = head [h];
While (u ){
U = next [u];
}
Next [s] = head [h];
Head [h] = s;
Return true;
}
Inline bool search (Node & s ){
Int h = hash (s. sum );
Int u = head [h];
While (u ){
If (sum [u]. sum = s. sum & sum [u].! = S. a & sum [u].! = S. B & sum [u]. B! = S. a & sum [u]. B! = S. B ){
Return true;
}
U = next [u];
}
Return false;
}
Bool solve (){
Node tmp;
Ans =-2147483646;
For (int I = n-1; I> = 0; -- I ){
For (int j = 0; j <n; ++ j) if (I! = J ){
Long t = S [I]-S [j] + ADD;
Tmp. sum = t; tmp. a = I; tmp. B = j;
If (search (tmp )){
Ans = S [I]; return true;
}
}
}
Return false;
}
Int main (){
While (scanf ("% d", & n), n ){
For (int I = 0; I <n; ++ I) scanf ("% d", & S [I]);
Sort (S, S + n );
Init_lookup_table ();
For (int I = 0; I <n; ++ I ){
For (int j = 0; j <n; ++ j) if (I! = J ){
Sum [rear]. sum = S [I] + ADD + S [j] + ADD;
Sum [rear]. a = I; sum [rear]. B = j;
Try_to_insert (rear );
++ Rear;
}
}
If (solve () printf ("% d \ n", ans );
Else printf ("no solution \ n ");
}
Return 0;
}
Author: shuangde800