华为OD机试 - 差值数组不同的字符串 - 数组(Java 2025 B卷 100分)

在这里插入图片描述

华为OD机试 2025B卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(A卷+E卷+B卷+C卷+D卷)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

给你一个字符串数组 words ,每一个字符串长度都相同,令所有字符串的长度都为 n 。

每个字符串 words[i] 可以被转化为一个长度为n - 1的 差值整数数组 difference[i] ,其中对于 0 <= j <= n - 2 有difference[i][j] = words[i][j+1] - words[i][j]。注意两个字母的差值定义为它们在字母表中 位置 之差,也就是说’a’ 的位置是 0 ,‘b’ 的位置是 1 ,‘z’ 的位置是 25 。

比方说,字符串 “acb” 的差值整数数组是 [2 - 0, 1 - 2] = [2, -1] 。
words 中所有字符串 除了一个字符串以外 ,其他字符串的差值整数数组都相同。你需要找到那个不同的字符串。

请你返回 words中 差值整数数组 不同的字符串。

二、输入描述

第一行输入一个字符串,包含两个数字,空格分隔,数组长度m和数字n,n表示字符串的长度

第二行输入一个字符串,m个长度为n的字符串,空格分隔

例如:

3 3
adc wzy abc

三、输出描述

请返回 words中 差值整数数组不同的字符串。

四、测试用例

测试用例1

1、输入

3 4
abcd bcde cdeg

2、输出

cdeg

3、说明

bcde 和 cdef 的差值数组为 [1, 1, 1],abcf 的为 [1, 1, 3]。

测试用例2

1、输入

4 2
ab cd ef ac

2、输出

ac

3、说明

ab, cd, ef 的差值数组为 [1],ac 的为 [2]。

五、解题思路

1、解题思路

核心思路是为每个输入字符串计算其“差值整数数组”。

然后,统计每种差值数组出现的次数。

根据题目,只有一个字符串的差值数组是独特的,其余 m-1 个字符串的差值数组是相同的。

因此,我们寻找那个只出现过一次的差值数组,并返回对应的原始字符串。

2、具体步骤:

  1. 计算差值数组 (getDifferenceArray 方法):
    • 遍历输入字符串 s 中的每个字符(除了最后一个)。
    • 计算 s[j+1] - s[j] 并将结果添加到差值列表 diff 中。
    • 字符相减会直接得到它们在ASCII(或Unicode)表中的位置差,这对于英文字母来说等同于它们在字母表中的位置差。
  2. 填充 diffMap (findUnique 方法):
    • 遍历输入的 words 数组中的每个 word。
    • 调用 getDifferenceArray(word) 计算其差值数组 diffArray。
    • 使用 diffMap.computeIfAbsent(diffArray, k -> new ArrayList<>()).add(word);:
    • 这行代码首先检查 diffMap 中是否已存在键 diffArray。
    • 如果不存在 (computeIfAbsent 的 lambda k -> new ArrayList<>() 被执行),则创建一个新的空 ArrayList 并将其与 diffArray 关联。
    • 然后,将当前的 word 添加到与 diffArray 关联的 List 中。
  3. 查找独特字符串 (findUnique 方法):
    • 遍历 diffMap 中的每一个条目 (Map.Entry)。
    • 对于每个条目,检查其值(即 List)的大小。
    • 如果 entry.getValue().size() == 1,这意味着这个差值数组模式只对应一个原始字符串,这个字符串就是我们要找的独特字符串。立即返回它。

六、Java算法源码

public class OdTest {

    /**
     * 计算给定字符串的差值数组。
     * @param s 输入字符串
     * @return 差值整数列表
     */
    public static List<Integer> getDifferenceArray(String s) {
        List<Integer> diff = new ArrayList<>();
        // 字符串长度至少为2才能计算差值
        if (s.length() < 2) {
            return diff; // 对于长度小于2的字符串,差值数组为空
        }
        // 遍历字符串计算相邻字符的差值
        for (int i = 0; i < s.length() - 1; i++) {
            diff.add(s.charAt(i + 1) - s.charAt(i));
        }
        return diff;
    }

    /**
     * 从字符串数组中找出具有唯一差值数组的字符串。
     * 题目保证了words.length >= 3(或至少存在一个唯一项,如果允许m=2,则会有两个计数为1的项,
     * 但题目描述"除了一个字符串以外,其他字符串...都相同"暗示主模式数量为m-1,独特模式数量为1)。
     * @param words 字符串数组
     * @return 具有唯一差值数组的字符串
     */
    public static String findUnique(String[] words) {
        if (words == null || words.length == 0) {
            return ""; // 处理空或null输入
        }
        if (words.length == 1) {
            return words[0]; // 如果只有一个单词,它本身就是独特的
        }

        // 使用Map来存储差值数组及其对应的字符串列表
        // 键: List<Integer> (差值数组)
        // 值: List<String> (所有具有该差值数组的原始字符串)
        Map<List<Integer>, List<String>> diffMap = new HashMap<>();

        // 遍历每个单词,计算其差值数组,并将其存入Map
        for (String word : words) {
            List<Integer> diffArray = getDifferenceArray(word);
            // computeIfAbsent确保键存在,然后将单词添加到与该差值数组关联的列表中
            diffMap.computeIfAbsent(diffArray, k -> new ArrayList<>()).add(word);
        }

        // 遍历Map,找到其对应字符串列表大小为1的条目
        // 这个条目的键就是独特的差值数组,其值列表中的字符串就是我们要找的
        for (Map.Entry<List<Integer>, List<String>> entry : diffMap.entrySet()) {
            if (entry.getValue().size() == 1) {
                return entry.getValue().get(0); // 返回该独特差值数组对应的字符串
            }
        }

        // 根据题目描述,总会找到一个独特的字符串,所以理论上不应到达这里。
        // 但为完整性,返回一个空字符串或抛出异常。
        return "";
    }

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

        // 读取数组长度m和字符串长度n
        int m = scanner.nextInt();
        int n = scanner.nextInt(); // n 在此实现中主要通过 word.length() 获取,但题目有此输入
        scanner.nextLine(); // 消耗掉nextInt后余下的换行符

        // 读取包含m个字符串的行
        String[] words = new String[m];
        String lineOfWords = scanner.nextLine();
        String[] inputWords = lineOfWords.split(" "); // 按空格分割字符串

        // 检查分割后的单词数量是否与m匹配
        if (inputWords.length != m) {
            // System.err.println("输入单词数量与m不匹配");
            // 根据实际情况处理错误,这里简单地取前m个或按实际数量
            // 为简单起见,我们假设输入总是正确的
        }

        for (int i = 0; i < m; i++) {
            words[i] = inputWords[i];
        }

        String result = findUnique(words);
        System.out.println(result);

        scanner.close();
    }
}

七、效果展示

1、输入

3 5
zyxwv vutsr abcde

2、输出

abcde

3、说明

zyxwv 和 vutsr 的差值数组为 [-1, -1, -1, -1],abcde 的为 [1, 1, 1, 1]。

在这里插入图片描述


🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2025 B卷 200分)

🏆本文收录于,华为OD机试(JAVA)真题(A卷+E卷+B卷+C卷+D卷)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哪 吒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值