Leetcode每日一题 构造限制重复的字符串

2182. 构造限制重复的字符串

题目描述:

给你一个字符串 s 和一个整数 repeatLimit ,用 s 中的字符构造一个新字符串 repeatLimitedString ,使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全部字符。
返回 字典序最大的 repeatLimitedString 。

如果在字符串 a 和 b 不同的第一个位置,字符串 a 中的字母在字母表中出现时间比字符串 b 对应的字母晚,则认为字符串 a 比字符串 b 字典序更大 。如果字符串中前 min(a.length, b.length) 个字符都相同,那么较长的字符串字典序更大。

示例一:

输入:s = "cczazcc", repeatLimit = 3
输出:"zzcccac"
解释:使用 s 中的所有字符来构造 repeatLimitedString "zzcccac"。
字母 'a' 连续出现至多 1 次。
字母 'c' 连续出现至多 3 次。
字母 'z' 连续出现至多 2 次。
因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。
该字符串是字典序最大的 repeatLimitedString ,所以返回 "zzcccac" 。
注意,尽管 "zzcccca" 字典序更大,但字母 'c' 连续出现超过 3 次,所以它不是一个有效的 repeatLimitedString 。

示例二:

输入:s = "aababab", repeatLimit = 2
输出:"bbabaa"
解释:
使用 s 中的一些字符来构造 repeatLimitedString "bbabaa"。 
字母 'a' 连续出现至多 2 次。 
字母 'b' 连续出现至多 2 次。 
因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。 
该字符串是字典序最大的 repeatLimitedString ,所以返回 "bbabaa" 。 
注意,尽管 "bbabaaa" 字典序更大,但字母 'a' 连续出现超过 2 次,所以它不是一个有效的 repeatLimitedString 。

提示:

  • 1 <= repeatLimit <= s.length <= 105
  • s 由小写英文字母组成

 思路:

1.和官方题解雷同,先统计频次,再从后往前加。摘录思路解释如下:

每次选择当前剩余的字典序最大的字符加到字符串末尾;如果字符串末尾的字符已经连续出现了 repeatLimit次,则将字典序次大的字符加到字符串末尾,随后继续选择当前剩余的字典序最大的字符加到字符串末尾,直至使用完字符或没有新的字符可以合法加入。

解释:根据反证法,我们只需要证明任意比上述方法构造出的字符串 ret的字典序更大的字符串都是不合法的即可。

根据字典序的定义,上述证明可以分为两部分:

1.从高位至低位逐位尝试使用字典序更大的字符替代,并逐个判断;

2.尝试在 ret 后添加新的字符,并逐个判断。

对于第一部分,任何使用更大的字符替代后的字符串要么使用了 sss 中不存在的字符,要么某一字符连续出现的次数大于 repeatLimit次,而这两种都是不合法的;对于第二部分,任何尝试添加新字符的字符串也一定是第一部分的两种情况之一,因而也是不合法的。

综上所述,按照上文方法构造的字符串的字典序一定是最大的。

说实话,没看太懂,但思路是这样的哈!

粗糙的代码:

class Solution(object):
    def repeatLimitedString(self, s, repeatLimit):
        """
        :type s: str
        :type repeatLimit: int
        :rtype: str
        """
        #构建一个存储字符频次的数组,0处存放“a”的频次
        count=[0]*26
        for i in s:
            count[ord(i)-ord('a')]+=1
        repe=[]
        i,j,m=25,24,0#加入新船的时候要从后往前选择加入,因为后面的字符字典序更大
        #m是指当前填充数字的数量
        while i>=0 and j >=0:
            if count[i]==0:
                m,i=0,i-1#不填这个数字了,所以要重新计算m
            elif m < repeatLimit:#如果没超过限制
                count[i]-=1
                repe.append(chr(ord('a')+i))#把这个字符加进去
                m+=1
            elif j>=i or count[j] == 0:#当前字符已经超过限制,查找可填入的其他字符
                j-=1
            else:#当前字符已经查过限制,需要其他字符填充进去,这时需要重置m
                count[j]-=1
                repe.append(chr(ord('a')+j))
                m=0
        
        return ''.join(repe)

精选优质题解:

python

from collections import Counter, deque
class Solution:
    def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
        count = Counter(s)
        count = sorted(count.items(), reverse=True)
        count = deque(count)
        res = ""
        while count:
            char, time = count.popleft()
            if time > repeatLimit and count:
                char2, time2 = count.popleft()
                if time2 > 1:
                    count.appendleft((char2, time2-1))
                    count.appendleft((char, time-repeatLimit))
                    count.appendleft((char2, 1))
                else:
                    count.appendleft((char, time-repeatLimit))
                    count.appendleft((char2, 1))
            res += char*min(time, repeatLimit)
        return res

 还有java:

class Solution {
    public String repeatLimitedString(String s, int repeatLimit) {
        int[] cnt = new int[26];
        for (int i = 0; i < s.length(); ++i) {
            ++cnt[s.charAt(i) - 'a'];
        }
        StringBuilder ans = new StringBuilder();
        for (int i = 25, j = 24; i >= 0; --i) {
            j = Math.min(j, i - 1);
            while (true) {
                for (int k = Math.min(cnt[i], repeatLimit); k > 0; --k) {
                    ans.append((char) ('a' + i));
                    --cnt[i];
                }
                if (cnt[i] == 0) {
                    break;
                }
                while (j >= 0 && cnt[j] == 0) {
                    --j;
                }
                if (j < 0) {
                    break;
                }
                ans.append((char) ('a' + j));
                --cnt[j];
            }
        }
        return ans.toString();
    }
}

你可能感兴趣的:(leetcode,算法,职场和发展)