19字典序最小的01字符串-青训营刷题

问题描述

小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。

例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过2次操作得到的字典序最小的字符串。

现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。


测试样例

样例1:

输入:n = 5, k = 2, s = "01010"
输出:'00101'

样例2:

输入:n = 7, k = 3, s = "1101001"
输出:'0110101'

样例3:

输入:n = 4, k = 1, s = "1001"
输出:'0101'

代码如下

public class Main {
    public static String solution(int n, int k, String s) {
        //记录前面有多少个1
        int count = 0;
        for(int i = 0; i < n; i++) {
            //遇1记录并跳过找0;
            if(s.charAt(i) == '1') {
                count++;
                continue;
            }
            //遇0则0往前移动k或者count个位置(哪个小取哪个)
            else{
                if(count!=0) {
                    if(count >= k) {
                        s = s.substring(0, i - k) + '0' + s.substring(i - k, i) + s.substring(i + 1);
                        k = 0;
                        break;
                    }
                    else{
                        //边界处理
                        if(i + 1 < s.length()){
                            s = s.substring(0, i - count) + '0' + s.substring(i - count, i) + s.substring(i + 1);
                        }
                        else{
                            s = s.substring(0, i - count) + '0' + s.substring(i - count, i);
                        }
                        //更新k
                        k-=count;
                    }
                }
            }
            if(k == 0) {
                break;
            }
        }
        return s;
    }
 
    public static void main(String[] args) {
        System.out.println(solution(5, 2, "01010").equals("00101"));
        System.out.println(solution(7, 3, "1101001").equals("0110101"));
        System.out.println(solution(4, 1, "1001").equals("0101"));
    }
}

 代码解释

这段代码实现了一个字符串操作的逻辑,目标是将字符串中的某些字符移动到前面,以满足特定的条件。以下是对代码的详细解释:

代码功能

该代码定义了一个 solution 方法,接收三个参数:

  1. n:字符串的长度。

  2. k:表示可以移动的“步数”。

  3. s:一个由字符 '0''1' 组成的字符串。

方法的目标是将字符串中的某些 '0' 向前移动,移动的步数由 k 决定,同时保证移动后的字符串满足特定的规则。

代码逻辑

  1. 变量初始化

    • count:用于记录当前已经遇到的 '1' 的数量。

  2. 遍历字符串

    • 使用 for 循环逐个检查字符串中的每个字符。

  3. 处理逻辑

    • 遇到 '1'

      • 增加 count 的值,表示又遇到一个 '1'

      • 使用 continue 跳过当前循环,继续检查下一个字符。

    • 遇到 '0'

      • 如果 count 不为零,说明前面有 '1',需要将当前的 '0' 向前移动。

      • 移动逻辑

        • 如果 count 大于等于 k,说明可以将当前的 '0' 向前移动 k 个位置。

          • 使用字符串拼接的方式,将 '0' 插入到当前位置减去 k 的位置。

          • k 设置为零,表示步数已经用完。

          • 使用 break 跳出循环,因为步数已经用完,无需继续处理。

        • 如果 count 小于 k,说明可以将 '0' 向前移动到第一个 '1' 的位置。

          • 同样使用字符串拼接的方式,将 '0' 插入到当前位置减去 count 的位置。

          • 更新 k 的值,减去已经使用的步数(即 count)。

        • 边界处理:如果当前字符是字符串的最后一个字符,需要避免索引越界。

  4. 循环结束

    • 如果在遍历过程中 k 已经用完(即 k == 0),则直接退出循环。

  5. 返回结果

    • 返回处理后的字符串。

示例解释

代码中还包含一个 main 方法,用于测试 solution 方法的正确性。以下是测试用例的解释:

  1. solution(5, 2, "01010")

    • 初始字符串:"01010"

    • 第一个 '0' 不需要移动。

    • 第二个 '0' 可以向前移动 2 个位置,最终结果为 "00101"

  2. solution(7, 3, "1101001")

    • 初始字符串:"1101001"

    • 第一个 '0' 可以向前移动 3 个位置,最终结果为 "0110101"

  3. solution(4, 1, "1001")

    • 初始字符串:"1001"

    • 第一个 '0' 可以向前移动 1 个位置,最终结果为 "0101"

注意事项

  1. 字符串操作效率

    • 代码中使用了多次字符串拼接(如 substring 和字符串拼接操作),这在 Java 中效率较低,尤其是对于较长的字符串。如果需要优化,可以考虑使用 StringBuilder

  2. 边界条件处理

    • 代码中对边界条件(如字符串末尾)进行了处理,避免了索引越界的问题。

  3. 逻辑限制

    • 该代码假设输入的字符串只包含 '0''1',且 k 的值不会超过字符串长度。

总结来说,这段代码通过模拟字符移动的过程,实现了将字符串中的 '0' 向前移动的功能,同时考虑了移动步数的限制和边界条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值