剑指offer--字符流中第一个出现一次的字符

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hanani_Jia/article/details/82559332

题目描述

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

输出描述:

如果当前字符流没有存在出现一次的字符,返回#字符。

  最开始看到这个题目的时候自己感觉没有思路,就直接跳过了,然后开始看其他的题目,但是在翻看自己博客的时候看到了一个可以解决这个问题的方法。就是哈希,因为学过哈希已经过去一段时间了,所以自己开始并没有想到这个方法。

 并且自己的应变能力和思维能力确实比较差,题目稍微有变动就不知道怎么去解决。自己之前写的时候是一个函数,通过传进来的参数是一个字符串来求解,但是这道题目却给了两个函数,让我发懵了很久。

  这里的insert函数主要是在组建字符串,这里是一个字符一个字符给你的,你要把他组起来。

class Solution

{

public:

//Insert one char from stringstream

void Insert(char ch)

{

str += ch;

hash[ch ]++;

}

//return the first appearence once char in current stringstream

char FirstAppearingOnce()

{

int i = 0;

for (i = 0; i < str.size(); i++)

{

if (hash[str[i]] == 1)

return str[i];

}

return '#';

}

int hash[256] = { 0 };

string str;

};

这里我们定义一个string类型的变量用来存储字符串,然后再定义一个哈希映射的数组。这里的思想就是我们把每个字符都映射到一个唯一的数组中的位置,数组中初始值都是0代表着这个数组中的字符都出现了0次,然后获取字符,没获取到一个字符,那就把这个数组中字符对应的位置的数字进行++,变成了几那就说明这个字符串出现了几次。

  之后要做的就是去遍历我们的数组,这里要注意的是,我们不能说把这个数组开始从0位置开始遍历,遇到第一个是1的就返回这个数,我们要找的是字符串中第一个出现的字符,所以当然要从字符串第一个开始,我们要找到字符串第一个字符对应的数组中的位置,然后看看是不是1不是的话找字符串中第二个字符对应的映射位置是不是1,以此类推,直到找到是1的那个为止。

for (i = 0; i < str.size(); i++)

{

if (hash[str[i]] == 1)

return str[i];

}

所以这里要格外的注意,i的条件是小于字符串的长度,而不是说256,然后每次访问的不是hash[i]而是hash[str[i]]。

https://blog.csdn.net/Hanani_Jia/article/details/80265815 这是我之前写过的字符串中只出现一次的字符。

下边是今天的选择题

 NumberList是一个顺序容器,以下代码执行后,NumberList里的元素依次为:

List<int> NumberList = new List<int>(){2,4,1,3,5};

for(int i = 0;i<NumberList.Count;++i)

{

    int v = NumberList[i];

    if(v%2 = = 0)

    {

        NumberList.Remove(v);//删除的是元素,而非下标

    }

}

A.2,4,1,3,5

B.2,1,3,5

C.4,1,3,5

D.1,3,5

这里我初始当然选择的是D,最初还认为这个题目应该是最简单的一个了,虽然当时认为可能会有坑, 但是看来看去也没看到哪里有,所以直接选择了D。正确答案是C

 List是STL库中的一个容器, list是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。由于其结构的原因,list 随机检索的性能非常的不好,因为它不像vector 那样直接找到元素的地址,而是要从头一个一个的顺序查找,这样目标元素越靠后,它的检索时间就越长。检索时间与目标元素的位置成正比。虽然随机检索的速度不够快,但是它可以迅速地在任何节点进行插入和删除操作。因为list 的每个节点保存着它在链表中的位置,插入或删除一个元素仅对最多三个元素有所影响,不像vector 会对操作点之后的所有元素的存储地址都有所影响,这一点是vector 不可比拟的。

list 的特点:

(1) 不使用连续的内存空间这样可以随意地进行动态操作;
(2) 可以在内部任何位置快速地插入或删除,当然也可以在两端进行push 和pop 。
(3) 不能进行内部的随机访问,即不支持[ ] 操作符和vector.at() ;
(4) 相对于verctor 占用更多的内存。

 所以这里我们传入2之后发现2是要被删除的,在删除完之后,因为list是一个顺序容器,所以后边的元素会往前移动那就变成了{4,1,3,5},这时候在进入for循环的时候i已经变成了1,他访问的是1位置的这个元素所以答案选择C。

 

 

猜你喜欢

转载自blog.csdn.net/Hanani_Jia/article/details/82559332