问题描述

在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符的位置。若为空串,返回-1。位置索引从0开始.

示例:
输入:sabcdsdf
输出:1

算法描述

定义一个52个元素的整型数组aCount,初始化为0,每个字母(大小写)依次对应一个,记录字母出现的次数;
定义一个52个元素的整型数组aPos,初始化为-1,每个字母(大小写)对应一个,记录字母第一次出现的位置;

每次遍历一个到字母,aCount数组里对应字母加1,判断目前aCount数组里该字母的计数是否为1,是则在aPos里记录字母出现位置;若已不是1,则将位置设为-1.
最后遍历aPos,不是-1同时又最小的那个就是第一个只出现一次的字符的位置。

运行时间O(n)

代码实现

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        //空串返回-1
        if (str == "") return -1;

        // 前26个元素代表小写字母,后26个元素代表大写字母
        int aCount[52], aPos[52];
        for (int i = 0; i < 52; i++) {
            aCount[i] = 0;
            aPos[i] = -1;
        }
        // 开始遍历
        for (int i = 0; i < str.length(); i++) {
            int pos = 0;
            if (str[i] >= 'a' && str[i] <= 'z') {
                pos = str[i] - 'a';
            }
            else {
                pos = str[i] - 'A' + 26;
            }
            aCount[pos] += 1;
            if (aCount[pos] == 1) {
                aPos[pos] = i;
            }
            else {
                aPos[pos] = -1;
            }
        }
        // 最后判断aPos数组
        int result = -1; // 如果没有,就返回 -1
        for (int i = 0; i < 52; i++){
            if (aPos[i] != -1) {
                if (result == -1) 
                    result = aPos[i];
                else
                    result = result < aPos[i] ? result : aPos[i];
            }
        }
        return result;
    }
};