2021.09.07 - 026.第一个只出现一次的字符

258 篇文章 0 订阅

1. 题目

在这里插入图片描述

2. 思路

(1) 哈希表

  • 创建一个内部类CharInfo,用于存储字符首次出现时的下标和是否只出现过一次的状态。
  • 首先遍历字符串,若哈希表中已经存在该字符,则将该字符只出现过一次的状态修改为false;若哈希表中不存在该字符,则将该字符及其CharInfo对象存入哈希表。
  • 最后遍历哈希表,找出只出现过一次且下标最小的字符,返回即可。

(2) 队列

  • 在(1)的基础上,舍弃了内部类,使用了队列。
  • 首先遍历字符串,当字符第一次出现时,将其同时加入队列,利用队列先进先出的特性,维持字符第一次出现的顺序。
  • 最后遍历队列,找出第一个只出现过一次的字符,返回即可。

(3) 有序哈希表

  • 在(1)的基础上,改为使用LinkedHashMap类。
  • 该类存储了键值对添加时的顺序,利用foreach循环遍历哈希表时,按照键值对添加时的顺序进行遍历。

(4) 数组

  • 由于题目说明了只会出现26个小写字母,因此可以声明长度为26的int数组,用于存储每个字母出现的次数。
  • 第一次遍历字符串存储每个字母出现的次数。
  • 第二次遍历字符串找到第一个出现次数为1的字母,返回即可。

3. 代码

import java.util.*;

public class Test {
    public static void main(String[] args) {
        Solution2 solution = new Solution2();
        System.out.println(solution.firstUniqChar("leetcode"));
    }
}

class Solution {
    private class CharInfo {
        private int index;
        private boolean unique;

        public CharInfo(int index, boolean unique) {
            this.index = index;
            this.unique = unique;
        }
    }

    public char firstUniqChar(String s) {
        char result = ' ';
        Map<Character, CharInfo> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.containsKey(s.charAt(i))) {
                map.get(s.charAt(i)).unique = false;
            } else {
                map.put(s.charAt(i), new CharInfo(i, true));
            }
        }
        int index = Integer.MAX_VALUE;
        for (Map.Entry<Character, CharInfo> entry : map.entrySet()) {
            if (entry.getValue().unique == true && entry.getValue().index < index) {
                result = entry.getKey();
                index = entry.getValue().index;
            }
        }
        return result;
    }
}

class Solution1 {
    public char firstUniqChar(String s) {
        Map<Character, Boolean> map = new HashMap<>();
        Queue<Character> queue = new LinkedList<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.containsKey(s.charAt(i))) {
                map.put(s.charAt(i), false);
            } else {
                map.put(s.charAt(i), true);
                queue.offer(s.charAt(i));
            }
        }
        while (!queue.isEmpty()) {
            char c = queue.poll();
            if (map.get(c) == true) {
                return c;
            }
        }
        return ' ';
    }
}

class Solution2 {
    public char firstUniqChar(String s) {
        Map<Character, Boolean> map = new LinkedHashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.containsKey(s.charAt(i))) {
                map.put(s.charAt(i), false);
            } else {
                map.put(s.charAt(i), true);
            }
        }
        for (Map.Entry<Character, Boolean> entry : map.entrySet()) {
            if (entry.getValue() == true) {
                return entry.getKey();
            }
        }
        return ' ';
    }
}

class Solution3 {
    public char firstUniqChar(String s) {
        int[] count = new int[26];
        for (int i = 0; i < s.length(); i++) {
            count[s.charAt(i) - 'a']++;
        }
        for (int i = 0; i < s.length(); i++) {
            if (count[s.charAt(i) - 'a'] == 1) {
                return s.charAt(i);
            }
        }
        return ' ';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值