在数组中查找重复项

给定一个由n个整数元素组成的数组,您将如何在O(n)时间内查找该数组中是否存在重复项,而不使用任何额外的空间。

如果有额外的空间,则意味着O(n)级的额外空间。

Xor运算符是否以任何方式提供帮助。


慕码人8056858
浏览 893回答 3
3回答

繁华开满天机

就地基数排序后进行线性扫描就地基数排序算法根据您实际认为的Radix排序的时间复杂度,此解决方案为O(N)时间,尽管我个人并不这么认为。我认为,如果您不对整数排序进行线性时间假设,那么该问题将无法解决。由于排序是就地的,因此只需要O(1)额外的存储。代码全为C ++ 11步骤1:基数排序template<typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>void RecurseOnRadixSort(std::vector<T>& myArray, T mask, int zerosEnd, int onesBegin){&nbsp; &nbsp; if (zerosEnd+1 >= onesBegin-1 || mask == 0)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; int zerosEnd2 = zerosEnd;&nbsp; &nbsp; int onesBegin2 = onesBegin;&nbsp; &nbsp; while(zerosEnd2+1 <= onesBegin2-1)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // swap ones to the right&nbsp; &nbsp; &nbsp; &nbsp; if ((myArray[zerosEnd2+1] & mask) != 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::swap(myArray[zerosEnd2+1], myArray[onesBegin2-1]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --onesBegin2;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++zerosEnd2;&nbsp; &nbsp; }&nbsp; &nbsp; mask >>= 1;&nbsp; &nbsp; //recurse on lhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, zerosEnd, zerosEnd2+1);&nbsp; &nbsp; //recurse on rhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, onesBegin2-1, onesBegin);}template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>void InPlaceRadixSort(std::vector<T>& myArray){&nbsp; &nbsp; int zerosEnd = -1;&nbsp; &nbsp; int onesBegin = static_cast<int>(myArray.size());&nbsp; &nbsp; T mask = static_cast<T>(1) << sizeof(T)*8-1;&nbsp; &nbsp; while(zerosEnd+1 <= onesBegin-1)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if ( (myArray[zerosEnd+1] & mask) != 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::swap(myArray[zerosEnd+1], myArray[onesBegin-1]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --onesBegin;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++zerosEnd;&nbsp; &nbsp; }&nbsp; &nbsp; mask = static_cast<T>(1) << sizeof(T)*8-2; // need to reassign in case of signed datatype&nbsp; &nbsp; //recurse on lhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, -1, zerosEnd+1);&nbsp; &nbsp; //recurse on rhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, onesBegin-1, static_cast<int>(myArray.size()));&nbsp; &nbsp; // swap negatives to the front&nbsp; &nbsp; auto iterSmallest = std::min_element(myArray.begin(), myArray.end());&nbsp; &nbsp; if (*iterSmallest < 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; std::reverse(myArray.begin(), myArray.end());&nbsp; &nbsp; &nbsp; &nbsp; iterSmallest = std::min_element(myArray.begin(), myArray.end());&nbsp; &nbsp; &nbsp; &nbsp; std::reverse(myArray.begin(), iterSmallest+1);&nbsp; &nbsp; &nbsp; &nbsp; std::reverse(iterSmallest+1, myArray.end());&nbsp; &nbsp; }}步骤2:线性扫描重复元素for (size_t i=0, j=1; j<myArray.size(); ++i,++j){&nbsp; &nbsp; if (myArray[i] == myArray[j])&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; std::cout << "Found duplicate element " << myArray[i];&nbsp; &nbsp; }}完整的代码#include <iostream>#include <string>#include <vector>#include <iostream>#include <vector>#include <algorithm>#include <ctime>#include <type_traits>using namespace std;#define N 10template <typename T>void PrintArray(const std::vector<T>& myArray){&nbsp; &nbsp; for (auto&& element : myArray)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; std::cout << element << std::endl;&nbsp; &nbsp; }}template<typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>void RecurseOnRadixSort(std::vector<T>& myArray, T mask, int zerosEnd, int onesBegin){&nbsp; &nbsp; if (zerosEnd+1 >= onesBegin-1 || mask == 0)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; int zerosEnd2 = zerosEnd;&nbsp; &nbsp; int onesBegin2 = onesBegin;&nbsp; &nbsp; while(zerosEnd2+1 <= onesBegin2-1)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // swap ones to the right&nbsp; &nbsp; &nbsp; &nbsp; if ((myArray[zerosEnd2+1] & mask) != 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::swap(myArray[zerosEnd2+1], myArray[onesBegin2-1]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --onesBegin2;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++zerosEnd2;&nbsp; &nbsp; }&nbsp; &nbsp; mask >>= 1;&nbsp; &nbsp; //recurse on lhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, zerosEnd, zerosEnd2+1);&nbsp; &nbsp; //recurse on rhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, onesBegin2-1, onesBegin);}template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>void InPlaceRadixSort(std::vector<T>& myArray){&nbsp; &nbsp; int zerosEnd = -1;&nbsp; &nbsp; int onesBegin = static_cast<int>(myArray.size());&nbsp; &nbsp; T mask = static_cast<T>(1) << sizeof(T)*8-1;&nbsp; &nbsp; while(zerosEnd+1 <= onesBegin-1)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if ( (myArray[zerosEnd+1] & mask) != 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::swap(myArray[zerosEnd+1], myArray[onesBegin-1]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --onesBegin;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++zerosEnd;&nbsp; &nbsp; }&nbsp; &nbsp; mask = static_cast<T>(1) << sizeof(T)*8-2; // need to reassign in case of signed datatype&nbsp; &nbsp; //recurse on lhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, -1, zerosEnd+1);&nbsp; &nbsp; //recurse on rhs&nbsp; &nbsp; RecurseOnRadixSort(myArray, mask, onesBegin-1, static_cast<int>(myArray.size()));&nbsp; &nbsp; // swap negatives to the front&nbsp; &nbsp; auto iterSmallest = std::min_element(myArray.begin(), myArray.end());&nbsp; &nbsp; if (*iterSmallest < 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; std::reverse(myArray.begin(), myArray.end());&nbsp; &nbsp; &nbsp; &nbsp; iterSmallest = std::min_element(myArray.begin(), myArray.end());&nbsp; &nbsp; &nbsp; &nbsp; std::reverse(myArray.begin(), iterSmallest+1);&nbsp; &nbsp; &nbsp; &nbsp; std::reverse(iterSmallest+1, myArray.end());&nbsp; &nbsp; }}int main() {&nbsp; &nbsp; srand(time(NULL));&nbsp; &nbsp; std::vector<int> myArray(N);&nbsp; &nbsp; for (size_t i=0;i<myArray.size();++i)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; myArray[i] = rand() % 100 * (rand() % 2 == 1?-1:1);&nbsp; &nbsp; }&nbsp; &nbsp; std::cout << "Vector before radix sort: " << std::endl;&nbsp; &nbsp; PrintArray(myArray);&nbsp; &nbsp; InPlaceRadixSort(myArray);&nbsp; &nbsp; std::cout << "Vector after radix sort: " << std::endl;&nbsp; &nbsp; PrintArray(myArray);&nbsp; &nbsp; for (size_t i=0, j=1; j<myArray.size(); ++i,++j)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (myArray[i] == myArray[j])&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::cout << "Found duplicate element " << myArray[i];&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return 0;}

暮色呼如

这是O(n)时间使用情况和O(1)空间使用情况的解决方案!Traverse the array. Do following for every index i of A[].{&nbsp; &nbsp; check for sign of A[abs(A[i])] ;&nbsp; &nbsp; if positive then&nbsp; &nbsp; &nbsp; &nbsp; make it negative by&nbsp; &nbsp;A[abs(A[i])]=-A[abs(A[i])];&nbsp; &nbsp; else&nbsp; // i.e., A[abs(A[i])] is negative&nbsp; &nbsp; this&nbsp; &nbsp;element (ith element of list) is a repetition}
打开App,查看更多内容
随时随地看视频慕课网APP