字典序最小的01字符串

刷题地址:144. 字典序最小的 01 字符串

题目:字典序最小的01字符串

题目描述:

小红有一个 01 字符串,她可以进行最多 k 次提作,每次操作可以交换相邻的两个字符,问可以得到的字典序最小的字符串是什么。

输入描述:

第一行包含两个整数,n(1 < n < 10^5)和 k(1 < k < 10^9),表示字符串的长度和可以进行的操作次数。

接下来一行一个长度为 n 的 01 字符串。

输出描述:

输出一个长度为 n 的字符串,表示字典序最小的字符串。 

输入示例:

5 2
01010

输出示例:

00101

解题思路 :

        采用双指针,用start标记最前面的1的位置,用end标记最后面的1的下一位(即start到end是连续的1子串),尽量往后换,可能11后面有0,当找到0时,不断往前交换,直到k=0 110,
        开始的思路:需要换的场景只有10,01不用换,11没法换,但11后面可能有0,当找到0时,不断往前交换,尽量让0和第一个1交互,这样才能保证字典序最小,重复这个过程,直到k=0
        思路优化:不用依次交换,如果有一组连着的1,例如111111,并且也不用交互,一共01两个值,直接赋值就可以。

大体流程:
    遍历字符串,直到end到末尾或者k=0
    start和end初始为0
    每次循环判断end的值
    (1)end=0;
            这时候有两种情况:
         (1)当前位置前面全是0,不需要交互,start,end继续往后遍历;
         (2)当前位置前面有1,需要交换
               (1)如果k>end-start,则直接交换开头的1, start++,end继续找下一个为0的位置
               (2)如果k=0,则不交换,需要退出循环了
               (3)如果0<k<end-start, 末尾end左移k位,交换end+1位和end-k位,k=0
    (2)end=1,start不动标记第一个1的位置,end继续遍历

AC代码:

import java.util.*;
class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        String s = sc.next();
        char[] sa = s.toCharArray();
        int start = 0, end = 0;
        //遍历end直到末尾,同时保证k>0
        while (end < n && k > 0) {
            //如果当前位置是0,需要判断当前位置前面有没有1,
            if (sa[end] == '0') {
                //这表示还没开始交换过,前面没有1,前边都是0
                if (start == end) {
                    start++;
                    end++;
                } else { //前边有1,需要判断能否交换
                    if (k >= end - start) {
                        sa[start] = '0';
                        sa[end] = '1';
                        start++;
                        end++;
                        k -= end - start;
                    } else {  //k=0的情况不存在,每次遍历都过滤掉了,只有k>0
                        sa[end-k] = '0';
                        sa[end] = '1';
                        k = 0;
                    }
                }
            } else {  //如果是1,start就不动了,end向后遍历
                end++;
            }
        }
        for (int i = 0; i < n; i++) {
            System.out.print(sa[i]);
        }
    }
}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值