[leetcode 周赛 159] 1234 替换子串等到平衡字符串

1234 Replace the Substring for Balanced String 替换子串等到平衡字符串

问题描述

有一个只含有 ‘Q‘, ‘W‘, ‘E‘, ‘R‘ 四种字符,且长度为 n 的字符串。

假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。

给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。

你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。

请返回待替换子串的最小可能长度。

如果原字符串自身就是一个平衡字符串,则返回 0

示例 1:

输入: s = "QWER"
输出: 0
解释: s 已经是平衡的了。

示例 2:

输入: s = "QQWE"
输出: 1
解释: 我们需要把一个 ‘Q‘ 替换成 ‘R‘,这样得到的 "RQWE" (或 "QRWE") 是平衡的。

示例 3:

输入: s = "QQQW"
输出: 2
解释: 我们可以把前面的 "QQ" 替换成 "ER"。

示例 4:

输入: s = "QQQQ"
输出: 3
解释: 我们可以替换后 3 个 ‘Q‘,使 s = "QWER"。

提示:

  • 1 <= s.length <= 10^5
  • s.length4 的倍数
  • s 中只含有 ‘Q‘, ‘W‘, ‘E‘, ‘R‘ 四种字符

思路

  • 读题
    平衡字符串:4种字符出现次数相等 通过替换子串中任意字符得到平衡字符串
    有些像玩游戏洗点 加点(力体敏法), 将高过平均值的削减到平均值以下, 再将削减得到的点数进行分配

滑动窗口(双指针)

以prev为起点, next向后移动, 直到满足条件, 再试着移动prev

  1. 满足条件则缩减了子串长度, 继续移动prev
  2. 不满足则next继续移动
  • 样例: "WQWQQRQE"

代码实现

滑动窗口

class Solution {
    public int balancedString(String s) {
        int len = s.length(), chrSize = 4;
        // 字符数量不足4个 或 不是4的倍数
        if (len < chrSize || len % chrSize != 0) {
            return -1;
        }

        int balanced = len / 4;
        char[] chrs = s.toCharArray();
        int[] cnt = new int[chrSize];
        for (char chr : chrs) {
            cnt[c2i(chr)]++;
        }
        // 如果已经是一个平衡字符串 不用修改
        if (check(cnt, balanced)) {
            return 0;
        }

        // 使用滑动窗口 [prev, next) 左闭右开
        int ans = Integer.MAX_VALUE, prev = 0, next = 0;
        while (next >= prev) {
            if (check(cnt, balanced)) {
                ans = Math.min(ans, next - prev);
                cnt[c2i(chrs[prev])]++;
                prev++;
            } else {
                if (next >= len) {
                    break;
                }
                cnt[c2i(chrs[next])]--;
                next++;
            }
            System.out.printf("ans:%d [prev:%d, next:%d] cnt:%s balanced:%d\n", ans, prev, next, Arrays.toString(cnt), balanced);
            System.out.println(s.substring(0, prev) + "][" + s.substring(next, len) + " --> [" + s.substring(prev, next) + "]");
        }

        return ans;
    }

    private boolean check(int[] cnt, int balanced) {
        return cnt[c2i('Q')] <= balanced &&
                cnt[c2i('W')] <= balanced &&
                cnt[c2i('E')] <= balanced &&
                cnt[c2i('R')] <= balanced;
    }

    /**
     * 字符映射为数字
     * @param chr 被映射字符
     * @return 映射字符定义的数字
     */
    private int c2i(char chr) {
        // Q:0 W:1 E:2 R:3
        if (chr == 'Q') {
            return 0;
        } else if (chr == 'W') {
            return 1;
        } else if (chr == 'E') {
            return 2;
        } else if (chr == 'R') {
            return 3;
        } else {
            return -1;
        }
    }
}

参考资源

第 159 场周赛 全球排名

原文地址:https://www.cnblogs.com/slowbirdoflsh/p/11779149.html

时间: 2024-12-10 12:01:34

[leetcode 周赛 159] 1234 替换子串等到平衡字符串的相关文章

[leetcode 周赛 159] 1233 删除子文件夹

1233 Remove Sub-Folders from the Filesystem 删除子文件夹 问题描述 你是一位系统管理员,手里有一份文件夹列表 folder,你的任务是要删除该列表中的所有 子文件夹,并以 任意顺序 返回剩下的文件夹. 我们这样定义「子文件夹」: 如果文件夹?folder[i]?位于另一个文件夹?folder[j]?下,那么?folder[i]?就是?folder[j]?的子文件夹. 文件夹的「路径」是由一个或多个按以下格式串联形成的字符串: /?后跟一个或者多个小写英

[leetcode 周赛 159] 1235 规划兼职工作

1235 Maximum Profit in Job Scheduling 规划兼职工作 问题描述 你打算利用空闲时间来做兼职工作赚些零花钱. 这里有?n?份兼职工作,每份工作预计从?startTime[i]?开始到?endTime[i]?结束,报酬为?profit[i]. 给你一份兼职工作表,包含开始时间?startTime,结束时间?endTime?和预计报酬?profit?三个数组,请你计算并返回可以获得的最大报酬. 注意,时间上出现重叠的 2 份工作不能同时进行. 如果你选择的工作在时间

[leetcode 周赛 159] 1232 缀点成线

1232 Check If It Is a Straight Line 缀点成线 问题描述 在一个?XY 坐标系中有一些点,我们用数组?coordinates?来分别记录它们的坐标,其中?coordinates[i] = [x, y]?表示横坐标为 x.纵坐标为 y?的点. 请你来判断,这些点是否在该坐标系中属于同一条直线上,是则返回 true,否则请返回 false. 示例 1: 输入: coordinates = [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]] 输

leetcode 1221. 分割平衡字符串

在一个「平衡字符串」中,'L' 和 'R' 字符的数量是相同的. 给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串. 返回可以通过分割得到的平衡字符串的最大数量. 示例 1: 输入:s = "RLRRLLRLRL"输出:4解释:s 可以分割为 "RL", "RRLL", "RL", "RL", 每个子字符串中都包含相同数量的 'L' 和 'R'.示例 2: 输入:s = "RLLLLRR

PHP算法之分割平衡字符串

在一个「平衡字符串」中,'L' 和 'R' 字符的数量是相同的. 给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串. 返回可以通过分割得到的平衡字符串的最大数量. 示例 1: 输入:s = "RLRRLLRLRL"输出:4解释:s 可以分割为 "RL", "RRLL", "RL", "RL", 每个子字符串中都包含相同数量的 'L' 和 'R'.示例 2: 输入:s = "RLLLLRR

java统计一个子串在指定字符串中出现的次数

今天查着用了用String类里的几个方法,分享下代码 题目要求:统计一个子串在指定字符串中出现的次数( 提示java字串出现了6次) 1 public class SearchSameString { 2 3 public static void main(String[] args) { 4 // 定义俩个字符串 5 String shortStr = "java"; 6 String longStr = "javasdfjavawerjavavsswetjavadfgdf

Linux sed 替换第一次出现的字符串

/********************************************************************************* * Linux sed 替换第一次出现的字符串 * 说明: * 需要替换配置文件中第一次出现的文本内容. * * 2016-12-16 深圳 南山平山村 曾剑锋 ********************************************************************************/ 一.参考

《剑指Offer》替换空格(将字符串中的空格替换为%20)

题目: 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为 We Are Happy.则经过替换之后的字符串为 We%20Are%20Happy. 思路: 这种替换问题要考虑是否会覆盖原字符串,若是在源字符串上直接替换. 看到这个问题我觉得很多人都会想到直接从头开始替换,即遇到空格就将其替换为%20,每次都要将空格后的字符后移两个字节.这种解法的时间复杂度为O(n^2)!!! 另外一种较好的解法是从后往前替换,具体做法是从头遍历计算所有空格数,计算出总的长度. 该解

sed 替换特定字符,字符串的行

1:单个字符替换 (1)将文件中的某一字符替换成其它字符 sed 'y/要替换的字符/替换后的字符/' 文件名 (2)替换以某一字符或字符串开头的行 sed '/^开头的字符串或字符/ y/要替换的字符/替换后的字符/' 文件名 (3)替换指定字符或字符串的单个字符 sed '/指定的字符串/ y/要替换的字符/替换后的字符/' 文件名 2替换多个字符串 (1)将文件中的指定的字符串全部进行替换 sed '/指定的字符串/ s/要替换的字符串/替换后的字符串/' 文件名 sed 's/要替换的字