題目描述
在字符串 s 中找出第一個只出現一次的字符。如果沒有,返回一個單空格。 s 只包含小寫字母。
示例:
s = “abaccdeff”
返回 “b”
s = “”
返回 " "
限制:
0 <= s 的長度 <= 50000
哈希數組(最優)
想想字符ASCII碼最大也就不超過256,並且都是正整數,因此開一個整型數組。下標代表字符對應的字符ASCII碼,值就是字符出現的次數。
//Java代碼
class Solution {
public char firstUniqChar(String s) {
if(s.length() == 0) return ' ';
if(s.length() == 1) return s.charAt(0);
int[] num = new int[256];
char[] ss = s.toCharArray();
for(char c: ss){
num[c]++;
}
for(char c: ss){
if(num[c] == 1){
return c;
}
}
return ' ';
}
}
//C++代碼
#include <bits/stdc++.h>
#include <string>
using namespace std;
int main(){
string s;
getline(cin, s);
int a[256];
char res = ' ';
memset(a, 0, sizeof(a));
for(int i = 0; i < s.length(); i++){
a[s[i]]++;
}
for(int i = 0; i < s.length(); i++){
if(a[s[i]] == 1){
res = s[i];
break;
}
}
cout<<res;
return 0;
}
數組暴力
直接暴力兩層for,只是這裏我用了一個boolean數組來記錄哪些需要重新遍歷一次的字符,從而減少暴力中的循環。(但是還是很暴力呀…)
class Solution {
public char firstUniqChar(String s) {
if(s.length() == 0) return ' ';
if(s.length() == 1) return s.charAt(0);
boolean vis[] = new boolean[s.length()];
for(int i = 0; i < s.length(); i++) vis[i] = false;
for(int i = 0; i < s.length(); i++){
if(!vis[i]){
int flag = 0;
vis[i] = true;
for(int j = i+1; j < s.length(); j++){
if(s.charAt(i) == s.charAt(j)){
flag = 1;
vis[j] = true;
}
}
if(flag == 0) return s.charAt(i);
}
}
return ' ';
}
}
哈希表
兩次遍歷字符串
- 第一次遍歷字符串。 將字符放入哈希表中。當第一次出現,key存字符,value存爲true。大於一次出現,即將value改爲false。
- 第二次遍歷字符串。 找value爲true的對應的key,即是第一個出現一次的字符
class Solution {
public char firstUniqChar(String s) {
if(s.length() == 0) return ' ';
if(s.length() == 1) return s.charAt(0);
HashMap<Character, Boolean> map = new HashMap<>();
char[] ss = s.toCharArray();
for(char c: ss){ //第一次遍歷所有字符,key是字符,value是出現次數,一次即true,兩次即false
if(map.get(c) != null) map.put(c, false);
else map.put(c, true);
//map.put(c, !map.containsKey(c));
}
for(char c: ss){ //找到第一個Key是true的字符即是第一個出現一次的字符
if(map.get(c)) return c;
}
return ' ';
}
}
有序哈希表
在哈希表的基礎上,有序哈希表中的鍵值對是按照插入順序排序的。即一次字符串遍歷+一次有序哈希表遍歷。顯然對比,有序哈希表的時間複雜度要好於哈希表
class Solution {
public char firstUniqChar(String s) {
if(s.length() == 0) return ' ';
if(s.length() == 1) return s.charAt(0);
Map<Character, Boolean> map = new LinkedHashMap<>();
char[] ss = s.toCharArray();
for(char c: ss) map.put(c, !map.containsKey(c));
for(Map.Entry<Character, Boolean> entry: map.entrySet()){
if(entry.getValue()) return entry.getKey();
}
return ' ';
}
}
學到了什麼?
- 字符串轉字符數字 char[] c = s.toCharArray();
- 字符串中單個字轉字符 char c = s.charAt(int index);
- 有序哈希表:在哈希表的基礎上,有序哈希表中的鍵值對是按照插入順序排序的。 即,Map<Character, Boolean> map = new LinkedHashMap<>();