【华为OD-E卷-寻找密码 100分(python、java、c++、js、c)】

【华为OD-E卷-寻找密码 100分(python、java、c++、js、c)】

题目

小王在进行游戏大闯关,有一个关卡需要输入一个密码才能通过,密码获得的条件如下:
在一个密码本中,每一页都有一个由 26 个小写字母组成的若干位密码,每一页的密码不同,需要从这个密码本中寻找这样一个最长的密码,从它的末尾开始依次去掉一位得到的新密码也在密码本中存在。
请输出符合要求的密码,如果有多个符合要求的密码,则返回字典序最大的密码。
若没有符合要求的密码,则返回空字符串。

输入描述

  • 密码本由一个字符串数组组成,不同元素之间使用空格隔开,每一个元素代表密码本每一页的密码

输出描述

  • 一个字符串

备注

  • 1 ≤ 密码本的页数 ≤ 10^5 1 ≤ 每页密码的长度 ≤ 10^5

用例

用例一:
输入:
h he hel hell hello
输出:
hello
用例二:
输入:
b ereddred bw bww bwwl bwwlm bwwln
输出:
bwwln

python解法

  • 解题思路:
  • 问题分析:

给定一个字符串列表 ps,我们需要找到其中一个最长的密码(即子串在列表中的"最长公共前缀")。这个密码必须满足:该密码的所有前缀(去掉最后一个字符的子串)也必须在列表中出现。

思路:

排序:首先,将字符串按其长度和字典序排序。长度优先排序是为了更容易找到最长的密码,而字典序排序保证了较短的密码会排在较长的密码之前。

检查每个密码的前缀:对列表中每个字符串,我们需要检查它的所有前缀是否也在列表中。如果一个密码的所有前缀都在列表中,那么它就是合法的密码。

逆向遍历:由于我们需要找出最长的密码,因此可以从最长的密码开始检查(即从 ps 列表的最后一个元素开始检查)。如果一个密码满足条件(所有前缀都在列表中),则直接返回该密码;否则,继续检查下一个密码。

步骤:

排序:首先对 ps 按长度和字典序排序。

检查前缀:从排序后的列表中,逆序检查每个密码及其前缀是否都存在于列表中。如果存在,返回该密码。

如果没有找到符合条件的密码,返回空字符串。

复杂度分析:

排序的时间复杂度是 O(n log n),其中 n 是密码列表的长度。

对每个密码检查其前缀,最坏情况下,检查所有密码的前缀的复杂度是 O(n * m),其中 m 是平均密码长度。由于排序后的列表是按长度和字典序排列,因此在大部分情况下,最长的密码会在较前面的位置,因此可以提前返回。

python 复制代码
ps = input().split()  # 输入密码列表

def pwd_finder(ps):
    # 按照密码的长度优先,字典序次之排序
    ps.sort(key=lambda x: (len(x), x))
    
    # 将密码列表转换为集合,便于快速查找前缀是否存在
    ps_set = set(ps)

    # 逆序遍历密码列表,寻找最长符合条件的密码
    for p in reversed(ps):
        # 检查该密码的所有前缀是否都在集合中
        if all(p[:-i] in ps_set for i in range(1, len(p))):
            return p  # 如果条件满足,返回该密码
    
    return ""  # 如果没有符合条件的密码,返回空字符串

# 输出结果
print(pwd_finder(ps))

java解法

  • 解题思路
  • 问题分析:

给定一组密码,我们需要找出最长的有效密码。一个密码是有效的当且仅当它的所有前缀(从最短到最大)都出现在密码列表中。

例如,对于密码 "abc",它的前缀包括 "a"、"ab"、"abc"。如果这些前缀都出现在密码列表中,那么 "abc" 就是一个有效密码。

思路:

排序:首先,密码列表需要按字典序排序。这是因为,字典序的排列能够帮助我们更高效地检查密码的前缀是否存在。我们可以从最长的密码开始检查。

前缀检查:对每个密码,检查它的所有前缀(从最短到最长)是否也存在于密码列表中。如果有任意一个前缀不存在,则该密码不是有效密码。

TreeSet:我们使用 TreeSet 来保存密码,因为它能够自动排序,并且提供高效的前缀查找(通过 contains 方法)。TreeSet 保证了元素的排序,使得我们可以从最大的密码开始检查。

步骤:

将密码列表转换为 TreeSet,这样可以去除重复的密码并自动按字典序排序。

遍历 TreeSet 中的密码,从最大密码开始检查其所有前缀。

对每个密码,检查它的所有前缀是否都存在于 TreeSet 中。如果找到一个有效的密码,则返回该密码。

复杂度分析:

排序:将密码列表转换为 TreeSet 的时间复杂度是 O(n log n),其中 n 是密码的数量。

前缀检查:对于每个密码,需要检查它的所有前缀,最坏情况下每个密码需要检查 O(m) 次,其中 m 是密码的最大长度。由于我们遍历整个 TreeSet,所以总复杂度为 O(n * m)。

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 输入密码列表并分割成数组
        String[] passwords = sc.nextLine().split(" ");
        // 调用函数找出最长的有效密码并输出
        System.out.println(findMaxValidPassword(passwords));
    }

    // 找出最长的有效密码
    public static String findMaxValidPassword(String[] passwords) {
        // 使用 TreeSet 来存储密码,自动排序
        TreeSet<String> sortedSet = new TreeSet<>(Arrays.asList(passwords));
        String maxPassword = "";

        // 从排序后的密码集合中倒序遍历(从最长的密码开始)
        for (String pwd : sortedSet.descendingSet()) {
            // 检查当前密码的所有前缀是否都存在于集合中
            if (allPrefixesExist(pwd, sortedSet)) {
                maxPassword = pwd;
                break;  // 找到第一个有效密码,直接返回
            }
        }

        return maxPassword;  // 返回最长的有效密码
    }

    // 检查密码的所有前缀是否都存在于集合中
    private static boolean allPrefixesExist(String pwd, Set<String> sortedSet) {
        // 检查密码的所有前缀
        for (int len = pwd.length() - 1; len > 0; len--) {
            // 如果某个前缀不在集合中,返回 false
            if (!sortedSet.contains(pwd.substring(0, len))) {
                return false;
            }
        }
        return true;  // 所有前缀都存在,返回 true
    }
}

C++解法

  • 解题思路
cpp 复制代码
更新中

C解法

解题思路

c 复制代码
更新中

JS解法

解题思路

  • 问题分析:

给定一个密码列表,我们需要找出其中的最长有效密码。一个密码是有效的当且仅当它的所有前缀(从最短到最大)都出现在密码列表中。

比如,如果密码是 "abc",它的前缀包括 "a"、"ab"、"abc"。如果这些前缀都出现在密码列表中,那么 "abc" 就是一个有效密码。

思路:

去重和排序:首先,我们将密码列表去重,并按长度从大到小排序(如果长度相同,则按字典序倒序)。这样可以确保我们从最长的密码开始检查,如果找到符合条件的密码,立即返回它。

前缀检查:对每个密码,检查它的所有前缀是否也存在于密码列表中。可以通过 substring 方法生成所有的前缀,并检查这些前缀是否在密码集合中存在。

最优解法:一旦找到一个密码的所有前缀都在集合中,我们立即返回该密码;否则继续检查下一个密码。

步骤:

将密码列表转换为 Set 以去除重复的密码并提高查找效率。

将密码列表按长度从大到小排序(相同长度时按字典序倒序排序),这样可以确保我们优先检查最长的密码。

对每个密码,检查它的所有前缀是否在 Set 中存在。如果满足条件,返回该密码。

如果没有任何密码符合条件,返回空字符串。

复杂度分析:

排序的时间复杂度是 O(n log n),其中 n 是密码的数量。

对每个密码,最坏情况下需要检查它的所有前缀,检查每个前缀的时间复杂度为 O(m),其中 m 是密码的最大长度。因此总时间复杂度是 O(n * m),其中 n 是密码的数量,m 是密码的最大长度

javascript 复制代码
const readline = require("readline");
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });

// 监听输入行并处理
rl.on("line", (line) => {
    const passwords = line.split(" ");  // 将输入的密码字符串按空格分割为数组
    console.log(findPassword(passwords));  // 调用函数并输出结果
});

// 寻找最长有效密码的函数
function findPassword(passwords) {
    const pwSet = new Set(passwords);  // 将密码列表转换为 Set,去重并提高查找效率

    // 按密码长度从大到小排序,长度相同则按字典序倒序排序
    passwords.sort((a, b) => b.length - a.length || b.localeCompare(a));

    // 遍历排序后的密码列表
    for (let pw of passwords) {
        let valid = true;  // 标记当前密码是否有效

        // 检查密码的所有前缀
        for (let i = pw.length - 1; i > 0; i--) {
            if (!pwSet.has(pw.substring(0, i))) {  // 如果某个前缀不在集合中,则当前密码无效
                valid = false;
                break;
            }
        }

        // 如果所有前缀都在集合中,则返回当前密码
        if (valid) return pw;
    }

    // 如果没有符合条件的密码,返回空字符串
    return "";
}

注意:

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

相关推荐
cuber膜拜9 分钟前
jupyter使用 Token 认证登录
ide·python·jupyter
张登杰踩1 小时前
pytorch2.5实例教程
pytorch·python
codists1 小时前
《CPython Internals》阅读笔记:p353-p355
python
Change is good1 小时前
selenium定位元素的方法
python·xpath定位
Change is good1 小时前
selenium clear()方法清除文本框内容
python·selenium·测试工具
陈平安Java and C4 小时前
MyBatisPlus
java
秋野酱5 小时前
如何在 Spring Boot 中实现自定义属性
java·数据库·spring boot
Bunny02125 小时前
SpringMVC笔记
java·redis·笔记
feng_blog66886 小时前
【docker-1】快速入门docker
java·docker·eureka
大懒猫软件6 小时前
如何运用python爬虫获取大型资讯类网站文章,并同时导出pdf或word格式文本?
python·深度学习·自然语言处理·网络爬虫