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

今天刷题遇到这么个题目:

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写). 如 输入"google" ----> 输出 4

一开始只想到了HashMap,但考虑到HashMap是无序的,便又换个思路, 考虑到嵌套Map,

map(字符,map(索引,出现次数))

又想了下,其实这么实现显得麻烦了,理论上来说肯定不会这么麻烦...所以又换了条路,最后看到别人写到了LinkedHashMap就恍然大悟...然后想起来了 这个map是有序的.那么问题就简单了...代码如下

class Solution_32 {
    public int FirstNotRepeatingChar(String str) {
        Map<Character, Integer> map = new LinkedHashMap<>();
        char s[] = str.toCharArray();

        for (int i = 0; i < s.length; i++) {
            if (!map.containsKey(s[i])) {
                map.put(s[i], 1);
            } else {
                map.put(s[i], map.get(s[i]) + 1);
            }
        }

        for (int i = 0; i < s.length; i++) {
            if (map.containsKey(s[i]) && map.get(s[i]) == 1)
                return i;
        }

        return -1;
    }
}

输出结果:


image.png

但是反过来想,看到

       for (int i = 0; i < s.length; i++) {
            if (map.containsKey(s[i]) && map.get(s[i]) == 1)
                return i;
        }

又去重新遍历了一次str数组,那么这时候_已经和Map是否有序无关了,因为是按"google"去顺序匹配,而不是按照HashMap去顺序匹配的,在hashmap里通过散列的方式去查找,所以即便在hashmap里按照字母排序,e出现第一次在l出现第一次的前面,它还是会去匹配l的

所以即便把代码改成hashmap也是对的

class Solution_32 {
    public int FirstNotRepeatingChar(String str) {
        Map<Character, Integer> map = new HashMap<>();
        char s[] = str.toCharArray();

        for (int i = 0; i < s.length; i++) {
            if (!map.containsKey(s[i])) {
                map.put(s[i], 1);
            } else {
                map.put(s[i], map.get(s[i]) + 1);
            }
        }

        for (int i = 0; i < s.length; i++) {
            if (map.containsKey(s[i]) && map.get(s[i]) == 1)
                return i;
        }

        return -1;
    }
}

那么,LinkedHashMap在什么时候更适合呢?思考了下,如果题目改成这样:

  • 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符, 如果没有则返回 -1(需要区分大小写).
  • google ---> l

这样就更适合LinkHashMap了
代码和结果如下:

class Solution32 {
    public int FirstNotRepeatingChar(String str) {
        //适合 找出第一个只出现一次的字符
        Map<Character, Integer> map = new LinkedHashMap<>();
        char s[] = str.toCharArray();

        for (int i = 0; i < s.length; i++) {
            if (!map.containsKey(s[i])) {
                map.put(s[i], 1);
            } else {
                map.put(s[i], map.get(s[i]) + 1);
            }
        }
        for (char k : map.keySet()) {
            if (map.get(k) == 1) {
                System.out.println(k + " : " + map.get(k));
                break;
            }
        }
        return -1;
    }
}
image.png

总结:

LinkedHashMap是有序存取,其底层有一个双向循环链表来维护其存储顺序,遍历的时候是按照插入顺序来遍历的。HashMap是散列存储,由于最后都是按照str的顺序遍历的,所以用什么map都无所谓...以后多深入思考吧,别放弃太快~~ : )

全部评论

相关推荐

12-15 12:50
河北工程大学
sta666:我也是这个国际商业化的,三天,一天一面,就通过了,不过我是后端实习生,好好面感觉能过。
点赞 评论 收藏
分享
程序员花海:实习太简单了 学历可以的 实习描述应该是先介绍业务 再介绍技术 技术咋推动业务的 做到了啥收益 有没有做实验 实验组和对照组有什么不同 你最后学到了什么 有没有参与处理过线上问题 有没有参与过公司的code review 有没有参与过技术分享 这些都是可以在实习描述中写的 并且实习和项目不一样不会撞车 应该放在最前面 放在教育背景下面 另外项目有点烂大街 可以看下我主页的简历优化案例
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务