如何计算字符串中唯一字符的数量?- 更新

6
例如,字符串“abc”应该包含3个唯一字符,而字符串“abcccd”应该包含4个唯一字符。在此过程中,我不允许使用Map、HashMap、TreeMap、Set、HashSet、StringBuffer或TreeSet。
到目前为止,我尝试使用for循环,但是当我运行程序时,得到的唯一字符数总是为0。由于我对Java相当陌生,因此我真的不知道应该怎么做。
编辑:所以我改变了代码,现在能够得到结果了,但是它的值比我想要的少1。例如输入'abc',结果会显示为“2个唯一字符”,而不是三个。为了解决这个问题,我在println语句中添加了(uniqueChars + 1)。这是一个好的修改吗?如果用户没有输入任何内容,程序将仍然显示有1个唯一字符。
更新后的代码:
    userText = userText.toLowerCase(); // userText is declared earlier in the program 
                                       // as the user's input. Setting this to lowercase 
                                       // so it doesn't say "a" and "A" are two different 
                                       // characters.
    int uniqueChars = 0;
    for (int i = 0; i < lengthText-1; i++) { // lengthText is declared earlier 
                                              // as userText.length();
        if (userText.charAt(i) != userText.charAt(i+1))
            uniqueChars++;
    }
    System.out.println("there are " + (uniqueChars + 1) + " unique characters in your string.");
}

3
你认为你的for循环会运行吗?看看你的终止条件。除此之外,你的逻辑有误,你只比较相邻的字符。 - Alexis C.
循环运行了,但是它给我错误的答案。如果我输入"abc",程序返回0个唯一字符,而不是3个。我还尝试在for循环中放置"i < lengthText",但仍然得到了错误的答案。 - newJavaUser
10个回答

4
这个怎么样?它是一个正则表达式解决方案,而不是循环:
public static int countUniqueCharacters(String input)
{
    String unique = input.replaceAll("(.)(?=.*?\\1)", "");
    return unique.length();
}

如果程序需要不区分大小写,可以使用以下代码替代:
public static int countUniqueCharacters(String input)
{
    String unique = input.replaceAll("(?i)(.)(?=.*?\\1)", "");
    return unique.length();
}

您可以将此方法改写成单行方法:return input.replaceAll(...).length(); 正则表达式解释:
  • .匹配任何字符
  • (...)创建一个捕获组,以便稍后引用
  • (?=...)创建一个前瞻,向前查看输入
  • .*?匹配字符和其匹配之间的任何内容(非贪婪匹配)
  • \\1匹配第一个捕获组
  • (?i)设置不区分大小写标志
因此,正则表达式将查找具有字符串中的重复项的任何字符,然后replaceAll将其替换为空字符串。 因此,像"cabbacbdbadbcabdaadcb"这样的输入会变为"adcb"(保留每个唯一字符的最后一个)。 然后,对于包含唯一字符的字符串,该字符串的长度就是答案。
如果出于某种原因,您需要唯一字符字符串,并且您需要它按原始顺序,则必须在剥离重复字符之前反转原始字符串(完成后再次反转)。 这将需要使用第三方库、StringBuffer或循环。

3
这是我想到的方案:
public static int countUniqueCharacters(String s) {
    String lowerCase = s.toLowerCase();
    char characters[] = lowerCase.toCharArray();
    int countOfUniqueChars = s.length();
    for (int i = 0; i < characters.length; i++) {
        if (i != lowerCase.indexOf(characters[i])) {
            countOfUniqueChars--;
        }
    }
    return countOfUniqueChars;
}

我只是逐个检查每个字符的索引,如果它与原始索引不同,就表示有多个出现次数。


你的答案有效!所以你最初将唯一字符的数量设置为长度,并将字符串转换为小写。然后,如果字符出现多次,您将通过多次出现的次数从唯一字符的数量中减去。谢谢! - newJavaUser
如果字符串s =“abcbc”,您的方法会返回3而不是1,对吗?因为indexOf()总是返回指定字符在此字符串中的第一个出现位置的索引。因此,对于稍后在字符串中出现的重复字符,它不会检测到第一次出现的重复字符。 - src3369
@src3369 是的,完全正确。 - Steffen
@Veluria:我想表达的是,这个解决方案行不通,因为它即使在字符串后面有重复出现的字符,仍然会将第一次出现的字符计算为唯一。 - src3369
@src3369 但这是有意的。请再次阅读原帖。 - Steffen

1
你可以创建一个名为uniqueChars的新字符串,并将其初始化为""。遍历要检查的字符串中的字符。如果uniqueChars.contains(charToCheck)false,则将该字符附加到uniqueChars。在循环结束时,uniqueChars.length()将告诉你有多少个唯一字符。虽然不太美观且效率低下,但应该可以工作。

1
这是一个关于如何编写文件、读取同一文件以及计算特定字符重复次数的程序:
package filereadexple;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;

        /*
         * This is a program here I am creating a file by using "filewriter" 
         * and it is named as count.char and I am reading a same file and 
         * then how count number of times the particular character repeated.
         */

public class CountNoOfPartChar {

    public static void main (String args[]){

        File file = new File ("count.char");

        try{
            FileWriter fw = new FileWriter("count.char");
            fw.write("In Xanadu did Kubla Khan");
            fw.write("\r\n");
            fw.write("A stately pleasure-dome decree:");
            fw.write("\r\n");
            fw.write("Where Alph, the sacred river, ran");
            fw.write("\r\n");
            fw.write("Through caverns measureless to man");
            fw.write("\r\n");
            fw.write("Down to a sunless sea.");
            fw.close();
            FileInputStream fis = new FileInputStream(file);
            int i;
            int occurs = 0;
            char current;
            while ((i=fis.available()) > 0){
                current = (char)fis.read();
                if(current == 'a'){
                    occurs++;
                }
            }
            System.out.println("The number of particular character repeated is : " + occurs);
        }
        catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}

1

使用 ArrayList,如果字符不存在,则添加一个字符:

list = new ArrayList<String>();
for ( /*   */ ) {  // same for loop you wrote
      String character = (String) text.charAt(i);

       if(!list.contains(character)) {  // note the '!'
            list.add(character);
       }
}

// and finally
int quantity = list.size();

0
      public class Main {
     public static void main(String[] args) {
   Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
getvalues(s1);
   }
         public static void getvalues(String s1) {
String s2 = s1.toLowerCase();
StringBuffer sb = new StringBuffer(s2);
int l = sb.length();
int count = 0;
for (int i = 0; i < l; i++) {
  count = 0;
  for (int j = i + 1; j < l; j++) {
    if (sb.charAt(i) == sb.charAt(j)) {
      sb.deleteCharAt(j);
      count++;
      j--;
      l--;
    }
  }
  if (count > 0) {
    sb.deleteCharAt(i);
    i--;
    l--;
  }
}
if (sb.length() == 0) {
  System.out.println(-1);
} else
  System.out.println(sb.length());
 }
 }

0
public class CharacterCount {
    public static void main(String[] args) {
        String s = "aaabbbcccddd";
        String t="";
        int count = 0;

        //Loop to find unique characters in a string and add it to new string called t
        //if a character is not found in a string indexOf returns -1
        for (int i = 0; i < s.length(); i++) {
            if (t.indexOf(s.charAt(i))==-1) t+=s.charAt(i);
        }

        //For every character new string t , loop though s find the count and display
        for (int i = 0; i < t.length(); i++) {
            count = 0;
            for (int j = 0; j < s.length(); j++) {
                if (t.charAt(i) == s.charAt(j)) count++;
            }
            System.out.println(t.charAt(i) + " " + count);
        }
    }
}

0
把它放进一个数组里,按字母顺序排序,然后应用你的逻辑(比较相邻的元素),这样怎么样?
v  = sort(v);//your sort method

int count = 0;
for (int i = 0;i< lengthText-1; i++) 
{ if v[i] == v[i + 1]  {
        i++;
    } else {
        count++;
    }
}

顺便说一下,你的程序不起作用是因为在你的for循环中使用了i == lengthText-1

0

与 @Alexandre Santos 相同的逻辑,但附有可工作的示例代码。复杂度为 O(N)。 仅适用于没有空格、数字或特殊字符的字母字符串。

这也可以用作 计数排序

public class CountChars 
{
    public static int countUniqCharacters(String str) {
        int[] counts = new int['z' - 'a' + 1];
        char[] arr = str.toLowerCase().toCharArray();

        for (char c: arr) {
            counts[c - 'a']++;
        }

        int unique = 0;
        for (int i: counts) {
            if (i > 0)
                unique++;
        }

        return unique;
    }

    public static void main(String[] args) {
        System.out.println("Unique char in " + args[0] 
                + " is " + CountChars.countUniqCharacters(args[0]));
    }
}

-1
使用向量。
    char[] letters = new char[26];
    for (char c : letters)
    {
        letters[c]=0;
    }

然后对于每个找到的字母,在向量中增加位置。如果任何条目的计数器大于1,则表示有重复。


那该怎么办呢?一个字符通常具有65-122的值范围,但这个数组没有这样的位置。 - Steffen
@Aru,使用c - 'A'(或者根据所需结果选择适当的方式)作为索引。但是,除非只使用字母并且检查不区分大小写/输入保证在一个大小写中,否则数组需要比26个元素更大。如果字符串中允许任何字符,则数组大小必须为65535(如果程序不区分大小写,则减去26)。 - Brian S
实际上,发布的特定循环将重复设置letters [0]'\0'。您需要使用普通的for循环来初始化默认值(尽管这不是必需的,因为char是一种原始类型)。将数组制作成int []对于计算重复项更好,或者如果只需要不同字母的数量,则使用boolean [] - Brian S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接