387. First Unique Character in a String
Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1.
Examples:
s = "leetcode"
return 0.
s = "loveleetcode",
return 2.
Note: You may assume the string contain only lowercase letters.
解题方法1:
首先考虑特殊情况。遍历两次:第一次定点索引,第二次判定
执行时间 16ms
int firstUniqChar(char* s) {
int length = strlen(s);
if(length == 1)
{
return 0;
}
for(int i=0;i<length;i++)//
{
for(int j = 0; j < length; j++)
{
if( i != j) //排除自己和自己比较的情况
{
if(s[i]-s[j] == 0) //两者相等,则此字符不可能是唯一字符,跳出循环,判定下一个
{
break;
}
else
{
if(j+1 >= length)//如果j扫描完,则找到解
{
return i;//返回下标
}
if(i == length-1) //如果i指向最后一个字符
{
if(j+2 >= length)//当j指向倒数第二个字符时,说明找到解
{
return i;
}
}
}
}
}
}
return -1;//没找到解,返回-1
}
改进:
通过定义一个标志位标志当前字符是否是唯一字符
执行时间 16ms
int firstUniqChar(char* s) {
int len=strlen(s);
if(len==1)//特殊情况优先考虑
return 0;
if(len==0)
return -1;
int flag=0;//标志s[i]是不是唯一字符,0是1不是
for(int i=0;i<len;i++)
{
flag=0;//每次都初始化
for(int j=0;j<len;j++)
if(s[i]==s[j]&&i!=j)
{
flag=1;
break;
}
if(flag==0)//s[i]是唯一字符且是第一个
return i;
}
return -1;
}
解题方法2:
通过定义额外的数组来记录个字母的个数,并通过数组来得到解
执行时间 8ms
int firstUniqChar(char* s) {
if(!s) {//特殊情况优先考虑
return -1;
}
int a[2][26];
for(int i =0;i<26;i++) {
a[0][i] = 0;//存储字符在字符串中的个数
a[1][i] = -1;//存储字符在字符串中的下标
}
int len = strlen(s);
int i = 0;
for(;i<len;i++) {
int t = s[i] - 'a';
a[0][t] += 1;
if(a[1][t] == -1) {
a[1][t] = i;
}
}
i = 0;
int r = -1;//记录第一个唯一字符的下标
for(;i<26;i++) {
if(a[0][i] == 1) {
if(r == -1) {//将第一次出现a[0][i] = 1字符的下标记录
r = a[1][i];
} else if(a[1][i] < r){//通过比较寻找第一个唯一字符
r = a[1][i];
}
}
}
return r;//返回第一个唯一字符的下标
}
改进:
/*
执行用时 : 12 ms, 在First Unique Character in a String的C提交中击败了98.86% 的用户
内存消耗 : 8.4 MB, 在First Unique Character in a String的C提交中击败了78.39% 的用户
*/
int firstUniqChar(char* s) {
int length = strlen(s);
int str[26]={0};
/*
int *str = (int *)malloc(26*sizeof(int));//记录26个字母出现的次数
memset(str,0,26*4);//初始化数组为0
此两条语句可以代替int str[26]={0};语句。但会增加执行用时,再此是为了了解这种方法
*/
int i = 0;
//计算各个字符出现的次数
for(i=0;i<length;i++)
{
str[s[i]-'a']++;
}
for(i=0;i<length;i++)
{
//当前字符只出现1次,输出索引
if(str[s[i]-'a'] == 1){
return i;
}
}
return -1;
}
/*
memset(str,0,26);//初始化数组为0
stdout:0,0,0,0,0,0,-1094844416,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,-1094795586,
出错~~!!!
*/
后记:
- 推荐两种改进算法,另两种是自己第一次做的,可以做为对比,总结出思考的缺陷,下次考虑更周全
- 注意memset()函数的使用