剑指 Offer 50. 第一个只出现一次的字符
题目:
思路:
【1】一种是先遍历数组,记录字符的个数,然后第二次遍历的时候取出,因为限制小写字母可以考虑int的26个数组记录,节约开销。
【2】当然第二种是遍历字符,因为只有26个,所以只需要遍历26次,但是在里面设计到两次查找,这种对于数据量大的时候是起到很大的优化。减少遍历的时间。
代码展示:
最优的遍历字符的做法:
//时间2 ms击败99.50% //内存41.9 MB击败50.94% class Solution { public char firstUniqChar(String s) { //根据提示做出限制 if (s == null || "".equals(s.trim())) { return ' '; } //为什么要设置,因为如果出现都是其他字符而不是小写字符的不规范情况是循环不会执行,且可以返回' ' int minIndex = s.length(); for (int i = 'a'; i <= 'z'; i++) { int index = s.indexOf(i); //有可能存在这个字符没有用,所以判断要大于-1时才算存在,而且如果某个字符的位置越前,则应该保留 if (index > -1 && s.lastIndexOf(i) == index && index < minIndex) { minIndex = index; } } return minIndex < s.length() ? s.charAt(minIndex) : ' '; } }
遍历两次的做法:
//时间5 ms击败84.87% //内存41.6 MB击败91.1% class Solution { public char firstUniqChar(String s) { int[] flag = new int[26]; for (char c : s.toCharArray()){ flag[c - 'a']++; } for (char c : s.toCharArray()){ if (flag[c - 'a'] == 1) return c; } return ' '; } } //时间3 ms击败99.40% //内存41.8 MB击败66.4% //将多余步骤抽出来减少消耗的时间 class Solution { public char firstUniqChar(String s) { int[] flag = new int[26]; char[] chars = s.toCharArray(); for (char c : chars){ flag[c - 'a']++; } for (char c : chars){ if (flag[c - 'a'] == 1) return c; } return ' '; } }