劍指offer 50_第一個只出現一次的字符(java)

面試題50. 第一個只出現一次的字符

在一個字符串(0<=字符串長度<=10000,全部由字母組成)中找到第一個只出現一次的字符,並返回它的位置, 如果沒有則返回 -1(需要區分大小寫).(從0開始計數)

思路一: 暴力法:

  • 時間: O(N^2)
  • 空間:O(N)
public class Solution {
    public int FirstNotRepeatingChar(String str) {
        // 暴力法
        int[] ans = new int[str.length()];
        for(int i = 0; i < str.length(); i++){
           for(int j = i+1; j < str.length(); j++){
               if(str.charAt(i) == str.charAt(j)) {
                   ans[i] += 1;
                   ans[j] += 1;
               }
           } 
        }
        boolean flag = false;
        int pos;
        for(pos = 0; pos < str.length(); pos++){
            if(ans[pos] == 0) {
                flag = true;
                break;
            }
        }
        if(flag == true) return pos;
        else return -1;
    }
}

思路二: 哈希表HashMap

步驟:

方法一的暴力法是兩層循環,用於判斷某字符後面是否有相同的字符; 可採用HashMap的鍵值判斷是否重複(值爲出現次數)

  1. 遍歷字符串 s ,使用哈希表統計 “各字符數量是否 >1 ”。
  2. 再遍歷字符串 s ,在哈希表中找到首個 “數量爲 1 的字符”,並返回下標。

優化

鍵 - 值,可將值改爲true(只出現一次) false(重複);(hashMap 結構的 Value 使用 Boolean 類型是一個更好的選擇,原因如下:

  1. 一個字母出現的次數大於 1 次就不符合要求了,這個時候使用 Fasle 標記狀態相對於 Integer 的不斷遞增更合理,也更省空間。
  2. 布爾值可以用來判斷,可以簡化代碼邏輯。

複雜度

  • 時間: O(N) N 爲字符串 s 的長度;需遍歷 s 兩輪,使用 O(N) ;HashMap 查找的操作複雜度爲 O(1);
  • 空間: O(N) HashMap 需存儲 N 個字符的鍵值對,使用 O(N)大小的額外空間。
import java.util.HashMap;
public class Solution {
    public int FirstNotRepeatingChar(String str) {
        //哈希表
        HashMap<Character, Boolean> dic = new HashMap<>();
        for(int i = 0; i < str.length(); i++){
            if(!dic.containsKey(str.charAt(i))) dic.put(str.charAt(i), true);
            else dic.put(str.charAt(i), false);
        }
        int pos = -1;
        for(int i = 0; i < str.length(); i++){
            if(dic.get(str.charAt(i))){
                pos = i;
                break;
            } 
        }
        return pos;
    }
}

思路三 優化內存

優化思路:

按照ASCII的值進行保存,開闢固定大小的內存,英文字母的ascii爲 a-z:97-122, A-Z:65-90, 0-9:48-57。,所以數組大小設置爲58個即可(不是52是想省去判斷大小寫的麻煩)。

複雜度

  • 時間: O(n)
  • 空間: O(58). O(1)?
import java.util.HashMap;
public class Solution {
    public int FirstNotRepeatingChar(String str) {
        // 優化內存~ 數組代替哈希表
        // 題目已知全是英文字母,則最多有58個字符,建立一個長度爲58的數組,其ASCII碼作爲數組的位置索引
        int[] res = new int[58];
        for(int i = 0; i < str.length(); i++){
            res[str.charAt(i) -'A']++;
        }
        for(int i = 0; i < str.length(); i++){
            if(res[str.charAt(i) - 'A'] == 1) return i;
        }
        return -1;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章