2016-12-29 7 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テストケース(print(char[]/int[])メソッドの代わりにカスタムのArrays.toStringの使用に注意してください)で、以下のコードをコメント

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

[c、a、b、d]の代わりに{b、c、a、d}を出力しないでください。 p = {2,0,1,3}なので、 'a'は2番目ではなく3番目の位置に移動します。 (0から開始インデックス) – wayfare

関連する問題