我有一个问题,我想在一个设置中替换2个数字" k" - 这样每次切换时,我得到最大可能的排列并在k-swaps之后打印出来。例如,对于k = 2,对于1步中的集合(1,4,2,5,3,3),我将交换(1,5)以创建(5,4,2,1,3,3)。在步骤2中,我将交换(2,3)以创建(5,4,3,1,3,2)。如果在n<第k点,我们已经有了最大的排列,例如(5,4,3,3,2,1)然后我们停下来。
到目前为止,这就是我所拥有的:
x<-y<-c(1,4,2,5,3,3)
sx<-sort(x,decreasing=TRUE)
if(k>=n){cat(sx)} else{ ### If we have more operations than numbers?
i<-0; k<-2
m<-max(y)
while(i<k){
if(all(sort(x,decreasing=TRUE)==y)){break}
i<-i+1
a<-max(which(y==m))
while(length(which(y[c(1:a)]<m))==0){
m<-m-1
a<-which(y==m) ### Location of the largest number
if(length(a)==0){
a<-1
next
}
a<-max(a)
}
y[c(min(which(y[c(1:a)]<m)),a)]<-y[c(a,min(which(y[c(1:a)]<m)))]
}
cat(y)
}
5 4 2 1 3 3
本质上,代码找到当前集合的最大值。然后找到此最大数字的最右侧出现。然后找到最左边的数字低于最大数字。然后切换它们。这一直持续到我们执行k步或者我们在k之前具有最大的排列。然后打印出来。
此代码有效,但如果大k超过10 ^ 4位数,则需要太长时间。有没有办法将复杂度降低到R?
中的O(n)答案 0 :(得分:0)
这里有一个O(n log n)
- 时间算法(O(n)
只有比较才有可能,但是你可能对输入数字有所了解。)
对于某些整数[i 2^j, (i+1) 2^j)
具有(零索引)边界i, j
的排列的每个子数组,将最小值和最大值存储在子数组中(即设置segment tree }结构)。
要查找时间间隔O(log n)
中的最大值,请将时间间隔分解为O(log n)
个基本时间间隔,并返回最大值的最大值。
要在基本时间间隔O(log n)
中找到最右边的最大值,如果其最大值等于目标,则重复下降到右子项,否则下降到左子项。
要在时间间隔O(log n)
中找到低于目标数的最左边的数字,请将间隔分解为O(log n)
个基本间隔,并找到最小值低于目标的最左边的基本间隔。从这个区间开始,如果最小值低于目标,则反复下降到左侧子项,否则下降到右侧子项。
按照你的例子:
1,5
4,5 1,2 3,3
5 4 2 1 3 3
我们刚刚移动5
,而4
位于正确的位置,因此我们希望数组其余部分的最大值。基本区间为2 1
和3 3
。最大值为3
。我们检查3 3
并发现最大值是在正确的孩子中,最后一直是。
现在我们寻找的最左边的数字小于3
。基本区间为2 1
和3 3
。我们发现2 1
的最小值小于3
,因此我们会对其进行检查。 2 1
的左侧孩子也是如此,因此2
是我们与3
交换的内容。
*1,5*
4,5 *1,2* *3,3*
5 4 3 1 3 2
*asterisks*
中的聚合可能需要更新(交换值的祖先)。这些中有O(log n)
个。我们自下而上。
*1,5*
4,5 1,3 *3,3*
5 4 3 1 3 2
1,5
4,5 1,3 *3,3*
5 4 3 1 3 2
1,5
4,5 1,3 2,3
5 4 3 1 3 2