为了账号安全,请及时绑定邮箱和手机立即绑定

leetcode 每日一题:387. 字符串中的第一个唯一字符

标签:
Python 算法

一起刷题吧

一、题目分析

输入:字符串
输出:第一个不重复的元素的下标
难度:简单
标签:哈希表,字符串

示例
s = "leetcode"
返回 0

s = "loveleetcode"
返回 2

二、参考代码

这个题目比较简单,也有很多的解法。最直接的解法就是遍历一遍,同时把次数计算好,然后再遍历一遍,每次遍历时看下当前这个字符的次数,如果是等于 1 的,则返回当前下标。

这个题目用 Python 实现很简单,Pythoncollections 库里提供了 Counter,用于统计 可迭代对象 里各个 对象 出现的次数。

看过原来题解的童鞋们肯定对 collections 库很熟悉了,因为用到过很多次,这里简单介绍下,个人认为这个库比较很好用,其中比较常用的是:

  • Counter:用于统计个数,使用和dict类似,提供了most_common()方法,可以获取到list,且这个list中的元素是一个tupletuple第一个元素是对象,第二个元素是这个对象出现的次数。最终这个列表是按次数倒序排序的
  • deque:队列,也可以用于栈。比 list 做入、出的操作要高效
  • OrderedDict:有序的 dict。不过在3.7之后,普通dict就已经是有序了

因此,这个题目用Counter其实可以很方便得到每个对象出现的次数。参考代码如下:

from collections import Counter

class Solution:
    def firstUniqChar(self, s: str) -> int:
        if not s:
            return -1

        record = Counter(s)
        for i in range(len(s)):
            if record[s[i]] == 1:
                return i
        return -1

在看题解的时候,看到两种比较好的思路,一种是在遍历的过程,去做查找,即判断是否会出现两次。那怎么通过查找能快速得到每个元素是否只会出现一次呢?很简单,即比较findLeftfindRight得到了index是否相等。参考代码如下:


class Solution:
    def firstUniqChar(self, s: str) -> int:
        if not s:
            return -1

        for i in range(len(s)):
            tmp = s.find(s[i])
            if s.find(s[i], tmp+1) == -1:
                return i
        return -1

另外一种比较好的思路,使用了队列,即保证队列的首位一定是当前只出现过一次的元素。参考代码如下:

class Solution:
    def firstUniqChar(self, s: str) -> int:
        # 通过 dict 保证唯一性,即入队的元素一定是去重后的
        position = dict()
        q = deque()
        n = len(s)
        for i, ch in enumerate(s):
            if ch not in position:
                position[ch] = i
                q.append((s[i], i))
            else:
                # 如果出现一个次数超过1的,则开始做出队判断
                # 但并不是每次都需要出队,当队首的次数仍然是1时,其实是不需要出队的
                position[ch] = -1
                while q and position[q[0][0]] == -1:
                    q.popleft()
        return -1 if not q else q[0][1]

# 作者:LeetCode-Solution
# 链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string/solution/zi-fu-chuan-zhong-de-di-yi-ge-wei-yi-zi-x9rok/
# 来源:力扣(LeetCode)
# 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、相似题目

另外类似的题目:451. 根据字符出现频率排序:

https://leetcode-cn.com/problems/sort-characters-by-frequency/

同样如果使用 Counter 的话,一行代码就可以搞定,参考代码如下:

from collections import Counter


class Solution:
    def frequencySort(self, s: str) -> str:
        if not s:
            return
        return "".join([c[0] * c[1] for c in Counter(s).most_common()])
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消