华为OD机考算法题:字符串比较

文章讲述了如何解决一个编程问题,给定两个长度相同的字符串A和B,以及整数V,找到A中满足字符ASCII码差值之和小于等于V的最大连续子串长度。作者提供了Java和JavaScript的代码实现,分析了时间复杂度和空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

题目部分

解读与分析

代码实现


题目部分

题目字符串比较
难度
题目说明给定字符串A、B和正整数V,A的长度与B的长度相等,请计算A中满足如下条件的最大连续子串的长度:
1、该连续子串在A和B中的位置和长度均相同。
2、该连续子串|A[i]–B[i]|之和小于等于V。其中|A[i]–B[i]|表示两个字母ASCII码之差的绝对值。
输入描述输入为三行:
第一行为字符串A,仅包含小写字符,1<=A.length<=1000。
第二行为字符串B,仅包含小写字符,1<=B.length<=1000。
第三行为正整数V,0<=V<=10000。
输出描述字符串最大连续子串的长度,要求该子串|A[i]–B[i]|之和小于等于V。
补充说明
------------------------------------------------------
示例
示例1
输入xxcdefg
cdefghi
5
输出2
说明字符串 A 为 xxcdefg,字符串 B 为 cdefghi,V = 5。
它的最大连续子串可以是 cd -> ef、de -> fg、ef -> gh、fg -> hi,所以最大连续子串是 2。


解读与分析

题目解读

两个字符串A、B的长度相等,设下标为 i 的字符 A[i] 与 B[i] 对应的 ASCII 码的绝对值为 diffAbs[i]。diffAbs 中连续的 n 个元素之和小于或等于 V,求 n 的最大值。

分析与思路

此题虽然难度虽然是“难”,实际很简单。

先遍历字符串A、B,依次计算每一个字符 A[i]、B[i] 的 ASCII 码的绝对值之差,存放到整型数组 diffAbs 中。

接着遍历 diffAbs,从第一个元素 diffAbs[0] 开始寻找连续元素之和小于或等于 V 的区块,设区块的左下标为 leftIndex,右下标为 rightIndex。初始值 leftIndex、rightIndex 均为 0,当区块中元素之和大于 V 时,leftIndex 向右移动(注意要保证 rightIndex >= leftIndex);当和小于 rightIndex 时,rightIndex 往右移动。直到 rightIndex 到达最后一个元素。在滑动过程中,( rightIndex - leftIndex + 1 ) 的最大值即为最大的连续个数。

需要遍历两次,其中第一次为遍历字符串A、B,第二次遍历数组 diffAbs。时间复杂度和空间复杂度均为 O(n)。

此题和往期的题《华为OD机考算法题:补种未成活胡杨》《华为OD机考算法题:根据某条件聚类最少交换次数》《华为OD机考算法题:区块链文件转储系统》比较类似。


代码实现

Java代码

import java.util.Scanner;

/**
 * 字符串比较
 * @since 2023.10.09
 * @version 0.1
 * @author Frank
 *
 */
public class StringComparation {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			String strA = sc.nextLine();
			String strB = sc.nextLine();
			String strV = sc.nextLine();
			int v = Integer.parseInt( strV );
			processStringComparation( strA, strB, v );
		}
	}
	
	private static void processStringComparation( String strA, String strB, int v )
	{
		int[] diffAbs = new int[ strA.length() ];
		for( int i = 0; i < diffAbs.length; i ++ )
		{
			int eachDiffAbs = Math.abs( strA.charAt( i ) - strB.charAt( i ) );
			diffAbs[i] = eachDiffAbs;
		}
		
		int leftIndex = 0;
		int rightIndex = 0;
		int maxCount = 0;
		int curSum = diffAbs[0];
		while( rightIndex <= diffAbs.length - 1 )
		{
			if( curSum > v )
			{
				if( leftIndex >= diffAbs.length - 1 )
				{
					break;
				}
				curSum -= diffAbs[ leftIndex ];
				leftIndex ++;				
				if( rightIndex < leftIndex )
				{					
					rightIndex = leftIndex;
					curSum += diffAbs[ rightIndex ];
				}
				continue;
			}
			
			// curSum <= v
			if( rightIndex - leftIndex + 1 >= maxCount )
			{
				maxCount = rightIndex - leftIndex + 1;
			}
			
			if( rightIndex >= diffAbs.length - 1 )
			{
				break;
			}
			rightIndex ++;
			curSum += diffAbs[ rightIndex ];
		}
		
		System.out.println( maxCount );
	}
}

JavaScript代码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
    while (line = await readline()) {
        var strA = line;
        var strB = await readline();
        var strV = await readline();
        var v = parseInt(strV);
        processStringComparation(strA, strB, v);
    }
}();

function processStringComparation(strA, strB, v) {

    var diffAbs = new Array();
    for (var i = 0; i < strA.length; i++) {
        var eachDiffAbs = Math.abs(strA.charCodeAt(i) - strB.charCodeAt(i));
        diffAbs[i] = eachDiffAbs;
    }

    var leftIndex = 0;
    var rightIndex = 0;
    var maxCount = 0;
    var curSum = diffAbs[0];
    while (rightIndex <= diffAbs.length - 1) {
        if (curSum > v) {
            if (leftIndex >= diffAbs.length - 1) {
                break;
            }
            curSum -= diffAbs[leftIndex];
            leftIndex++;
            if (rightIndex < leftIndex) {
                rightIndex = leftIndex;
                curSum += diffAbs[rightIndex];
            }
            continue;
        }

        // curSum <= v
        if (rightIndex - leftIndex + 1 >= maxCount) {
            maxCount = rightIndex - leftIndex + 1;
        }

        if (rightIndex >= diffAbs.length - 1) {
            break;
        }
        rightIndex++;
        curSum += diffAbs[rightIndex];
    }

    console.log(maxCount);
}

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值