剑指offer自学系列(五)

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

class Solution {
public:
    void Insert(char ch) {
        s += ch;
        hash[ch]++;
    }
    char FirstAppearingOnce() {
        for (int i = 0; i < s.size();i++) {
            if (hash[s[i]] == 1)
                return s[i];
        }
        return '#';
    }
private:
    string s;
    char hash[256] = { 0 };
}

题目分析:

字符串流键入,在插入函数处,我们将字符串连接起来形成字符串,由于字符串值不超过256,所以将hash表设为256长度的数组,我们想要找出第一个非重复的字符,重复的必然hash[ch]==2,所以非重复的只要判断条件为1即可。

下面再看一个常见的算法题,数学中常用的全排列,我思考了两天时间,发现自己真是蠢,把结果输出一下就能弄懂别人代码的思路了,吸取教训,下面看题:

题目描述:

输入一个字符串,打印出该字符串的全排列,例如,输入“abc”,则得到abc,acb,bac,bca,cba,cab六种结果,其实往更深层次考虑还有重复的情况,我们首先考虑不重复的情况,全排列算法

题目分析:

首先按数学的思路,我们固定第一个字符a,然后求后面的bc有几种全排列,我们发现这就是一个递归问题,但是我们希望得到全部的全排列,因此我们每轮需要把首字符换成字符中的一个值,这里我们用一个循环可以解决。

#include <iostream>
using namespace std;

int sum = 0;//记录有多少种组合

void Swap(char str[], int a, int b)
{
    char temp = str[a];
    str[a] = str[b];
    str[b] = temp;
}

void Perm(char str[], int begin, int end)
{
    if (begin == end)
    {
        for (int i = 0; i <= end; i++)
        {
            cout << str[i];
        }
        cout << endl;
        sum++;
    }
    else
    {
        for (int j = begin; j <= end; j++)
        {
            //cout << "swap(" << str << "," << begin << "," << j << ")" << endl;
            Swap(str, begin, j);
            //cout << "perm(" << str << "," << begin+1 << "," << end << ")" << endl;
            Perm(str, begin + 1, end);
            //cout << "swap(" << str << "," << j << "," << begin << ")" << endl;
            Swap(str, j, begin);
        }
    }
}

int main()
{
    int n;
    char c[16];
    char tmp;


    cin >> n;
    tmp = getchar();    // 接受回车
    if (1 <= n && n <= 15) {
        for (int i = 0; i < n; i++) {
            c[i] = getchar();
        }
        Perm(c, 0, n - 1);
    }
    cout << sum;
    cout << endl;
    return 0;
}
posted @ 2019-04-13 13:56  薛定谔的哈士奇  阅读(99)  评论(0编辑  收藏  举报