我正在解决这个问题: 编写一个接受字符串并打印第一个非重复字符的函数。换句话说,我需要找到第一个在整个字符串中只出现一次的字符。 我知道解决方案已经可用,但下面是我编码的内容:
#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表现得像这样?
答案 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)