小美的密码

[题目链接](https://www.nowcoder.com/practice/e95f6a9dec8242cbb3a0ca24ab98e8be)

思路

小美有 个候选密码,她会按照长度从小到大的顺序依次尝试,相同长度的密码随机尝试,且相同的密码只尝试一次。问最少和最多各需要尝试多少次。

分析

由于尝试顺序是按长度从小到大的,所以:

  • 所有长度比正确密码短的候选密码一定会先被尝试完;
  • 与正确密码等长的那一组中,由于顺序随机,正确密码可能第一个被尝试(最好情况),也可能最后一个被尝试(最坏情况)。

设去重后,长度比正确密码短的候选密码共 个,与正确密码等长的候选密码共 个,则:

$$

$$

实现步骤

  1. 读入正确密码和所有候选密码;
  2. 对候选密码去重
  3. 按长度统计每组有多少个不同的密码;
  4. 累加所有长度小于正确密码长度的组的密码数,得到
  5. 取与正确密码等长的组的密码数,得到
  6. 输出

样例演示

输入中候选密码为 ["abc", "ab", "ac", "ac"],正确密码为 "ab"

去重后为 ["abc", "ab", "ac"]。按长度分组:

  • 长度 2:"ab", "ac"(共 2 个)
  • 长度 3:"abc"(共 1 个)

正确密码 "ab" 的长度为 2,没有更短的密码,所以

$$

输出 1 2

复杂度分析

  • 时间复杂度:,其中 是密码的平均长度,主要开销在字符串去重(哈希集合操作)。
  • 空间复杂度:,存储去重后的密码集合。

代码

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

int main() {
    int n;
    cin >> n;
    string correct;
    cin >> correct;

    set<string> seen;
    map<int, int> lenCount;

    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        if (seen.insert(s).second) {
            lenCount[s.size()]++;
        }
    }

    int correctLen = correct.size();
    int before = 0;
    for (auto& [len, cnt] : lenCount) {
        if (len < correctLen) {
            before += cnt;
        }
    }

    int sameGroup = lenCount[correctLen];
    cout << before + 1 << " " << before + sameGroup << endl;
    return 0;
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String correct = sc.next();

        Set<String> seen = new HashSet<>();
        Map<Integer, Integer> lenCount = new TreeMap<>();

        for (int i = 0; i < n; i++) {
            String s = sc.next();
            if (seen.add(s)) {
                lenCount.merge(s.length(), 1, Integer::sum);
            }
        }

        int correctLen = correct.length();
        int before = 0;
        for (Map.Entry<Integer, Integer> e : lenCount.entrySet()) {
            if (e.getKey() < correctLen) {
                before += e.getValue();
            }
        }

        int sameGroup = lenCount.getOrDefault(correctLen, 0);
        System.out.println((before + 1) + " " + (before + sameGroup));
    }
}