2010-08-23 110 views
5

我的问题是,我有2个字符串,说String1 & String2。现在我想检查这两个字符串是否包含相同的字符,而不管它们的顺序如何。如何比较包含相同字符的2个字符串

假设String1= "qwerty"String2= "qywter"。现在这些字符串包含相同的字符,但顺序不同。那么是否有任何函数可以用来表明这些字符串包含相同的字符?可以equals()方法做到这一点?

所有帮助表示赞赏。

+6

应的结果是在什么情况下,他们有相同的字符,但不相同的字符数? (如“qwerty”和“qywtery”?)它们包含相同的字符,但不包含相同数量的字符。 – MikeTheReader 2010-08-23 18:29:26

回答

17
char[] chars1 = string1.toCharArray(); 
char[] chars2 = string2.toCharArray(); 
Arrays.sort(chars1); 
Arrays.sort(chars2); 

return Arrays.equals(chars1, chars2); 
+1

但他们返回什么? – prasad 2010-08-23 18:36:17

+0

@prasad - 我不明白你的评论 – Bozho 2010-08-23 18:37:48

+0

我的意思是,做“返回Arrays.equals(chars1,chars2);”声明 返回一个布尔值或一个int? – prasad 2010-08-23 18:39:26

2

您可以使用String.equals,尽管是间接的。首先,你需要一个辅助方法:

// given a String, sorts its chars and return it as another String 
public static String sorted(String s) { 
    char[] arr = s.toCharArray(); 
    Arrays.sort(arr); 
    return new String(arr); 
} 

然后,你可以有:

String s1 = "qwerty"; 
    String s2 = "qywter"; 

    System.out.println(sorted(s1)); // eqrtwy 

    System.out.println(sorted(s1).equals(sorted(s2))); // true 

注意,这不是最有效的算法 - 这是O(N log N)时间,并利用多余的空间 - 但应该工作罚款的短弦。对于长字符串,您希望手动通过每个char(或Unicode代码点)(而不是toCharArray()),并且可能使用线性时间counting sort

如果你不关心具体的字符数匹配(例如"xxxyyy""xy"具有相同的字符,尽管在不同的数字),那么你可以使用一组类似的表示(java.util.BitSet)。

// given a string, returns its used char set as a java.util.BitSet 
public static BitSet usedChar(String s) { 
    BitSet bs = new BitSet(); 
    for (int i = 0; i < s.length(); i++) { 
     bs.set(s.charAt(i)); 
    } 
    return bs; 
} 

然后,你可以有:

System.out.println(
     usedChar("xxxyyy").equals(usedChar("xy")) 
    ); // true 

    System.out.println(
     usedChar("xyz").equals(usedChar("abc")) 
    ); // false 
2

这取决于你是否真的想要的字符或你真的想码点,然后它的事项是否要算重复与否。这里有一个解决方案:

public class a { 
    public static void main(String[] args) { 
    String s1 = "qwerty"; 
    String s2= "qywter"; 
    System.out.println(codePointSet(s1).equals(codePointSet(s2))); 
    } 
    public static Set<Integer> codePointSet(String s) { 
    Set<Integer> set = new TreeSet<Integer>(); 
    for (int i = 0, cp; i < s.length(); i += Character.charCount(i)) { 
     cp = s.codePointAt(i); 
     set.add(cp); 
    } 
    return set; 
    } 
} 
0

String.equals()将不适用于您的特定情况。您可能需要编写自己的方法来以这种方式来对字符串进行等同处理。

1
int[] f = new int[(int)char.MaxValue]; 
foreach (var c in string1) f[(int)c]++; 
foreach (var c in string2) f[(int)c]--; 
return f.Max() == 0 && f.Min() == 0; 

当string1.length()>> char.MaxValue和它具有较低的大O符号复杂度时,这是更好的解决方案。

编辑这实际上是C#代码,但您可以很容易地在Java中实现类似的结果。

+0

有趣的方法,但肯定不是Java。 – 2010-08-23 18:33:13

0

如果您有需要比较长的字符串,你并不需要成功的保证,你可以做这样的事情:

  1. 确保字符串的长度相同
  2. 为每个图像
  3. 加起来所有字符(铸成整数)
  4. 加起来字符的平方(再次铸成整数)
  5. 比较平方和和资金
  6. 如果它们相同,则字符串包含相同的字符。

其实我花了一些时间试图弄清楚哪里不行,但我想不出一个。我的直觉告诉我,我在这里错过了一些东西,或者这是一个很好的比较器。

0

两个步骤需要

  1. 做两个字符串的异或,如果XOR为0,那么你肯定部分。

  2. 如果xor为0,则找到两个字符串的ascii值的总和,如果ascii总和相同,则 这两个字符串都是相同的。

希望这有助于