-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtwo_missing_numbers.cpp
131 lines (114 loc) · 3.8 KB
/
two_missing_numbers.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* FIND TWO MISSING NUMBERS IN A SEQUENCE
*
* This program finds two missing numbers from a sequence [1, 2, ..., n] when given n-2 numbers.
* Two modern C++ methods are implemented:
*
* 1. Simple (Brute-force) Solution using Sum and Product:
* - Computes the sum and product of the expected full sequence and the given numbers.
* - Derives the missing numbers by solving the equations:
* s = missing1 + missing2
* p = missing1 * missing2
* - Limitations: Risk of integer overflow in product calculation.
*
* 2. Optimal (Efficient) Solution using Bitwise XOR:
* - Merges the given numbers with the complete sequence.
* - Leverages XOR properties to cancel out duplicates and isolate the missing numbers.
*
* ASCII Illustration:
*
* Suppose n = 8 and the given numbers are: [1, 3, 5, 6, 4, 7]
* The full sequence is: [1, 2, 3, 4, 5, 6, 7, 8]
* Missing numbers: 2 and 8
*
* Example Input/Output:
* Input: [1, 3, 5, 6, 4, 7]
* Output: [2, 8] (order does not matter)
*/
#include <cassert>
#include <cmath>
#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
// Simple (Brute-force) Solution using Sum and Product
std::pair<int, int> findMissingNumbersMethod1(const std::vector<int>& numbers) {
std::pair<int, int> missing;
int sumGiven = 0, prodGiven = 1;
int n = static_cast<int>(numbers.size()) + 2;
int sumFull = 0, prodFull = 1;
for (int num : numbers) {
sumGiven += num;
prodGiven *= num;
}
for (int i = 1; i <= n; ++i) {
sumFull += i;
prodFull *= i;
}
int s = sumFull - sumGiven; // Sum of the two missing numbers.
int p = prodFull / prodGiven; // Product of the two missing numbers.
// Solve the quadratic: x^2 - s*x + p = 0.
missing.first = (s + static_cast<int>(sqrt(s * s - 4 * p))) / 2;
missing.second = s - missing.first;
if (missing.first > missing.second)
std::swap(missing.first, missing.second);
return missing;
}
// Helper function: Finds the position of the first set bit in num.
int findFirstSetBitPosition(int num) {
int pos = 0;
while (((num & 1) == 0) && (pos < 32)) {
num >>= 1;
++pos;
}
return pos;
}
// Helper function: Checks if the bit at position pos is set.
bool isBitSet(int num, int pos) {
return ((num >> pos) & 1) == 1;
}
// Optimal (Efficient) Solution using Bitwise XOR
std::pair<int, int> findMissingNumbersMethod2(const std::vector<int>& numbers) {
std::pair<int, int> missing;
int n = static_cast<int>(numbers.size()) + 2;
std::vector<int> combined;
combined.reserve(numbers.size() + n);
// Merge the given numbers with the complete sequence [1, 2, ..., n].
combined.insert(combined.end(), numbers.begin(), numbers.end());
for (int i = 1; i <= n; ++i) {
combined.push_back(i);
}
int xorAll = 0;
for (int num : combined) {
xorAll ^= num;
}
int pos = findFirstSetBitPosition(xorAll);
missing.first = missing.second = 0;
for (int num : combined) {
if (isBitSet(num, pos))
missing.second ^= num;
else
missing.first ^= num;
}
if (missing.first > missing.second)
std::swap(missing.first, missing.second);
return missing;
}
// Test cases for correctness
void test() {
using TestCase = std::pair<std::vector<int>, std::pair<int, int>>;
std::vector<TestCase> testCases = {
{{1, 3, 5, 6, 4, 7}, {2, 8}},
{{1}, {2, 3}},
{{3, 4}, {1, 2}},
};
for (const auto& [input, expected] : testCases) {
assert(findMissingNumbersMethod1(input) == expected);
assert(findMissingNumbersMethod2(input) == expected);
}
std::cout << "All tests passed!\n";
}
int main() {
test();
return 0;
}