You are on page 1of 18

DATA STRUCTURES AND ALGORITHMS

02
SOLVE A CHALLENGING CODE PROBLEM
MAXIMUM PAIRWISE PRODUCT

IMRAN IHSAN
ASSISTANT PROFESSOR, AIR UNIVERSITY, ISLAMABAD
WWW.IMRANIHSAN.COM

LECTURES ADAPTED FROM:


DANIEL KANE, NEIL RHODES
DEPARTMENT OF CS & ENGINEERING
UNIVERSITY OF CALIFORNIA, SAN DIEGO
PROBLEM DESCRIPTION

• Given a sequence of non-negative integers a0,…,an−1, find the maximum


pairwise product, that is, the largest integer that can be obtained by
multiplying two different elements from the sequence or, more formally,

max aiaj
0≤i≠j≤n−1

ai and aj with i≠j


(it can be the case that ai=aj).

2
INPUT / OUTPUT

• Input
• The first line of the input contains an integer n.
• The next line contains n non-negative integers a0,…,an−1
(separated by spaces).

• Constraints
2 ≤ n ≤ 2⋅105;
0 ≤ a0,…,an−1 ≤ 105.

• Output
• Output a single number — the maximum pairwise product.

3
SAMPLE 1

• Input:
1. 3
2. 1 2 3

• Output:
1. 6

• Explanation:
6=2×3

4
SAMPLE 2

• Input:
1. 10
2. 7 5 14 2 8 8 10 1 2 3

• Output:
1. 140

• Explanation:
140 = 14 × 10

5
STARTER SOLUTION
1 #include <iostream>
2 #include <vector>
3
4 using std::vector;
5 using std::cin;
6 using std::cout;
7
8 int MaxPairwiseProduct(const vector<int>& numbers) {
9 int result = 0;
10 int n = numbers.size();
11 for (int i = 0; i < n; ++i) {
12 for (int j = i + 1; j < n; ++j) {
13 if (numbers[i] * numbers[j] > result) {
14 result = numbers[i] * numbers[j];
15 }
16 }
17 }
18 return result;
19 }
20
21 int main() {
22 int n;
23 cin >> n;
24 vector<int> numbers(n);
25 for (int i = 0; i < n; ++i) {
26 cin >> numbers[i]; }
27
28 int result = MaxPairwiseProduct(numbers);
29 cout << result << "\n";
30 return 0;
31 }
32
33

6
TEST THE SYSTEM

• Input:
1. 2
2. 100000 90000

• Output:
1. 410065408

• Explanation:
Correct Output: 9000000000
Failed Case: Wrong Answer

7
FIXING AN INTEGER OVERFLOW BUG
1 #include <iostream>
2 #include <vector>
3
4 using std::vector;
5 using std::cin;
6 using std::cout;
7
8 double MaxPairwiseProduct(const vector<int>& numbers) {
9 double result = 0;
10 int n = numbers.size();
11 for (int i = 0; i < n; ++i) {
12 for (int j = i + 1; j < n; ++j) {
13 if (((double)numbers[i]) * numbers[j] > result) {
14 result = ((double)numbers[i]) * numbers[j];
15 }
16 }
17 }
18 return result;
19 }
20
21 int main() {
22 int n;
23 cin >> n;
24 vector<int> numbers(n);
25 for (int i = 0; i < n; ++i) {
26 cin >> numbers[i]; }
27
28 double result = MaxPairwiseProduct(numbers);
29 cout << result << "\n";
30 return 0;
31 }
32
33

8
TEST AGAIN

• Input:
1. 2
2. 100000 90000

• Output:
1. 9000000000

• Explanation:
Correct Answer

9
HOWEVER SYSTEM FAILS AGAIN
TIME LIMIT EXCEEDED

• Our program performs about n2 steps on a sequence of length n.


• For the maximal possible value n = 200,000 =2⋅105,
• The number of steps is about 10,000,000,000=1010.
• This is too much.
• Modern machines can perform roughly 109 basic operations per second.
• Thus, we need a faster algorithm.

• In search of an inspiration, you start to play with small examples.


• How to find the maximal pairwise product of a sequence 1,2,3,4?
• Well, of course, it suffices to multiply the two largest numbers — 3 and 4.
• And this is true in general since all numbers in our sequence are non-negative.

10
IMPLEMENTING A FASTER SOLUTION
1 double MaxPairwiseProductFast(const vector<int>& numbers) {
2 int n = numbers.size();
3 int max_index1 = -1;
4 for (int i = 0; i < n; ++i)
5 if ((max_index1 == -1) || (numbers[i] > numbers[max_index1]))
6 max_index1 = i;
7
8 int max_index2 = -1;
9 for (int j = 0; j < n; ++j)
10 if ((numbers[j] != numbers[max_index1]) &&
11 ((max_index2 == -1) || (numbers[j] > numbers[max_index2])))
12 max_index2 = j;
13
14 return ((double)(numbers[max_index1])) * numbers[max_index2];
15 }
16
17 int main() {
18 int n;
19 cin >> n;
20 vector<int> numbers(n);
21 for (int i = 0; i < n; ++i) {
22 cin >> numbers[i];
23 }
24
25 double result1 = MaxPairwiseProduct(numbers);
26 double result2 = MaxPairwiseProductFast(numbers);
27
28 cout << result1 << "\n" << result2;
29 return 0;
30 }
31
32
33

11
TESTING

• Input:
1. 3
2. 7 2 5

• Output:
1. 35
2. 35

• Explanation:
Satisfactory

12
STRESS TEST
1 while (true) {
2 int n = rand() % 10 + 2;
3 cerr << n << "\n";
4
5 vector<int> a;
6 for (int i = 0; i < n; ++i) {
7 a.push_back(rand() % 100000);
8 }
9
10 for (int i = 0; i < n; ++i) {
11 cerr << a[i] << ' ';
12 }
13 cerr << "\n";
14
15 double res1 = MaxPairwiseProduct(a);
16 double res2 = MaxPairwiseProductFast(a);
17
18 if (res1 != res2) {
19 cerr << "Wrong answer: " << res1 << ' ' << res2 << "\n";
20 break;
21 }
22 else {
23 cerr << "OK\n";
24 }
25 }
26
27
28
29
30
31
32
33

13
RUN STRESS TEST
1 ...
2 OK
3
4 3
5 67232 68874 69499
6 OK
7
8 8
9 6132 56210 45236 95361 68380 16906 80495 95298
10 OK
11
12 11
13 62180 1856 89047 36823 14251 8362 34171 93584 87362 83341 8784
14 OK
15
16 6
17 21468 16859 82178 70496 82939 44491
18 OK
19
20 11
21 68165 30342 87637 74297 2904 32873 86010 87637 66131 82858 82935
22 Wrong answer: 7680243769 7537658370
23
24
25
26
27
28
29
30
31
32
33

14
STRESS TEST – SMALL & SIMPLE INPUT
1 while (true) {
2 int n = rand() % 4 + 2;
3 cerr << n << "\n";
4
5 vector<int> a;
6 for (int i = 0; i < n; ++i) {
7 a.push_back(rand() % 10);
8 }
9
10 for (int i = 0; i < n; ++i) {
11 cerr << a[i] << ' ';
12 }
13 cerr << "\n";
14
15 double res1 = MaxPairwiseProduct(a);
16 double res2 = MaxPairwiseProductFast(a);
17
18 if (res1 != res2) {
19 cerr << "Wrong answer: " << res1 << ' ' << res2 << "\n";
20 break;
21 }
22 else {
23 cerr << "OK\n";
24 }
25 }
26
27
28
29
30
31
32
33

15
A FASTER SOLUTION
1 double MaxPairwiseProductFast(const vector<int>& numbers) {
2 int n = numbers.size();
3 int max_index1 = -1;
4 for (int i = 0; i < n; ++i)
5 if ((max_index1 == -1) || (numbers[i] > numbers[max_index1]))
6 max_index1 = i;
7
8 int max_index2 = -1;
9 for (int j = 0; j < n; ++j)
10 if ((numbers[j] != numbers[max_index1]) &&
11 ((max_index2 == -1) || (numbers[j] > numbers[max_index2])))
12 max_index2 = j;
13
14 cout << max_index1 << ‘ ‘ << max_index2 << “\n”;
15
16 return ((double)(numbers[max_index1])) * numbers[max_index2];
17 }
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

16
FINDING A SMALL AND SIMPLE TEST CASE
1 ...
2 3
3 7 3 6
4 0 2
5 OK
6
7 5
8 2 9 3 1 9
9 1 2
10 Wrong answer: 81 27
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

17
A FASTER SOLUTION – CORRECT ANSWER
1 double MaxPairwiseProductFast(const vector<int>& numbers) {
2 int n = numbers.size();
3 int max_index1 = -1;
4 for (int i = 0; i < n; ++i)
5 if ((max_index1 == -1) || (numbers[i] > numbers[max_index1]))
6 max_index1 = i;
7
8 int max_index2 = -1;
9 for (int j = 0; j < n; ++j)
10 if ((j != max_index1) && ((max_index2 == -1) || (numbers[j] > numbers[max_index2])))
11 max_index2 = j;
12
13 return ((double)(numbers[max_index1])) * numbers[max_index2];
14 }
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

18

You might also like