【问题标题】:How can I find the number of unique characters in a string?如何找到字符串中唯一字符的数量?
【发布时间】:2014-08-25 17:15:48
【问题描述】:

我没有发现任何特别的用途。

我正在尝试找出一个函数来计算字符串中每个字符的出现次数,以便我可以从长度的末尾将它们拉出来,以找出该字符串中使用了多少同质字符。

我尝试过使用嵌套循环,第一个应用,第二个扫描字符串,如果它没有出现在字符串的其他地方,则有条件地满足字符:

size_t CountUniqueCharacters(char *str)
{
    int i,j;
    char unique[CHAR_MAX];
    for(i=strlen(str); i>=0; i--)
    {
        for(j=strlen(str); j>=0; j--)
        {
            if(str[i] != unique[j])
                unique[j] = str[i];
        }
    }
    return strlen(unique);
}

这并不好。

如果您愿意限制某人键入诸如 "aaaaaaaaaaaaa" 之类的懒惰名称,这将非常有用。

【问题讨论】:

  • 这真的不是什么大问题,它非常接近于“我可以拥有 teh codez”,这对于这个论坛来说通常不是最佳选择。
  • 我没有要求“代码”,小标题清楚地说明了问题所在。寻找一个函数或方法.. 我没有说我需要一个完整的代码。伪代码也适合我。
  • 我不完全理解这个问题(第二句话对我来说毫无意义) - 您是否正在寻找一种方法,它需要一个字符串和一个字符并返回该字符在字符串?
  • @Daniel noo.. 正如标题所说的“所有字符出现”。这意味着类似.. char* str = "Cannono"; printf("%i", ccnt(str)); 返回 4 因为在“Cannono”中我们有 4 个不同的字符。
  • 哦,您正在寻找字符串中 unique 字符的数量。你试过什么?

标签: c count character charactercount


【解决方案1】:

这是一个简单的 C++ 解决方案。此方法复杂度为 O(n):

int countDistinct(string s) 
{ 

    unordered_map<char, int> m; 
  
    for (int i = 0; i < s.length(); i++) { 
        m[s[i]]++; 
    } 
  
    return m.size(); 
} 

【讨论】:

  • 你应该分析unordered_map机制的复杂度,这样整体复杂度不会导致O(n),我认为。
  • 据我所知,unordered_map 的复杂度为 O(n)
  • 这个答案太长了,您不需要跟踪频率,因此可以使用 unordered_set。请参阅下面的answer,它在相同的时间复杂度下更短。
【解决方案2】:

此方法具有O(n^2) 的复杂性,但在O(n) 中执行此操作非常有可能(虽然有点复杂)。

int CountUniqueCharacters(char* str){
    int count = 0;

    for (int i = 0; i < strlen(str); i++){
         bool appears = false;
         for (int j = 0; j < i; j++){
              if (str[j] == str[i]){
                  appears = true;
                  break;
              }
         }

         if (!appears){
             count++;
         }
    }

    return count;
}

该方法遍历字符串中的所有字符 - 对于每个字符,它检查该字符是否出现在任何先前的字符中。如果不是,则该字符是唯一的,并且计数会增加。

【讨论】:

  • 我做了完全相同的事情,但是有一个逻辑错误.. 没有将条件放在第二个循环之后的第一个循环中。
【解决方案3】:

我发现以下计算不同字符的方法非常简单,在O(n) 中。 这里的逻辑是,只要遍历字符数组,对于每个字符 计数1,即使它重复,也只需用1 覆盖该值。 完成遍历后,只需对所有字符的出现求和即可。

int count_distinc_char(const char *a){
     int c_arr[MAX_CHAR] = {0};
     int i, count = 0;
     for( i = 0; a[i] != '\0'; i++){
         c_arr[a[i] - 'a'] = 1;
     }    
     for( i = 0; i < MAX_CHAR; i++){
         count += c_arr[i];
     }
     return count;
}

【讨论】:

    【解决方案4】:

    您可以为此目的使用 HashSet 或 unordered_set,但它的最坏情况时间复杂度为 O(N)。因此,最好使用 256 个内存位置的数组或arr[256]。这在 O(256)~ O(1) 时间内给出了所需的输出

    【讨论】:

      【解决方案5】:

      创建一个链表来存储字符串中找到的字符及其出现的节点结构如下,

      struct tagCharOccurence 
      {
          char ch;
          unsigned int iCount;
      };
      

      现在一个一个地读取字符串中的所有字符,当你读取一个字符时,检查它是否存在于你的链表中,如果是,则增加它的计数,如果在链表中找不到字符,则插入一个新节点将“ch”设置为读取字符并将计数初始化为一。

      通过这种方式,您将仅在单次传递中获得每个字符的出现次数。 您现在可以使用链表打印字符的次数与遇到的次数一样多。

      【讨论】:

        【解决方案6】:

        我在 Stack Overflow 上寻找其他内容时遇到了这个问题。但我仍然发布了一个可能对某些人有帮助的解决方案:

        这也用于实现 huffman conding here。在那里你需要知道每个字符的频率,所以比你需要的多一点。

        #include <climits>
        const int UniqueSymbols = 1 << CHAR_BIT;
        const char* SampleString = "this is an example for huffman encoding";
        

        左移运算符向左移动 lhs(即 1)CHAR_BIT 次,因此乘以 2^8(在大多数计算机上)为 256,因为 UTF-8 中有 256 个唯一符号

        在您的main 中有

        int main() {
            // Build frequency table
            int frequencies[UniqueSymbols] = {0};
            const char* ptr = SampleString;
            while (*ptr != '\0') {
                ++frequencies[*ptr++];
            }
        }
        

        我发现它非常小而且很有帮助。唯一的缺点是这里frequencies的大小是256,唯一性就是检查哪个值是1。

        【讨论】:

        • 感谢您的跟进。这似乎是查找表的变体。它们的缺点通常是占用了大量内存,但速度非常快且易于实现。
        【解决方案7】:

        如果您使用的是 C++,这里有一个具有最佳时间复杂度的单线:

        int numUniqeChars = std::unordered_set<char>(std::begin(str), std::end(str)).size();
        
        

        【讨论】:

        • 你是说int numUniqeChars = std::size(std::unordered_set&lt;char&gt;(std::begin(str), std::end(str)));
        • @gov 是的,感谢您的关注,现在已修复。
        • 因为c++11不支持std::size,可以使用std::unordered_set&lt;char&gt; uset(std::begin(str), std::end(str)); int numUniqeChars = uset.size();
        • @gov 很好的标注,我更改了答案以使其适用于旧版本的 C++。
        【解决方案8】:

        在这个算法中,成本更低,速度更高。因为每次搜索都是在一个较小的字符串中完成的。它也不需要在字符串或“拆分”或“(列表或数组)”之间进行比较。

        QString out = "";
        QString str = "Does he not know that God sees?";
        while (str.size() > 0) {
           out += str[0];
           str = str.replace(str[0],"",Qt::CaseInsensitive);
        }
        qDebug() << out << out.size();
        

        输出:“是 hntkwaG 吗?” 13

        忽略不区分大小写并在字母之间使用 ,。

        QString out = "";
        QString str = "Does he not know that God sees?";
        while (str.size() > 0) {
           out += str[0];
           if(str.size() != 1)
               out += ',';
           str = str.replace(str[0],"");
        }
        qDebug() << out;
        

        输出: "D,o,e,s, ,h,n,t,k,w,a,G,d,?"

        要排序,请参考此链接:Sort filenames naturally with Qt

        【讨论】:

          【解决方案9】:

          这里是计算唯一字数的 C 程序的源代码。 C程序编译成功,在Linux系统上运行

          int i = 0, e, j, d, k, space = 0;
          
          char a[50], b[15][20], c[15][20];
          
          
          
          printf("Read a string:\n");
          
          fflush(stdin);
          
          scanf("%[^\n]s", a);
          
          for (i = 0;a[i] != '\0';i++)        //loop to count no of words
          
          {
          
              if (a[i] =  = ' ')
          
                  space++;
          
          }
          
          i = 0;
          
          for (j = 0;j<(space + 1);i++, j++)    //loop to store each word into an 2D array
          
          {
          
              k = 0;
          
              while (a[i] != '\0')
          
              {
          
                  if (a[i] == ' ')
          
                  {
          
                      break;
          
                  }
          
                  else
          
                  {
          
                      b[j][k++] = a[i];
          
                      i++;
          
                  }
          
              }
          
              b[j][k] = '\0';
          
          }
          
          i = 0;
          
          strcpy(c[i], b[i]);
          
          for (e = 1;e <= j;e++)        //loop to check whether the string is already present in the 2D array or not
          
          {
          
              for (d = 0;d <= i;d++)
          
              {
          
                  if (strcmp(c[i], b[e]) == 0)
          
                      break;
          
                  else
          
                  {
          
                      i++;
          
                      strcpy(c[i], b[e]);
          
                      break;
          
                  }
          
              }
          
          }
          
          printf("\nNumber of unique words in %s are:%d", a, i);
          
          return 0;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-01-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-07-09
            相关资源
            最近更新 更多