Map和Set

一 . Map和Set


    • 知识点

1.1 TreeMap

key必须是可比较的 || 设置Comparable<>

不可以放null

当插入同样的key,第二次key对应的value会 覆盖 第一次key对应的value

1.2 HashMap

可以放null

存储是根据底层的哈希函数找的对应的位置 (不是有序存储)

1.3 Set的底层是Map
1.4 哈希函数

直接定制法,除留余数法,平方取中法,随机数法,数字分析法,折中法

1.5 哈希冲突

闭散列(线性探测、二次探测)、开散列(链地址法)、多次散列


    • 习题

2.1 复制带随机指针的链表

https://leetcode.cn/problems/copy-list-with-random-pointer/submissions/

Map和Set_第1张图片
public Node copyRandomList(Node head) {
        Map map = new HashMap<>();
        // 1.第一次遍历
        Node cur = head;
        while (cur != null) {
            Node node = new Node(cur.val);
            map.put(cur,node);
            cur = cur.next;
        }
        // 2.第二次遍历
        cur = head;
        while (cur != null) {
            map.get(cur).next = map.get(cur.next);
            map.get(cur).random = map.get(cur.random);
            cur = cur.next;
        }
        return map.get(head);
    }

2.2 前k个高频单词

https://leetcode.cn/problems/top-k-frequent-words/description/

Map和Set_第2张图片

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] p = {"i","love","leetcode","i","love","coding"};
        List ret = topKFrequent(p,3);
        for (String s:ret){
            System.out.println(s);
        }
    }

    public static List topKFrequent(String[] words, int k) {
        HashMap map = new HashMap<>();
        // 1.统计次数
        for (int i = 0; i < words.length; i++) {
            if(map.containsKey(words[i])){
                int count = map.get(words[i])+1;
                map.put(words[i],count);
            } else{
                map.put(words[i],1);
            }
        }
        // 2.建立大小为 k 的小根堆
        PriorityQueue> min = new PriorityQueue<>(k,new Comparator>() {
            @Override
            public int compare(Map.Entry o1, Map.Entry o2) {
                // 频率相同的时候,变成大根堆, 不然list的时候顺序是错的
                if(o1.getValue().compareTo(o2.getValue()) == 0 ){
                    return o2.getKey().compareTo(o1.getKey());
                }
                return o1.getValue().compareTo(o2.getValue());
            }
        });

        // 3.遍历map,先放满k,在k+1个和堆顶比较
        for (Map.Entry entry : map.entrySet()){
            // 没满k个直接放进去
            if (min.size() < k) {
                min.add(entry);
            } else {
                // 满了
                Map.Entry top = min.peek();
                // entry的val比堆顶的 val 多 把堆顶的换成entry
                if (entry.getValue() > top.getValue()) {
                    min.poll();
                    min.add(entry);
                } else {
                    // 没堆顶多 但是val同
                    if(entry.getValue().compareTo(top.getValue()) == 0){
                        // 单词词典序排列
                        if(entry.getKey().compareTo(top.getKey()) < 0){
                            min.poll();
                            min.add(entry);
                        }
                    }
                }
            }

        }

        // 创建的是小根堆 但要求次数从高到低, 所以还要 reverse
        List ret = new ArrayList<>();
        for (int i = 0; i < k; i++) {
            ret.add(min.poll().getKey());
        }
        Collections.reverse(ret);
        return ret;
    }
}

你可能感兴趣的:(笔记,java,数据结构)