【LeetCode - Java】387. 字符串中的第一个唯一字符 (简单)

1. 题目描述

在这里插入图片描述

2. 解题思路

一开始看到这条题目我就产生一种想法,我看到一个数,我再往后看看它还有没有出现不就得了?但当我尝试判断“aabb”这种字符串时发现,判断第一个a是没有问题的,但判断第二个a时后面已经是没有a的存在,会误判,因此在这个算法中必须让他有“记忆”,需要使用哈希表储存前面曾经出现的字符以免误判。

实现第一种方法后发现性能不太优,既然我对每个字符都要看一眼后面,那我也可以统计所有字符后再进行判断,正如我在【LeetCode - Java】350. 两个数组的交集 II (简单)中所说的,对于这种需要“全局观”的题目来说,统计是一个很好的方法,我们可以统计每一个字符的出现次数,然后再遍历一次字符串,判断其出现次数是否为1,当然使用哈希表记录出现次数的没有问题的,但对于这种字符种类数不大且确定的(小写英文字母26个),使用数组的速度会快很多。

噢?可以用数组代替哈希表,那么第一种方法自然也可以,于是也尝试了一番发现比“全局观”还要更好一些。

3. 代码实现

3.1 逐位判断 哈希表记忆

public int firstUniqChar(String s) {
        HashSet<Character> set = new HashSet<>();
        for (int i = 0; i < s.length(); i++) {
            int j;
            if (!set.contains(s.charAt(i))) {
                for (j = i + 1; j < s.length(); j++) {
                    if (s.charAt(i) == s.charAt(j)) {
                        set.add(s.charAt(i));
                        break;
                    }
                }
                if (j == s.length())
                    return i;
            }
        }
        return -1;
    }

3.2 统计次数 哈希表

public int firstUniqChar(String s) {
        Hashtable<Character, Integer> table = new Hashtable<>();
        for (int i = 0; i < s.length(); i++) {
            if(table.putIfAbsent(s.charAt(i),1)!=null){
                table.put(s.charAt(i),table.putIfAbsent(s.charAt(i),1)+1);
            }
        }
        for (int i = 0; i < s.length(); i++) {
            if(table.get(s.charAt(i))==1)
                return i;
        }
        return -1;
    }

3.3 统计次数 数组

public int firstUniqChar(String s) {
        int[] count = new int[26];
        for (int i = 0; i < s.length(); i++) {
            count[s.charAt(i) - 'a'] = count[s.charAt(i) - 'a'] + 1;
        }
        for (int i = 0; i < s.length(); i++) {
            if (count[s.charAt(i) - 'a'] == 1)
                return i;
        }
        return -1;
    }

在这里插入图片描述

3.4 逐位判断 数组

int[] count = new int[26];
        for (int i = 0; i < s.length(); i++) {
            int j;
            if (count[s.charAt(i) - 'a'] == 0) {
                for (j = i + 1; j < s.length(); j++) {
                    if (s.charAt(i) == s.charAt(j)) {
                        count[s.charAt(i) - 'a']++;
                        break;
                    }
                }
                if (j == s.length())
                    return i;
            }
        }
        return -1;

在这里插入图片描述

3.5 对比

逐位判断因为每判断一位元素都需要向后看一眼,因此其时间复杂度是O(n²),而统计方法的时间复杂度是O(n),单纯从时间复杂度的对比而言,统计是比逐位判断更优的,但由于诸位判断中带有一种“早停”的性质,因此在实际表现上却是逐位判断比统计更优。对于空间复杂度而言,使用哈希表的空间复杂度都是O(n),使用数组的空间复杂度是O(1),不过同样由于哈希表所存储的元素一定是会小于等于26的,因此实际表现上哈希表的空间表现会更优。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值