Массив Рекурсия - PullRequest
6 голосов
/ 30 мая 2010

У меня есть задание, которое я не могу понять, любые указатели будут высоко оценены, это выглядит так:

Существует ряд лампочек, представленных в виде массива true / false, есть переключатель для каждой лампочки, щелкая ее по любой лампочке, вы переключаете ее, а также 2 соседние (1 слева и еще 1) справа; если щелкнуть лампочку переключателя на краю - конечно, переключается только 1 рядом).

Для этого необходим метод, который принимает массив из серии включенных / выключенных лампочек и еще один, представляющий другое состояние предположительно 1-го массива после нажатия некоторых переключателей. ! Поэтому необходимо использовать рекурсию, чтобы выяснить, есть ли комбинация щелчков переключателя, которые преобразуют массив 1 в массив 2.

Вот подпись метода:

public static boolean disco(boolean[] init, boolean[] target)

Вернет true, если массив init можно преобразовать в target , в противном случае - false. Метод должен быть статическим и не использовать loops & любые другие статические и глобальные переменные, только локальные.

Пример:

boolean[] init = {true, false, true, false, true, false};
boolean[] target = {false, true, false, true, false, true};

Для более 2 массивов disco (init, target) вернет true, потому что переключение 1-й и 4-й лампочек даст целевое состояние (помните, что смежные лампочки также переключались).

Ответы [ 4 ]

7 голосов
/ 30 мая 2010

новая версия

public static boolean disco(boolean[] init, boolean[] target)  
{  
  return recurse(init,boolean,0);  
}  

public static boolean recurse(boolean[] init, boolean[] target, int min)  
{  
  if (min == init.length)  
    if (init == target)  
      return true;  
    else  
      return false;  
  boolean[] temp = "init with a change at min";  
  boolean a = recurse(init, target, min+1);  
  boolean b =   recurse(temp, target, min+1);  
  return a||b;
}  

новая новая версия

Я разбил его на три случая:

Случай 1 : длина% 3 = 0
Изменяя первую и вторую лампочки, вы можете повлиять на изменение только на 3-ю. Тогда изменение на 4 и 5 сделает 6-го единственным измененным. Мы видим, что мы можем заменить каждую лампочку с индексом, делимым на 3.
Работая в обратном направлении (начиная с конца), мы можем сделать то же самое, но на этот раз это показывает, что мы можем заменить лампочки с индексами (i + 1), кратными 3.
Объединяя эти два, мы видим, что если мы хотим изменить индекс 0,1 mod 3, мы можем. Но затем, чтобы изменить 2, мы просто должны изменить соседнюю 0,1 пару, а затем сделать изменение средней. Так что во всех случаях они разрешимы.

Случай 2 : длина% 3 = 1
Как и в первом случае, но мы можем повлиять на единичные изменения в 0,2 мод 3, и, таким образом, сжать 1 мод 3 случая.

Дело 3 : длина% 3 = 2
Работа только вперед и назад приводит к случаям 0 mod 3. Единственные оставшиеся движения, которые мы имеем, вносят два изменения в луковицы (так как мы можем игнорировать любые изменения в позициях 0). Изменение 1 или 2 перевернет положение, окруженное двумя 0, тогда как изменение 0 поменяет четность в соседних блоках по 1,2, у которых есть 0 между ними (это проще, если вы рисуете). Но то, что я пока показал, это то, что все 0 можно исправить, и в любом смежном 1,2 вы можете исправить оба, если они неправильны, не меняя ничего другого. Если вы ошибаетесь, вы распространяете изменение на соседнюю пару из 1,2. Это изменение может быть перенесено в случае необходимости. Это означает, что любое четное количество ошибок в 1,2 позициях может быть исправлено, но нечетное число не может быть исправлено. Все ошибки в позиции 0 могут быть исправлены.

public static boolean disco(boolean[] init, boolean[] target)  
{  
  if (init.length%3 == 0 || init.length%3 == 1)
    return true;
  return recurse(init,target,0, true);
}

public static boolean recurse(boolean[] init, boolean[] target, int index, boolean even)
{
  if (index = init.length)
    return even;
  if (init[index] != target[index] && index%3 != 0)
    even = !even;
  return recurse(init, target, index+1, even);
}
4 голосов
/ 30 мая 2010

Так вот в словах как бы я это сделал:

Если осталось 3 или менее равных 3 лампочки, очень легко проверить, можно ли их переключать, чтобы это было правильно.

Если имеется более трех лампочек, выполните следующие действия:

Проверьте правильность первой лампы. Если это так, продолжайте рекурсивно, начиная с подмассива, начинающегося со второй лампочки.

Если первая лампочка неправильна, переключите вторую лампу (переключение первой лампочки не будет работать, потому что тогда предыдущие лампочки переключались обратно) Теперь первая лампочка правильная. Продолжайте с подрешеткой, начинающейся со второй лампочки.

2 голосов
/ 31 мая 2010

Подсказка: пусть a1, a2, ..., ak, ..., a будут входными данными, а b1, b2, ..., bk, ..., bn желаемыми выходными данными.

Вы можете рекурсивно проверить левую и правую стороны, а затем объединить результат. Хитрая часть объединяет результат.

Начните с левой стороны.

  1. Проверка a1, a2, ..., ak, true для b1, b2, ..., bk, true.
    1. если истина, то проверить a1, a2, ..., ak на b1, b2, ..., bk.
      1. если true, то решение от a1, a2, ..., ak до b1, b2, ..., bk не может включать в себя переключение k-го переключателя
      2. если false, то решение от a1, a2, ..., ak до b1, b2, ...,! Bk должно включать в себя переключение k-го ключа
    2. если false, то проверить a1, a2, ..., ak на b1, b2, ..., bk
      1. если true, то решение от a1, a2, ..., ak до b1, b2, .., bk должно включать переключение k-го ключа
      2. если false, то растворение от a1, a2, ..., ak до b1, b2, ...,! Bk не может включать переключение k-го ключа

После двух тестов на левой стороне вы можете выполнить аналогичные тесты на правой стороне. Вы сможете объединить значения теста, потому что вы будете знать, был ли переключатель kth переключен или нет.

1 голос
/ 31 мая 2010

Спасибо всем за помощь, вот что я придумал:

public static boolean disco(boolean[] init, boolean[] target)
{
    if (java.util.Arrays.equals(init, target)) {
        return true;
    } else {
        return disco(init, target, 0);
    }
}

private static boolean disco(boolean[] init, boolean[] target, int i)
{
    if (i > init.length-1) {
        return false;
    }

    disco(init, target, i+1);
    boolean t = false;

    if (init[i] != target[i]) {
        switchBulb(init, target, i);
    }

    if (java.util.Arrays.equals(init, target)) {
        t = true;
    }

    return t;
}

private static void switchBulb(boolean[] init, boolean[] target, int i)
{
    if ( (i > 1) && (init[i-1] != target[i-1]) && (init[i-2] != target[i-2]) ) {
        // If there's a series of 3 opposite-to-target bulbs, switch the middle one & from both sides
        init[i-1] = !init[i-1];
        init[i] = !init[i];
        init[i-2] = !init[i-2];
    } else if (i > 0 && i < init.length-1) {
        // There's only 1 bulb or 2 adjacent bulbs that are opposite of target.
        if (i == 1 && (init[0] != target[0]) ) {
            // First 2 bulbs are opposite of target's, so switch the 1st one.
            init[i-1] = !init[i-1];
            init[i] = !init[i];
        } else if ( (i == init.length-2) && (init[i+1] != target[i+1]) ) {
            init[i+1] = !init[i+1];
            init[i] = !init[i];
        } else {
            init[i] = !init[i];
            init[i-1] = !init[i-1];
            init[i+1] = !init[i+1];
        }
    } else {
        // First bulb or last bulb.
        init[i] = !init[i];
        if (i == 0) {
            init[i+1] = !init[i+1];
        } else {
            init[i-1] = !init[i-1];
        }
    }
}

Я чувствую, что мое использование рекурсии здесь минимально, могло бы быть намного чище, если бы рекурсия использовалась правильно. Есть мысли? Я говорю о функции switchBulb, ее можно заменить более сложной логикой рекурсии, или я ошибаюсь?

Как и в случае, если вы просто перебираете луковицы одну за другой и сравниваете их с целевым массивом, вам не нужно делать это правильно для ВСЕХ комбинаций ламп (см. Пример), так как вы имитируете случайное переключение ламп с рекурсии? Или есть шаблон? Должно быть, если нет, как бы он знал, когда остановиться?

Я думаю, что я получил решение, опубликую позже, если кому-то будет интересно ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...