我试图写来自用户的接收与大小“N”的阵列的功能,具有值0之间---> N-1的函数应该返回“1”,如果所有的值之间0 --- - > N-1是否有否则返回0的我们可以假定数字该用户将输入仅有效的值。在0 ----> N-1之间。
示例:N = 5,值:2,1,4,0,3 ---->返回1, N = 5,值:2,3,4,0,3 ---->返回0
我尝试了各种方法来解决此问题。
想过一个因子,但发现有很多方法可以让使用重复的号码和唯一编号相同的阶乘。也考虑过对数字求和,但是仍然有太多方法可以得到相同的答案。有什么办法可以确保我只有唯一的项目而没有子数组?
我们不能使用子数组(另一个计数器数组等),并且该功能应运行O(n)。
答案 0 :(得分:4)
如果允许您修改输入数组,则可以在O(N)中解决该问题。
观察:
如果对数组进行排序,则问题将不复存在。
对值也为0 ... N-1的数组0 ... N-1进行排序也很简单,由于每个元素的位置都是其值,因此可以迭代一次,将元素交换到其最终位置
在交换期间仅需要额外检查一下,位置 i 上的元素尚未具有值 i ,这意味着 i 在数组中出现两次。
int check(unsigned* a, unsigned size) {
for (unsigned i = 0; i < size; ++i) {
unsigned b = a[i];
if (b != i) {
do {
if (b < 0 || b >= size)
return false; // value out of range
unsigned c = a[b];
if (b == c)
return false; // duplicate value
a[b] = b;
b = c;
} while (b != i);
a[i] = i;
}
}
return true;
}
请注意,内部循环使解决方案看起来为O(N 2 ),但事实并非如此-每个元素最多访问两次。需要内部循环来解决循环,如{1,2,3,0}
一样。
答案 1 :(得分:3)
这是我的版本。它在O(n)中运行。
这个想法是要操纵原始数组并向其添加N以便标记已遇到的所有值。然后我们进行一次扫描,检查所有值均大于或等于N,然后将其更改回原始值。
唯一的警告是数组必须是可变的。
#include <stdio.h>
int check(unsigned* a, size_t size) {
for (size_t i = 0; i < size; ++i) {
if (a[i] >= size) {
return 0;
}
}
for (size_t i = 0; i < size; ++i) {
size_t const x = a[i] % size;
a[x] = x + size;
}
int result = 1;
for (size_t i = 0; i < size; ++i) {
if (a[i] < size) {
result = 0;
} else {
a[i] = a[i] - size;
}
}
return result;
}
int main() {
unsigned a1[] = {0,5,1,3,2,4};
unsigned a2[] = {0,5,1,3,0,0};
printf("a1: %d\n",check(a1,sizeof(a1)/sizeof(*a1)));
printf("a2: %d\n",check(a2,sizeof(a2)/sizeof(*a2)));
}
答案 2 :(得分:2)
所有的值都是正的,所以我们可以利用我们的目的位标志。
迭代阵列;对于每个元素,请检查它是否为负,是否为负,然后减去1。如果它在有效范围[0,N-1]之外,则输入数组当然是无效的,尽管您说我们不必担心这个。
如果在范围内,则将其用作数组本身的索引;如果找到的值为正,则使其为负,然后减去1。如果值为负,则意味着存在重复的元素(您已经对其进行了符号交换)。
(以下简称“减去1”的是要考虑的0,其保持相同否定时)
由于信鸽原理,如果您到达的最后一个元素没有重复且没有超出范围,则输入数组将仅包含[0,N-1]范围内的所有元素。如果您对将数组都保留为负数感到不满意,则可以进行最后遍操作以翻转每个数字的符号。
bool check(int *arr, int N) {
bool ret = true;
for(int i = 0; i < N && ret; ++i) {
int v = arr[i];
if(v < 0) v = -v - 1;
if(v >= N || arr[v] < 0) ret = false;
else arr[v] = -arr[v] - 1;
}
for(int i = 0; i < N; ++i) {
if(arr[i] < 0) arr[i] = -arr[i] - 1;
}
return ret;
}