【问题标题】:Checking if two Strings are anagram of each other using basic Java [duplicate]使用基本Java检查两个字符串是否是彼此的字谜[重复]
【发布时间】:2016-07-10 21:43:03
【问题描述】:

我正在 java Netbeans 中编写以下代码,这对于正常的字谜非常有效。但是,如果两个文本字段包含包含重复字母的单词,则代码将无法工作。可能是什么问题,我该如何解决?我对 Java 很基础,还不能理解数组。

String s1= t1.getText(); 
String s2= t2.getText();  
int b=0,c=0;
if(s1.length()!=s2.length())
   System.out.print("No");
else {
   for(int i=0;i<s1.length();i++) {
      char s = s1.charAt(i);
      for(int j=0;j<s2.length();j++) {
         if(s==s2.charAt(j)){
            b++;
         } 
      }
      if(b==0)
         break;
   }
   if(b==0)
      System.out.print("No");
   else 
      System.out.print("YES");
} 
System.out.print(b);

【问题讨论】:

  • 请注意,您可以使用 toCharArray() 从字符串中获取两个 char 数组,使用 Arrays.sort 对它们进行排序,并确保两个数组具有完全相同的内容。
  • 我在某个地方看到过这个东西,但我对数组一点也不熟悉。难道没有其他方法可以使用吗?如果没有,我最好学习数组。
  • @prakharlondhe 无论如何你都应该学习数组。它们是编码中非常常见的数据结构。
  • @prakharlondhe 如果您正在寻找不使用数组的解决方案,您可以更新您的问题。

标签: java anagram


【解决方案1】:

我会寻求更简单的推理:如果两个字符串在排序后完全匹配,则它们是字谜。 所以在Java中它会是这样的:

    String s1 = "cat";
    String s2 = "tac";
    boolean isAnagram = false;
    if (s1.length() == s2.length()) {
        char[] s1AsChar = s1.toCharArray();
        char[] s2AsChar = s2.toCharArray();
        Arrays.sort(s1AsChar);
        Arrays.sort(s2AsChar);
        isAnagram = Arrays.equals(s1AsChar, s2AsChar);
    } 

【讨论】:

  • 如果长度不同,我会添加长度比较以快速失败
  • 哇,看来我应该发表我的评论作为答案:D。
  • @sasha 不需要 - Arrays.equals() 为你做这些
  • @Bohemian 我的意思是在排序之前,如果没有必要跳过它
  • @IvanValeriani 你是对的。我要看看到底什么是字谜。我的英语不好。删除我的帖子 5 ... 4 ...
【解决方案2】:

您想比较已排序的字符。这是一个单行:

return Arrays.equals(s1.chars().sorted().toArray(),
    s2.chars().sorted().toArray());

Arrays.equals() 为您比较长度和所有元素。

【讨论】:

    【解决方案3】:

    在我的解决方案中,我们计算第一个字符串中每个字符的出现次数,然后从第二个字符串中的计数中减去它。最后,检查字符数是否不为 0 则这两个字符串不是 anagram。

    public static boolean isAnagram(String a, String b){
        //assume that we are using ASCII
        int[] charCnt = new int[256];
        for(int i = 0; i < a.length(); i++){
            charCnt[a.charAt(i)]++;
        }
        for(int i = 0; i< b.length(); i++){
            charCnt[b.charAt(i)]--;
        }
        for(int i = 0; i<charCnt.length; i++){
            if(charCnt[i] != 0) return false;
        }
        return true;
    }
    

    【讨论】:

    • 对逻辑的一点改进:在第二个 for 循环中,确定 charCnt[b.charAt(i)] 是否小于 0
    【解决方案4】:

    由于您似乎是初学者,因此这里有一个不涉及其他类或流中的函数的解决方案。它只涉及数组的使用以及char 也可以代表int 的事实。

    public static void main(String[] args) throws ParseException {
        String s1= "anagram"; 
        String s2= "margana";  
        // We make use of the fact that a char does also represent an int.
        int lettersS1[] = new int[Character.MAX_VALUE];
        int lettersS2[] = new int[Character.MAX_VALUE];
        if(s1.length()!=s2.length())
           System.out.print("No");
        else {
           // Loop through the String once
           for(int i = 0; i<s1.length() ;++i) {
               // we can just use the char value as an index
               // and increase the value of it. This is our identifier how often 
               // each letter was aviable in the String. Alse case insensitive right now
               lettersS1[s1.toLowerCase().charAt(i)]++;
               lettersS2[s2.toLowerCase().charAt(i)]++;
           }
           // set a flag if the Strings were anagrams
           boolean anag = true;
           // We stop the loop as soon as we noticed they are not anagrams
           for(int i = 0;i<lettersS1.length&&anag;++i) {
               if(lettersS1[i] != lettersS2[i]) {
                   // If the values differ they are not anagrams.
                   anag = false;
               }
           }
           // Depending on the former loop we know if these two strings are anagrams
           if(anag) {
               System.out.print("Anagram");
           } else {
               System.out.print("No anagram");
           }
        } 
    }
    

    【讨论】:

      【解决方案5】:

      另一种解决方案,基于出现计数器:

      static boolean areAnagrams(CharSequence a, CharSequence b) {
          int len = a.length();
          if (len != b.length())
              return false;
      
          // collect char occurrences in "a"
          Map<Character, Integer> occurrences = new HashMap<>(64);
          for (int i = 0; i < len; i++)
              occurrences.merge(a.charAt(i), 1, Integer::sum);
      
          // for each char in "b", look for matching occurrence
          for (int i = 0; i < len; i++) {
              char c = b.charAt(i);
              int cc = occurrences.getOrDefault(c, 0);
              if (cc == 0)                        
                  return false;            
              occurrences.put(c, cc - 1);
          }
          return true;
      }
      

      虽然这个解决方案不如“排序和比较”那么优雅,但它可能更适用于不太可能成为字谜的长字符串,因为它在 O(n) 中运行而不是O(n logn) 并在第二个字符串的某个位置找不到匹配项时立即返回。


      走出“Basic Java”领域,我修改了算法来处理surrogate pairs。这里收集和匹配的不是chars,而是int codepoints:

      static boolean areAnagrams(CharSequence a, CharSequence b) {
          int len = a.length();
          if (len != b.length())
              return false;
      
          // collect codepoint occurrences in "a"
          Map<Integer, Integer> ocr = new HashMap<>(64);
          a.codePoints().forEach(c -> ocr.merge(c, 1, Integer::sum));
      
          // for each codepoint in "b", look for matching occurrence
          for (int i = 0, c = 0; i < len; i += Character.charCount(c)) {
              int cc = ocr.getOrDefault((c = Character.codePointAt(b, i)), 0);
              if (cc == 0)                        
                  return false;            
              ocr.put(c, cc - 1);
          }
          return true;
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-05
        • 2013-10-26
        • 2016-04-07
        • 1970-01-01
        • 2011-05-13
        • 2013-08-18
        • 2021-01-11
        • 2019-05-02
        相关资源
        最近更新 更多