《劍指offer》 面試題50. 第一個只出現一次的字符

題目描述

在字符串 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 ' ';
    }
}

哈希表

兩次遍歷字符串

  1. 第一次遍歷字符串。 將字符放入哈希表中。當第一次出現,key存字符,value存爲true。大於一次出現,即將value改爲false。
  2. 第二次遍歷字符串。 找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 ' ';
    }
}

學到了什麼?

  1. 字符串轉字符數字 char[] c = s.toCharArray();
  2. 字符串中單個字轉字符 char c = s.charAt(int index);
  3. 有序哈希表:在哈希表的基礎上,有序哈希表中的鍵值對是按照插入順序排序的。 即,Map<Character, Boolean> map = new LinkedHashMap<>();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章