【机考】华为OD2022.11.01机考题目思路与代码

本文详细解析了华为OD2022.11.01机考中的三道题目,包括WASD字符串达到“完美走位”的子串最小长度问题,潜在密码的查找,以及简化版羊、狼、农夫过河问题。通过优化算法,将暴力枚举改为高效解决方案,降低时间复杂度。
摘要由CSDN通过智能技术生成

题目一

描述

输入一个长度为4的倍数的字符串,字符串中仅包含WASD四个字母。

将这个字符串中的连续子串用同等长度的仅包含WASD的字符串替换,如果替换后整个字符串中WASD四个字母出现的频数相同,那么我们称替换后的字符串是“完美走位”。

求子串的最小长度。

示例

输入:
WASDAASD

输出:
1

说明:
将第二个A替换为W,即可得到完美走位  
输入:
AAAA

输出:
3

说明:
将其中三个连续的A替换为WSD,即可得到完美走位  

思路与代码

这题我并没有AC,用例通过率95.45%,确定是效率问题,经过改进后时间复杂度从O(n3)降低为O(n2)。

首先确定一下如何判断一个子串被替换后可以让整个字符串变成“完美走位”。

假设要替换的子串长度为m,子串前长度n1,子串后长度n2,:

image.png

在最开始,用HashMap统计整个字符串中WASD的出现频数,得到map

然后用HashMap统计m子串中WASD的出现频数,得到insideMap

用map各个键的值减去insideMap中对应键的值,可得n1+n2中WASD频数映射,写回insideMap

找到insideMap中最大的值,乘四然后减去所有值的和,就是替换m后成为完美走位需要的m的长度needSteps

如果m的长度大于等于needSteps,m经过替换后整个字符串可以成为完美走位。

最简单的方式就是暴力枚举,检查各个m是否符合要求,取最短的m的长度,即可得到答案:

/**
 * 求需要替换的最小连续走位长度
 * 完美走位:WASD四个字母出现次数相同
 * 输入步数为4的倍数
 */
public class P1 {
    private static Scanner scanner=new Scanner(System.in);

    public static void main(String[] args) {
        String str=scanner.nextLine();

        //获取字符串本身的统计信息
        HashMap<Character,Integer> map=getAmountMap(str);
        //如果已经是完美走位,输出0,不检查
        if(map.get('A')==map.get('S')&&map.get('S')==map.get('W')&&map.get('W')==map.get('D')){
            System.out.println(0);
            return;
        }

        //记录已知的可行最小替换长度
        int minLen=str.length();
        //对每一个字母开头的序列进行检查
        for(int i=0;i<str.length();i++){
            //对每一个字母开头往后长度小于等于minLen的序列,检查可否替换后形成完美走位
            for(int j=0;j<minLen&&i+j<str.length();j++){
                //获取这段字符串中的统计
                HashMap<Character,Integer> insideMap=getAmountMap(str.substring(i,i+j+1));
                //得到源字符串减去字串后其他部分(外串)的统计信息
                insideMap.put('A',map.get('A')-insideMap.get('A'));
                insideMap.put('S',map.get('S')-insideMap.get('S'));
                insideMap.put('W',map.get('W')-insideMap.get('W'));
                insideMap.put('D',
  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值