剑指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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章