C++ 在单个字符串中查找重复次数最多和次最多的字符

C++ 在单个字符串中查找重复次数最多和次最多的字符,c++,C++,我可以找到重复次数最多的字符,但是我找不到第二个重复次数最多的字符 我不明白找到第二重复字符的逻辑 void most_frequent_letter(string str, struct frequents result[]) int len = str.length(); int max = 0, i = 0, k = 0, Secmax = 0, m = 0; for (i = 0 ; i <= len; ++i) { if (str[i] >

我可以找到重复次数最多的字符,但是我找不到第二个重复次数最多的字符

我不明白找到第二重复字符的逻辑

void most_frequent_letter(string str, struct frequents result[])



    int len = str.length();

    int max = 0, i = 0, k = 0, Secmax = 0, m = 0;

for (i = 0 ; i <= len; ++i)
{
    if (str[i] >= 48 && str[i] <= 57)
    {
        result[0].count = 0;
        break;
    }
    if(str[i] >= 65 && str[i] <= 90)
    {
        str[i] += 32;

    }
    result[i].letter = str[i];
    result[i].count++;

    if (result[i].count > max && result[i].letter != ' ')
    {
        max = result[i].count;
        result[0].count = result[i].count;
        result[0].letter = str[i];

    }


}
cout << result[0].letter << endl;
void most\u frequents\u字母(string str,struct frequents result[])
int len=str.length();
int max=0,i=0,k=0,Secmax=0,m=0;
对于(i=0;i=48&&str[i]=65&&str[i]max&&result[i]。字母!=“”)
{
max=结果[i]。计数;
结果[0]。计数=结果[i]。计数;
结果[0],字母=str[i];
}
}

cout没有给出
struct frequents
背后的详细信息,但从提供的代码中,我猜只考虑了字母(
isalpha()
)。
虽然问题中的代码看起来像C,但它被标记为C++,使用了<代码> STD::String >,因此这里提出C++解决方案。 建议的解决方案使用每个字母带有一个计数器的向量(
'a'
'z'
)。
第一阶段包括计算句子中字母的每次出现次数(忽略大小写)。
然后在该向量中找到最大元素,得到重复次数最多的字母。
在取消相应计数器后,同一向量中的下一个最大元素给出第二个重复次数最多的字母

#include <iostream>
#include <string>
#include <cctype>
#include <vector>
#include <algorithm>

std::vector<int> // letter counts
count_letters(const std::string &str)
{
  auto counts=std::vector<int>(1+'z'-'a');
  for(const auto &c: str)
  {
    if(std::isalpha(c))
    {
      ++counts[std::tolower(c)-'a'];
    }
  }
  return counts;
}

int
main()
{
  const auto txt=std::string{"Here is a sentence"};
  auto counts=count_letters(txt);
  const auto max_iter=std::max_element(cbegin(counts), cend(counts));
  const auto max_index=std::distance(cbegin(counts), max_iter);
  std::cout << "max: " << char('a'+max_index)
                       << " (" << counts[max_index] << ")\n";
  counts[max_index]=0; // cancel first max found
  const auto second_max_iter=std::max_element(cbegin(counts), cend(counts));
  const auto second_max_index=std::distance(cbegin(counts), second_max_iter);
  std::cout << "second max: " << char('a'+second_max_index)
                              << " (" << counts[second_max_index] << ")\n";
  return 0;
}

struct frequents
后面的细节没有给出,但从提供的代码中,我猜只考虑了字母(
isalpha()
) 虽然问题中的代码看起来像C,但它被标记为C++,使用了<代码> STD::String >,因此这里提出C++解决方案。 建议的解决方案使用每个字母带有一个计数器的向量(
'a'
'z'
)。
第一阶段包括计算句子中字母的每次出现次数(忽略大小写)。
然后在该向量中找到最大元素,得到重复次数最多的字母。
在取消相应计数器后,同一向量中的下一个最大元素给出第二个重复次数最多的字母

#include <iostream>
#include <string>
#include <cctype>
#include <vector>
#include <algorithm>

std::vector<int> // letter counts
count_letters(const std::string &str)
{
  auto counts=std::vector<int>(1+'z'-'a');
  for(const auto &c: str)
  {
    if(std::isalpha(c))
    {
      ++counts[std::tolower(c)-'a'];
    }
  }
  return counts;
}

int
main()
{
  const auto txt=std::string{"Here is a sentence"};
  auto counts=count_letters(txt);
  const auto max_iter=std::max_element(cbegin(counts), cend(counts));
  const auto max_index=std::distance(cbegin(counts), max_iter);
  std::cout << "max: " << char('a'+max_index)
                       << " (" << counts[max_index] << ")\n";
  counts[max_index]=0; // cancel first max found
  const auto second_max_iter=std::max_element(cbegin(counts), cend(counts));
  const auto second_max_index=std::distance(cbegin(counts), second_max_iter);
  std::cout << "second max: " << char('a'+second_max_index)
                              << " (" << counts[second_max_index] << ")\n";
  return 0;
}

这是一个很好的例子,如果您愿意,可以对其进行优化

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <iterator>

void find_most_repeated(std::string strData)
{
    std::map<char, int> mChars;

    for (int i = 0; i < strData.size(); i++)
        mChars[strData[i]] ++;

    std::vector<std::pair<char, int>> v{ std::make_move_iterator(begin(mChars)), std::make_move_iterator(end(mChars)) };

    std::sort(begin(v), end(v), 
        [](const std::pair<char, int>&  p1, const std::pair<char, int>&  p2) {return p1.second > p2.second; });

    std::cout << v[0].first << " " << v[1].first << std::endl;
}

int main()
{
    find_most_repeated(std::string("asdaaaasssaaaaa"));
}
#包括
#包括
#包括
#包括
#包括
#包括
void find_most_repeated(std::string strData)
{
标准::map mChars;
对于(int i=0;ip2.second;});

std::cout这是一个运行良好的示例,如果您愿意,可以对其进行优化

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <iterator>

void find_most_repeated(std::string strData)
{
    std::map<char, int> mChars;

    for (int i = 0; i < strData.size(); i++)
        mChars[strData[i]] ++;

    std::vector<std::pair<char, int>> v{ std::make_move_iterator(begin(mChars)), std::make_move_iterator(end(mChars)) };

    std::sort(begin(v), end(v), 
        [](const std::pair<char, int>&  p1, const std::pair<char, int>&  p2) {return p1.second > p2.second; });

    std::cout << v[0].first << " " << v[1].first << std::endl;
}

int main()
{
    find_most_repeated(std::string("asdaaaasssaaaaa"));
}
#包括
#包括
#包括
#包括
#包括
#包括
void find_most_repeated(std::string strData)
{
标准::map mChars;
对于(int i=0;ip2.second;});

std::cout例如,我认为您可以将字母计数器存储为
std::map
。然后您只需对字符串进行迭代,如果计数器已经包含当前的
char
,您可以将其递增,否则添加它并将值设置为零

然后:

  • 搜索最高的计数值:您将获得最频繁的字母
  • 删除贴图中的相应元素
  • 再次搜索最高的计数值:您将得到第二个最频繁的字母

下面的例子应该更加明确:

#include <map>
#include <algorithm>

bool compare(const std::pair<char, int> & a, const std::pair<char, int> & b)
{
    return (a.second < b.second);
}
bool most_frequent_letter(const std::string & str, std::pair<char, char> & results)
{
    if(str.length() >= 2)
    {
        std::map<char, int> counter;

        for(const char & c : str)
            ++counter[c];

        std::map<char, int>::const_iterator it_max = std::max_element(counter.cbegin(), counter.cend(), &compare);
        char c_max = it_max->first;

        counter.erase(it_max);

        it_max = std::max_element(counter.cbegin(), counter.cend(), &compare);
        char c_second = it_max->first;

        results = std::make_pair(c_max, c_second);
        return true;
    }
    else
        return false;
}
我测试了它,它成功地工作了


我试图使这个例子尽可能简单,我希望它会有所帮助。

我想你可以将一个字母计数器存储为一个
std::map
。然后你只需迭代你的字符串,如果计数器已经包含当前的
char
,你可以增加它,否则你可以添加它并将值设置为零

然后:

  • 搜索最高的计数值:您将获得最频繁的字母
  • 删除贴图中的相应元素
  • 再次搜索最高的计数值:您将得到第二个最频繁的字母

下面的例子应该更加明确:

#include <map>
#include <algorithm>

bool compare(const std::pair<char, int> & a, const std::pair<char, int> & b)
{
    return (a.second < b.second);
}
bool most_frequent_letter(const std::string & str, std::pair<char, char> & results)
{
    if(str.length() >= 2)
    {
        std::map<char, int> counter;

        for(const char & c : str)
            ++counter[c];

        std::map<char, int>::const_iterator it_max = std::max_element(counter.cbegin(), counter.cend(), &compare);
        char c_max = it_max->first;

        counter.erase(it_max);

        it_max = std::max_element(counter.cbegin(), counter.cend(), &compare);
        char c_second = it_max->first;

        results = std::make_pair(c_max, c_second);
        return true;
    }
    else
        return false;
}
我测试了它,它成功地工作了


我试图使这个示例尽可能简单,希望它能有所帮助。

在获取字符串中最频繁的前两个字符时,这里有一个稍微不同的转折点。由于
std::map
是一个按键排序的关联容器,请参见,在创建初始映射后,列出中每个字符的频率de>std::map
,您只需将成员转过来(即
,并将第一个映射的结果添加到第二个映射,指定
std::greer
排序(而不是默认的
std::less
排序顺序)

例如:

void find_most_repeated (std::string str)
{
    std::map<char, int> mchars;
    std::map<int, char, std::greater<int>> mfreq;
    size_t nmostfreq = 0;

    for (const auto& c : str)           /* fill char/occurrence map */
        mchars[c]++;

    if (mchars.size() < 2) {            /* validate 2 unique chars in str */
        std::cerr << "error: str consists of a single character.\n";
        return;
    }

    for (const auto& pair : mchars)     /* fill sorted occurrence/char map */
        mfreq[pair.second] = pair.first;

    for (const auto& pair : mfreq) {    /* output 2 most frequent chars */
        std::cout << " " << pair.second;
        if (++nmostfreq == 2)
            break;
    }
    std::cout << '\n';
}

我相信可能还有十几种方法可以解决这个问题。

在获取字符串中最常见的前两个字符时,这里有一个稍微不同的方法。由于
std::map
是一个按键排序的关联容器,请参见,在创建初始映射后,列出
std::map中每个字符的频率
,您只需将成员转过来(即
并将第一个映射的结果添加到第二个映射,指定
std::greer
排序(而不是默认的
std::less
排序顺序)

例如:

void find_most_repeated (std::string str)
{
    std::map<char, int> mchars;
    std::map<int, char, std::greater<int>> mfreq;
    size_t nmostfreq = 0;

    for (const auto& c : str)           /* fill char/occurrence map */
        mchars[c]++;

    if (mchars.size() < 2) {            /* validate 2 unique chars in str */
        std::cerr << "error: str consists of a single character.\n";
        return;
    }

    for (const auto& pair : mchars)     /* fill sorted occurrence/char map */
        mfreq[pair.second] = pair.first;

    for (const auto& pair : mfreq) {    /* output 2 most frequent chars */
        std::cout << " " << pair.second;
        if (++nmostfreq == 2)
            break;
    }
    std::cout << '\n';
}
我相信可能还有十几种方法可以解决这个问题。

不要使用“幻数”,比如
65
,而是使用
'a'
等。更好的方法是:使用
isdigit
isalpha
toupper
等。还有
用于(I=0;I
用于(I=0;I
还有其他一些问题。你不觉得吗