编程进阶网编程进阶网
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 01.翻转字符串
  • 02.字符串替换空格
  • 03.把字符串转换成整数
  • 04.回文字符串
  • 05.字符串的排列
  • 06.第一个只出现一次的字符
  • 07.把字符串转换成整数
  • 08.翻转单词顺序
  • 09.左旋转字符串
  • 10.表示数值字符串
  • 11.查找最长公共前缀
  • 12.第一个不重复的字符

12.第一个不重复的字符

目录介绍

  • 01.题目要求
  • 02.问题分析
  • 03.实例代码

01.题目要求

  • 问题如下所示:
    • 请实现一个函数用来找出字符流中第一个只出现一次的字符。
  • 示例 :
    • 例如,当从字符流中只读出前两个字符“Go”时,第一个只出现一次的字符是‘g’。当从该字符流中读出前六个字符“google”时,第一个只出现1次的字符是”l”。

02.问题分析

  • 字符只能一个接着一个从字符流中读出来。可以定义一个数据容器来保存字符在字符流中的位置。当一个字符第一次从字符流中读出来时,把它在字符流中的位置保存到数据容器里。当这个字符再次从字符流中被读出来时,那么它就不是只出现一次的字符,也就可以被忽略了。这时把它在数据容器里保存的值更新成一个特殊的值(比如负值)。
  • 为了尽可能高校地解决这个问题,需要在O(1)时间内往容器里插入一个字符,以及更新一个字符对应的值。这个容器可以用哈希表来实现。用字符的ASCII码作为哈希表的键值,而把字符对应的位置作为哈希表的值。

03.实例代码

  • 如下所示
public class Test {
    /**
     * 题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。
     */
    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 = '\0';
            // 用于记录最小的索引,对应的就是第一个不重复的数字
            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;
        }
    }
}
贡献者: yangchong211
上一篇
11.查找最长公共前缀