Проверьте, равны ли две строки вращательно друг другу - PullRequest
4 голосов
/ 13 июня 2019

Мне нужна ваша помощь в следующем: я пытаюсь разработать функцию, которая должна проверять, равны ли две строки аргумента по вращению друг другу.Например, «abcd» станет «cdab», если мы повернем его по часовой стрелке дважды, поэтому моя функция должна возвращать «true», если приведенные выше строки представлены в качестве аргументов.Моя первоначальная идея для решения этой проблемы состояла в том, чтобы проверить, существует ли постоянный сдвиг между каждым символом в обеих строках, поэтому я попытался

function areRotEq (str1, str2) {
    var shift = null;
    for(char of str1){
        if(!shift) shift = str2.indexOf(char);
        else if (shift != str2.indexOf(char)) return false
    }
    return true;
}

Но он не может правильно оценить даже вышеупомянутые простые строки и возвращает «ложь»,Если бы вы могли указать мне правильное направление, чтобы выяснить, почему мой код не работает, или, возможно, предложить какой-то более эффективный метод для решения моей проблемы, который был бы очень признателен.Заранее спасибо!

Ответы [ 6 ]

4 голосов
/ 13 июня 2019

Вот альтернативный подход:

Сначала выполните «быстрые» проверки, которые являются абсолютно истинными или ложными.

Затем проверьте первый символ str1 в str2.Разделите его на этом этапе и вставьте первую часть позади последней.Если они равны, они вращаются.

предупреждение: это не будет работать для строк, которые содержат один и тот же символ несколько раз.

function areRotEq (str1, str2) {
    if (str1 === str2) return true;
    if (str1.length !== str2.length) return false;
    
    var start2 = str2.indexOf(str1[0]);
    if (start2 === -1) return false;

    return str1 === str2.slice(start2) + str2.slice(0, start2)
}

console.log(
  areRotEq("abcd", "abcd"),
  areRotEq("abcd", "acdb"),
  areRotEq("abcd", "dabc"),
  areRotEq("dcab", "abdc")
);
2 голосов
/ 13 июня 2019

Вот как я решил эту проблему. Я в основном продолжаю смещать str1, пока он не совпадет с str2, или пока я не попробую каждую комбинацию смены.

function areRotEq (str1, str2) {
    for(let i=0; i<str1.length; ++i) {
        // shift str1
        str1 = str1[str1.length-1] + str1.substring(0, str1.length-1);
        if(str1 === str2) {
            return true;
        }
    }
    return false;
}


console.log(
    areRotEq('12345', '34512'), // true
    areRotEq('12345', '23451'), // true
    areRotEq('12345', '12354') // false
);
1 голос
/ 13 июня 2019

Ваше решение не работает, потому что вы неправильно рассчитали смещение, вот как вы можете это исправить:

function areRotEq (str1, str2) {
    var shift = null;
    let i = 0;
    for(char of str1){
        if(!shift) shift = str2.indexOf(char);
        else {
            const currentShift = Math.abs(str2.indexOf(char) - i);
            if (shift != currentShift) return false;
        } 
        i++;
    }
    return true;
}

Вот решение для конкатенации:

function areRotEq (str1, str2) {
    if (str1.length != str2.length) return false;
    return (str1 + str1).indexOf(str2) != -1;
}
0 голосов
/ 13 июня 2019

Вы можете представить строку в виде структуры колоды, а именно колоду персонажей (возможность помещать элементы в начало и в конец коллекции, как колода карт).Довольно удобно, массив JavaScript предоставляет эту функциональность из коробки (через методы очереди и стека shift и push. По сути, мы вынимаем первый символ в строке и перемещаем его в последнюю позицию и делаем новыйпроверка на равенство. Мы повторяем эту операцию, пока строка не будет сдвинута (или повернута) к ее начальному значению:

function areRotEq(str1, str2) {
    if (str1.length !== str2.length) {
        return false;
    }

    if (str1 === str2) {
        return true;
    }

    let str1Array = str1.split('');
    let tempEl;

    for (let i = 0; i < str1.length - 1; i++) {
        tempEl = str1Array.shift();
        str1Array.push(tempEl);

        if (str1Array.join('') === str2) {
            return true;
        }
    }

    return false;
}
0 голосов
/ 13 июня 2019

Я бы использовал findIndex для строк, содержащих более 1 буквы, и удалил бы их

function areRotEq(str1, str2) {
    const str1Array = str1.split('');
    const str2Array = str2.split('');
    for (let i = str1Array.length - 1; i >= 0 ; i--) {
        const index = str2Array.findIndex(letter => letter === str1Array[i]);
        if (index === -1) {
            return false;
        }
        str2Array.splice(index, 1);
    }
    return str2Array.length === 0;
}
console.log(areRotEq('abcda', 'cdaba'));
0 голосов
/ 13 июня 2019

Вы можете использовать цикл for и увеличивать индекс для первой строки с 0 и далее, уменьшая индекс второй строки с ее длины. С помощью этих двух индексов вы можете сравнить определенные символы внутри строки.

function areRotEq(str1, str2) {
  for (var a = 0; a < str1.length; a++) {
    if (str1.charAt(a) != str2.charAt(str2.length - (a + 1))) {
      return false;
    }
  }
  return true;
}
console.log(areRotEq("abcd", "dcba"));
...