2016-12-29 62 views
1

我一直在嘗試執行在此線程中討論的內容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(); 
    } 

}

+1

您的問題究竟是什麼?你得到一個不正確的輸出?如果是的話,你會得到什麼,你期望什麼? – kraskevich

+0

是的,輸出是錯誤的。 – wayfare

回答

1

不要使用很數組元素,以保持位移值(即初始數組的元素之間的互換),你這是怎麼搞砸你的代碼。相反,使用一些O(1)臨時變量來保持「置換」值和源自該值的位置。

評論下面的代碼,用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] 
+0

很好的解釋。現在它是有道理的。謝謝! – wayfare

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; 
} 
+0

提出了建議的變化,但我認爲我沒有得到期望的輸出。 輸入:char [] arr = {'a','b','c','d'}; int [] p = {2,0,1,3};並且輸出是[c,a,b,d] 如果您能解釋爲什麼需要這種更改,這也會非常有幫助。 – wayfare

+0

@wayfare [c,a,b,d]對我來說看起來是正確的。您不需要最後一次交換,因爲沒有它就會轉換整個循環。 – kraskevich

+0

不應輸出爲{b,c,a,d}而不是[c,a,b,d]?因爲p = {2,0,1,3},所以'a'去第三個位置而不是第二個位置。 (從0開始索引) – wayfare