Welcome to Subscribe On Youtube
3081. Replace Question Marks in String to Minimize Its Value
Description
You are given a string s
. s[i]
is either a lowercase English letter or '?'
.
For a string t
having length m
containing only lowercase English letters, we define the function cost(i)
for an index i
as the number of characters equal to t[i]
that appeared before it, i.e. in the range [0, i - 1]
.
The value of t
is the sum of cost(i)
for all indices i
.
For example, for the string t = "aab"
:
cost(0) = 0
cost(1) = 1
cost(2) = 0
- Hence, the value of
"aab"
is0 + 1 + 0 = 1
.
Your task is to replace all occurrences of '?'
in s
with any lowercase English letter so that the value of s
is minimized.
Return a string denoting the modified string with replaced occurrences of '?'
. If there are multiple strings resulting in the minimum value, return the lexicographically smallest one.
Example 1:
Input: s = "???"
Output: "abc"
Explanation: In this example, we can replace the occurrences of '?'
to make s
equal to "abc"
.
For "abc"
, cost(0) = 0
, cost(1) = 0
, and cost(2) = 0
.
The value of "abc"
is 0
.
Some other modifications of s
that have a value of 0
are "cba"
, "abz"
, and, "hey"
.
Among all of them, we choose the lexicographically smallest.
Example 2:
Input: s = "a?a?"
Output: "abac"
Explanation: In this example, the occurrences of '?'
can be replaced to make s
equal to "abac"
.
For "abac"
, cost(0) = 0
, cost(1) = 0
, cost(2) = 1
, and cost(3) = 0
.
The value of "abac"
is 1
.
Constraints:
1 <= s.length <= 105
s[i]
is either a lowercase English letter or'?'
.
Solutions
Solution 1: Greedy + Priority Queue
According to the problem, we can find that if a letter $c$ appears $v$ times, then the score it contributes to the answer is $1 + 2 + \cdots + (v - 1) = \frac{v \times (v - 1)}{2}$. To make the answer as small as possible, we should replace the question marks with those letters that appear less frequently.
Therefore, we can use a priority queue to maintain the occurrence times of each letter, take out the letter with the least occurrence times each time, record it in the array $t$, then increase its occurrence times by one, and put it back into the priority queue. Finally, we sort the array $t$, and then traverse the string $s$, replacing each question mark with the letters in the array $t$ in turn.
The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Where $n$ is the length of the string $s$.
-
class Solution { public String minimizeStringValue(String s) { int[] cnt = new int[26]; int n = s.length(); int k = 0; char[] cs = s.toCharArray(); for (char c : cs) { if (c == '?') { ++k; } else { ++cnt[c - 'a']; } } PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]); for (int i = 0; i < 26; ++i) { pq.offer(new int[] {cnt[i], i}); } int[] t = new int[k]; for (int j = 0; j < k; ++j) { int[] p = pq.poll(); t[j] = p[1]; pq.offer(new int[] {p[0] + 1, p[1]}); } Arrays.sort(t); for (int i = 0, j = 0; i < n; ++i) { if (cs[i] == '?') { cs[i] = (char) (t[j++] + 'a'); } } return new String(cs); } }
-
class Solution { public: string minimizeStringValue(string s) { int cnt[26]{}; int k = 0; for (char& c : s) { if (c == '?') { ++k; } else { ++cnt[c - 'a']; } } priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq; for (int i = 0; i < 26; ++i) { pq.push({cnt[i], i}); } vector<int> t(k); for (int i = 0; i < k; ++i) { auto [v, c] = pq.top(); pq.pop(); t[i] = c; pq.push({v + 1, c}); } sort(t.begin(), t.end()); int j = 0; for (char& c : s) { if (c == '?') { c = t[j++] + 'a'; } } return s; } };
-
class Solution: def minimizeStringValue(self, s: str) -> str: cnt = Counter(s) pq = [(cnt[c], c) for c in ascii_lowercase] heapify(pq) t = [] for _ in range(s.count("?")): v, c = pq[0] t.append(c) heapreplace(pq, (v + 1, c)) t.sort() cs = list(s) j = 0 for i, c in enumerate(s): if c == "?": cs[i] = t[j] j += 1 return "".join(cs)
-
func minimizeStringValue(s string) string { cnt := [26]int{} k := 0 for _, c := range s { if c == '?' { k++ } else { cnt[c-'a']++ } } pq := hp{} for i, c := range cnt { heap.Push(&pq, pair{c, i}) } t := make([]int, k) for i := 0; i < k; i++ { p := heap.Pop(&pq).(pair) t[i] = p.c p.v++ heap.Push(&pq, p) } sort.Ints(t) cs := []byte(s) j := 0 for i, c := range cs { if c == '?' { cs[i] = byte(t[j] + 'a') j++ } } return string(cs) } type pair struct{ v, c int } type hp []pair func (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].v < h[j].v || h[i].v == h[j].v && h[i].c < h[j].c } func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }