《剑指offer》 第50.1题 第一次只出现一次的字符。
第一个只出现一次的字符
https://www.nowcoder.com/practice/1c82e8cf713b4bbeb2a5b31cf5b0417c?tpId=13&tqId=11187&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
题目描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
这个题目既然是找是否出现,并且由于每个字符需要返回第一次出现,因此需要记录次数,可以使用数组来完成出现次数的统计,而数组可以改进成TreeSet,因为实现了排序,或者是使用Map集合来统计次数。
写法1:
利用数组统计次数,这里可以建一个二维数组,但是,考虑到ASCII码中,字符对应某个数字,所以可以将字符对应的数字当做数组的角标,因此,可以只用一个一维数组即可。(也就是说,当你写一个arr[a],是会被认成arr[97],而Map不行)
注意:ASCII码一共是127个数,而小写z对应的是122,因此数组可以设置的最小角标数为122,所以最小必须创建一个123的数组,也可以128,这样所有的字符都能统计(PS:有人用256我是没想到为什么,大家知道的可以告诉我)。
当然,也可以使用偏移量,毕竟A-Z对应的ASCII码为65-90,a-z对应的ASCII码值为97-122,用65到122这58个数也可以代替,所以使用偏移量需要做减法,然后创建大小58的数组即可。甚至可以用两次偏移,这样就只用大小52的数组了。但是为了少死一点脑细胞(我不想换算),我使用的是123个。不死脑细胞还占用空间较小的做法。
字符对应的数字,将该数字作为索引,该索引处的元素用来统计出现的次数,遍历完后,再进行一次遍历,找到次数只为1的,并返回该数组中索引所表示的字符。就是这么个逻辑。
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str==null || str.length() == 0)
return -1;
int[] count = new int[123];
//类似hash的方法来存储字符出现的次数
for(int i=0; i < str.length();i++)
count[str.charAt(i)]++;//进行统计
//添加完字符后,再访问一遍数组,可以找到某个只出现一次的字符
for(int i=0; i < str.length();i++){
if(count[str.charAt(i)]==1)
return i;
//这里不能遍历count数组,因为遍历count数组只能返回出现1次的字符,或者是某个字符出现的次数
//只有再拿着原字符串数组的角标遍历,才能将角标和出现次数对应上
}
return -1;
}
}
//这个方法也可以改写成Set。只不过需要保证是有序的Set。写法2:
使用Map集合来做,逻辑大致相同,只是添加的时候改动比较大。添加时,需要和Map的key比较,然后对Value进行维护。
import java.util.HashMap;
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str.length() == 0|| str == null){
return -1;
}
HashMap<Character,Integer> map = new HashMap<>();
for(int i = 0; i < str.length();i++){
//Map的逻辑是,如果Map不包含这个key,那就添加,注意添加的是字符,和出现的次数(添加时默认是1)
if(!map.keySet().contains(str.charAt(i))){
map.put(str.charAt(i),1);
}else{//包含,则计数+1.map.get(str.charAt(i))就是拿到这个具体的次数即value
map.put(str.charAt(i),map.get(str.charAt(i))+1);
}
}
for(int i = 0; i < str.length();i++){//老规矩,只能对原字符串再次遍历
if(map.get(str.charAt(i)) == 1){
return i;
}
}
return -1;//没找到就返回-1
}
}
//keySet() 返回一个 SetMap视图中包含的键。刷刷题

查看11道真题和解析