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" is 0 + 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 }
    

All Problems

All Solutions