题目描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
思路
1.设置一个52大小的数组来存储字符
空间复杂度是O(1),时间复杂度是O(n)
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str.length() < 1){
return -1;
}
int[] arr = new int[52];
for(int i = 0;i < str.length();i++){
char c = str.charAt(i);
if(c >= 'a' && c <= 'z'){
if(arr[c-'a'] == 0)
arr[c-'a'] = i+1;
else
arr[c-'a'] = -1;
}else{
int index = c - 'A' + 26;
if(arr[index] == 0)
arr[index] = i+1;
else
arr[index] = -1;
}
}
return search(arr);
}
public int search(int[] arr){
int min = Integer.MAX_VALUE;
for(int i = 0;i < 52;i++){
if(arr[i] == -1 || arr[i] == 0){
continue;
}else{
min = min > arr[i] - 1? arr[i]-1:min;
}
}
return min;
}
}
2.看剑指offer上的思路,使用HashMap
但是空间复杂度是O(n),不推荐,第一种方法是较好的
import java.util.HashMap;
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str.length() < 1){
return -1;
}
HashMap<Character,Integer> hm = new HashMap<>();
for(int i = 0;i < str.length();i++){
char c = str.charAt(i);
if(hm.containsKey(c)){
int count = hm.get(c);
hm.put(c,++count);
}else{
hm.put(c,1);
}
}
for(int i = 0;i < str.length();i++){
char c = str.charAt(i);
if(hm.get(c) == 1){
return i;
}
}
return -1;
}
}
3.CYC写的开了256的数组,原因是总共有256个ASCLL字符
public int FirstNotRepeatingChar(String str) {
int[] cnts = new int[256];
for (int i = 0; i < str.length(); i++)
cnts[str.charAt(i)]++;
for (int i = 0; i < str.length(); i++)
if (cnts[str.charAt(i)] == 1)
return i;
return -1;
}
4、举一反三
相关题目:
(1)定义一个函数,从第一个字符串中删除在第二个字符串中出现过的所有字符
思路:可以创建一个用数组实现的简单哈希表,存储第二个字符串
遍历第一个字符串,如果字符串1中的字符出现在第二个字符串中,就删除它
(2)定义一个函数,删除字符串中所有出现的重复字符
思路:创建一个用数组实现的简单哈希表,遍历字符串,如果之前出现过,直接删除就行了
(3)在英语中,如果两个单词中出现的字母相同,并且两个字母出现的次数也相同,那么这两个单词互为变位词。
请完成一个函数,判断输入的两个字符串是不是互为变位词
思路:就是用数组实现一个简单的哈希表,遍历第一个字符串,用数组统计字符串中每个字符出现的次数,然后遍历第二个字符串,对应的数组中字符的次数减一,如果数组中的所有的次数都是0,那么这两个字符串就互为变位词。
我原来以为要使用两个数组,但是这样加一减一的操作,就会减少了一个数组空间的使用。