Algorithm 从n“的堆栈中查找k个元素的所有组合的算法;随机地;
我有一个类似于这里描述的问题: 我正在寻找类似的东西,包括从n到k的所有可能组合。但是,我需要一个子集来与之前绘制的子集有很大的不同。例如,如果我要从8个元素的集合中绘制3个元素的子集,则以下算法对我没有用处,因为每个子集都与之前绘制的子集非常相似: 11100000, 11010000, 10110000, 01110000, 我正在寻找一种算法,该算法以更“随机”的方式选择子集,即一个子集中的大多数元素在下一个子集中不被重用: 11100000, 00010011, 00101100, 有人知道这样的算法吗 我希望我的问题有意义,有人能帮我解决() 亲切问候,Algorithm 从n“的堆栈中查找k个元素的所有组合的算法;随机地;,algorithm,combinations,Algorithm,Combinations,我有一个类似于这里描述的问题: 我正在寻找类似的东西,包括从n到k的所有可能组合。但是,我需要一个子集来与之前绘制的子集有很大的不同。例如,如果我要从8个元素的集合中绘制3个元素的子集,则以下算法对我没有用处,因为每个子集都与之前绘制的子集非常相似: 11100000, 11010000, 10110000, 01110000, 我正在寻找一种算法,该算法以更“随机”的方式选择子集,即一个子集中的大多数元素在下一个子集中不被重用: 11100000, 00010011, 00101100,
Christian随机选择k元素怎么样。即选择p在1和n之间随机的pth,然后对剩下的进行重新排序,并选择q在1和n-1之间的qth,以此类推
也许我误解了。你还想要所有的可能性吗?在这种情况下,您总是可以先生成它们,然后从列表中选择随机项首先从n中生成k的所有可能组合,然后借助随机函数重新排列它们 如果在向量中有结果,则在向量中循环:对于每个元素,让它随元素在随机位置改变位置 当然,对于较大的k和n来说,这会变慢。通过“随机查找”,我想你指的是词典中的距离。。这是否适用于组合
i
与i-1
,或i
与之前的所有组合
如果是,以下是一些建议:
- 由于大多数组合器产生有序输出,因此有两种选择:
- 设计或找到一个以某种方式产生非有序输出的发生器
- 在一个绑定数组文件/db中枚举并存储足够的/所有组合
- 如果您决定使用door#2,那么您可以通过1和组合的#之间的随机整数访问随机排序的组合
- 作为最后一项检查,使用组合之间的差异/距离度量来比较当前和以前的组合,例如,对于Perl中的无符号
: $vec1->Lexicompare($vec2)>=$MIN\u LEX\u DISTBit::Vector
- 您可以在门#1后面再看一眼,因为即使是
和n
的中等值,也可以得到一个大数组:k
刚刚看到你对安克的评论。。。也许lexicompare仍然可以帮助您跳过类似的组合?这并不是随机的,但根据您的需要,它可能适合您
如果仔细选择p,您将得到看似随机的组合。接近1或N的值将产生差异很小的值。最好选择接近N/4或N/5的值。您还可以为您需要的每个迭代随机生成P。
作为我的后续评论,下面是一些代码,允许您根据“索引”以colex顺序确定子集的组成。 不知羞耻地从我自己的任务中偷来
//////////////////////////////////////
// NChooseK
//
// computes n!
// --------
// k!(n-k)!
//
// using Pascal's identity
// i.e. (n,k) = (n-1,k-1) + (n-1,k)
//
// easily optimizable by memoization
long long NChooseK(int n, int k)
{
if(k >= 0 && k <= n && n >= 1)
{
if( k > n / 2)
k = n - k;
if(k == 0 || n == 0)
return 1;
else
return NChooseK(n-1, k-1) + NChooseK(n-1, k);
}
else
return 0;
}
///////////////////////////////////////////////////////////////////////
// SubsetColexUnrank
// The unranking works by finding each element
// in turn, beginning with the biggest, leftmost one.
// We just have to find, for each element, how many subsets there are
// before the one beginning with the elements we have already found.
//
// It stores its results (indices of the elements present in the subset) into T, in ascending order.
void SubsetColexUnrank(long long r, int * T, int subsetSize)
{
assert( subsetSize >= 1 );
// For each element in the k-subset to be found
for(int i = subsetSize; i >= 1; i--)
{
// T[i] cannot be less than i
int x = i;
// Find the smallest element such that, of all the k-subsets that contain it,
// none has a rank that exceeds r.
while( NChooseK(x, i) <= r )
x++;
// update T with the newly found element
T[i] = x;
// if the subset we have to find is not the first one containing this element
if(r > 0)
{
// finding the next element of our k-subset
// is like finding the first one of the same subset
// divided by {T[i]}
r -= NChooseK(x - 1, i);
}
}
}
//////////////////////////////////////
//恩乔塞克
//
//计算n!
// --------
//k!(n-k)!
//
//使用帕斯卡恒等式
//即(n,k)=(n-1,k-1)+(n-1,k)
//
//易于通过记忆进行优化
长NChooseK(整数n,整数k)
{
如果(k>=0&&k=1)
{
如果(k>n/2)
k=n-k;
如果(k==0 | | n==0)
返回1;
其他的
返回NChooseK(n-1,k-1)+NChooseK(n-1,k);
}
其他的
返回0;
}
///////////////////////////////////////////////////////////////////////
//次级综合银行
//取消分级的工作方式是查找每个元素
//反过来,从最大最左边的一个开始。
//我们只需要找到,对于每个元素,有多少子集
//在我们已经找到的元素开始之前。
//
//它将其结果(子集中元素的索引)按升序存储到T中。
void subsetclexunrank(长-长r,int*T,int subsetSize)
{
断言(子集大小>=1);
//对于要查找的k子集中的每个元素
对于(int i=subsetSize;i>=1;i--)
{
//T[i]不能小于i
int x=i;
//找到最小的元素,在包含它的所有k-子集中,
//没有一个等级超过r。
while(NChooseK(x,i)0)
{
//寻找k-子集的下一个元素
//就像找到同一子集的第一个一样
//除以{T[i]}
r-=NChooseK(x-1,i);
}
}
}
随机输入,随机输出
colex顺序是这样的,它的unranking函数不需要从中选择要工作的元素的集合的大小;元素的数量假定为NChooseK(集合的大小,子集的大小)。根据您要做的事情,您可以做扑克牌之类的事情。保留两个列表:
Source
是您的源(未使用)列表;第二个是“已拾取”列表。当您从Source
中随机选取k
项时,您会将它们移动到您的Used
列表中
如果k
项