剑指offer(36):第一个只出现一次的字符
来源:互联网 发布:东方财富mac 编辑:程序博客网 时间:2024/06/06 19:03
题目描述
在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符的位置。若为空串,返回-1。位置索引从0开始。
分析
直观思路:从头到尾扫描字符串,访问到某个字符是将其和后面的每个字符比较。如果没有发现重复字符,则只出现一次,即找到该字符。但是如果字符串有n个字符,则每个字符需要与后面的
推荐思路:只进行一趟扫描,时间复杂度为
牛客AC:
import java.util.LinkedHashMap;import java.util.Map;import java.util.Map.Entry;public class Solution { public int FirstNotRepeatingChar(String str) { if(str == null || str.length() <= 0) return -1; // LinkedHashMap 保证输出顺序与输入顺序一致 Map<Character, Integer> mapCount = new LinkedHashMap<Character, Integer>(); // 字符和对应的而次数 Map<Character, Integer> mapIndex = new LinkedHashMap<Character, Integer>(); // 字符和首次出现的索引 for(int i = 0; i < str.length(); i++) { char c = str.charAt(i); if(mapCount.containsKey(c)) { int count = mapCount.get(c) + 1; // mapCount.replace(c, count); // replace java1.8才开始支持 mapCount.remove(c); mapCount.put(c, count); } else { mapCount.put(c, 1); mapIndex.put(c, i); } } char resChar = '0'; int resIndex = -1; for(Entry<Character, Integer> entry : mapCount.entrySet()) { // 只出现一次的字符和首次出现的索引 if(entry.getValue() == 1) { resChar = entry.getKey(); resIndex = mapIndex.get(resChar); //System.out.println(resIndex); break; } } return resIndex; // 如需返回首次出现的索引,修改即可 }}
相关问题扩展
1、定义一个函数,输入两个字符串,从第一个字符串中删除在第二个字符串中出现过的所有字符。例如从第一个字符串“We are students”中删除在第二个字符串“aeiou”中出现过的字符得到“W r Stdnts”。
思路:使用HashMap存储第二个字符串,对第一个字符串进行一次扫描,每扫描到一个字符就判断map.containsKey(),如果出现,则删除该字符。
public String removeAppeared(String iniStr, String appearStr) { if(iniStr == null || iniStr.length() <= 0) return null; if(appearStr == null || appearStr.length() <= 0) return iniStr; // map存储第二个字符串 Map<Character, String> map = new HashMap<Character, String>(); for(int i = 0; i < appearStr.length(); i++) { char c = appearStr.charAt(i); map.put(c, null); } // 判断是否出现过 StringBuffer sb = new StringBuffer(); for(int i = 0; i < iniStr.length(); i++) { char c = iniStr.charAt(i); if(map.containsKey(c)) continue; sb.append(c); } return sb.toString();}
2、定义一个函数,删除字符串中所有重复出现的字符。例如输入“google”,删除重复字符之后的结果是“gole“。
思路:和上题类似,对字符串进行一趟扫描,每扫描到一个字符就判断map.containsKey(),如果出现,则删除该字符。
public String removeRepeat(String iniStr) { if(iniStr == null || iniStr.length() <= 0) return null; Map<Character, Boolean> map = new HashMap<Character, Boolean>(); StringBuffer sb = new StringBuffer(); for(int i = 0; i < iniStr.length(); i++) { char c = iniStr.charAt(i); if(map.containsKey(c)) { // 如果map包含key,则该字符一定出现过 continue; } else { map.put(c, true); sb.append(c); } } return sb.toString(); }
3、在英语中,如果两个单词中出现的字母相同,并且每个字母出现的次数也相同,那么这两个单词互为变位词(Anagram)。例如silent与listen、evil与live等。请完成一个函数,判断输入的两个字符串是不是互为变位词。
思路:使用HashMap存储字符串中每个字符出现的次数。对第一个字符串扫描一次,每扫描一个字符,相应的字符的次数增加1;对第二个字符串扫描一次,每扫描一个字符,相应的字符的次数减去1。如果扫描完第二个字符后,HashMap中所有的值都是0,那么这两个字符串就是互为变位词。
public boolean isAnagram(String str1, String str2) { if(str1 == null || str1.length() <= 0 || str2 == null || str2.length() <=0 || str1.length() != str2.length()) return false; boolean isAnagram = false; // 返回值 // 遍历第一个字符串,存储字符及其次数 Map<Character, Integer> map = new HashMap<Character, Integer>(); for(int i = 0; i < str1.length(); i++) { char c = str1.charAt(i); if(map.containsKey(c)) { int count = map.get(c) + 1; // 每次加1 map.remove(c); map.put(c, count); } else { map.put(c, 1); } } // 比那里第二个字符串,更新次数 for(int i = 0; i < str2.length(); i++) { char c = str2.charAt(i); if(map.containsKey(c)) { int count = map.get(c) - 1; // 每次减1 map.remove(c); map.put(c, count); } else { return isAnagram; } } // 判断所有的字符的次数是否为0 for(Integer value : map.values()) { if (value != 0) return isAnagram; } isAnagram = true; return isAnagram; }
参考
1. 何海涛,剑指offer名企面试官精讲典型编程题(纪念版),电子工业出版社
- 第一个只出现一次的字符 (剑指offer)
- 【剑指offer】第一个只出现一次的字符
- 剑指offer(35)第一个只出现一次的字符
- 剑指offer--第一个只出现一次的字符
- 剑指offer-35 第一个只出现一次的字符
- 剑指Offer之 - 第一个只出现一次的字符
- 《剑指offer》第一个只出现一次的字符位置
- 剑指offer:第一个只出现一次的字符位置
- 剑指Offer--第一个只出现一次的字符位置
- 【剑指Offer】第一个只出现一次的字符位置
- 【剑指offer】之第一个只出现一次的字符
- 剑指offer:第一个只出现一次的字符位置
- [剑指offer]第一个只出现一次的字符位置
- 《剑指offer》-第一个只出现一次的字符位置
- 剑指offer|第一个只出现一次的字符位置
- 剑指Offer:第一个只出现一次的字符
- 【剑指offer】第一个只出现一次的字符
- 剑指offer----第一个只出现一次的字符
- Android 基础动画
- JavaScript的回调问题
- php面试题及答案
- DirectX开发中找不到dxtrans.h的问题的解决
- 关于SEL的一些总结
- 剑指offer(36):第一个只出现一次的字符
- C# 在使用FindWindowEx的参数使用详解
- OTA2-android 升级基本原理
- com.MySQL.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Every derived table must have its own ali
- C#设计模式--工厂方法
- Android JNI配置及入门
- iOS 最新AppStore审核指南
- 关于android中alarm的使用
- pageContext对象