[题目解析]哈希表专题:119、147、298、358、373 | 豆包MarsCode AI刷题

64 阅读8分钟

119.游戏队友搜索

问题描述

在一款多人游戏中,每局比赛需要多个玩家参与。如果发现两名玩家至少一起玩过两局比赛,则可以认为这两名玩家互为队友。现在你有一份玩家(通过玩家ID标识)和比赛局次(通过比赛ID标识)的历史记录表,目标是帮助某位指定玩家找到所有符合条件的队友。

测试样例

样例1:

输入:id = 1, num = 10, array = [[1,1], [1,2], [1,3], [2,1], [2,4], [3,2], [4,1], [4,2], [5,2], [5,3]] 输出:[4, 5]

样例2:

输入:id = 2, num = 6, array = [[2,1], [2,3], [1,1], [1,2], [3,1], [4,3]] 输出:[]

样例3:

输入:id = 3, num = 8, array = [[3,1], [3,2], [3,3], [4,1], [5,2], [6,3], [7,1], [7,2]] 输出:[7]

解决方案

首先找出指定玩家玩过哪些比赛,然后遍历比赛历史记录表,用一个哈希表记录每个玩家玩过的指定玩家玩过的比赛数量,最后遍历哈希表,如果该玩家与指定玩家玩过的比赛数量大于等于2,那么该玩家是符合条件的队友。上述做法的时间复杂度是O(n)O(n)

参考代码

import java.util.*;
public class Main {
    public static void main(String[] args) {
        // Add your test cases here
        System.out.println(solution(1, 10, new int[][]{{1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 4}, {3, 2}, {4, 1}, {4, 2}, {5, 2}, {5, 3}}).equals(new int[]{4, 5}));
    }

    public static int[] solution(int id, int num, int[][] array) {
        // Edit your code here
        HashSet<Integer> S = new HashSet<>();
        for (int i = 0; i < num; i++) {
            if (array[i][0] == id) {
                S.add(array[i][1]);
            }
        }
        HashMap<Integer, Integer> mp = new HashMap<>();
        for (int i = 0; i < num; i++) {
            if (array[i][0] == id) {
                continue;
            }
            if (S.contains(array[i][1])) {
                if (mp.containsKey(array[i][0])) {
                    mp.replace(array[i][0], mp.get(array[i][0]) + 1);
                } else {
                    mp.put(array[i][0], 1);
                }
            }
        }
        ArrayList<Integer> res = new ArrayList<>();
        for (Integer i : mp.keySet()) {
            if (mp.get(i) >= 2) {
                res.add(i);
            }
        }
        int[] ret = new int[res.size()];
        int i = 0;
        for (Integer x : res) {
            ret[i++] = x;
        }
        return ret;
    }
}

147.寻找独一无二的糖葫芦串

问题描述

小C有nn串长度为mm的糖葫芦,每串糖葫芦可以用一个字符串表示。每个糖葫芦的甜度是所有字符甜度的总和,其中每个字符的甜度为该字符与 'a' 的差值。例如,字符 'a' 的甜度为 0,字符 'b' 的甜度为 1,依次类推,字符 'z' 的甜度为 25。

你需要帮助小C找到甜度最大的独一无二的糖葫芦。糖葫芦独一无二当且仅当它与其他n1n-1根糖葫芦都不同,且翻转后的字符串也不能与其他糖葫芦相同。例如,糖葫芦 "abc""cba" 视为相同的糖葫芦。

如果没有独一无二的糖葫芦,则返回0。

测试样例

样例1:

输入:n = 3, m = 3, strings = ["ccz", "cba", "zcc"] 输出:3

样例2:

输入:n = 2, m = 3, strings = ["abc", "cba"] 输出:0

样例3:

输入:n = 5, m = 2, strings = ["aa", "bb", "ab", "ba", "cc"] 输出:4

解决方案

首先用一个哈希表记录一下每个字符串的出现次数,然后遍历String数组,如果该字符串的出现次数大于1或者该字符串的翻转字符串出现过,那么直接跳过。这里有一个地方需要注意,就是当一个字符串的所有字符都相同的时候,上面的做法会出现误判(这个时候字符串的翻转就是它本身)。所以在此之前需要判断一个字符串中是否所有字符都相同,并且上述的判断条件变成了如果字符串的出现次数大于1或者该字符串的翻转字符串出现过并且该字符串不是所有字符都相同。不跳过的话,遍历该字符串,计算该字符串的甜度,并更新最大的甜度。由于如果没有独一无二的糖葫芦,返回0,那么答案的初始值设成0就好了,既能求最大值,又可以满足特殊情况的要求。上述做法的时间复杂度为O(nm)O(nm)

参考代码

import java.util.HashMap;

public class Main {
    public static int solution(int n, int m, String[] strings) {
        // write code here
        HashMap<String, Integer> mp = new HashMap<>();
        for (String s : strings) {
            mp.put(s, mp.getOrDefault(s, 0) + 1);
        }
        int res = 0;
        for (String s : strings) {
            boolean flag = true;
            for (int i = 1; i < m; i++) {
                if (s.charAt(i) != s.charAt(0)) {
                    flag = false;
                    break;
                }
            }
            String tt = new StringBuilder(s).reverse().toString();
            if (mp.get(s) > 1 || mp.containsKey(tt) && !flag) {
                continue;
            }
            int t = 0;
            for (int i = 0; i < m; i++) {
                t += s.charAt(i) - 'a';
            }
            if (t > res) {
                res = t;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(solution(3, 3, new String[]{"ccz", "cba", "zcc"}) == 3);
        System.out.println(solution(2, 3, new String[]{"abc", "cba"}) == 0);
        System.out.println(solution(5, 2, new String[]{"aa", "bb", "ab", "ba", "cc"}) == 4);
    }
}

298.素数元素的统计

问题描述

小R给定了一个整数数组,要求你统计出其中有多少个元素既是素数,且这些素数元素的出现次数也是素数。需要注意的是,数组中元素的出现次数也应计算在内。比如,数组 [1, 2, 3, 2, 5, 7, 7, 7, 5] 中,元素 2 出现了两次,而 7 出现了三次,这些次数也都需要判断是否为素数。

测试样例

样例1:

输入:a = [1, 2, 3, 2, 5, 7, 7, 7, 5] 输出:3

样例2:

输入:a = [1, 4, 6, 8, 10, 12] 输出:0

样例3:

输入:a = [3, 3, 3, 5, 5, 5, 5] 输出:1

解决方案

首先遍历该数组,用哈希表记录每个数的出现次数。然后再次遍历该数组,如果当前元素是素数,并且它的出现次数也是素数,那么让答案加一。判断一个数是否是素数可以从2遍历到该数的平方根,然后检测每个数是否是该数的因子,如果存在一个数是该数的因子,那么该数不是素数,否则,该数是素数。由于判断一个数是否是素数的时间复杂度是O(n)O(\sqrt{n}),所以上述做法的时间复杂度是O(n1.5)O(n^{1.5})

参考代码

import java.util.*;

public class Main {
    public static boolean isPrime(int x) {
        if (x == 1) {
            return false;
        }
        boolean ok = true;
        for (int i = 2; i <= x / i; i++) {
            if (x % i == 0) {
                ok = false;
                break;
            }
        }
        return ok;
    }
    public static int solution(List<Integer> a) {
        // write code here
        HashMap<Integer, Integer> mp = new HashMap<>();
        for (Integer x : a) {
            mp.put(x, mp.getOrDefault(x, 0) + 1);
        }
        int res = 0;
        for (Integer x : mp.keySet()) {
            if (isPrime(x) && isPrime(mp.get(x))) {
                res++;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(solution(Arrays.asList(1, 2, 3, 2, 5, 7, 7, 7, 5)) == 3);
        System.out.println(solution(Arrays.asList(1, 4, 6, 8, 10, 12)) == 0);
        System.out.println(solution(Arrays.asList(3, 3, 3, 5, 5, 5, 5)) == 1);
    }
}

358.单词出现频率统计

问题描述

小U在学习英文时,需要统计英文句子中每个单词的出现次数,并按照字母顺序将统计结果进行排序。请你帮助小U编写一个程序,统计输入的英文句子中每个单词的出现次数,并将结果按字母顺序排序后输出。

测试样例

样例1:

输入:s = "New to Python or choosing between Python 2 and Python 3 Read Python 2 or Python 3" 输出:['2:2', '3:2', 'New:1', 'Python:5', 'Read:1', 'and:1', 'between:1', 'choosing:1', 'or:2', 'to:1']

样例2:

输入:s = "hello world hello python" 输出:['hello:2', 'python:1', 'world:1']

样例3:

输入:s = "the quick brown fox jumps over the lazy dog" 输出:['brown:1', 'dog:1', 'fox:1', 'jumps:1', 'lazy:1', 'over:1', 'quick:1', 'the:2']

解决方案

首先以空格为分隔符将每个单词分开,并存入到字符串数组中,然后遍历字符串数组,用哈希表记录每个单词的出现次数。最后将哈希表的keySet取出来按照字典序进行排序,并将每个单词的出现次数附加到每个单词后面。上述做法的时间复杂度是O(nlogn)O(nlogn)

参考代码

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

public class Main {
    public static List<String> solution(String s) {
        // write code here
        String[] a = s.split(" ");
        HashMap<String, Integer> mp = new HashMap<>();
        for (String ss : a) {
            mp.put(ss, mp.getOrDefault(ss, 0) + 1);
        }
        ArrayList<String> res = new ArrayList<>();
        for (String ss : mp.keySet()) {
            res.add(ss);
        }
        Collections.sort(res);
        for (int i = 0; i < res.size(); i++) {
            res.set(i, res.get(i) + ":" + mp.get(res.get(i)));
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(solution("New to Python or choosing between Python 2 and Python 3 Read Python 2 or Python 3").equals(List.of("2:2", "3:2", "New:1", "Python:5", "Read:1", "and:1", "between:1", "choosing:1", "or:2", "to:1")));
        System.out.println(solution("hello world hello python").equals(List.of("hello:2", "python:1", "world:1")));
        System.out.println(solution("the quick brown fox jumps over the lazy dog").equals(List.of("brown:1", "dog:1", "fox:1", "jumps:1", "lazy:1", "over:1", "quick:1", "the:2")));
    }
}

373.字母出现次数统计

问题描述

小R得到了一个由小写字母组成的字符串 s,她想知道有多少个小写字母在字符串中至少出现了 k 次。请你帮她解决这个问题。

测试样例

样例1:

输入:s = "aaabcd", k = 2 输出:1

样例2:

输入:s = "aacbcbdefghijklmnopqrstuvwxyz", k = 1 输出:26

样例3:

输入:s = "zzzzzzabc", k = 3 输出:1

解决方案

遍历字符串,用哈希表记录每个字符的出现次数。然后遍历哈希表,如果某个字符的出现次数大于等于k,就让答案加一。上述做法的时间复杂度是O(n)O(n)

参考代码

import java.util.HashMap;

public class Main {
    public static int solution(String s, int k) {
        // write code here
        HashMap<Character, Integer> mp = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            mp.put(s.charAt(i), mp.getOrDefault(s.charAt(i), 0) + 1);
        }
        int res = 0;
        for (Character c : mp.keySet()) {
            if (mp.get(c) >= k) {
                res++;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(solution("aaabcd", 2) == 1);
        System.out.println(solution("aacbcbdefghijklmnopqrstuvwxyz", 1) == 26);
        System.out.println(solution("zzzzzzabc", 3) == 1);
    }
}