自学内容网 自学内容网

【华为OD-E卷-字母组合 100分(python、java、c++、js、c)】

【华为OD-E卷-字母组合 100分(python、java、c++、js、c)】

题目

每个数字关联多个字母,关联关系如下:
0 关联 “a”,”b”,”c” 1 关联 “d”,”e”,”f” 2 关联 “g”,”h”,”i” 3 关联 “j”,”k”,”l” 4 关联 “m”,”n”,”o” 5 关联 “p”,”q”,”r” 6 关联 “s”,”t” 7 关联 “u”,”v” 8 关联 “w”,”x” 9 关联 “y”,”z” 输入一串数字后,通过数字和字母的对应关系可以得到多个字母字符串(要求按照数字的顺序组合字母字符串);
屏蔽字符串:屏蔽字符串中的所有字母不能同时在输出的字符串出现,如屏蔽字符串是abc,则要求字符串中不能同时出现a,b,c,但是允许同时出现a,b或a,c或b,c等;
给定一个数字字符串和一个屏蔽字符串,输出所有可能的字符组合;
例如输入数字字符串78和屏蔽字符串ux,输出结果为uw,vw,vx;数字字符串78,可以得到如下字符串uw,ux,vw,vx;由于ux是屏蔽字符串,因此排除ux,最终的输出是uw,vw,vx;

输入描述

  • 第一行输入为一串数字字符串,数字字符串中的数字不允许重复,数字字符串的长度大于0,小于等于5;

第二行输入是屏蔽字符串,屏蔽字符串的长度一定小于数字字符串的长度,屏蔽字符串中字符不会重复

输出描述

  • 输出可能的字符串组合

用例

用例一:
输入:
78
ux
输出:
uw,vw,vx,
用例二:
输入:
78
x
输出:
uw,vw,

python解法

  • 解题思路:
  • 字母映射关系: 每个数字(从0到9)映射到一定的字母集合。例如,数字2对应字母"abc",数字3对应字母"def"。通过一个 char_map 列表来记录这些映射关系。char_map[i] 表示数字 i 对应的字母集合。

队列(Queue)用于生成组合: 我们使用一个队列来逐步生成所有可能的字母组合。每次从队列中取出一个当前的组合(初始为空字符串""),然后将每个字母组合进来,形成新的组合,继续加入队列。

过滤条件: 在生成每一个新的字母组合时,判断这个组合是否包含屏蔽字符串中的所有字符。如果不包含,则将这个组合加入队列。过滤条件由 contains_all 函数检查,确保新生成的组合满足不含有屏蔽字符串的所有字符。

最终返回: 经过所有处理后,所有符合条件的字母组合会在队列中。最终将这些组合合并成一个字符串,返回。

from collections import deque

# 获取符合条件的所有字母组合
def get_combinations(nums, filter_str):
    # 数字到字母的映射,数字0对应"abc",数字1对应"def"等
    char_map = ["abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx", "yz"]

    # 使用队列存储生成的字母组合,初始时队列中只有空字符串
    queue = deque([""])

    # 对输入的每个数字进行处理
    for num in nums:
        # 获取当前数字对应的字母集合
        letters = char_map[int(num)]
        size = len(queue)

        # 对队列中当前的每个组合进行扩展
        for _ in range(size):
            # 取出队列中的一个组合
            path = queue.popleft()

            # 对当前组合,尝试添加所有可能的字母
            for letter in letters:
                # 生成新的组合
                new_path = path + letter

                # 如果新组合不包含屏蔽字符串中的所有字符,则加入队列
                if not contains_all(new_path, filter_str):
                    queue.append(new_path)

    # 返回符合条件的所有组合,多个组合用逗号分隔
    return ",".join(queue) + ","

# 检查组合是否包含屏蔽字符串中的所有字符
def contains_all(s, filter_str):
    # 遍历屏蔽字符串中的每个字符,检查它是否出现在当前组合中
    for c in filter_str:
        if c not in s:
            return False
    return True

# 输入处理
nums = input().strip()  # 输入数字串
filter_str = input().strip()  # 输入屏蔽字符串
print(get_combinations(nums, filter_str))  # 输出符合条件的字母组合

java解法

  • 解题思路
  • 字母映射关系: 每个数字(0到9)对应一定的字母集合。可以使用一个数组 map 来表示这种映射关系。map[i] 表示数字 i 对应的字母集合。例如,map[2] 对应字母 “abc”。

生成所有字母组合: 由于输入的数字串 nums 可能对应多个字母,我们需要生成所有可能的字母组合。可以通过类似多重循环的方式生成这些组合,每个数字选择一个字母进行拼接。为了避免直接使用多层循环,我们使用一个数组 indices 来表示每个数字在其对应字母集合中的当前位置,然后利用该数组进行组合生成。

组合生成:

从左到右遍历每个数字,选择其对应字母集合中的一个字母。
使用一个 StringBuilder 来拼接当前组合,并将其加入结果列表 result,如果该组合不包含屏蔽字符串中的所有字符。
递增逻辑:

当我们生成一个字母组合后,需要递增组合的 “位置”。如果某一位的字母已经到达其字母集合的最后一个字母,则回退到该集合的第一个字母,并递增上一位。
如果所有的字母集合都回退到第一个字母,说明所有组合已经生成完毕。
返回结果:

最终,将所有符合条件的字母组合连接成一个以逗号分隔的字符串,返回。

import java.util.*;

public class Main {
    // 数字与字母的映射关系
    static String nums;
    static String filter;
    static String[] map = {"abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx", "yz"};
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读取数字串和过滤字符串
        nums = sc.nextLine();
        filter = sc.nextLine();
        // 输出符合条件的字母组合
        System.out.println(getResult());
    }
    
    // 获取所有符合条件的字母组合
    public static String getResult() {
        int n = nums.length();  // 获取数字串长度
        int[] indices = new int[n];  // 数组用于跟踪每个数字对应字母集合中的当前位置
        List<String> result = new ArrayList<>();  // 存储符合条件的字母组合
        
        // 使用while循环生成所有可能的字母组合
        while (true) {
            StringBuilder sb = new StringBuilder();
            // 根据当前的 indices 数组生成字母组合
            for (int i = 0; i < n; i++) {
                sb.append(map[nums.charAt(i) - '0'].charAt(indices[i]));  // 通过 map 获取字母
            }
            // 如果字母组合不包含屏蔽字符串中的所有字符,则添加到结果列表
            if (!containsAll(sb.toString(), filter)) {
                result.add(sb.toString());
            }
            
            // 寻找下一个字母组合
            int pos = n - 1;  // 从最后一位开始查找
            while (pos >= 0) {
                // 如果当前位的字母集合还有更多的字母,递增该位的索引
                if (indices[pos] < map[nums.charAt(pos) - '0'].length() - 1) {
                    indices[pos]++;
                    break;
                } else {
                    // 如果该位已到达字母集合的最后一个字母,回退并继续递增上一位
                    indices[pos] = 0;
                    pos--;
                }
            }
            // 如果所有位都回退到最初的状态,说明已生成所有组合,跳出循环
            if (pos < 0) break;
        }
        
        // 将所有符合条件的组合以逗号分隔并返回
        return String.join(",", result) + ",";
    }
    
    // 检查字符串是否包含过滤字符串中的所有字符
    public static boolean containsAll(String s, String filter) {
        // 遍历过滤字符串中的每个字符,检查是否在当前组合中
        for (char c : filter.toCharArray()) {
            if (!s.contains(String.valueOf(c))) {
                return false;
            }
        }
        return true;
    }
}

C++解法

  • 解题思路
更新中

C解法

  • 解题思路

更新中

JS解法

  • 解题思路

更新中

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏


原文地址:https://blog.csdn.net/CodeClimb/article/details/144514574

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!