Является ли это правильным решением
Да это. Позвольте мне попытаться дезинформировать вашу идею использования стеков с учетом того, что сказал @rici.
Вы хотите пройти через символы строки один раз. Это, как течет ваш алгоритм:
1. Initialize a stack containing the string. (Stack A)
2. Pop top most element of Stack A and push into Stack B thereby initializing Stack B
3. Pop from Stack B and pop from Stack A and check if they are equal.
4. If they aren't push both the elements in Stack B. (The popped element from Stack A is pushed later to preserve order)
5. Do step 3 till Stack A is empty.
Stack B should contain the chracters with adjacent duplicates removed.
выше алгоритм явно O(N)
потому что на каждом шаге 3, мы, безусловно, выскакивают элемент отключения стека A и, следовательно, размер стека A уменьшается на 1 после каждого шага 3 .
canyone объяснить решение o (n), объясненное в сообщении?
Приходит к recursive algorithm, на котором вы хотите повесить. Вот как это идет:
В любой момент времени функции removeUtil
имеет два значения - один является массивом символов str
, из которого мы должны удалить соседние дубликаты, а другой персонаж last_removed
.
Псевдо код с некоторым описанием -
1. It checks if the first two characters of the str are same, if they are:
update last_removed and call removeUtil again on the remaining characters
(hence the str ++)
2. If first two characters are not same, we do the same exercise as in 1
only this time we start from str[1], hence removeUtil(str+1, last_removed);
3. Now the returned value from call in 2 is stored in a rem_str because we have
characters that didn't match like str[0] in 2 that are orphan and need to be appended
in the final array just like we pushed elements into the stack in your case.
4. Let's assume the string is 'abbac'-
In the first call we reach here -> removeUtil("bbac", '\0');
str[0] -> 'a'
Now this call -> removeUtil("bbac", '\0'); returns "ac"
and when the recursion unfolds at this point rem_str -> "ac"
str[0] -> 'a'
Hence this :
if (rem_str[0] && rem_str[0] == str[0])
{
*last_removed = str[0];
return (rem_str+1); // In our case this would return "c" to the previous function call
}
5. if (rem_str[0] == '\0' && *last_removed == str[0])
return rem_str;
Consider the string they mention -> "acbbcddc"
So at some point we have situation where:
this call happens-> removeUtil("bbcddc", '\0');
followed by -> removeUtil("cddc", 'b');
followed by -> removeUtil("ddc", 'b');
followed by -> removeUtil("c", 'd');
That returns 'c' and considering the str[0] in the string "cddc" , it goes to case 4
and therefore 'c' gets removed returning an empty string and last_removed -> 'c'.
So removeUtil("bbcddc", '\0'); returns an empty string with last_removed -> 'c'.
However, here str[0] is the same as the last_removed character and therefore should be removed.
6. If none of the following string matches that means str[0] should be appended to final answer.
rem_str--;
rem_str[0] = str[0];
return rem_str;
И здесь также, так как мы пересекающие массив символов и «формирующими» окончательный массив символов, которые получают, возвращенный соответствующее добавление и удаления символов, время сложность O(N)
.
Sidenote - Всякий раз, когда вы думаете о рекурсии, его всегда легче думать о нем, как о глубине вызова функций, а затем возвращать значения, которые затем собираются, чтобы вернуть окончательный результат.
В любом случае, я надеюсь, что смогу прояснить себя и надеюсь, что это поможет вам начать работу в правильном направлении.
Зачем держать 'char_popped', когда вы можете просто посмотреть на вершине стека? (Если проверка того, что стек пуст, слишком болезненна, а затем нажмите на значение дозорного значения, прежде чем вы начнете.) – rici