zoukankan      html  css  js  c++  java
  • 剑指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)

  • 相关阅读:
    springboot2.0集成RestTemplate
    RestTemplate HttpMessageConverter报错的解决方案no suitable HttpMessageConverter
    vue条件渲染+列表渲染+事件处理器
    vue计算属性+vue中class与style绑定
    vue选项数据+vue模板语法
    vue安装配置+生命周期
    sass案例--实现高仿今日头条H5版新闻列表页
    sass内置函数
    sass继承+嵌套+条件控制
    sass常见的基本数据类型+加减乘除基本运算
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/12599528.html
Copyright © 2011-2022 走看看