Перетяжка, Премия ТПрогер, 13.11
Перетяжка, Премия ТПрогер, 13.11
Перетяжка, Премия ТПрогер, 13.11

Реализуйте метод сжатия строки на основе счетчика повторяющихся символов

Аватар Типичный программист
Отредактировано

13К открытий14К показов

Например, строка aabcccccaaa должна превратиться в а2b1с5аЗ. Если «сжатая» строка оказывается длиннее исходной, метод должен вернуть исходную строку.

			public String compressBad(String str) {
	String mystr = "";
	char last = str.charAt(0);
	int count = 1;
	for (int i = 1; i < str.length(); i++) {
		if (str.charAt(i) == last) { // Находим повторяющийся символ
			count++;
		} else {	// Вставляем счетчик символа и обновляем последний символ
			mystr += last + count;
			last = str.charAt(i);
			count = 1;
		}
	}
	return mystr + last + count;
}
		

Этот код не отслеживает случай, когда сжатая строка получается длиннее исходной. Но эффективен ли этот алгоритм?

Давайте оценим время выполнения этого кода: 0(р + k²), где р — размер исходной строки, a k — количество последовательностей символов. Например, если строка aabccdeeaa содержит 6 последовательностей символов. Алгоритм работает медленно, поскольку используется конкатенация строк, требующая обычно 0(n²) времени.

Улучшить код можно, используя, например StringBuffer в Java:

			String compressBetter(String str) {
	/* Проверяем, вдруг сжатие создаст более длинную строку */
	int size = countCompression(str);
	if (size >= str.length()) {
		return str;
	}

	StringBuffer mystr = new StringBuffer();
	char last = str.charAt(0);
	int count = 1;
	for (int i = 1; i < str.length(); i++)	{
		if (str.charAt(i) == last) { // Найден повторяющийся символ
			count++;
		} else { // Вставляем счетчик символов, обновляем последний символ
			mystr.append(last);	// Вставляем символ
			mystr.append(count);	// Вставляем счетчик
			last = str.charAt(i);
			count = 1;
		}
	}

	/* В строках 15-16 символы вставляются, когда
	* изменяется повторяющийся символ. Мы должны обновить строку
	* в конце метода, так как	самый последний	повторяющийся символ
	* еще не был установлен в	сжатой строке
	* */
	mystr.append(last);
	mystr.append(count);
	return mystr.toString();
}

int countCompression(String str) {
	char last = str.charAt(0);
	int size = 0;
	int count = 1;
	for (int i = 1; i < str.length(); i++) {
		if (str.charAt(i) == last) {
			count++;
		} else	{
			last = str.charAt(i);
			size += 1 + String.valueOf(count).length();
			count = 0;
		}
	}
	size += 1 + String.valueOf(count).length();
	return size;
}
		

Этот алгоритм намного эффективнее. Обратите внимание на проверку размера в строках 2—5.

Если мы не хотим (или не можем) использовать stringBuffer, можно решить эту задачу иначе. В строке 2 рассчитывается конечный размер строки, что позволит создать массив подходящего размера:

			String compressAlternate(String str) {
	/* Проверяем, вдруг сжатие создаст более длинную строку */
	int size = countCompression(str);
	if (size >= str.length()) {
		return str;
	}

	char[] array = new char[size];
	int index = 0;
	char last = str.charAt(0);
	int count = 1;
	for (int i = 1; i < str.length(); i++) {
		if (str.charAt(i) == last) { // Найдите повторяющийся символ
			count++;
		}	else {
			/* Обоновляем счетчик повторяющихся символов */
			index = setChar(str, array, last, index, count);
			last = str.charAt(i);
			count = 1;
		}
	}

	/* Обновляем строку с последним набором повторяющихся символов */
		index = setchar(str, array, last, index, count); 
                return String.valueOf(array);
}

int setChar(String str, char[] array, char c, int index,
			int count) {
	array[index] = c;
	index++;

	/* Конвертируем счетчик в строку */
	char[] cnt = String. valueOf (count) .toCharArray();

	/* Копируем символы от большего разряда к меньшему */
	for (char х : cnt) {
		array[index] = х;
		index++;
	}
	return index;
}

int countCompression(String str) {
	/* так же, как и раньше	*/
}
		

Подобно предыдущему решению, этот код потребует O(N) времени и 0(N) пространства.

Разбор задачи по книге «Карьера программиста. Как устроиться на работу в Google, Microsoft или другую ведущую IT-компанию»

Следите за новыми постами
Следите за новыми постами по любимым темам
13К открытий14К показов