LeetCode解题 387. 字符串中的第一个唯一字符

版权声明:本文为博主原创文章,转载请联系作者获得授权并注明出处。 https://blog.csdn.net/qq_34172340/article/details/84643074

文章已同步更新到本人个人博客跳转链接
题目描述:
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

案例:

s = "leetcode"
返回 0.

s = "loveleetcode",
返回 2.

注意事项:您可以假定该字符串只包含小写字母。

这道题很容易做出来,但是想要提交通过,就必须降低时间复杂度,否则会超时。

class Solution:
	"""
    :type s: str
    :rtype: int
    """
    def firstUniqChar(s):
        for elem in s:
            if s.count(elem) == 1:
                return s.index(elem)
        
        return -1

这是我的第一版本,看着很简洁,对字符串进行遍历,每一个都count一下,等于1,返回索引,否则返回-1,自己电脑上运行,没问题,在线提交答案,超时。时间复杂度O(n)。需要遍历、统计大量的重复字符,太浪费时间。

接下来想法去优化,避免去统计重复的字符串,就先要去重,我选择了使用内置模块collections中的Counter方法,下面是第二版本:

class Solution:
    def firstUniqChar(self, s):
        """
        :type s: str
        :rtype: int
        """
        from collections import Counter
        s_dict = Counter(s)
        num = len(s)
        count = 0
        for elem in s_dict:
            if s_dict[elem] == 1:
                elem_index = s.index(elem)
                if elem_index <= num:
                	   # 保持num 始终是不重复字符的最小索引
                    num = elem_index
                    # num是第一个字符的时候,就不需要继续了,
                    if num == 0:
                        break
            else:
                # count 统计遍历次数,用来判断是不是没有不重复的字符
                count += 1
        if count == len(s_dict):
            return -1
        else:
            return num

使用Counter计数,这样就会返回一个有键值对组成的Counter对象,键是字符串中的元素,值是该元素出现的次数,由于它是无序的,还不能满足获取索引的要求,需要一个指针,让他始终指向索引最小的不重复元素,num初始值是字符串的长度,只要有索引比num小的不重复字符,就把较小的索引赋值给num,考虑到会有没有不重复的字符这种情况,不能直接返回num,需要判断一下。测试通过后,我有迫不及待的提交了,果然,是用Counter后大幅度的降低了遍历次数,通过了,超过了87%的提交答案。
在这里插入图片描述

回头看看自己的代码,添加注释,做记录,突然感觉count这里,还可以优化一下;每遍历一次,做一个加操作,如果字符串特别长、不重复字符特别多,假设字符串长度为n,不重复字符串数量为m,在使用Counter返回的对象里,索引最小的字符在最后一位的话,就要做m次加操作,怎么在提高一下呢?脑子里有几个思路,选了一个试试,踩了几次‘雷’后,第三版本诞生了,

class Solution:
    def firstUniqChar(self, s):
        """
        :type s: str
        :rtype: int
        """
        from collections import Counter
        if s and s.count(s[0])==1:
            return 0
        length = len(s) + 1
        s_dict = Counter(s)
        num = length
        for elem in s_dict:
            if s_dict[elem] == 1:
                elem_index = s.index(elem)
                if elem_index <= num:
                    num = elem_index
                    if num == 0:
                        break
        if num < length:
            return num
        else:
            return -1

这里先对字符串s进行判断,不为空、0位索引的字符串为不重复字符串这种极端情况,直接返回结果,length比s的长度大1,最后,只要num小于length,num就是正确结果,否则,就没有不重复字符,直接返回-1,提交结果不出所料,又提高了2%。
在这里插入图片描述
这已经是我目前能做出来的最好结果了,以后有更优解,再来更新!

猜你喜欢

转载自blog.csdn.net/qq_34172340/article/details/84643074