【2023华为od-C卷-第一题-字符串变换的最小字符串】100%通过率(JavaScript&Java&Python&C++)

本题已有网友报告代码100%通过率

OJ &答疑服务

购买任意专栏,即可私信博主,获取答疑/辅导服务

OJ权限获取可以在购买专栏后访问网站:首页 - CodeFun2000

题目描述

给定一个字符串 s s s,最多只能进行一次变换,返回变换后能得到的最小字符串(按照字典序进行比较)。

变换规则:交换字符串中任意两个不同位置的字符。

输入描述

一串小写字母组成的字符串 s s s s s s是都是由小写字符组成, 1 ≤ s . l e n g t h ≤ 1000 1 \le s.length \le 1000 1s.length1000

输出描述

按照要求进行变换得到的最小字符串

样例1

输入

abcdef

输出

abcdef

说明 a b c d e f abcdef abcdef 已经是最小字符串,不需要交换

样例2

输入

bcdefa

输出

acdefb

说明 a a a b b b 进行位置交换,可以等到最小字符串

思路:贪心

由于题目中说了最多只能交换一次,也就是可以不交换或者交换一次,从贪心的角度,那么一定选择字符串中最小的那一个字符作为整个字符串靠前的字符更优,如果出现多个相同的最小字符,那么显然应该选择最靠近字符串末尾的那一个。证明如下:

假设一个字符串,最小的字符用 ∗ * 表示,非最小的字符用 @ @ @表示,假设一个字符串可以写成如下形式: @ @ ∗ @ @ ∗ @@*@@* @@@@,那么可以枚举交换策略,如下:

源串: @ @ ∗ @ @ ∗ @@*@@* @@@@

策略一: ∗ @ @ @ @ ∗ *@@@@* @@@@

策略二: ∗ @ @ ∗ @ @ *@@*@@ @@@@

可以看到,第二种策略一定优于第一种策略,因为相同位置上,将更加靠后的最小字符交换靠前的字符会更优。

JavaScript代码

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

let s = '';

rl.on('line', (line) => {
  s = line;

  const t = [...s].sort();

  for (let i = 0; i < s.length; i++) {
    if (s[i] !== t[i]) {
      for (let j = s.length - 1; j >= 0; j--) {
        if (s[j] === t[i]) {
          s = s.substring(0, i) + s[j] + s.substring(i + 1, j) + s[i] + s.substring(j + 1);
          break;
        }
      }
      break;
    }
  }

  console.log(s);
  rl.close();
});

Python代码

s = input()
t = sorted(s)

for i in range(len(s)):
    if s[i] != t[i]:
        for j in range(len(s) - 1, -1, -1):
            if s[j] == t[i]:
                s = s[:i] + s[j] + s[i+1:j] + s[i] + s[j+1:]
                break
        break

print(s)

Java代码

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        char[] charArray = s.toCharArray();
        char[] sortedArray = Arrays.copyOf(charArray, charArray.length);
        Arrays.sort(sortedArray);

        for (int i = 0; i < charArray.length; i++) {
            if (charArray[i] != sortedArray[i]) {
                for (int j = charArray.length - 1; j >= 0; j--) {
                    if (charArray[j] == sortedArray[i]) {
                        char temp = charArray[i];
                        charArray[i] = charArray[j];
                        charArray[j] = temp;
                        break;
                    }
                }
                break;
            }
        }

        System.out.println(new String(charArray));
    }
}

C++代码

#include <bits/stdc++.h>
using namespace std;
int main(void) {
    string s;
    cin >> s;
    string t(s);
    sort(t.begin(), t.end());
    for (int i = 0; i < s.size(); i++) {
        if (s[i] != t[i]) {
            for (int j = s.size() - 1; j >= 0; j--) {
                if (s[j] == t[i]) {
                    swap(s[i], s[j]);
                    break;
                }
            }
            break;
        }
    }
    cout << s << endl;
}
  • 22
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值