(A卷,200分)- 递增字符串(Java & JS & Python)

题目描述

定义字符串完全由 ‘A’ 和 ‘B’组成,当然也可以全是’A’或全是’B’。如果字符串从前往后都是以字典序排列的,那么我们称之为严格递增字符串。
给出一个字符串s,允许修改字符串中的任意字符,即可以将任何的’A’修改成’B’,也可以将任何的’B’修改成’A’,
求可以使s满足严格递增的最小修改次数。

0 < s的长度 < 100000。

输入描述

输入一个字符串: “AABBA”

输出描述

输出:1

用例

输入 AABBA
输出 1
说明 修改最后一位得到AABBB。

题目解析

新增一个用例:

AAABAAABBBBABB

该用例只需要修改两次。

我的解题思路如下:

首先,我们需要记录字符串长度为total,然后统计字符串中A的数量,记为A。

然后用动态规划,即定义一个dp数组,dp[i]的含义是 [0,i]闭区间内有多少个A。

统计好后,我们可以假设将 0 ~ i 闭区间内全部变成A,需要修改多少次?

0~i闭区间内理论会有 i+1 个A,而目前有dp[i] 个A,因此需要修改 i + 1 – dp[i] 次。

接着考虑将 i+1 ~ str.length-1 区间内全部变成B,需要修改多少次?

dp[i]表示 0~i闭区间内A的数量,那么 i+1~str.length-1 区间内A的数量= A – dp[i]

因此需要修改A – dp[i]次

因此,一共需要修改 i + 1 – dp[i] + A – dp[i] 次

我们从 0 ~ str.length-1 遍历出每一个 i 带入上面公式,保留最小的结果,就是题解。

另外,本题0 < s的长度 < 100000,如果使用dp数组的话,最坏需要定义一个100000长度的数组,这是有可能爆内存的,因此,下面代码中我不是dp数组,直接使用leftA变量。

补充一下:上面逻辑遗漏考虑两个分界线位置:

如上图所示,分别是-1索引位置和n索引位置,即上图两个绿色箭头位置。

前面逻辑,只考虑分界线位置在数组索引的0~n-1,因此当用例如下时:

BBABB

使用上面逻辑会产生问题。

此时,我们应该记录将字符串全部修改为A的次数,和全部修改为B的次数,即上面两个绿色箭头分界线。

JavaScript算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.on("line", (line) => {
  console.log(getResult(line));
});

function getResult(str) {
  const total = str.length;
  const A = str.replaceAll("B", "").length; // 字符串str中共有多少个A

  // 如果全B或全A,则直接返回0
  if (A == 0 || A == total) return 0;

  // 修改为全A或者全B的次数取最小值
  let ans = Math.min(A, total - A);

  let leftA = 0;
  for (let i = 0; i < total; i++) {
    if (str[i] == "A") leftA++;
    ans = Math.min(i + 1 - leftA + A - leftA, ans);
  }

  return ans;
}

Java算法源码

import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    String str = sc.next();
    System.out.println(getResult(str));
  }

  public static int getResult(String str) {
    int total = str.length();
    int A = str.replaceAll("B", "").length(); // 字符串str中共有多少个A

    // 如果全B或全A,则直接返回0
    if (A == 0 || A == total) return 0;

    // 修改为全A或者全B的次数取最小值
    int ans = Math.min(A, total - A);

    int leftA = 0;
    for (int i = 0; i < total; i++) {
      if (str.charAt(i) == 'A') leftA++;
      ans = Math.min(i + 1 - leftA + A - leftA, ans);
    }

    return ans;
  }
}

Python算法源码

# 输入获取
s = input()


# 算法入口
def getResult(s):
    total = len(s)
    A = len(s.replace("B", ""))  # 字符串str中共有多少个A

    # 如果全B或全A,则直接返回0
    if A == 0 or A == total:
        return 0

    # 修改为全A或者全B的次数取最小值
    ans = min(A, total - A)

    leftA = 0
    for i in range(total):
        if s[i] == 'A':
            leftA += 1

        ans = min(i + 1 - leftA + A - leftA, ans)

    return ans


# 算法调用
print(getResult(s))

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?