我在面试中被问到了这个问题。在一百万个数字中,除了一个数字以外,其他所有数字都有一个重复的数字。如何找到那个唯一的数字?使用哪种算法可以获得良好的时间和空间复杂度?我想到了使用异或门的方法,但我仍然不知道如何实现。
我在面试中被问到了这个问题。在一百万个数字中,除了一个数字以外,其他所有数字都有一个重复的数字。如何找到那个唯一的数字?使用哪种算法可以获得良好的时间和空间复杂度?我想到了使用异或门的方法,但我仍然不知道如何实现。
2 ^ 3
是 1
。 - 0xF1试试这个
int[] a = {1, 2, 1, 2, 3};
Arrays.sort(a);
for(int i = 0; i < a.length; i++) {
if (i == 0 && a[i] != a[i + 1] || i == a.length -1 || a[i] != a[i - 1] && a[i] != a[i + 1]) {
System.out.println(a[i]);
break;
}
}
另一个简单的解决方案:可以使用两个位集(bitsets),一个用于标记数字的存在,另一个用于标记重复。我们遍历数组并标记每个元素的存在和重复。然后我们遍历位集以找到一个被标记为存在但未标记为重复的数字。
int[] numbers = new int[] { 1, 1, 2, 2, 3, 4, 4, 5, 5 };
BitSet bs1 = new BitSet();
BitSet bs2 = new BitSet();
int largestNumber = 0;
for (int i = 0; i < numbers.length; i++) {
int number = numbers[i];
if (bs1.get(number) == false) {
// Mark for existence
bs1.set(number);
} else {
// Mark for duplicating
bs2.set(number);
}
if (number > largestNumber) {
largestNumber = number;
}
}
for (int i = 0; i <= largestNumber; i++) {
if (bs1.get(i) && !bs2.get(i)) {
System.out.println("Non duplicating number is: " + i);
}
}
}
O(N)
// Assuming the duplicate are going by pair
// x ^x == 0 and x ^0 == x
int find_unique(const std::vector<int>& v)
{
assert(v.size() % 2 == 1);
int res = 0;
for (auto value : v) {
res ^= value;
}
return res;
}
O(N log N)
int find_unique(std::vector<int>& v)
{
if (v.empty()) { throw std::runtime_error("empty vector"); }
std::sort(v.begin(), v.end());
auto it = std::unique(v.begin(), v.end());
if (it == v.begin()) { throw std::runtime_error("no unique number"); }
if (it != v.begin() + 1) { throw std::runtime_error("several unique numbers"); }
return v[0];
}
int find_unique(std::vector<int>& v)
{
if (v.empty()) { throw std::runtime_error("empty vector"); }
if (v.size() == 1) { return v[0]; }
std::sort(v.begin(), v.end());
if (v[0] != v[1]) { return v[0]; }
for (int i = 1, size = v.size(); i + 1 < size; ++i) {
if (v[i] == v[i - 1]) { continue; }
if (v[i] == v[i + 1]) { ++i; continue; } // we may skip v[i + 1]
return v[i];
}
return v.back();
}
int getSingleNumber(){
map<int, int> numbers;
for (all input items)
{
numbers[currentInputItem]++;
}
for( map<int,int>::iterator ii=numbers.begin(); ii!=numbers.end(); ++ii)
{
if ( (*ii).second == 1 ) return (*ii).first;
}
}
我相信如果我们将快速排序(搜索)技术和异或运算结合起来,我们可以得到最快的代码。虽然我正在尝试,但同时请纠正我这个想法是否错误。
顺便说一下,这有很多用例。虽然问题与语言无关,需要清晰的算法,但我提到了一些读者可能会发现有用的用例。
0可能是重复的...或负数...
System.out.println(33 ^ 33 ^ 7 ^ 0 ^ 0 ^ 5 ^ 7 ^ 5);
返回0(这里是一个重复项)
重复项可能超过2个:
System.out.println(1 ^ 1 ^ 2 ^ 3 ^ 3 ^ 3);
返回1,而不是2...
等等,这个问题可能比我们最初想象的要复杂。