我一直在尝试实现此线程Algorithm to apply permutation in constant memory space中所讨论的内容。但是,我无法正确理解问题解决方案或我的代码有一些我无法检测和修复的错误。蚂蚁的帮助表示赞赏。
public class ArrayPermute{
public static void main(String[] args){
char[] arr = {'a','b','c','d'};
int[] p = {2,0,1,3};
for(int i=0; i<arr.length; i++){
int tmp = i;
while(p[tmp] >= 0){
char t = arr[p[tmp]];//d
arr[p[tmp]] = arr[tmp];
arr[tmp]=t;
int _tmp = p[tmp];
p[tmp] = -1;
tmp = _tmp;
print(arr);
print(p);
}
}
for(char i: arr){
System.out.print(i + " ");
}
}
public static void print(char[] arr){
for(char c: arr){
System.out.print(c + " " );
}
System.out.println();
}
public static void print(int[] arr){
for(int c: arr){
System.out.print(c + " " );
}
System.out.println();
}
}
答案 0 :(得分:1)
不要使用数组元素来保持位移值(即在初始数组的元素之间交换),这就是你搞砸代码的方式。
相反,使用一些O(1)临时变量来保持&#34;取代&#34;价值以及来自该价值的地方。
以下评论代码,包含2个测试用例(请注意使用Arrays.toString
代替您的自定义print(char[]/int[])
方法)
import java.util.Arrays;
public class InPlacePermutation {
static public void inPlacePermute(char arr[], int p[]) {
for(int i=0; i<p.length; i++) {
if(p[i]<0) continue; // already visited
char toMove=arr[i]; // value-at-hand
int currIx=i; // index from where the value-at-hand originated
while(currIx>=0 && p[currIx]!=i) { // as long as we aren't back where we started
int destIx=p[currIx];
if(destIx<0) {
// the permutation is bad, we are stepping again
// on places we stepped before. This should not happen
throw new IllegalArgumentException("bad permutation");
}
// take the value "at hand" before it get overwritten
char destVal=arr[destIx];
// place current "value at hand" in the destination
arr[destIx]=toMove;
// update bookkeeping the vals/indexes values
p[currIx]=-1; // mark where we've been
currIx=destIx; // then take a step further
toMove=destVal; // don't forget to carry the new "value at hand"
}
// now we are back where we started with a "value at hand"
arr[i]=toMove;
p[currIx]=-1; // mark the source of the moved value as visited
}
}
static public void main(String[] args) {
char[] arr = {'a','b','c','d'};
int[] p = {2,0,1,3};
System.out.print("arr:"+Arrays.toString(arr)+" + pmt:"+Arrays.toString(p) + " =>");
inPlacePermute(arr, p);
System.out.println(" "+Arrays.toString(arr));
System.out.println();
// two cycles and one in place
arr = new char[]{'a','b','c','d', 'e', 'f'};
p = new int[]{2,3,4,1,0,5};
System.out.print("arr:"+Arrays.toString(arr)+" + pmt:"+Arrays.toString(p) + " =>");
inPlacePermute(arr, p);
System.out.println(" "+Arrays.toString(arr));
}
}
输出:
arr:[a, b, c, d] + pmt:[2, 0, 1, 3] => [b, c, a, d]
arr:[a, b, c, d, e, f] + pmt:[2, 3, 4, 1, 0, 5] => [e, d, a, b, c, f]
答案 1 :(得分:0)
当您到达周期的开始时,您不需要进行交换。也就是说,它应该像:
int tmp = i;
int start = i;
while (p[tmp] >= 0 && p[tmp] != start) {
// Your code here doesn't change
}
if (p[tmp] == start) {
p[tmp] = -1;
}