2023_华为OD机试真题_Java_010_真正的密码

该博客讨论了华为在线开发者(OD)测试中的一道Java编程题,涉及如何找出字符串数组中符合条件的潜在密码,并确定唯一的最长真正密码。解题关键在于利用字典树(Trie树)数据结构,通过深度优先搜索(DFS)策略检查字符串的子串是否全部存在于数组中。题目对时间复杂度的要求是O(N * M^2),其中N为字符串数组长度,M为平均字符串长度。
摘要由CSDN通过智能技术生成

真正的密码

题目描述

在一行中输入一个字符串数组,如果其中一个字符串的所有以索引0开头的子串在数组中都有,那么这个字符串就是潜在密码,

在所有潜在密码中最长的是真正的密码,如果有多个长度相同的真正的密码,那么取字典序最大的为唯一的真正的密码,求唯一的真正的密码。

输入描述

输出描述

示例1

输入

h he hel hell hello o ok n ni nin ninj ninja

输出

ninja

说明

按要求,hellookninja都是潜在密码。
检查长度,helloninja是真正的密码。
检查字典序,ninja是唯一真正密码。

示例2

输入

a b c d f

输出

f

说明

按要求,a b c d f 都是潜在密码。
检查长度,a b c d f 是真正的密码。
检查字典序,f是唯一真正密码。

思路解析

这道题目可以使用字典树(Trie树)来解决。

首先,我们需要构建一个字典树来存储所有的字符串。然后,对于每个字符串,我们可以在字典树中进行查找以其首字母开头的所有子串,如果查找到的所有子串都存在于字典树中,那么这个字符串就是一个潜在密码。

接着,我们可以在所有潜在密码中寻找最长的那个,如果有多个长度相同的真正的密码,就取字典序最大的为唯一的真正的密码。

具体实现时,可以采用深度优先搜索(DFS)来在字典树中查找以某个字符串开头的所有子串,同时记录潜在密码的长度和字典序,找到最长的那个即可。

总的时间复杂度为 O ( N ∗ M 2 ) O(N*M^2) O(NM2) ,其中 N N N 为字符串数组的长度, M M M 为字符串的平均长度, M 2 M^2 M2 是因为在深度优先搜索中需要枚举所有子串。

参考解题 Java

import java.util.*;
 
public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
 
    String[] arr = sc.nextLine().split(" ");
    System.out.println(getResult(arr));
  }
 
  public static String getResult(String[] arr) {
    // 字典序升序
    Arrays.sort(arr);
 
    // samePre统计相同首字母的字符串
    HashMap<Character, ArrayList<String>> samePre = new HashMap<>();
 
    for (String s : arr) {
      Character prefix = s.charAt(0);
      samePre.putIfAbsent(prefix, new ArrayList<>());
      samePre.get(prefix).add(s);
    }
 
    // ans用于缓存潜在密码
    ArrayList<String> ans = new ArrayList<>();
 
    for (Character prefix : samePre.keySet()) {
      // 获取相同首字母的密码
      ArrayList<String> list = samePre.get(prefix);
 
      // 由于密码初始时已经按照字典序升序,因此我们从相同首字母的最后一个密码开始找它的所有前缀子串
      for (int i = list.size() - 1; i >= 0; i--) {
        // 假设pass是潜在密码
        String pass = list.get(i);
        // 潜在密码一共有pass.length()个前缀子串,如果list数量少于pass.length(),则必然找不到所有前缀子串
        if (pass.length() > list.size()) continue;
        // 为了方便查找,我们将list压入set集合中
        HashSet<String> set = new HashSet<>(list);
 
        int j = pass.length() - 1;
        while (j >= 1) {
          // 开始构造pass的前缀子串substring
          String substring = pass.substring(0, j);
          if (set.contains(substring)) {
            // 如果找到了当前的前缀子串,则继续找下一个前缀子串
            j--;
          } else {
            // 如果有一个前缀子串找不到,那么说明pass就不是潜在密码
            break;
          }
        }
 
        // 如果j=0,说明当前pass的所有前缀子串都能找到,
        if (j == 0) {
          // 因此pass就是潜在密码,可以加入ans
          ans.add(pass);
          // 且此时pass必然是相同首字母中最长的潜在密码,因此该首字母下的其他潜在密码就不需要再找了
          break;
        }
      }
    }
 
    // 所有潜在密码优先按照长度降序,长度相同,再按照字典序降序
    ans.sort((a, b) -> a.length() != b.length() ? b.length() - a.length() : b.compareTo(a));
 
    // 取最大的
    return ans.get(0);
  }
}
华为2023年的OD机试题目包含多个部分,其中有一个是“异常打卡Java”,是一道Java编程题目。 题目要求程序实现一个打卡系统,包含登录、签到、签退、查询历史记录等功能。要求使用Java语言编写,同时需要对程序中可能出现的异常进行处理,确保程序的稳定性和安全性。 对于这道题目,我们可以从以下几个方面进行思考和实现: 第一,需要使用Java语言编写程序,其中涉及到Java基础语法、数据类型、运算符、流程控制等知识点。需要熟悉Java编程语言的基本规则和开发环境,如JDK、Eclipse等。 第二,需要实现一个打卡系统,包括用户登录、签到、签退、查询历史记录等功能。这需要用到Java的面向对象编程思想,通过定义类、对象、方法等来实现系统的功能。 第三,需要对程序中可能出现的异常进行处理,通过try-catch语句等方式来捕获异常,并进行相应的处理。需要能够识别和处理常见的异常类型,如空指针异常、数组越界异常等。 在实现上述功能的同时,还需要考虑程序的稳定性和安全性,例如防止SQL注入、XSS攻击等安全问题。需要注意代码实现的效率和可读性,注重代码规范和注释,以便后续维护和更新。 总之,在华为OD2023机试中的异常打卡Java这一题目中,我们需要综合运用Java编程知识和面向对象思想,能够处理程序中可能发生的异常,确保程序的稳定性和安全性。需要注重代码防御和安全性,同时需要考虑代码的可读性和规范性。这是一道具有一定难度和挑战性的Java编程题目,但通过认真学习和练习,相信大家可以取得好的成绩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值