我无法提出最佳解决方案(O(n)时间)以递归方式从字符串中删除相邻的重复项。我的尝试:
public static String removeDuplicate(String s) {
if ( s == null ) return null;
if ( s.length() <= 1 ) return s;
if( s.substring(1,2).equals(s.substring(0,1)))
return removeDuplicate(s.substring(1));
else return s.substring(0,1) + removeDuplicate(s.substring(1));
}
但它不适用于以下情况:
"azxxzy" -> "ay"
在上面的例子中,这些是字符串转换:
azxxzy azzy AY
示例输入输出:
输入:azxxzy输出:ay
输入:caaabbbaacdddd输出:空字符串
输入:acaaabbbacdddd输出:acac
更新
我已在下面发布了一个答案版本。
答案 0 :(得分:3)
正如您的问题评论中提到的那样,String
操作已经是O(n),因为String
是不可变的。这可以通过使用Character
s的数组来解决。由于您还要删除内容,因此您还应该在该数组中使用null
,以防止每次删除字符时都要移动内容。最后,您需要对数组进行额外的传递,以将其转换为字符串。
您要问的真正问题更简单。从xx
之类的字符串中删除azxxzy
会将xx
之前和之后的字符放在彼此旁边,它们可能是相同的。因此,只需再次检查:将光标放在一个位置。继续使用字符串zzy
而不是zy
。
复杂性将保持为O(n),因为每个字符最多检查两次,最多可以删除一次。
由于你专门要求一个递归的答案,我会假设这是一个家庭作业练习并将实现留给你(使用Character
数组并添加起始位置的索引作为方法的额外参数)。非递归算法会更高效,也更容易实现!
答案 1 :(得分:0)
我将它转换为char数组。此外,我不确定这完成的速度有多快,但你的问题似乎没有强调O-time,你只想要一个有效的(如果我正确地读了你的问题)。
转换为char数组意味着您不必使用不可变的字符串(因此每次进行更改时都必须重新构建它们)。
public static String removeDuplicate(String string) {
if(string == null) return null;
return String.copyValueOf(removeDuplicate(string.toCharArray()));
}
public static char[] removeDuplicate(char[] chars) {
if(chars.length < 1) return new char[0];
else if(chars.length == 1) return chars;
for(int i=0; i<chars.length-1; i++) {
if(chars[i] == chars[i+1]) {
char[] before = Arrays.copyOfRange(chars, 0, i);
char[] after = Arrays.copyOfRange(chars, i+2, chars.length);
char[] combined = new char[before.length + after.length];
System.arraycopy(before, 0, combined, 0, before.length);
System.arraycopy(after, 0, combined, before.length, after.length);
chars = removeDuplicate(combined);
break;
}
}
return chars;
}
你可以用这个来测试它:
public static void main(String args[]) {
System.out.println(removeDuplicate("azxxzy"));
System.out.println(removeDuplicate("Does this have any duplicates?"));
System.out.println(removeDuplicate("Nfggfoyy frttrfihht dfbllbfoedssssdsnpr''rp'tuiiu"));
}
答案 2 :(得分:0)
我想出了这个丑陋的解决方案,JasonC的想法(实际上我的第一个想法,我没有追求)将字符附加到输出中,以防万一从输出中删除相邻的重复。
public static String removeDuplicate(String s) {
StringBuilder builder = new StringBuilder();
char lastchar = '\0';
for (int i = 0; i < s.length(); i++) {
String str = builder.toString();
if (!str.equals("")
&& (str.charAt(str.length() - 1) == s.charAt(i))) {
builder.deleteCharAt(str.length() - 1);
} else if (s.charAt(i) != lastchar)
builder.append(s.charAt(i));
lastchar = s.charAt(i);
}
return builder.toString();
}
<强>更新强> 但最好的解决方案是:在this
的帮助下public static String removeDuplicates(String s) {
if (s.isEmpty()) {
return s;
}
char[] buf = s.toCharArray();
char lastchar = buf[0];
// i: index of input char
// o: index of output char
int o = 1;
for (int i = 1; i < buf.length; i++) {
if (o > 0 && buf[i] == buf[o - 1]) {
lastchar = buf[o - 1];
while (o > 0 && buf[o - 1] == lastchar) {
o--;
}
} else if (buf[i] == lastchar) {
// Don't copy to output
} else {
buf[o++] = buf[i];
}
}
return new String(buf, 0, o);
}
答案 3 :(得分:0)
您还可以使用堆栈:
public class StackDemo {
public static void main(String[] args) throws Exception {
CharStackArray stack = new CharStackArray(15);
char[] dupliactes = { 'a', 'z', 'x', 'x', 'z', 'y' };
stack.removeAdjacentDuplicate(dupliactes);
}
}
class CharStackArray {
private char[] array;
private int top;
private int capacity;
public void removeAdjacentDuplicate(char[] arr) throws Exception {
for (int i = 0; i < arr.length; i++) {
if (isEmpty()) { // if stack is empty
push(arr[i]);
display();
System.out.println();
} else {
int count = 0;
int j = i;
/*
* while top of stack is equal to next value in array (ie same
* adjacent values)
*/
while (j < arr.length && peek() == arr[j]) {
count++; // count of same occurences
j++;
}
if (count == 0) { // no same occurence
push(arr[i]); // push to stack
display();
System.out.println();
} else {
for (int k = 1; k < count; k++) // skip the array index for
// same adjacent duplicates
i++;
pop(); // pop the duplicate value from stack
display();
System.out.println();
}
}
}
}
public CharStackArray(int cap) {
capacity = cap;
array = new char[capacity];
top = -1;
}
public void push(char data) {
array[++top] = data;
}
public char pop() throws Exception {
return array[top--];
}
public void display() {
for (int i = 0; i <= top; i++) {
System.out.print(array[i] + "->");
}
}
public char peek() throws Exception {
return array[top];
}
public boolean isEmpty() {
return (top == -1);
}
}
<强>输出:强>
A-&GT;
A-&GT; Z-&GT;
A-&GT; Z-&GT; X-&GT;
A-&GT; Z-&GT;
A-&GT;
A-&GT; Y-&GT;
答案 4 :(得分:0)
非递归的简单解决方案是
public class RemoveAdjucentDuplicates {
public static void main(String[] args) {
String s = "azxxzy";
s = "geeksforgeeg";
System.out.println(remove(s));
}
static String remove(String s) {
char res[] = new char[s.length()];
int j = 0;
res[j] = s.charAt(0);
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) != res[j]) {
res[++j] = s.charAt(i);
} else {
res[j--] = '\u0000';
}
}
String result = String.valueOf(res);
return result.substring(0,j+1);
}
}
答案 5 :(得分:0)
public class RemoveAdjacant
{
public String replaceAdjacent(String s)
{
if (s.equals(""))
return s;
String adjacentString = "";
char cha;
int count = 1;
for (int i = 0; i < s.length(); i++)
{
cha = s.charAt(i);
adjacentString = adjacentString + cha;
for (int j = 1 + i; j < s.length(); j++)
{
if (cha == s.charAt(j))
{
adjacentString = adjacentString + cha;
count++;
} else
{
if (count >= 3)
break;
else
{
count = 1;
adjacentString = "";
break;
}
}
}
if (count >= 3)
{
int index = s.indexOf(adjacentString);
s = s.substring(0, index)
+ s.substring(index + adjacentString.length());
return replaceAdjacent(s);
}
}
return s;
}
public static void main(String[] args)
{
RemoveAdjacant ra = new RemoveAdjacant();
Scanner scan = new Scanner(System.in);
System.out.println("Enter string");
String s = scan.nextLine();
System.out.println("rem string=" + ra.replaceAdjacent(s));
}
}
答案 6 :(得分:0)
我猜,最好使用递归。此外,字符串到字符数组的转换也会消耗一些时间。所以,我更喜欢使用正常的字符串输入。
我的代码在某种程度上看起来如下(我使用过Java 8):
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch;
/*
"Given a string, remove the consecutive character pairs repetitively.
input: saabbs , output :
input: aaabbbccc , output : abc"
*/
class Solution {
public static String removeDuplicates(String s) {
int count=0;
String sout = "";
if (s.isEmpty() || s.length()==1) {
return s;
}
else{
s=s+" ";
for(int i=0; i<s.length()-1;i++){
if(s.charAt(i)!= s.charAt(i+1) || s.charAt(i+1)==' '){
sout = sout+s.charAt(i);
}else{
count++;
i=i+1;
}
}
}
//int count=0;
for(int i=0; i<sout.length()-1;i++){
if(sout.charAt(i)==sout.charAt(i+1))
count++;
}
if(count>0){
return removeDuplicates(sout);
}else
return sout;
}
public static void main(String[] args) throws IOException{
Stopwatch timer = Stopwatch.createStarted();
// String s = "saabbs";
String s1 = "aaabbbccc";
//System.out.println("Output1:\t"+removeDuplicates(s));
System.out.println("Output2:\t"+removeDuplicates(s1));
timer.stop();
System.out.printf("Time taken: %,10d microseconds\n", timer.elapsed(TimeUnit.MICROSECONDS));
}
}
答案 7 :(得分:0)
package algorithms;
public class Sample {
public static void main(String args[]){
new Sample().fix("Whaaaatupducck");
}
public void fix(String input){
StringBuilder sb = new StringBuilder();
for(int index = 0; index<input.length()-1 ;index++){
System.out.println("compare "+
input.charAt(index)+
" and "+
input.charAt(index+1));
if(input.charAt(index) == input.charAt(index+1)){
continue; // skipping repeats
}else{
sb.append(input.charAt(index));
}
if((index+2) == input.length()){
sb.append(input.charAt(index+1)); // handling last character
}
}
System.out.println("Result : "+sb.toString());
}
}
输出:
比较W和h |比较h和a |比较a和a比较a和a 比较a和a比较a和t |比较t和u |比较你和p | 比较p和d |比较d和u |比较你和c |比较c和c | 比较c和k |
结果:
Whatupduck
答案 8 :(得分:0)
这是删除所有相邻重复项的简单递归python解决方案。
def rmv(st,i):
if i==len(st)-1:
return
if not st:
return
if st[i]==st[i+1]:
tmp=st[i]
while(i<len(st) and st[i]==tmp):
st.pop(i)
if not i-1:
rmv(st,i-1)
else:
rmv(st,0)
else:
rmv(st,i+1)
inp=list("azxxzy")
rmv(inp,0)
print ''.join(inp)
该程序将 ay 打印为输出。
答案 9 :(得分:0)
另一个使用stack的解决方案:
private static String remove(String str1) {
StringBuilder sb = new StringBuilder();
Stack<Character> stack = new Stack<Character>();
stack.push(str1.charAt(0));
int inx = 1;
char lastDeleted = '\0';
while(!stack.isEmpty() && inx < str1.length()){
if(str1.charAt(inx) == stack.peek()) {
//repeating character found..
lastDeleted = stack.pop();
}else if(str1.charAt(inx) == lastDeleted) {
//repeating character found but already removed from the stack.
}else {
//when a new character is introduced..
stack.push(str1.charAt(inx));
}
inx++;
if(stack.isEmpty() && inx < str1.length()) {
//if stack is empty, then insert at least one element if present..
stack.push(str1.charAt(inx));
inx++;
}
}
if(stack.isEmpty()) {
return "";
}else {
while(!stack.isEmpty()) {
sb.insert(0, stack.pop());
}
}
return sb.toString();
}
答案 10 :(得分:0)
public class RemoveAdjacentDuplicates {
public static void main(String[] args) {
System.out.println(removeDuplicates("azxxzy"));
}
public static String removeDuplicates(String S) {
char[] stack = new char[S.length()];
int i = 0;
for(int j = 0 ; j < S.length() ; j++) {
char currentChar = S.charAt(j);
if(i > 0 && stack[i-1] == currentChar) {
i--;
}else {
stack[i] = currentChar;
i++;
}
}
return new String(stack , 0 , i);
}
}
该程序的结果是:
input - "azxxzy"
output - "ay"
答案 11 :(得分:0)
public static void removeDuplicates(String str)
{
if(str.length()<=1)
{
System.out.println(str);
return;
}
String n=new String();
int count=0;
for(int i=0;i<str.length();i++)
{
while(i<str.length()-1 && str.charAt(i)==str.charAt(i+1))
{
if(i<str.length()-2 && str.charAt(i)!=str.charAt(i+2))
i+=2;
else
i++;
count++;
}
if(i!=str.length()-1){
n=n+str.charAt(i);
}
else if(i==str.length()-1 && str.charAt(i)!=str.charAt(i-1)){
n=n+str.charAt(i);
}
}
if(count>0)
removeDuplicates(n);
else
System.out.println(n);
}
}
结果:
Input: acaaabbbacdddd
Output : acac
Input : azxxzy
Output: ay