字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
案例:
s = "leetcode" 返回 0. s = "loveleetcode", 返回 2.
注意事项:您可以假定该字符串只包含小写字母。
注意:所有需要相对于数组而言比较复杂的数据结构的方法暂且不表!
方法一:
遍历整个字符串,利用26长度的int[]标记每一个字符第一次出现的位置,如果出现了两次,则标记为int的最大值。之后从数组中寻找最小的值即可:
public int firstUniqChar(String s) {
//first, make a flag set to signal the existed chars
//second, make a flag set to store the "unique" chars, which is unique "now"
char[] chars = s.toCharArray();
int[] resultSet = new int[26];
BitSet doubleFlag = new BitSet();
for (int i = 0 ; i < chars.length ; i ++) {
int index = chars[i] - 'a';
if (resultSet[index] == 0)
resultSet[index] = i + 1;
else
resultSet[index] = Integer.MAX_VALUE;
}
int result = Integer.MAX_VALUE;
for (int i = 0 ; i < 26 ; i ++)
result = resultSet[i] != 0 && resultSet[i] < result ? resultSet[i] : result;
return result == Integer.MAX_VALUE ? -1 : result - 1;
}
方法二:
利用String类的方法,寻找26个字母出现的第一个位置和最后一个位置,两者相比较,通过固定的26次循环,找出只出现一次且下标最小的情况,也是答案排名中耗时少的:
public int firstUniqChar0(String s) {
int index;
int lastIndex;
int result = Integer.MAX_VALUE;
for (char c = 'a' ; c <= 'z' ; c ++) {
index = s.indexOf(c);
lastIndex = s.lastIndexOf(c);
if (index != -1 && lastIndex == index && result > index)
result = index;
}
return result == Integer.MAX_VALUE ? -1 : result;
}
其实这道题一开始想直接利用循环双链表做出来一个队列来写的,然后突然就想到了可以利用int[]下标映射连续的'a'-'z',同时可以记录下来下标(利用数组中的值)
这启示我们,可以将数组看成Map<Integer, T>来看待,只是里面的某些方法要自己写罢了。