zoukankan      html  css  js  c++  java
  • 【剑指Offer学习】【面试题55:字符流中第一个不反复的字符】

    题目:请实现一个函数用来找出字符流中第一个仅仅出现一次的字符。


    举例说明

      比如,当从字符流中仅仅读出前两个字符“go”时。第一个仅仅出现一次的字符是‘g’。当从该字符流中读出前六个字符“google”时,第一个仅仅出现1次的字符是”l”。

    解题思路

      字符仅仅能一个接着一个从字符流中读出来。能够定义一个数据容器来保存字符在字符流中的位置。当一个字符第一次从字符流中读出来时,把它在字符流中的位置保存到数据容器里。当这个字符再次从字符流中被读出来时。那么它就不是仅仅出现一次的字符。也就能够被忽略了。

    这时把它在数据容器里保存的值更新成一个特殊的值(比方负值)。
      为了尽可能高校地解决问题。须要在O(1)时间内往容器里插入一个字符,以及更新一个字符相应的值。这个容器能够用哈希表来实现。用字符的ASCII码作为哈希表的键值,而把字符相应的位置作为哈希表的值。

    代码实现

    public class Test55 {
        /**
         * 题目:请实现一个函数用来找出字符流中第一个仅仅出现一次的字符。
         */
        private static class CharStatistics {
            // 出现一次的标识
            private int index = 0;
            private int[] occurrence = new int[256];
    
            public CharStatistics() {
                for (int i = 0; i < occurrence.length; i++) {
                    occurrence[i] = -1;
                }
            }
    
            private void insert(char ch) {
                if (ch > 255) {
                    throw new IllegalArgumentException( ch + "must be a ASCII char");
                }
    
                // 仅仅出现一次
                if (occurrence[ch] == -1) {
                    occurrence[ch] = index;
                } else {
                    // 出现了两次
                    occurrence[ch] = -2;
                }
    
                index++;
            }
    
            public char firstAppearingOnce(String data) {
                if (data == null) {
                    throw new IllegalArgumentException(data);
                }
    
                for (int i = 0; i < data.length(); i++) {
                    insert(data.charAt(i));
                }
                char ch = '';
                // 用于记录最小的索引,相应的就是第一个不反复的数字
                int minIndex = Integer.MAX_VALUE;
                for (int i = 0; i < occurrence.length; i++) {
                    if (occurrence[i] >= 0 && occurrence[i] < minIndex) {
                        ch = (char) i;
                        minIndex = occurrence[i];
                    }
                }
    
                return ch;
            }
        }
    
        public static void main(String[] args) {
            System.out.println(new CharStatistics().firstAppearingOnce("")); // ''
            System.out.println(new CharStatistics().firstAppearingOnce("g")); // 'g'
            System.out.println(new CharStatistics().firstAppearingOnce("go")); // 'g'
            System.out.println(new CharStatistics().firstAppearingOnce("goo")); // 'g'
            System.out.println(new CharStatistics().firstAppearingOnce("goog")); // ''
            System.out.println(new CharStatistics().firstAppearingOnce("googl")); // l
            System.out.println(new CharStatistics().firstAppearingOnce("google")); // l
        }
    }

    执行结果

    这里写图片描写叙述

  • 相关阅读:
    2019.6.20刷题统计
    36 线程 队列 守护线程 互斥锁 死锁 可重入锁 信号量
    35 守护进程 互斥锁 IPC 共享内存 的方式 生产者消费者模型
    34 进程 pid ppid 并发与并行,阻塞与非阻塞 join函数 process对象 孤儿进程与僵尸进程
    33 udp 域名 进程
    32 粘包 文件传输
    31 socket客户端. 服务器 异常 语法
    30 网络编程
    29 元类 异常
    26 封装 反射 常用内置函数
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5347652.html
Copyright © 2011-2022 走看看