字符串-只出现一次的字符串
默写代码:
publicclassSolution{/** * @param str: str: the given string * @return: char: the first unique character in a given string */publiccharfirstUniqChar(Stringstr){// Write your code hereMap<Character,Integer>map=newHashMap<>();// 0if(str==null||str.length()==0)returnstr.charAt(0);// countfor(Characterc:str.toCharArray()){map.put(c,map.getOrDefault(c,0)+1);}for(inti=0;i<str.length();i++){charc=str.charAt(i);if(map.get(c)==1){returnc;}}returnstr.charAt(0);}}为什么 Map<Character, Integer> map = new HashMap<>();用包装类
因为Java 泛型只支持引用类型,不支持基本类型。这是 Java 语言设计的硬性规定,与集合框架的实现机制直接相关。
核心原因:
泛型擦除机制
Java 泛型是编译期语法糖,运行时会擦除类型信息变为Object。char/int是基本类型,不属于Object子类,无法参与擦除转换。Character/Integer作为包装类,继承自Object,完全符合要求。集合存储的是对象引用
HashMap内部实现依赖Node<K,V>节点存储键值对,其字段类型是K和V,只能是引用类型。基本类型没有引用概念。
编码便利性:自动装箱/拆箱
虽然必须用包装类,但 Java 5+ 的自动装箱机制让你几乎无感:
map.put('a',1);// 'a' 自动装箱为 Character,1 自动装箱为 Integercharc=map.keySet().iterator().next();// 自动拆箱intcount=map.get('a');// 自动拆箱⚠️ 你代码的致命 Bug
if(str==null||str.length()==0)returnstr.charAt(0);// 空串时 charAt(0) 会抛异常!应改为:
if(str==null||str.length()==0)return' ';// 或抛异常效率优化:数组秒杀
这道题最优解是数组计数(ASCII 范围),比 HashMap 快 3-5 倍:
publiccharfirstUniqChar(Stringstr){if(str==null||str.length()==0)return' ';int[]count=newint[256];// ASCII 范围for(charc:str.toCharArray())count[c]++;for(charc:str.toCharArray())if(count[c]==1)returnc;return' ';}记住:唯手熟尔,模板刻在骨子里才能秒。
2.// ASCII 范围为什么是256呢?
因为 8位二进制最多能表示256个不同数值(2^8 = 256),范围是0 ~ 255。
详细解释:
标准 ASCII 码
只定义了128个字符(0-127),包括字母、数字、控制符等。扩展 ASCII 码
早期系统为了容纳更多符号,把范围扩展到256(0-255),涵盖了拉丁字母、制表符等。编程惯例
在面试算法题中,题目默认字符串由可见字符组成,其 ASCII 值都在256范围内。用new int[256]能100%覆盖所有可能性,且内存占用极小(仅 1KB)。Java char 类型
Java 的char虽然是 16 位(Unicode),但本题涉及的字符都在 ASCII 子集内,所以用 256 的数组完全够用。
记住这个模板:
int[]cnt=newint[256];// 字符计数器标配这是刷题肌肉记忆的一部分,唯手熟尔,直接刻进脑子里。