给定1和n之间只读n + 1个整数的数组,找到一个在线性时间内使用少于O(n)空间重复的数字,并按顺序遍历流O(1)次。
Sample Input: [3 4 1 4 1]
Sample Output : 1/4(any one of these)
如果有多个可能的答案(如上面的示例中所示),请输出任何答案。
如果没有重复,则输出-1。
我尝试解决这个问题:
int Solution::repeatedNumber(const vector<int> &A) {
vector<bool> v(A.size(), true);
for (int i = 0; i < A.size(); i++) {
if (v[A[i]])
v[A[i]] = false;
else
return A[i];
}
}
这已经被接受了,但这比内存中的O(n)小?
答案 0 :(得分:3)
你想知道为什么会被接受是正确的。这个答案显然是O(n)空间复杂性。您分配了一些与n成比例增长的数据,使其成为O(n)空间。无论判断你的程序是错误的接受它。法官可能会接受你的分数,因为你使用的字节数少于A分配的字节数,但这只是猜测。
编辑:以下代码实际上并不是解决问题的方法。它是对上述问题的一个简单问题的解决方案。下面的解决方案忽略了必须只读取流的约束。经过一些研究后,似乎这个问题是一系列类似问题的非常困难的版本“给定1到n之间的数字范围,找到重复/缺失的数字”。如果只重复一个数字,并且只有O(n)时间要求,则可以使用上面的bool向量。如果只有一个数字重复,但你被限制在恒定空间,你可以实现这个solution,我们使用高斯公式来找到从1到n的整数之和,并从数组的总和中减去它。如果数组有两个缺失的数字,并且你被限制为恒定时间,你可以实现这个solution我们使用数组的和和乘积来创建一个方程组,可以用O(n)求解与O(1)空间的时间。要解决上面提出的问题,看起来必须按照monstrosity的顺序执行某些操作。
这是一个解决这个问题的解决方案:
你可以这样做:
#include<vector>
#include<iostream>
int repeating(std::vector<int>& arr)
{
for (int i = 0; i < arr.size(); i++)
{
if (arr[abs(arr[i])] >= 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else {
return abs(arr[i]);
}
}
}
int main()
{
std::vector<int> v{1,2,3,4,5,1};
std::cout<<repeating(v)<<std::endl;
std::cout<<sizeof(v)*sizeof(v[0])<<std::endl;
return 0;
}
上述程序使用输入数组本身来跟踪重复项。对于每个索引i,数组计算arr [i]。数组设置arr(arr [i])为负数。否定值是一种易于反转的操作(只需取元素的绝对值),因此它可用于标记数组的索引而不会破坏数据的完整性。如果你遇到一个索引,使得arr [abs(arr [i])]为负数,你知道你在数组之前已经看过abs(arr [i]))。这使用O(1)空间复杂度,遍历数组一次,并且可以修改以返回任何或所有重复的数字。
答案 1 :(得分:3)
std::vector<bool>
是一个bitset,所以它将使用n位。在Big-O表示法中,O(n / 8)= O(n),这意味着空间不小于O(n)。
我认为他们不会查看实际程序,而只是在某些示例运行中测量其空间消耗。因此,使用位向量可以让它相信它比O(n)更好。
但我同意你的看法。它不应被接受。
答案 2 :(得分:1)
我有一个需要O(sqrt(N))空间和O(N)时间的解决方案,并且遍历列表两次 - 假设可以在O(1)时间内计算整数平方根(对于任意时间)大N,这可能至少是O(log(N))操作。
A1
,填充为0。x
k=floor(sqrt(x))
A1[k]
A1[k]>2k+1
,k²
和(k+1)²-1
之间必须至少有一个重复。 (对于k=floor(sqrt(N))
,阈值为N-k²).
Remember
k`并打破第一次迭代A2
的布尔数组2k+1
,内容为false
。x
:
A2[x-k²]
,如果是,x
是重复的A2[x-k²]
该解决方案也适用于更大和更小的数组(不需要完全是N + 1),如果没有重复,第一次迭代将运行到最后。两个临时数组都是O(k)(如果你是迂腐的,第一个是O(k * log(k)),因为它必须存储大小为sqrt(N)的整数。)
答案 3 :(得分:0)
std::vector<bool>
与其他向量不同。
std::vector<bool>
是std::vector
类型bool
的节省空间的专业化。
这就是为什么它可能占用更少的内存的原因,因为它可能代表一个字节(如位集)表示多个布尔值。
答案 4 :(得分:-1)
它在内存中是常量(O(1)),因为你只是简单地进行比较,而不是创建一个新的数据结构来容纳任何东西或进行任何比较。
您也可以使用像unordered_set这样的哈希表,但是它会使用O(N)内存 - 但仍然是O(N)时间复杂度。
我不完全确定这是否是一个“接受”的解决方案(你发布了什么,因为这是创建一个大小的矢量(sizeofA) - 但只是根据你的需要提供解决方案。