這是一個正確的解決方案
是的。讓我試着清理使用堆棧的想法,並考慮@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,我們肯定是突然離開棧中的一個元素,因此棧中的大小每一個步驟3後下降了1
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)
。
旁註 - 每當想到遞歸時,總會更容易想到它,就像函數深度調用unfolding,然後返回值,然後收集它們以返回最終結果。
無論如何,我希望我能澄清一下自己,希望這能讓你開始朝正確的方向發展。
爲什麼要保持'char_popped'時,你可以看看堆棧的頂部? (如果檢查堆棧是否爲空太痛苦,那麼在開始之前先推送一個標記值。 – rici 2014-11-09 17:20:08