leetcode
leetcode 1901 ~ 1950
构造限制重复的字符串

构造限制重复的字符串

难度:

标签:

题目描述

代码结果

运行时间: 87 ms, 内存: 17.0 MB


/*
 * 思路:
 * 1. 使用Stream对字符串s的字符进行排序,并计数。
 * 2. 遍历排序后的字符,并按repeatLimit的要求构造结果字符串。
 */

import java.util.*;
import java.util.stream.Collectors;

public class Solution {
    public String repeatLimitedString(String s, int repeatLimit) {
        // 获取字符频率和字典序排序的列表
        List<Map.Entry<Character, Long>> sortedEntries = s.chars()
                .mapToObj(c -> (char) c)
                .collect(Collectors.groupingBy(c -> c, Collectors.counting()))
                .entrySet()
                .stream()
                .sorted((a, b) -> b.getKey().compareTo(a.getKey()))
                .collect(Collectors.toList());
        
        StringBuilder result = new StringBuilder();
        
        for (int i = 0; i < sortedEntries.size(); i++) {
            Map.Entry<Character, Long> entry = sortedEntries.get(i);
            char current = entry.getKey();
            long freq = entry.getValue();
            long count = Math.min(freq, repeatLimit);
            for (int j = 0; j < count; j++) {
                result.append(current);
            }
            sortedEntries.set(i, Map.entry(current, freq - count));
            if (freq - count > 0) {
                if (i + 1 < sortedEntries.size()) {
                    result.append(sortedEntries.get(i + 1).getKey());
                    long nextFreq = sortedEntries.get(i + 1).getValue() - 1;
                    if (nextFreq > 0) {
                        sortedEntries.set(i + 1, Map.entry(sortedEntries.get(i + 1).getKey(), nextFreq));
                    } else {
                        i++; // skip the next entry
                    }
                    i--; // reprocess the current entry
                }
            }
        }
        return result.toString();
    }
}

解释

方法:

此题解采用排序和贪心策略构建字典序最大的字符串。首先,使用计数器统计字符串s中每个字符的出现次数。然后,对字符进行降序排序。通过迭代排序后的字符列表,贪心地构建结果字符串。每次尝试添加最大字母直到达到其限制repeatLimit,如果剩余数量仍较多,则尝试插入次大字母一次,以打破重复序列,再继续添加最大字母。此过程循环进行,直到无法添加更多字符为止。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在贪心选择时优先尝试添加字典序最大的字符直到达到其repeatLimit?
在构造字典序最大的字符串时,优先使用字典序最大的字符可以确保结果字符串尽可能大。贪心策略的核心是每一步都做出在当前看来最优的选择,这里的最优即为尽可能地使用字典序最大的字符。repeatLimit的限制确保了在保持字符最大化的同时,也不会超过字符的重复使用限制,从而平衡了结果字符串的构成。
🦆
在处理只剩一个字符时,为什么选择添加该字符的最大可能重复数而不是尝试其他可能的字符组合?
当只剩一个字符时,选择添加该字符的最大可能重复数是因为没有其他字符可以选择用来打破重复或增加字符串长度。此时,使用剩余的单一字符到其最大重复限制是唯一可行的选择,以确保字符串尽可能长且符合repeatLimit的要求。
🦆
当f指针的字符数量大于s指针的字符数量乘以repeatLimit时,为什么选择重复添加f指针的字符和s指针的字符的组合直到s用完?
当f指针的字符数量远大于s指针的字符数量乘以repeatLimit时,如果只使用f指针的字符,很快就会达到该字符的重复限制。为了最大化使用f指针的字符同时避免违反repeatLimit,通过插入s指针的字符来打破可能的重复序列。这种方式可以有效利用字符库存,同时保持字符串的字典序尽可能大。
🦆
在代码中如何处理当fc的数量小于sc的数量乘以repeatLimit时的情况,具体的逻辑是怎样的?
当fc的数量小于sc的数量乘以repeatLimit时,表示fc字符不足以填满可能的插入点。代码中,这种情况通过先尽可能地重复使用fc字符直到达到其repeatLimit,然后使用sc字符。计算fc能重复使用的次数,然后剩余的fc字符数量按照其实际数量添加。这样的处理方式保证了即使在字符数量有限的情况下,也能尽量构建出字典序最大的字符串。

相关问题