- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
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)。
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<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--) {
if (!sortedSet.contains(pwd.substring(0, len))) {
return false;
}
}
return true;
}
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
C++解法
更新中
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
C解法
更新中
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
JS解法
给定一个密码列表,我们需要找出其中的最长有效密码。一个密码是有效的当且仅当它的所有前缀(从最短到最大)都出现在密码列表中。
比如,如果密码是 “abc”,它的前缀包括 “a”、“ab”、“abc”。如果这些前缀都出现在密码列表中,那么 “abc” 就是一个有效密码。
思路:
去重和排序:首先,我们将密码列表去重,并按长度从大到小排序(如果长度相同,则按字典序倒序)。这样可以确保我们从最长的密码开始检查,如果找到符合条件的密码,立即返回它。
前缀检查:对每个密码,检查它的所有前缀是否也存在于密码列表中。可以通过 substring 方法生成所有的前缀,并检查这些前缀是否在密码集合中存在。
最优解法:一旦找到一个密码的所有前缀都在集合中,我们立即返回该密码;否则继续检查下一个密码。
步骤:
将密码列表转换为 Set 以去除重复的密码并提高查找效率。
将密码列表按长度从大到小排序(相同长度时按字典序倒序排序),这样可以确保我们优先检查最长的密码。
对每个密码,检查它的所有前缀是否在 Set 中存在。如果满足条件,返回该密码。
如果没有任何密码符合条件,返回空字符串。
复杂度分析:
排序的时间复杂度是 O(n log n),其中 n 是密码的数量。
对每个密码,最坏情况下需要检查它的所有前缀,检查每个前缀的时间复杂度为 O(m),其中 m 是密码的最大长度。因此总时间复杂度是 O(n * m),其中 n 是密码的数量,m 是密码的最大长度
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);
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 "";
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏
评论记录:
回复评论: