erlang算法系列-leetclode-2182. 构造限制重复的字符串(中等)

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

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

返回 字典序最大的 repeatLimitedString 。

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

示例 1:

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

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

提示:

1 <= repeatLimit <= s.length <= 10^5
s 由小写英文字母组成

解题思路

贪心处理,每次加RepeatLimit个最大的字母,然后加一个次大的字母。直到没有字母可加。

-spec repeat_limited_string(S :: unicode:unicode_binary(), RepeatLimit :: integer()) -> unicode:unicode_binary().
repeat_limited_string(S, RepeatLimit) ->
    L = binary_to_list(S),
    Tree = gb_trees:empty(),
    NewTree = lists:foldl(fun(Key, Acc) ->
        case gb_trees:lookup(Key, Acc) of
            {value, Value} ->
                gb_trees:update(Key, Value + 1, Acc);
            _ ->
                gb_trees:insert(Key,1, Acc)
        end
    end, Tree, L),
    do_repeat(1, RepeatLimit, NewTree, [])
  .

do_repeat(0, Limit, Tree, List) ->
    list_to_binary(lists:reverse(List));
do_repeat(1, Limit, Tree, List) ->
    case gb_trees:size(Tree) of
        0 ->
            do_repeat(0, Limit, Tree, List);
        1 ->
            {Key, Value, Tree1} = gb_trees:take_largest(Tree),
            Min = min(Value, Limit),
            L = lists:duplicate(Min, Key),
            do_repeat(0, Limit, Tree1,  L ++ List);
        _ -> 
            {Key1, Value1, Tree1} = gb_trees:take_largest(Tree),
            Min = min(Value1, Limit),
            L = lists:duplicate(Min, Key1),
            List1 = L ++ List,
            if
                Value1 > Min ->
                    {Key2, Value2, Tree2} = gb_trees:take_largest(Tree1),
                    Tree3 = gb_trees:insert(Key1,Value1 - Min, Tree2),
                    if
                        Value2 > 1 ->
                            Tree4 = gb_trees:insert(Key2,Value2 - 1, Tree3);
                        true ->
                            Tree4 = Tree3
                    end,
                     do_repeat(1, Limit, Tree4,  [Key2 | List1]);
                true ->
                    do_repeat(1, Limit, Tree1,  List1)
            end
    end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值