2016-12-29 9 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