【LeetCode】1417. 重新格式化字符串

187 阅读2分钟

image.png

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

    image.png

  • 题目示例

    image.png

  • 题目解析

    • 1 <= s.length <= 500
    • s 仅由小写英文字母和/或数字组成

二、思路分析:

我们拿到题目,读取题目内容要求对指定的字符串按照数字与字母交替的方式进行格式化输出,那么给定的字符串以及不满足格式化的条件是什么呢?我们继续对题目细节进行审题:

  • s字符串是由小写字母和数字
  • s字符串格式化要求相邻的字符不能一样
  • s字符串无法满足格式化要求则返回空字符

根据题目的要求,对字符串按字母和数字交替排序规则,我们能推出符合格式的条件如下:

  • 满足格式化要求:数字字符numflag与字母字符strflag的数量绝对差要小于等于1
  • 当数字字符numflag与字母字符strflag值绝对差大于1时,则返回空字符
  • numflag次数可以使用for循环遍历字符串s,满足ss >= "0" and ss <= "9"
  • 一般普通的写法:
    for ss in s:
        if ss >= "0" and ss <= "9":
            numflag +=1
    
  • 推荐的优雅写法,使用sum()函数,一行代码搞定
    numflag = sum(c.isdigit() for c in s)
    

那么知道格式化要求后,我们需要对符合格式化的字符串按照数字与字母交替排序,排序的思路如下:

  • 因为题目给的参数是字符串,是不可变数据类型,因此我们需要将字符串s转换成可变数据类型list
  • 我们需要判断numflag数字字符数量与strflag字母字符数量的大小,决定排在奇偶位置上
  • 当numflag大于strflag时,则数字字符排在偶数位,反之则排在奇数位

根据以上思路,我们可以使用双指针i和j变量来决定奇偶位置,再使用for循环遍历字符串s:

  • ss是数字字符,则ans[i]赋值为ss,则i指针+2
  • ss是字母字符,则ans[j]赋值为ss,则j指针+2
    class Solution(object):
        def reformat(self, s):
            """
            :type s: str
            :rtype: str
            """
            numflag = sum(c.isdigit() for c in s)
            strflag = len(s) - numflag
            if abs(numflag-strflag) > 1:
                return ""
    
            if numflag > strflag:
                i = 0
                j = 1
            else:
                i = 1
                j = 0
            ans = [0]*len(s)
            for ss in s:
                if ss.isdigit():
                    ans[i] = ss
                    i +=2
                else:
                    ans[j] = ss
                    j +=2
    
            return "".join(ans)
    

在对字符串字符进行交替排序时,我们可以使用一个临时变量来记录numflag与strflag的大小情况

  • flag 赋值为numflag与strflag大小判断
  • 在for循环只遍历偶数位置
  • 当ans[i].isdigit()与flag结果不一致时,奇数位于偶数位的元素进行交换
  • 当ans[j].isdigit()与flag结果不一致,则奇数位往右移到2位
    class Solution(object):
        def reformat(self, s):
            """
            :type s: str
            :rtype: str
            """
            numflag = sum(c.isdigit() for c in s)
            strflag = len(s) - numflag
            if abs(numflag-strflag) > 1:
                return ""
            flag = numflag < strflag  
            ans = list(s)
            j = 1
            for i in range(0,len(s),2):
               if  ans[i].isdigit() != flag: 
                    while  ans[j].isdigit() != flag:
                       j +=2
                    ans[i],ans[j] = ans[j],ans[i]
    
            return "".join(ans)
    
  • 方法二:正则表达式

    本题中会涉及到字符串,我们也可以使用正则表达,结合itertools.zip_longest进行合并。
    class Solution:
        def reformat(self, s: str) -> str:
            a=re.findall(r'\d',s)
            b=re.findall(r'[a-z]',s)
            if abs(len(a)-len(b))>1:
                return ''
            a,b=sorted([a,b],key=len)
            return ''.join(map(''.join,itertools.zip_longest(b,a,fillvalue='')))
    

三、总结:

本题考察我们对字符串元素按照交替排序的方式使用双指针模拟方法实现,难点在于交替的条件怎么定义,直接定义偶数与奇数位的起始点,或者使用一个flag临时变量控制,AC提交记录如下:

image.png

  • 时间复杂度: O(n),n为字符串s的长度
  • 空间复杂度:O(n),使用临时的数组来移动元素

以上是本期内容,欢迎大佬们点赞评论,下期见~~