力扣每日一题(包含运行时间从1344ms到72ms的改进过程)--上升下降字符串(简单)(简单难度还挺复杂的题)

题目描述

在这里插入图片描述

输出示例

在这里插入图片描述

题解一

思路一

其实就是两个遍历,不停输出当前最小和最大,并且需要pop出来相对应的字符。
但其实代码实现起来,我感觉有点难度

代码一(附带讲解)

class Solution:
	# 寻找下一个最小值(在从小到大遍历中用到),输入为当前值和当前列表,输出为下一个最小值和它的index
    def find_next_min(self, formal_min, s:list):
        min_num = max(s)
        min_index = -1
        for i in range(len(s)):
            if (s[i]<=min_num and s[i]>formal_min):
                min_num = s[i]
                min_index = i

        if min_index == -1:
            for i in range(len(s)):
                if (s[i]==formal_min):
                    min_num=s[i]
                    min_index=i

        return min_num,min_index
        
	# 寻找下一个最大值(在从大到小遍历中用到),输入为当前值和当前列表,输出为下一个最大值和它的index
    def find_next_max(self, formal_max, s:list):
        max_num = min(s)
        max_index = -1
        for i in range(len(s)):
            if (s[i]>=max_num and s[i]<formal_max):
                max_num = s[i]
                max_index = i
        if max_index == -1:
            for i in range(len(s)):
                if (s[i]==formal_max):
                    max_num = s[i]
                    max_index = i

        return max_num,max_index

	# 用来进行字符串重拍
    def sortString(self, s: str) -> str:
        ls = list(s)
        new_str='' #用来返回的string
        while(True):
            if (len(ls) == 0):
                break
			# 当前最小值和最大值(字符串会变化),以及其index
            now_min_num, min_index = min_num, pp = self.find_next_min('`', ls)
            now_max_num, max_index = max_num, pp = self.find_next_max('{', ls)
			
			#不断迭代从小往大遍历
            while(min_num < now_max_num):
                new_str += ls.pop(min_index)
                min_num,min_index = self.find_next_min(min_num,ls)
                now_max_num = max(ls)
            new_str += ls.pop(min_index)

            if (len(ls) == 0):
                break

            now_min_num, min_index = min_num, pp = self.find_next_min('`', ls)
            now_max_num, max_index = max_num, pp = self.find_next_max('{', ls)

			#不断迭代从大往小遍历
            while(max_num > now_min_num):
                new_str += max_num
                ls.pop(max_index)
                max_num,max_index = self.find_next_max(max_num,ls)
                now_min_num = min(ls)
            new_str += max_num
            ls.pop(max_index)

        return str(new_str)

运行结果

看到如此复杂迭代的代码,我就已经预知这个不太好了
在这里插入图片描述

题解二

思路二

既然题目中说所有字符均为小写字符, 那么我们可以先把所有的字符先都放在对应的“桶”里。然后不停往返遍历,到了终点,就从头再来一次,直到所有桶内所有字符都被取走

代码二

class Solution:
    def fill_backet(self,backet,str):
        for i in range(len(str)):
            backet[ord(str[i]) - ord('a')] += 1

    def check_empty(self,backet):
        for i in range(0,26):
            if backet[i] > 0 :
                return False
        return True

    def traverse(self,new_str,backet):
        i=0
        difference = 1
        while(True):
            if (backet[i]>0):
                new_str += chr(i + ord('a'))
                backet[i] -= 1
            i+=difference

            #到达26 或 0
            if (i == 26):
                difference = -1
                i+=difference
            else:
                if (i == -1):
                    difference = 1
                    i+=difference

            if self.check_empty(backet):
                return new_str

    def sortString(self, s: str) -> str:
        backet = [0] * 26
        self.fill_backet(backet,s)
        new_str = ""
        new_str = self.traverse(new_str,backet)
        return new_str

运行结果

用时从1.3k ms到了 124 ms,时间不到之前的0.1
虽然简化了不少,但是还是不够理想
在这里插入图片描述

代码改进

其实不必要每次都去check_empty,可以记录操作次数,一个长度为n的字符串操作次数应该是n
所以:

    def traverse(self,new_str,backet,lenth):
        i=0
        difference = 1
        operation_times = 0
        while(True):
            if (backet[i]>0):
                new_str += chr(i + ord('a'))
                operation_times+=1
                backet[i] -= 1
            i+=difference

            #到达26 或 0
            if (i == 26):
                difference = -1
                i+=difference
            else:
                if (i == -1):
                    difference = 1
                    i+=difference

            if operation_times == lenth:
                return new_str

很快啊,我们就获得了显著性的突破:
在这里插入图片描述

官方代码(十分简洁)

思路还是跟我的一样,不过大佬写出来的代码就是简洁

class Solution:
    def sortString(self, s: str) -> str:
        num = [0] * 26
        for ch in s:
            num[ord(ch) - ord('a')] += 1
        
        ret = list()
        while len(ret) < len(s):
            for i in range(26):
                if num[i]:
                    ret.append(chr(i + ord('a')))
                    num[i] -= 1
            for i in range(25, -1, -1):
                if num[i]:
                    ret.append(chr(i + ord('a')))
                    num[i] -= 1

        return "".join(ret)

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/increasing-decreasing-string/solution/shang-sheng-xia-jiang-zi-fu-chuan-by-leetcode-solu/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在这里插入图片描述
显然,这个相比我的代码更加好,因为内存消耗高一些其实无所谓(硬件越来越发达),运行时间才是王道

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值