• 剑指offer 34. 第一个只出现一次的字符 & leetcode 剑指 Offer 50. 第一个只出现一次的字符


    34. 第一个只出现一次的字符

    思路一:计数排序

    先使用计数排序统计每个字符出现的次数,然后再次遍历字符串,判断每个字符出现的次数,返回第一个次数为1的字符

    由于限定了所有字符为字母,所以可以统计每个字符出现的次数,然后第二次遍历字符串,判断每个字符出现的次数,找到第一个次数为一的返回即可

    这里计数数组长度设置为 58, 是因为 大写字符的 ASCII 范围为 65 - 90, 小写字符的ASCII 范围为 97 - 122,所以从 65 - 122 共58个单位长度

    public class Solution {
        public int FirstNotRepeatingChar(String str) {
            // 计数排序
            // 数组长度只需 58即可 112 - 65 + 1 = 58
            int[] count = new int[58];
            for(int i = 0; i < str.length(); i++){
                count[str.charAt(i) - 'A']++;
            }
           
            // 再次遍历 str 字符串,找到第一个字符对应的个数为1即可
            for(int i = 0; i < str.length(); i++){
                if(count[str.charAt(i) - 'A'] == 1){
                    return i;
                }
            }
            return -1;
        }
    }

    复杂度分析:

    时间复杂度:最多遍历两次字符串,所以时间复杂度为O(n)

    空间复杂度:借助了一个长度为58的数组,是常量级的,所以空间复杂度为O(1)

    注:

    Java 中的字符在于整数做加减运算的时候也会转换成 ASCII 来做运算,所以可以作为下标来使用。

    leetcode 剑指 Offer 50. 第一个只出现一次的字符

    在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

    示例:

    s = "abaccdeff"
    返回 "b"
    
    
    s = "" 
    返回 " "

    思路一:同上思路一,使用计数排序实现

     1 class Solution {
     2     public char firstUniqChar(String s) {
     3         // 先使用计数排序统计每个字符出现的次数
     4         int[] counts = new int[26];
     5         int len = s.length();
     6         for(int i = 0; i < len; i++){
     7             counts[s.charAt(i) - 'a']++;
     8         }
     9 
    10         // 然后再次遍历字符串,判断每个字符出现的次数,返回第一个次数为1的字符
    11         for(int i = 0; i < len; i++){
    12             if(counts[s.charAt(i) - 'a'] == 1){
    13                 return s.charAt(i);
    14             }
    15         }
    16         
    17         return ' ';
    18     }
    19 }

    leetcode 运行时间为8ms, 空间为39.4MB

    复杂度分析:

    时间复杂度:最多遍历两次字符串,所以时间复杂度为O(2n)

    空间复杂度:需要一个大小为26的数组,但是大小时产量级的,所以空间复杂度为O(1)

    思路二:使用LinkedHashMap这个有序 hash表实现

    LinkedHashMap不仅可以统计出现次数,还可以维护一个插入顺序,所以减少了第二次扫描字符串的开销

     1 class Solution {
     2     public char firstUniqChar(String s) {
     3         // 先使用计数排序统计每个字符出现的次数
     4         LinkedHashMap<Character, Boolean> map = new LinkedHashMap<>();
     5         int len = s.length();
     6         for(int i = 0; i < len; i++){
     7             map.put(s.charAt(i), !map.containsKey(s.charAt(i)));    // 如果重复则置为false
     8         }
     9 
    10         // 遍历map,因为mp的大小最大为26, 所以这次循环的时间复杂度为O(1)
    11         for(Map.Entry<Character, Boolean> en : map.entrySet()){
    12             if(en.getValue() == true){
    13                 return en.getKey();
    14             }
    15         }
    16 
    17         return ' ';
    18     }
    19 }

    leetcode运行时间为:38ms, 时间为39.5MBb, 根据前面思路介绍的,案例来说这个时间应该比思路一快才对,但是事实就是慢这么多,我觉得应该是思路一用的是数组来计数,所以效率较高,但是如果使用hashmap来计数的话,那时间上应该会比当前解法慢

    复杂度分析:

    时间复杂度:遍历了一次字符串,花费时间为O(n), 虽然后面还是有一个遍历map的循环,但是循环次数最多为26次,可以忽略不计,所以总的时间复杂度为O(n)

    空间复杂度:借用了一个大小为26的 LinkedHashMap, 常量级别的,所以空间复杂度为O(1)

  • 相关阅读:
    windows 2012 r2怎么进入本地组策略
    ESXI | ESXI6.7如何在网页端添加用户并且赋予不同的权限
    exsi 6.7u2 不能向winows虚拟机发送ctrl+alt+del
    正确安装Windows server 2012 r2的方法
    gitkraken生成ssh keys并连接git
    GitKraken 快速配置 SSH Key
    寒假学习进度六
    寒假学习进度五——活动之间的跳转以及数据的传递
    寒假学习进度四(解决Android studio的com.android.support.v4.view.ViewPager报错问题)
    寒假学习进度三——安卓的一些基本组件
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/12599528.html
Copyright © 2020-2023  润新知