You are given three integers: a
, b
, and c
, representing the maximum number of letters 'a', 'b', and 'c' you can use, respectively.
Your task is to construct the longest possible "happy" string using at most a
'a's, b
'b's, and c
'c's, subject to these constraints:
At first glance, we might consider brute-forcing all possible permutations of 'a', 'b', and 'c', checking if each is "happy". However, this approach is computationally infeasible due to the sheer number of possible strings as the counts grow.
Instead, we should focus on a greedy strategy. The key insight is that to maximize the string length, we should always try to use the letter with the highest remaining count, unless doing so would create three consecutive identical letters. If it would, we pick the next most frequent letter instead.
This is similar to always picking the most "plentiful" resource unless a rule prevents us, in which case we pick the next best option. We repeat this process until no valid moves remain.
The solution can be broken down into the following steps:
Let's walk through an example with a = 1
, b = 1
, c = 7
.
Brute-force approach:
a + b + c
(since all possible orderings are considered).
To solve the "Longest Happy String" problem, we use a greedy strategy: always append the most available letter unless it would create three in a row, in which case we pick the next best option. This efficiently builds the longest valid string by avoiding forbidden substrings and making the best local choice at each step. The approach is simple, elegant, and runs in linear time relative to the total number of letters allowed.
import heapq
class Solution:
def longestDiverseString(self, a: int, b: int, c: int) -> str:
max_heap = []
for cnt, ch in [(-a, 'a'), (-b, 'b'), (-c, 'c')]:
if cnt != 0:
heapq.heappush(max_heap, (cnt, ch))
result = []
while max_heap:
cnt1, ch1 = heapq.heappop(max_heap)
if len(result) >= 2 and result[-1] == result[-2] == ch1:
if not max_heap:
break
cnt2, ch2 = heapq.heappop(max_heap)
result.append(ch2)
cnt2 += 1
if cnt2 != 0:
heapq.heappush(max_heap, (cnt2, ch2))
heapq.heappush(max_heap, (cnt1, ch1))
else:
result.append(ch1)
cnt1 += 1
if cnt1 != 0:
heapq.heappush(max_heap, (cnt1, ch1))
return ''.join(result)
#include <queue>
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
string longestDiverseString(int a, int b, int c) {
priority_queue<pair<int, char>> pq;
if (a) pq.push({a, 'a'});
if (b) pq.push({b, 'b'});
if (c) pq.push({c, 'c'});
string res = "";
while (!pq.empty()) {
auto [cnt1, ch1] = pq.top(); pq.pop();
int len = res.size();
if (len >= 2 && res[len-1] == ch1 && res[len-2] == ch1) {
if (pq.empty()) break;
auto [cnt2, ch2] = pq.top(); pq.pop();
res += ch2;
if (--cnt2) pq.push({cnt2, ch2});
pq.push({cnt1, ch1});
} else {
res += ch1;
if (--cnt1) pq.push({cnt1, ch1});
}
}
return res;
}
};
import java.util.*;
class Solution {
public String longestDiverseString(int a, int b, int c) {
PriorityQueue<int[]> pq = new PriorityQueue<>((x, y) -> y[0] - x[0]);
if (a > 0) pq.offer(new int[]{a, 'a'});
if (b > 0) pq.offer(new int[]{b, 'b'});
if (c > 0) pq.offer(new int[]{c, 'c'});
StringBuilder sb = new StringBuilder();
while (!pq.isEmpty()) {
int[] first = pq.poll();
int len = sb.length();
if (len >= 2 && sb.charAt(len-1) == first[1] && sb.charAt(len-2) == first[1]) {
if (pq.isEmpty()) break;
int[] second = pq.poll();
sb.append((char)second[1]);
if (--second[0] > 0) pq.offer(second);
pq.offer(first);
} else {
sb.append((char)first[1]);
if (--first[0] > 0) pq.offer(first);
}
}
return sb.toString();
}
}
var longestDiverseString = function(a, b, c) {
let arr = [];
if (a > 0) arr.push([a, 'a']);
if (b > 0) arr.push([b, 'b']);
if (c > 0) arr.push([c, 'c']);
let res = [];
while (arr.length > 0) {
arr.sort((x, y) => y[0] - x[0]);
let [cnt1, ch1] = arr[0];
let len = res.length;
if (len >= 2 && res[len-1] === ch1 && res[len-2] === ch1) {
if (arr.length < 2) break;
let [cnt2, ch2] = arr[1];
res.push(ch2);
if (--cnt2 === 0) arr.splice(1, 1);
else arr[1][0] = cnt2;
} else {
res.push(ch1);
if (--cnt1 === 0) arr.shift();
else arr[0][0] = cnt1;
}
}
return res.join('');
};