1405. Longest Happy String (M)

Longest Happy String (M)

A string is called happy if it does not have any of the strings 'aaa', 'bbb' or 'ccc' as a substring.

Given three integers a, b and c, return any string s, which satisfies following conditions:

  • s is happy and longest possible.
  • s contains at most a occurrences of the letter 'a', at most b occurrences of the letter 'b' and at most c occurrences of the letter 'c'.
  • swill only contain 'a', 'b' and 'c' letters.

If there is no such string s return the empty string "".

Example 1:

Input: a = 1, b = 1, c = 7
Output: "ccaccbcc"
Explanation: "ccbccacc" would also be a correct answer.

Example 2:

Input: a = 2, b = 2, c = 1
Output: "aabbc"

Example 3:

Input: a = 7, b = 1, c = 0
Output: "aabaa"
Explanation: It's the only correct answer in this case.

Constraints:

  • 0 <= a, b, c <= 100
  • a + b + c > 0

题意

一个不包含"aaa"或"bbb"或"ccc"子串的字符串被称为Happy String。要求用a个’a’、b个’b’、c个’c’组合成一个最长的Happy String。

思路

贪心。为了使得到的字符串最长,每次拼接字符时都应该尽可能消耗掉剩余数量最多的字符。步骤为:每次选出当前剩余数量最多的字符x和第二多的字符y,若x数量大于等于2,则拼接上2个x,否则拼接上1个x;此时判断x拼接后剩余数量是否比y多,若比y多则拼接上一个y,否则不需要拼接y,进入下一个循环。该步的关键思想为:每一次循环尽可能消耗掉剩余数量最多的字符,然后视情况拼接一个数量第二多的字符来当作分隔字符,以保证在下一个循环中选出的数量最多的字符x一定可以尽可能多地拼接在结果字符串的末尾(即不会出现拼接两个字符x会导致三个连续x的情况)。

解题思路及递归解法出处为LeetCode论坛解答 votrubac - C++/Java a >= b >= c


代码实现 - 递归

class Solution {
    public String longestDiverseString(int a, int b, int c) {
        return helper(a, b, c, "a", "b", "c");
    }

    private String helper(int lg, int md, int sm, String lgc, String mdc, String smc) {
        if (lg < md) return helper(md, lg, sm, mdc, lgc, smc);
        if (md < sm) return helper(lg, sm, md, lgc, smc, mdc);
        if (md == 0) return lgc.repeat(Math.min(lg, 2));

        int lgToUse = Math.min(lg, 2);
        int mdToUse = lg - lgToUse < md ? 0 : 1;
        return lgc.repeat(lgToUse) + mdc.repeat(mdToUse) + helper(lg - lgToUse, md - mdToUse, sm, lgc, mdc, smc);
    }
}

代码实现 - 优先队列

class Solution {
    public String longestDiverseString(int a, int b, int c) {
        Queue<Pair> q = new PriorityQueue<>((x, y) -> y.count - x.count);
        StringBuilder sb = new StringBuilder();
        if (a > 0) q.offer(new Pair('a', a));
        if (b > 0) q.offer(new Pair('b', b));
        if (c > 0) q.offer(new Pair('c', c));
        
        while (q.size() > 1) {
            Pair first = q.poll();
            Pair second = q.poll();

            sb.append(first.letter);
            first.count--;
            if (first.count > 0) {
                sb.append(first.letter);
                first.count--;
            }
            
            if (second.count <= first.count) {
                sb.append(second.letter);
                second.count -= 1;
            }
            
            if (first.count>0) q.offer(first);
            if (second.count>0) q.offer(second);
        }
        
        if (!q.isEmpty()) {
            Pair last = q.poll();
            sb.append(last.letter);
            last.count--;
            if (last.count > 0) {
                sb.append(last.letter);
            }
        }
        
        return sb.toString();
    }

    class Pair {
        char letter;
        int count;

        public Pair(char letter, int count) {
            this.letter = letter;
            this.count = count;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值