C ++字符串元素查找

时间:2014-03-23 08:09:19

标签: c++ string map

我正在解决这个问题: 编写一个接受字符串并打印第一个非重复字符的函数。换句话说,我需要找到第一个在整个字符串中只出现一次的字符。 我知道解决方案已经可用,但下面是我编码的内容:

#include <iostream>
#include <string>
#include <unordered_map>


using namespace std;


void main()
{
    string S1;
    int NonRepeatElement,StringLenght,temp;
    unordered_map <char, int> ElementMap;
    unordered_map<char,int>::iterator it;
    char KeyValue;

    cout<<"Please enter your string"<<endl;

    cin>>S1;

    StringLenght=S1.length();

    NonRepeatElement=0;

    for(int i=0;i<StringLenght;i++)
        {
            if(ElementMap.find(S1[i]) == ElementMap.end())
                ElementMap[S1[i]]=1;
            else
                ElementMap.find(S1[i])->second++;
        }

    for(it=ElementMap.begin();it!=ElementMap.end();++it)
    {
        if(it->second==1)
        { KeyValue=it->first;
          break;
        }
    }


   for(int i=0;i<StringLenght;i++)
   {
       if(S1[i]==KeyValue)
       {
           cout<<"First Non Repeating character is "<<S1[i]<<endl;
           break;
       }
   }

}

现在我得到的元素只出现一次,但它不是第一个真正的元素,而是它的第一个有序元素。 例如。如果输入字符串是zaaabbcccdjjj 那么输出就不是z了 任何人都可以建议为什么即使unordered_map表现得像这样?

2 个答案:

答案 0 :(得分:1)

您不应该枚举地图。构建地图后,您应该枚举字符串

#include <iostream>
#include <string>
#include <unordered_map>

int main()
{
    unordered_map <char, int> ElementMap;
    std::string S1;

    cout<<"Please enter your string"<<endl;
    if (cin >> S1)
    {
        for (std::string::iterator it = S1.begin(); it != S1.end(); ++it)
            ++ElementMap[*it];

        for (std::string::iterator it = S1.begin(); it != S1.end(); ++it)
        {
            if (ElementMap[*it] == 1)
            {
                std::cout << "First non-repeating character is " << *it << '\n';
                break;
            }
        }
    };

    return 0;
}

替代方案:查找表

如果输入数据的域是固定的并且(在这种情况下是),则使用简单的查找表的另一种方法。 char数据类型最多包含(1 << CHAR_BIT)个元素,值本身可用作表的直接索引。因此,您可以这样做:

#include <iostream>
#include <string>
#include <climits>

int main()
{
    std::cout << "Please enter your string: ";

    std::string s;
    if (std::cin >> s)
    {
        unsigned int elems[ 1 << CHAR_BIT ]={};
        for (auto ch : s)
            ++elems[static_cast<unsigned char>(ch)];

        for (auto ch : s)
        {
            if (elems[static_cast<unsigned char>(ch)] == 1)
            {
                std::cout << "First non-repeating character is " << ch << '\n';
                break;
            }
        }
    };

    return 0;
}

每个元素查找的好处是O(1)复杂度,无论是在初始“map”群体上还是在重复枚举中,用于查找第一个1。总复杂度为O(2N),即O(N),其中N是字符串长度。为了在大输入流中查找唯一字符,这将显着优于基于散列或基于顺序的动态映射。

但是有一个成本:不要尝试使用32位char类型;一个4gB的自动阵列无法回家。

答案 1 :(得分:0)

这看起来很复杂。您所要做的就是检查元素[i]和元素[i + 1]。只要它们相等,你就增加一个计数。当他们不同时,你检查计数。如果计数没有增加,则您有一个非重复元素。

在伪代码中:

* set count = 0
* for i = 0 to n-1
    if element[i] == element [i+1] then count++
    else
       if count == 0 then print element[i] and break
       else count = 0 (and continue)