好久没有写过了,今儿就写了道简单题,看完题后,感觉思路很简单,就循环去找就好了,先上第一次提交的代码,里面有详细的注释
public static int firstUniqChar(String s) {
// 取每一个字符
for (int i = 0; i < s.length(); i++) {
// 获取字符
char examine = s.charAt(i); // 将这个字符当成临时变量
int count = 0; // 个数统计
// 循环找它是否重复
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == examine){
count++;
}
// 重复则进行下一个字符
if (count > 1){
break;
}
// 打印返回结果
if (j == s.length() - 1 && count == 1) {
return i;
}
}
}
return -1;
}
看着没什么毛病是吧,哈哈,就去提交了,用判题机测了一下,看看结果
可以看到,通过是通过了,但是执行用时着实有点儿惨不忍睹,分析一下代码,由于是两层循环,所以时间复杂度是O(n2) ,然后就想看能不能换一种写法,就想用hashmap的key和value了,刚好用来存储每个字符的个数,直接上代码,里面有注释
// 定义一个hashmap表
Map<Character,Integer> map = new HashMap<>();
// 每次取一个的值
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
// 判断表内是否已经存在
// 存在:对应位置的value+1
// 不存在:插入一个,且value = 0
//getOrDefault(Object key, V defaultValue)
//意思就是当Map集合中有这个key时,就使用这个key对应的value值,如果没有就使用默认值defaultValue
int value = map.getOrDefault(ch,0);
// 将值放入map表
map.put(ch,value+1);
}
// 循环map表,找到第一个value = 1的值
for (int i = 0; i < s.length(); i++) {
if (map.get(s.charAt(i))==1){
return i;
}
}
return -1;
看着还不错哈,用到了map里的一个方法,
getOrDefault(Object key, V defaultValue),意思就是当Map集合中有这个key时,就使用这个key对应的value值,如果没有就使用默认值defaultValue
看看判题机结果
执行用时还说的过去,但是感觉把题复杂化了,就看题解,里面有一种说用数组对应位置直接存储,听上去不错的样子哈,直接上代码
public static int firstUniqChar2(String s){
// 定义一个数组,存储26个字母的位置
int [] arr = new int[26];
// 统计各个字符的个数
for (int i = 0; i < s.length(); i++) {
arr[s.charAt(i) - 'a'] += 1;
}
// 遍历数组,找到第一个等于1的字符
for (int i = 0; i <s.length(); i++) {
if (arr[s.charAt(i) - 'a'] == 1) {
return i;
}
}
return -1;
}
看着很精简哈,时间复杂度是O(n)
结果也挺好
算法就是一次次优化的过程,所以,加油哈,“骚”年…