华为OD机试 - 匿名信(Python/JS/C/C++ 2024 E卷 100分)

在这里插入图片描述

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

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

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

一、题目描述

电视剧《分界线Q》里面有一个片段,男主为了向警察透露案件细节,且不暴露自己,于是将报刊上的字减下来,剪拼成匿名信。
现在一名举报人,希望借鉴这部片段,使用英文报刊为范本来剪拼举报信。
但为了增加文章的混淆程度,尽量避免每个单词中字母数量一致即可,不关注每个字母的顺序。
解释:单词n允许抄袭过n的字母组合。

报纸代表newspaper,匿名信代表anonymousLetter,求报纸内容是否可以拼成匿名信。

二、输入描述

第一行newspaper内容,包括1N个字符,并且空格分开

第二行anonymousLetter内容,包括1N个字符,并且空格分开。

newspaper和anonymousLetter的字符串中均为英文字母组成,且每个字母只能使用一次;

newspaper内容中的每个字符中字母顺序可以任意调整,但必须保证字符串的完整性(每个字符串不能有多余字母)

1 < N < 100,

1 <= newspaper.length,anonymousLetter.length <= 104

三、输出描述

如果报纸可以拼成匿名信返回true,否则返回false

四、测试用例

测试用例1:

1、输入

ab cd
ab

2、输出

true

3、说明

测试用例2:

1、输入

ab ef
aef

2、输出

false

3、说明

五、解题思路

  1. 读取输入,包括报纸内容和匿名信内容。
  2. 将报纸和匿名信中的每个单词进行字母排序,得到其“规范形式”。
    • 例如,单词“ab”排序后仍为“ab”,单词“aef”排序后为“aef”。
  3. 统计报纸中每种规范形式的单词出现次数,存入一个哈希映射 newspaperMap 中。
  4. 统计匿名信中每种规范形式的单词出现次数,存入另一个哈希映射 letterMap 中。
  5. 遍历匿名信中的每种规范形式,检查报纸中是否有足够数量的对应单词。
    • 如果报纸中某种规范形式的单词数量少于匿名信中需要的数量,则返回 false。
  6. 如果所有匿名信中的单词都在报纸中有足够的对应单词,则返回 true。

六、Python算法源码

# 导入所需模块
import sys

def calculate_total_cost(newspaper_words, letter_words):
    """
    计算报纸内容是否可以拼成匿名信
    :param newspaper_words: 报纸中的单词列表
    :param letter_words: 匿名信中的单词列表
    :return: 如果可以拼成匿名信返回True,否则返回False
    """
    # 使用字典统计报纸中每种规范形式的单词出现次数
    newspaper_map = {}
    for word in newspaper_words:
        sorted_word = ''.join(sorted(word))  # 将单词字母排序
        if sorted_word in newspaper_map:
            newspaper_map[sorted_word] += 1
        else:
            newspaper_map[sorted_word] = 1
    
    # 使用字典统计匿名信中每种规范形式的单词出现次数
    letter_map = {}
    for word in letter_words:
        sorted_word = ''.join(sorted(word))  # 将单词字母排序
        if sorted_word in letter_map:
            letter_map[sorted_word] += 1
        else:
            letter_map[sorted_word] = 1
    
    # 检查报纸中是否有足够的单词来组成匿名信
    for sorted_word, required_count in letter_map.items():
        available_count = newspaper_map.get(sorted_word, 0)
        if available_count < required_count:
            return False  # 如果报纸中对应单词数量不足,返回False
    return True  # 所有单词数量足够,返回True

def main():
    # 读取标准输入的所有行,并去除多余空格
    lines = sys.stdin.read().splitlines()
    lines = [line.strip() for line in lines if line.strip()]
    
    # 检查输入是否至少包含两行
    if len(lines) < 2:
        print("false")
        return
    
    # 读取报纸内容,并分割成单词列表
    newspaper_words = lines[0].split()
    
    # 读取匿名信内容,并分割成单词列表
    letter_words = lines[1].split()
    
    # 调用函数计算结果
    can_form = calculate_total_cost(newspaper_words, letter_words)
    
    # 输出结果
    print("true" if can_form else "false")

if __name__ == "__main__":
    main()

七、JavaScript算法源码

// 导入所需模块
const readline = require('readline');

// 创建接口以读取标准输入
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let inputLines = [];

// 读取每一行输入
rl.on('line', (line) => {
    inputLines.push(line.trim());
    // 当读取了至少两行输入时,开始处理
    if (inputLines.length === 2) {
        rl.close();
    }
});

// 输入读取完成后处理
rl.on('close', () => {
    // 读取报纸内容并分割成单词数组
    const newspaperWords = inputLines[0].split(/\s+/);
    
    // 读取匿名信内容并分割成单词数组
    const letterWords = inputLines[1].split(/\s+/);
    
    // 计算报纸是否可以拼成匿名信
    const canForm = calculateTotalCost(newspaperWords, letterWords);
    
    // 输出结果
    console.log(canForm ? "true" : "false");
});

/**
 * 计算报纸内容是否可以拼成匿名信
 * @param {string[]} newspaperWords 报纸中的单词数组
 * @param {string[]} letterWords 匿名信中的单词数组
 * @returns {boolean} 如果可以拼成匿名信返回true,否则返回false
 */
function calculateTotalCost(newspaperWords, letterWords) {
    // 使用对象统计报纸中每种规范形式的单词出现次数
    const newspaperMap = {};
    for (let word of newspaperWords) {
        const sortedWord = sortLetters(word); // 将单词字母排序
        if (newspaperMap.hasOwnProperty(sortedWord)) {
            newspaperMap[sortedWord] += 1;
        } else {
            newspaperMap[sortedWord] = 1;
        }
    }
    
    // 使用对象统计匿名信中每种规范形式的单词出现次数
    const letterMap = {};
    for (let word of letterWords) {
        const sortedWord = sortLetters(word); // 将单词字母排序
        if (letterMap.hasOwnProperty(sortedWord)) {
            letterMap[sortedWord] += 1;
        } else {
            letterMap[sortedWord] = 1;
        }
    }
    
    // 检查报纸中是否有足够的单词来组成匿名信
    for (let sortedWord in letterMap) {
        const requiredCount = letterMap[sortedWord];
        const availableCount = newspaperMap[sortedWord] || 0;
        if (availableCount < requiredCount) {
            return false; // 如果报纸中对应单词数量不足,返回false
        }
    }
    return true; // 所有单词数量足够,返回true
}

/**
 * 将单词中的字母按字母序排序,并返回排序后的字符串
 * @param {string} word 原始单词
 * @returns {string} 排序后的单词
 */
function sortLetters(word) {
    return word.split('').sort().join('');
}

八、C算法源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 定义最大单词数和最大单词长度
#define MAX_WORDS 10000
#define MAX_WORD_LENGTH 100

// 比较函数,用于qsort
int cmp_char(const void *a, const void *b) {
    return (*(char*)a - *(char*)b);
}

int main() {
    char newspaper_line[1000001]; // 假设每行最多100万字符
    char letter_line[1000001];
    
    // 读取报纸内容
    if (fgets(newspaper_line, sizeof(newspaper_line), stdin) == NULL) {
        printf("false\n");
        return 0;
    }
    
    // 读取匿名信内容
    if (fgets(letter_line, sizeof(letter_line), stdin) == NULL) {
        printf("false\n");
        return 0;
    }
    
    // 分割报纸内容成单词
    char *newspaper_words[MAX_WORDS];
    int newspaper_count = 0;
    char *token = strtok(newspaper_line, " \n");
    while (token != NULL && newspaper_count < MAX_WORDS) {
        newspaper_words[newspaper_count++] = token;
        token = strtok(NULL, " \n");
    }
    
    // 分割匿名信内容成单词
    char *letter_words[MAX_WORDS];
    int letter_count = 0;
    token = strtok(letter_line, " \n");
    while (token != NULL && letter_count < MAX_WORDS) {
        letter_words[letter_count++] = token;
        token = strtok(NULL, " \n");
    }
    
    // 使用哈希表模拟报纸中的单词频率
    // 由于C没有内置哈希表,这里使用排序和二分查找的方法
    // 首先,创建一个数组存储报纸中排序后的单词
    char **sorted_newspaper = (char**)malloc(newspaper_count * sizeof(char*));
    for (int i = 0; i < newspaper_count; i++) {
        int len = strlen(newspaper_words[i]);
        sorted_newspaper[i] = (char*)malloc((len + 1) * sizeof(char));
        strcpy(sorted_newspaper[i], newspaper_words[i]);
        qsort(sorted_newspaper[i], len, sizeof(char), cmp_char); // 排序字母
    }
    
    // 排序整个报纸单词数组
    // 使用指针数组排序
    for (int i = 0; i < newspaper_count - 1; i++) {
        for (int j = i + 1; j < newspaper_count; j++) {
            if (strcmp(sorted_newspaper[i], sorted_newspaper[j]) > 0) {
                char *temp = sorted_newspaper[i];
                sorted_newspaper[i] = sorted_newspaper[j];
                sorted_newspaper[j] = temp;
            }
        }
    }
    
    // 创建一个数组存储匿名信中排序后的单词
    char **sorted_letter = (char**)malloc(letter_count * sizeof(char*));
    for (int i = 0; i < letter_count; i++) {
        int len = strlen(letter_words[i]);
        sorted_letter[i] = (char*)malloc((len + 1) * sizeof(char));
        strcpy(sorted_letter[i], letter_words[i]);
        qsort(sorted_letter[i], len, sizeof(char), cmp_char); // 排序字母
    }
    
    // 排序匿名信中的单词
    for (int i = 0; i < letter_count - 1; i++) {
        for (int j = i + 1; j < letter_count; j++) {
            if (strcmp(sorted_letter[i], sorted_letter[j]) > 0) {
                char *temp = sorted_letter[i];
                sorted_letter[i] = sorted_letter[j];
                sorted_letter[j] = temp;
            }
        }
    }
    
    // 统计报纸中每种单词的频率
    // 使用两个数组存储唯一单词和对应频率
    char **unique_newspaper = (char**)malloc(newspaper_count * sizeof(char*));
    int *freq_newspaper = (int*)malloc(newspaper_count * sizeof(int));
    int unique_count = 0;
    for (int i = 0; i < newspaper_count; i++) {
        if (i == 0 || strcmp(sorted_newspaper[i], sorted_newspaper[i - 1]) != 0) {
            unique_newspaper[unique_count] = sorted_newspaper[i];
            freq_newspaper[unique_count] = 1;
            unique_count++;
        } else {
            freq_newspaper[unique_count - 1]++;
        }
    }
    
    // 统计匿名信中每种单词的频率
    char **unique_letter = (char**)malloc(letter_count * sizeof(char*));
    int *freq_letter = (int*)malloc(letter_count * sizeof(int));
    int unique_letter_count = 0;
    for (int i = 0; i < letter_count; i++) {
        if (i == 0 || strcmp(sorted_letter[i], sorted_letter[i - 1]) != 0) {
            unique_letter[unique_letter_count] = sorted_letter[i];
            freq_letter[unique_letter_count] = 1;
            unique_letter_count++;
        } else {
            freq_letter[unique_letter_count - 1]++;
        }
    }
    
    // 检查每个匿名信中的单词是否在报纸中有足够的数量
    int can_form = 1; // 默认可以
    for (int i = 0; i < unique_letter_count; i++) {
        // 使用二分查找在报纸中查找单词
        int left = 0;
        int right = unique_count - 1;
        int found = 0;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            int cmp = strcmp(unique_letter[i], unique_newspaper[mid]);
            if (cmp == 0) {
                if (freq_newspaper[mid] < freq_letter[i]) {
                    can_form = 0; // 不足
                }
                found = 1;
                break;
            } else if (cmp < 0) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        if (!found) {
            can_form = 0; // 未找到
            break;
        }
        if (can_form == 0) {
            break;
        }
    }
    
    // 输出结果
    if (can_form) {
        printf("true\n");
    } else {
        printf("false\n");
    }
    
    // 释放动态分配的内存
    for (int i = 0; i < newspaper_count; i++) {
        free(sorted_newspaper[i]);
    }
    free(sorted_newspaper);
    free(sorted_letter);
    free(unique_newspaper);
    free(freq_newspaper);
    free(unique_letter);
    free(freq_letter);
    
    return 0;
}

九、C++算法源码

#include <bits/stdc++.h>
using namespace std;

/**
 * 将字符串中的字母按字母序排序,并返回排序后的字符串
 * @param word 原始字符串
 * @return 排序后的字符串
 */
string sortLetters(const string &word) {
    string sorted = word;
    sort(sorted.begin(), sorted.end());
    return sorted;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    string newspaper_line;
    string letter_line;
    
    // 读取报纸内容
    if (!getline(cin, newspaper_line)) {
        cout << "false\n";
        return 0;
    }
    
    // 读取匿名信内容
    if (!getline(cin, letter_line)) {
        cout << "false\n";
        return 0;
    }
    
    // 分割报纸内容成单词
    vector<string> newspaper_words;
    string word;
    stringstream ss_newspaper(newspaper_line);
    while (ss_newspaper >> word) {
        newspaper_words.push_back(word);
    }
    
    // 分割匿名信内容成单词
    vector<string> letter_words;
    stringstream ss_letter(letter_line);
    while (ss_letter >> word) {
        letter_words.push_back(word);
    }
    
    // 使用unordered_map统计报纸中每种规范形式的单词出现次数
    unordered_map<string, int> newspaper_map;
    for (const auto &w : newspaper_words) {
        string sorted_word = sortLetters(w); // 将单词字母排序
        newspaper_map[sorted_word]++;
    }
    
    // 使用unordered_map统计匿名信中每种规范形式的单词出现次数
    unordered_map<string, int> letter_map;
    for (const auto &w : letter_words) {
        string sorted_word = sortLetters(w); // 将单词字母排序
        letter_map[sorted_word]++;
    }
    
    // 检查报纸中是否有足够的单词来组成匿名信
    bool can_form = true;
    for (const auto &entry : letter_map) {
        const string &sorted_word = entry.first;
        int required_count = entry.second;
        int available_count = newspaper_map[sorted_word];
        if (available_count < required_count) {
            can_form = false;
            break;
        }
    }
    
    // 输出结果
    cout << (can_form ? "true" : "false") << "\n";
    
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为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、付费专栏及课程。

余额充值