题解一:暴力
主体思路:
选定一个字母,遍历往后所有的字母,找是否出现相同的字母:
1、将所有相同的字母设置为' ',防止后续重新被遍历到。开始下一个字母;
2、遍历完所有字母都不相同,即为最后的答案;
3、所有字母都不是唯一出现则返回-1。

图示:
图片说明

复杂度分析:
时间复杂度:O(n^2),双层循环;
空间复杂度:O(1),没有申请其他空间;
实现如下:

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        for(int i=0;i<str.size();++i){
            if(str[i]==' ')continue;//之前已经判断过不是唯一字符,无需判断;
            int flag=0;
            for(int j=i+1;j<str.size();++j){
                if(str[i]==str[j]){//相同
                    flag=1;//标记该字符不是唯一
                    str[j]=' ';//打上标记,防止后续重复判断
                }
            }
            if(!flag)return i;//唯一出现过的字符
        }
        return -1;//没有一个字符是唯一出现
    }
};

题解二:采用hash表存储字符出现频率
主要思路:
1、遍历数组,统计每个字符出现的频率,并存入hash表中;
2、遍历数组,并查询在hash表中出现的次数,当为1时,返回下标,遍历结束都没有找到返回-1;

图示:
图片说明

复杂度分析:
时间复杂度:O(n),双次循环;
空间复杂度:O(1),字母只有26个,为常数;

实现如下:

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        unordered_map<char,int> u_map;
        for(auto i:str){//C++11语法
           u_map[i]++;//统计每个字符的次数
        }
        for(int i=0;i<str.size();i++){
            if(u_map[str[i]]==1)return i;//找到字符出现次数唯一的情况,返回下标
        }
        return -1;//没有一个字符是唯一出现
    }
};

题解三:数组
主要思路:与题解二一样,因为都是小写字母,所以使用可以数组充当hash表的作用;
复杂度分析:
时间复杂度:O(n),双次循环;
空间复杂度:O(1),char大小256,为常数;
实现如下:

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        int flag[256] = { 0 };//hash表
    for (auto i : str) {
        flag[i]++;//统计每个字符的次数
    }
    for (int i = 0; i < str.size(); ++i) {
        if (flag[str[i]] == 1)return i;//找到字符出现次数唯一的情况,返回下标
    }
    return -1;//没有一个字符是唯一出现
    }
};