Как узнать является ли строка анаграммой палиндрома за O(n) и без дополнительной памяти?

Рейтинг: 2Ответов: 1Опубликовано: 17.02.2023

На входе даётся рандомная строка без спец символов и пробелов. Нужно вывести 1, если строка - перестановка палиндрома и 0, если нет. В этой статье описывается метод с использованием битового вектора, но, так как с этим я не знаком, возможно ли решить данную задачу по-другому? Я пытался сделать так, но не укладываюсь в ограничения:

function solution(s) {
  const obj = {};
  s.split("").forEach(elem => {
    if(obj[elem]) {
      obj[elem]--;
    } else {
      obj[elem]===0 ? obj[elem]++ : obj[elem] = 1;
    }
  })
  return (Object.values(obj).reduce((a,b) => a+b) > 1) ? 0 : 1;
}

Ответы

▲ 1

Про битовый вектор. Как это понимаю я. Предположим что в строке могут быть только буквы латинского алфавита в нижнем регистре. Т.е. таких букв может быть 26. Т.е. для хранения информации будет достаточно 32 битного числа. Первый бит будет хранить информацию о букве a, второй о b, третий - c и т.д. Устанавливать или сбрасывать биты можно с помощью битовых операций. Если назначить буквам числа (так сказать индексы). a = 1 b = 2 c = 4 d = 8 и т.д. до z как степени двойки.

Дальше предположим, есть переменная vector = 0; Т.е. все биты сброшены. Е Начинаем проход по строке. Встретилась буква b - нужно установить второй бит. В данной случае можно и нужно использовать операцию XOR.
vector = vector XOR 2

Почему XOR? - потому что с ее помощью можно решить задачу подсчета четного числа букв.

Т.е. когда в следующий раз попадется буква b - то сделав еще раз XOR для vector и 2 - мы сбросим второй бит в ноль. Тем самым не нужна дополнительная проверка в каком он находится состоянии. XOR все "сделает" за нас.

А дальше надо будет проверить получился ли vector равный 0. Или же там установлен всего лиш один бит. Проверить на то что есть один бит - можно сравненим числа vector с теми числами, которые мы приписывали для букв (степень двойки).

Как вариант, решение может быть таким. Здесь obj это по сути битовый вектор, который упоминается в вопросе. Если символ встречается первый раз, то свойство добавляется (в числе ставится бит в соответствующую поизицию). Если символ встречается второй раз, то свойство удаляется из объекта (в числе сбрасывается бит в соответствующей позиции).

После цикла проверяем что в объекте нет свойств или осталось только одно - в таком случае строка подходит под условия.

function solution(s) {
  const obj = Object();
  s.split("").forEach(elem => {
    if(obj[elem]) {
      delete obj[elem];
    } else {
      obj[elem] = 1;
    }
  })
  return Object.keys(obj).length<=1?1:0;
}

console.log(solution("dfghgfd"));
console.log(solution("aaa"));
console.log(solution("abcdefg"));