【剑指offer-JZ50】第一个只出现一次的字符

112 阅读2分钟

最先想到的就是map散列的思想,在Java中,用HashMap,先遍历一次存下每个字符出现的次数,然后再弄一个循环,找到第一个值为1的key,然后查找这个key在字符串中的下标。


但是需要注意的是HashMap存储时是按hash值大小的顺序存的,对于输入顺序来说是无序的,没办法找到多个只出现一次的字符中,哪个是第一个出现的。

解决的办法就是在第二个循环中,不是遍历HashMap,而是遍历字符串,每取到一个字符就去HashMap中用get查找一次,这样就可以保证顺序输出,另外get操作的复杂度是常数,不用担心【外层遍历+内层查找】的复杂度超出O(N)的问题。


方案二:LinkedHashMap 是按输入顺序存储的,可以用来弥补HashMap无序存储的问题,这样在第二个循环中,就可以直接遍历 LinkedHashMap。


方案三(不成功):也是散列存储的思想,用int数组直接保存字符,会自动把字符转化为ASCII的int值,也是先遍历字符串,存每个字符出现的个数;第二个遍历用来取值,但是也会有一个顺序的问题,存储的顺序是按照字典序存的,同样没办法确定多个只出现一次的字符的先后顺序,并且没办法向方案1一样,【外层遍历字符串+内层查找数组】,因为这样时间复杂度就是O(NxN),不符合题目要求。



import java.util.*;
public class JZ50 {
    /*// 方案三(不成功)
    public static int FirstNotRepeatingChar(String str) {
        int[] ids = new int[128];   // 注意开辟的空间为ASCII字符的个数,不是字符串的长度。因为字符会转化为ASCII的值
        for (int i = 0; i < str.length(); i++) {
            ids[str.charAt(i)] += 1;
        }
        for (int j = 0; j < 128; j++) {
            if (ids[j] == 1) {          //  会在多个只出现一次的字符中,先找到字典序最小的
                return str.indexOf((char) j);
            }
        }
        return -1;
    }*/

    // 方案二
    public static int FirstNotRepeatingChar(String str) {
        LinkedHashMap<Character, Integer> ids = new LinkedHashMap<>();
        for (int i = 0; i < str.length(); i++) {
            char key = str.charAt(i);
            if (ids.containsKey(key)) {
                ids.put(key, ids.get(key) + 1);
            } else {
                ids.put(key, 1);
            }
        }
        // 迭代器遍历
        Iterator<Map.Entry<Character, Integer>> iterator = ids.entrySet().iterator();
        Map.Entry<Character, Integer> entry;
        while (iterator.hasNext()) {
            entry = iterator.next();
            if (entry.getValue() == 1) {
                return str.indexOf(entry.getKey());
            }
        }
        return -1;
    }


    public static void main(String[] args) throws Exception {
        String str = "google";
        System.out.println(FirstNotRepeatingChar(str));
        ;
    }
}



题源:www.nowcoder.com/practice/1c…