题目描述:
在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符。 如输入 abaccdeff,则输出 b。
输入:
输入有多组数据
每一组输入一个字符串。
输出:
输出第一个只出现一次的字符下标,没有只出现一次的字符则输出-1
我们这里有两种解题思路
1.蛮力法。
遍历数组,每找到一个字符是遍历一下整个数组,看看该字符是否存在数组下表不一致,但是ASSIC码值一样的字符还存在,如果不存在,则是返回该字符,如果存在,则继续遍历。该算法的时间复杂度为O(n*n),显然这样的效率不是很高。
1 /** 2 * 利用两次循环,时间复杂度O(n*n) 3 * 4 * @author yfy 5 * @param args 6 * 需要查找的字符串 7 * @param len 8 * 字符串长度 9 * @return 返回第一个出现一次字符的ASSIC码值,如果没有只出现一次的字符,则返回-1 10 */ 11 int firstNotRepeatingChar(char[] args, int len) { 12 int j; 13 for (int i = 0; i < len; i++) { 14 for (j = 0; j < len; j++) { 15 if (i != j) { 16 if (args[i] == args[j]) { 17 break; 18 } 19 } 20 } 21 // 沒有找到和这个字符相等的字符。 22 if (j == len) { 23 return args[i]; 24 } 25 } 26 return -1; 27 }
2.空间换时间
利用hash表,把字符串照中出现的字符,映射到hash表中,并统计每个字符出现的次数,再次遍历字符串的每次字符,直到找到第一个出现一次的字符。算法时间复杂度O(n)。
1 /** 2 * 利用hash表,把每次字符做成对hash的映射 3 * 4 * @author yfy 5 * @param args 需要查找的字符串 6 * @param len 字符数组长度 7 * @return 返回第一个出现一次字符的ASSIC码值,如果没有只出现一次的字符,则返回-1 8 */ 9 int firstNotRepeatingChar(char[] args, int len) { 10 11 // 定义一个hash长度为 ASSIC码值长度+1 12 int[] hash = new int[128]; 13 14 // 把字符数组映射到hash表中 15 for (int i = 0; i < len; i++) { 16 hash[args[i]]++; 17 } 18 19 // 再次遍历数组,找到第一个出现一次的字符。 20 for (int i = 0; i < len; i++) { 21 if (hash[args[i]] == 1) { 22 char ch = args[i]; 23 return ch; 24 } 25 } 26 27 // 没有找到出现出现一次的字符 28 return -1; 29 }
算法改进
在上面这个算法中,我们的时间复杂度为O(n),但是我们要对字符数组遍历两次,如果字符数组数量很大,遍历两次还是有点多呢,可以不可以只遍历一次呢。当然是可以的,因为我们查找的ASSIC码中的字符,那么最多可能有128种字符,可以把出现过的字符按先后顺序都记录在一个字符数组中,我们第二次遍历只需要遍历这个字符数组中出现次数为一的字符。
1 /** 2 * 利用hash表,把每次字符做成对hash的映射 3 * 4 * @author yfy 5 * @param args 需要查找的字符串 6 * @param len 字符数组长度 7 * @return 返回第一个出现一次字符的ASSIC码值,如果没有只出现一次的字符,则返回-1 8 */ 9 int firstNotRepeatingChar2(char[] args, int len) { 10 // 定义一个hash长度为 ASSIC码值长度 11 int[] hash = new int[128]; 12 13 char[] exsited = new char[128]; 14 int count = 0; 15 16 // 把字符数组映射到hash表中 17 for (int i = 0; i < len; i++) { 18 19 // 如果这个字符是第一次出现,则把该字符放入字符数组exsited中 20 if (hash[args[i]] == 0) { 21 exsited[count++] = args[i]; 22 } 23 hash[args[i]]++; 24 } 25 26 // 遍历数组exsited,找到第一个出现一次的字符。 27 for (int i = 0; i < count; i++) { 28 if (hash[exsited[i]] == 1) { 29 char ch = args[i]; 30 return ch; 31 } 32 } 33 // 没有找到出现出现一次的字符 34 return -1; 35 }