找到一个算法recursively remove all adjacent duplicates in a given string这是原始问题。我想到了一个使用堆栈的算法。
1.Initialize a stack and a char_popped variable
2.Push the first char of str into the stack.
3.now iterate through the characters of string.
if the top of stack matches with the character
{
pop the character from the stack,
char_popped=character
}
else
{
if(character==char_popped)
{DONT DO ANYTHING}
else
push the character on the stack
char_popped=null
}
堆栈上剩下的是结果字符串。
辅助空间:O(n)复杂性:O(n)
这是一个正确的解决方案,而且这个解决了帖子中解释的o(n)解决方案吗?
答案 0 :(得分:4)
这是一个正确的解决方案
是的。让我尝试消除你使用堆栈的想法,考虑到@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中弹出一个元素,因此在每个步骤3之后,堆栈A的大小会减少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)
。
Sidenote - 每当考虑递归时,总是更容易想到它,就像函数深度调用展开然后返回值然后被收集以返回最终结果。
无论如何,我希望我能够澄清自己并希望这能让你开始朝着正确的方向前进。
答案 1 :(得分:0)
检查一下:
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
for (int i = 1; i < str.length(); i++)
{
if (str.charAt(i) == str.charAt(i-1))
{
str = str.substring(0, i-1) + str.substring(i+1);
i = 0;
}
}
if (str.length() == 0) {
System.out.println("Empty String");
} else {
System.out.println (str);
}
答案 2 :(得分:0)
package tryout.examples;
import java.util.Scanner;
public class RemovingAdjacentCharacterUsingStack
{
public static void main(String[] args)
{
Scanner in =new Scanner(System.in);
String str=in.next();
CharStack cs=new CharStack(10);
char [] arr=str.toCharArray();
for(int i=0;i<arr.length;i++)
{
if(i==0 || cs.top==-1)
{
cs.push(arr[i]);
}
else
{
if(cs.peek()==arr[i])
{
cs.pop();
}
else
{
cs.push(arr[i]);
}
}
}
System.out.println("after removing adjacent same characters-->");
cs.display();
}
}
class CharStack
{
private char[] finalCharArray;
public int top;
public CharStack(int capacity)
{
top = -1;
finalCharArray=new char[capacity];
}
public void push(char element)
{
finalCharArray[++top]=element;
}
public char pop()
{
return finalCharArray[top--];
}
public void display()
{
for(int i=0;i<=top;i++)
{
System.out.println(finalCharArray[i]);
}
}
public char peek()
{
return finalCharArray[top];
}
public boolean isEmpty() {
return (top == -1);
}
}