从Java中删除重复的string

我正在尝试迭代通过一个string,以删除重复的字符。

例如,stringaabbccdef应该成为abcdef ,stringabcdabcd应该成为abcd

这是我到目前为止:

 public class test { public static void main(String[] args) { String input = new String("abbc"); String output = new String(); for (int i = 0; i < input.length(); i++) { for (int j = 0; j < output.length(); j++) { if (input.charAt(i) != output.charAt(j)) { output = output + input.charAt(i); } } } System.out.println(output); } } 

什么是最好的方法来做到这一点?

将string转换为char数组,并将其存储在LinkedHashSet 。 这将保持您的sorting,并删除重复。 就像是:

 String string = "aabbccdefatafaz"; char[] chars = string.toCharArray(); Set<Character> charSet = new LinkedHashSet<Character>(); for (char c : chars) { charSet.add(c); } StringBuilder sb = new StringBuilder(); for (Character character : charSet) { sb.append(character); } System.out.println(sb.toString()); 

我会使用LinkedHashSet的帮助。 删除dups(因为我们正在使用一个集合,维护顺序,因为我们正在使用链接列表impl)。 这是一个肮脏的解决scheme。 可能还有更好的办法。

 String s="aabbccdef"; Set<Character> set=new LinkedHashSet<Character>(); for(char c:s.toCharArray()) { set.add(Character.valueOf(c)); } 

试试这个简单的解决

 public String removeDuplicates(String input){ String result = ""; for (int i = 0; i < input.length(); i++) { if(!result.contains(String.valueOf(input.charAt(i)))) { result += String.valueOf(input.charAt(i)); } } return result; } 

创build一个StringWriter。 在for循环中使用charAt(i)运行原始string。 保持chartypes的variables保持最后的charAt值。 如果迭代并且charAt值等于该variables中存储的值,则不要添加到StringWriter。 最后,使用StringWriter.toString()方法并获取一个string,然后用它来做你所需要的。

  String input = "AAAB"; String output = ""; for (int index = 0; index < input.length(); index++) { if (input.charAt(index % input.length()) != input .charAt((index + 1) % input.length())) { output += input.charAt(index); } } System.out.println(output); 

但是如果input具有相同的元素,或者它是空的,你不能使用它!

 public class RemoveRepeated4rmString { public static void main(String[] args) { String s = "harikrishna"; String s2 = ""; for (int i = 0; i < s.length(); i++) { Boolean found = false; for (int j = 0; j < s2.length(); j++) { if (s.charAt(i) == s2.charAt(j)) { found = true; break; //don't need to iterate further } } if (found == false) { s2 = s2.concat(String.valueOf(s.charAt(i))); } } System.out.println(s2); } } 

这是Dave对答案的改进。

它使用HashSet而不是稍微更昂贵的LinkedHashSet ,并重新使用结果的chars缓冲区,消除了对StringBuilder的需要。

 String string = "aabbccdefatafaz"; char[] chars = string.toCharArray(); Set<Character> present = new HashSet<>(); int len = 0; for (char c : chars) if (present.add(c)) chars[len++] = c; System.out.println(new String(chars, 0, len)); // abcdeftz 

你不能。 您可以创build一个删除重复项的新string。 你为什么不使用StringBuilder(或者StringBuffer,据推测)?

您可以运行string并将唯一字符存储在char []数组中,以跟踪您所看到的唯一字符。 然后你可以使用String(char[], int, int)构造函数创build一个新的String。

此外,这个问题有点模棱两可 – “重复”意味着相邻的重复吗? (换句话说, abcab会发生什么?)

好的伙计们,我find了一个更好的方法来做到这一点

 public static void alpha(char[] finalname) { if (finalname == null) { return; } if (finalname.length <2) { return; } char empty = '\000'; for (int i=0; i<finalname.length-1; i++) { if (finalname[i] == finalname[i+1]) { finalname[i] = empty; } } String alphaname = String.valueOf(finalname); alphaname = alphaname.replace("\000", ""); System.out.println(alphaname); } 

Oldschool的方式(正如我们在苹果写这样的任务)[基本,适应Java]:

 int i,j; StringBuffer str=new StringBuffer(); Scanner in = new Scanner(System.in); System.out.print("Enter string: "); str.append(in.nextLine()); for (i=0;i<str.length()-1;i++){ for (j=i+1;j<str.length();j++){ if (str.charAt(i)==str.charAt(j)) str.deleteCharAt(j); } } System.out.println("Removed non-unique symbols: " + str); 

删除string中的重复字符而不使用任何附加缓冲区的代码。 注:一个或两个额外的variables是好的。 额外的数组不是:

 import java.util.*; public class Main{ public static char[] removeDupes(char[] arr){ if (arr == null || arr.length < 2) return arr; int len = arr.length; int tail = 1; for(int x = 1; x < len; x++){ int y; for(y = 0; y < tail; y++){ if (arr[x] == arr[y]) break; } if (y == tail){ arr[tail] = arr[x]; tail++; } } return Arrays.copyOfRange(arr, 0, tail); } public static char[] bigArr(int len){ char[] arr = new char[len]; Random r = new Random(); String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-=_+[]{}|;:',.<>/?`~"; for(int x = 0; x < len; x++){ arr[x] = alphabet.charAt(r.nextInt(alphabet.length())); } return arr; } public static void main(String args[]){ String result = new String(removeDupes(new char[]{'a', 'b', 'c', 'd', 'a'})); assert "abcd".equals(result) : "abcda should return abcd but it returns: " + result; result = new String(removeDupes(new char[]{'a', 'a', 'a', 'a'})); assert "a".equals(result) : "aaaa should return a but it returns: " + result; result = new String(removeDupes(new char[]{'a', 'b', 'c', 'a'})); assert "abc".equals(result) : "abca should return abc but it returns: " + result; result = new String(removeDupes(new char[]{'a', 'a', 'b', 'b'})); assert "ab".equals(result) : "aabb should return ab but it returns: " + result; result = new String(removeDupes(new char[]{'a'})); assert "a".equals(result) : "a should return a but it returns: " + result; result = new String(removeDupes(new char[]{'a', 'b', 'b', 'a'})); assert "ab".equals(result) : "abba should return ab but it returns: " + result; char[] arr = bigArr(5000000); long startTime = System.nanoTime(); System.out.println("2: " + new String(removeDupes(arr))); long endTime = System.nanoTime(); long duration = (endTime - startTime); System.out.println("Program took: " + duration + " nanoseconds"); System.out.println("Program took: " + duration/1000000000 + " seconds"); } } 

如何阅读和谈论上面的代码:

  1. 名为removeDupes的方法需要一个名为arr的原始字符数组。
  2. arr作为原始字符数组“按值”返回。 传入的arr是在Main的成员方法removeDupes的末尾收集的垃圾。
  3. 该algorithm的运行时复杂度是O(n),或者更具体地说是O(n +(小常量)),该常量是整个原始字符数组中的唯一字符。
  4. copyOfRange不会显着增加运行时复杂度,因为它只复制一个小的常量项目。 被称为arr的char数组并没有一路走过。
  5. 如果您将null传递给removeDupes,则该方法返回null。
  6. 如果传递一个空的原始字符数组或一个包含一个值的数组,则返回未修改的数组。
  7. removeDupes方法的速度与物理上尽可能的快,充分利用L1和L2caching,所以分支redirect保持在最低限度 。
  8. 一个2015年的标准问题,负担不起的计算机应该能够完成这个方法与一个原始的字符数组,包含15亿和25秒之间的5亿字符。

解释这个代码是如何工作的:

传入数组的第一部分用作最终返回的唯一字符的存储库。 在函数的开始处,答案是:“0和1之间的字符”在0和尾部之间。

我们在循环之外定义variablesy,因为我们想要find我们正在查看的数组索引已经在仓库中重复的第一个位置。 当find一个副本时,发生重复并退出,y ==尾部返回false,并且存储库不被提供。

当我们正在查看的索引x没有在我们的仓库中被表示时,那么我们将这个索引拖到我们仓库的尾部,并在索引尾部和尾部增加尾部。

最后,我们返回数组0和尾部之间的数组,它应该小于或等于原始数组的长度。

针对编码采访的谈话要点:

如果将y ++更改为++ y,程序的行为会有所不同吗? 为什么或者为什么不。

最后的数组拷贝是否代表O(n)代表运行时复杂度为O(n * n)而不是O(n)的另一个“N”传递? 为什么或者为什么不。

你可以用一个.equalsreplacedouble等于比较原始字符吗? 为什么或者为什么不?

这种方法可以改变,以便“替代”,而不是像现在这样“按价值”? 为什么或者为什么不?

你可以通过在'arr'开头sorting唯一值的存储库来提高这个algorithm的效率吗? 在哪种情况下会更有效率?

这是我想分享的另一个逻辑。 你从string长度的中间开始比较,然后往后走。

testing:input =“azxxzy”; 输出=“ay”;

 String removeMidway(String input){ cnt = cnt+1; StringBuilder str = new StringBuilder(input); int midlen = str.length()/2; for(int i=midlen-1;i>0;i--){ for(int j=midlen;j<str.length()-1;j++){ if(str.charAt(i)==str.charAt(j)){ str.delete(i, j+1); midlen = str.length()/2; System.out.println("i="+i+",j="+j+ ",len="+ str.length() + ",midlen=" + midlen+ ", after deleted = " + str); } } } return str.toString(); } 

这是另一种方法

 void remove_duplicate (char* str, int len) { unsigned int index = 0; int c = 0; int i = 0; while (c < len) { /* this is just example more check can be added for capital letter, space and special chars */ int pos = str[c] - 'a'; if ((index & (1<<pos)) == 0) { str[i++] = str[c]; index |= (1<<pos); } c++; } str[i] = 0; } 

如果string是ASCIIstring,另一个可能的解决scheme是维护一个由256个布尔元素组成的数组,以表示string中的ASCII字符外观。 如果一个angular色第一次出现,我们保留它并附加到结果。 否则,只需跳过它。

 public String removeDuplicates(String input) { boolean[] chars = new boolean[256]; StringBuilder resultStringBuilder = new StringBuilder(); for (Character c : input.toCharArray()) { if (!chars[c]) { resultStringBuilder.append(c); chars[c] = true; } } return resultStringBuilder.toString(); } 

这种方法也将使用Unicodestring。 你只需要增加chars大小。

使用JDK7的解决scheme:

 public static String removeDuplicateChars(final String str){ if (str == null || str.isEmpty()){ return str; } final char[] chArray = str.toCharArray(); final Set<Character> set = new LinkedHashSet<>(); for (char c : chArray) { set.add(c); } final StringBuilder sb = new StringBuilder(); for (Character character : set) { sb.append(character); } return sb.toString(); } 
  public static void main(String a[]){ String name="Madan"; System.out.println(name); StringBuilder sb=new StringBuilder(name); for(int i=0;i<name.length();i++){ for(int j=i+1;j<name.length();j++){ if(name.charAt(i)==name.charAt(j)){ sb.deleteCharAt(j); } } } System.out.println("After deletion :"+sb+""); } 
  String str = "eamparuthik@gmail.com"; char[] c = str.toCharArray(); String op = ""; for(int i=0; i<=c.length-1; i++){ if(!op.contains(c[i] + "")) op = op + c[i]; } System.out.println(op); 
 public static String removeDuplicateChar(String str){ char charArray[] = str.toCharArray(); StringBuilder stringBuilder= new StringBuilder(); for(int i=0;i<charArray.length;i++){ int index = stringBuilder.toString().indexOf(charArray[i]); if(index <= -1){ stringBuilder.append(charArray[i]); } } return stringBuilder.toString(); } 
 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class RemoveDuplicacy { public static void main(String args[])throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Enter any word : "); String s = br.readLine(); int l = s.length(); char ch; String ans=" "; for(int i=0; i<l; i++) { ch = s.charAt(i); if(ch!=' ') ans = ans + ch; s = s.replace(ch,' '); //Replacing all occurrence of the current character by a space } System.out.println("Word after removing duplicate characters : " + ans); } } 
 import java.util.Scanner; public class dublicate { public static void main(String... a) { System.out.print("Enter the String"); Scanner Sc = new Scanner(System.in); String st=Sc.nextLine(); StringBuilder sb=new StringBuilder(); boolean [] bc=new boolean[256]; for(int i=0;i<st.length();i++) { int index=st.charAt(i); if(bc[index]==false) { sb.append(st.charAt(i)); bc[index]=true; } } System.out.print(sb.toString()); } } 
 public static void main(String[] args) { int i,j; StringBuffer str=new StringBuffer(); Scanner in = new Scanner(System.in); System.out.print("Enter string: "); str.append(in.nextLine()); for (i=0;i<str.length()-1;i++) { for (j=1;j<str.length();j++) { if (str.charAt(i)==str.charAt(j)) str.deleteCharAt(j); } } System.out.println("Removed String: " + str); } 

这是@Dave提出的解决scheme的改进。 在这里,我只在单循环中实现。

让我们重复使用 set.add(T item)方法的返回 ,并且如果add是成功的,则将其同时添加到StringBuffer中

这只是O(n)。 没有必要再做一个循环。

 String string = "aabbccdefatafaz"; char[] chars = string.toCharArray(); StringBuilder sb = new StringBuilder(); Set<Character> charSet = new LinkedHashSet<Character>(); for (char c : chars) { if(charSet.add(c) ){ sb.append(c); } } System.out.println(sb.toString()); // abcdeftz 

简单的解决方法是遍历给定的string,并将每个唯一的字符放入另一个string(在本例中为variables结果 ),如果该string不包含该特定字符,则最终返回结果string作为输出。

下面是工作和testing的代码片段,用于删除具有O(n)时间复杂度的给定string中的重复字符。

 private static String removeDuplicate(String s) { String result=""; for (int i=0 ;i<s.length();i++) { char ch = s.charAt(i); if (!result.contains(""+ch)) { result+=""+ch; } } return result; } 

如果input是夫人,那么输出将是疯狂的
如果input是anagram,那么输出将是angrm

希望这可以帮助。
谢谢

为了简单的代码 – 我已经采取了硬核input,也可以通过使用Scanner类input

  public class KillDuplicateCharInString { public static void main(String args[]) { String str= "aaaabccdde "; char arr[]= str.toCharArray(); int n = arr.length; String finalStr=""; for(int i=0;i<n;i++) { if(i==n-1){ finalStr+=arr[i]; break; } if(arr[i]==arr[i+1]) { continue; } else { finalStr+=arr[i]; } } System.out.println(finalStr); } }