【发布时间】:2013-07-01 20:20:28
【问题描述】:
我有以下向量v = [r1 r2 r3 r4 r5 .... rn],带有r 整数。
我要检查:
如果r1 不等于r2 不等于r3 ... 不等于rn(彼此不同):
打印 v
else(有些元素相等,有些不相等):
打印相等元素的索引。
【问题讨论】:
标签: matlab
我有以下向量v = [r1 r2 r3 r4 r5 .... rn],带有r 整数。
我要检查:
如果r1 不等于r2 不等于r3 ... 不等于rn(彼此不同):
打印 v
else(有些元素相等,有些不相等):
打印相等元素的索引。
【问题讨论】:
标签: matlab
我推荐使用unique 命令。它将返回所有唯一值的值。
如果您想检查矩阵v 中的所有值是否唯一,我会使用以下命令:
everything_is_unique = length(unique(v))==length(v);
您还可以返回相等元素的索引。
请参阅the documentation on unique 了解更多信息。
【讨论】:
除了使用 unique 之外,您还可以对元素进行排序并检查它们是否都不同:
all(diff(sort(v)))
通过使用带有更多输入参数的排序,您可以获得所需的索引。
【讨论】:
我将再提供一个解决方案,并对迄今为止尝试的所有方法进行比较。
我的解决方案基于以下观察结果:当使用 sort() 或 unique() 等内置函数时,您会失去提前逃生的机会。也就是说,sort() 必须完全 对向量进行排序,然后才能继续使用算法,即使如果在sort 中已经检测到两个相等的值,则不需要这样做。
因此,我简单地遍历数组,并使用any() 将当前值与所有后续值进行比较。这可以解决其中一些问题,并且在很多情况下都可以很好地工作。
但是,最坏情况的复杂度是 O(N²),这比 sort() 差很多,后者只有 O(N·log(N)) 。所以像往常一样,这一切都取决于上下文:)
试试这个:
clc
N = 1e4;
% Zigzag's solution
tic
for ii = 1:1e2
v = randi(N, N,1);
length(unique(v))==length(v);
end
toc
% Dennis Jaheruddin's solution
tic
for ii = 1:1e4
v = randi(N, N,1);
all(diff(sort(v)));
end
toc
% My solution
tic
for ii = 1:1e4
v = randi(N, N,1);
cond = true;
for jj = 1:numel(v)
if any(v(jj) == v(jj+1:end))
cond = false;
break;
end
end
end
toc
随机数在循环内生成,以确保会出现各种不同的情况。我的电脑上的结果:
Elapsed time is 16.787976 seconds. % unique
Elapsed time is 14.284696 seconds. % sort + diff
Elapsed time is 5.376655 seconds. % loop + any
因此,提前退出的显式循环(假设feature accel 已开启)实际上比标准的“矢量化”方法快了近三倍:)
PS - 我还尝试嵌套 another 循环以尝试改进在检测相等值之前必须比较 all 值(首先 v(jj)==v(jj+1:end) 在 @ 之前被完全评估987654331@ 可以开始做它的工作),但是在这里,开销真的开始妨碍(或者 JIT 不能很好地应对这种事情,我不知道)。理论上,这当然应该更快,但不幸的是,不是在 MATLAB 中:)
但是,改变随机数生成
v = randi(N, N,1);
进入
v = randi(N*N, N,1);
结果却大相径庭:
Elapsed time is 0.162625 seconds. % unique
Elapsed time is 0.147369 seconds. % sort + diff
Elapsed time is 30.767247 seconds. % loop + any
这里我只使用了 100 次迭代而不是 10.000 次,原因很明显:)
【讨论】: