1. 程式人生 > >LeetCode - 381. Insert Delete GetRandom O(1) - Duplicates allowed(允許重複)

LeetCode - 381. Insert Delete GetRandom O(1) - Duplicates allowed(允許重複)

LeetCode - 381. Insert Delete GetRandom O(1) - Duplicates allowed(允許重複)

題目連結

題目

在這裡插入圖片描述

解析

做這題之前先做LeetCode - 380

這一題加上了可以加入重複的元素,題目就變得複雜了一些。

  • 大體思路還是使用HashMap + ArrayList,只不過MapHashMap<Integer, ArrayList<Integer>>的形式,而List則是ArrayList<int[]>形式;
  • 其中Mapkey存的是值val,而對應的value
    存的是一個下標的集合,即List中值是val的下標的集合;
  • List中每個位置也要存兩個資訊,一個是值val(陣列[0]位置),另一個存這個值valmap中的下標集合中的位置(陣列[1]位置);

下圖展示了儲存

容器中有261829

在這裡插入圖片描述

新增元素很簡單,維護maplist即可。

例如新增元素6:
在這裡插入圖片描述

刪除元素思想也是和最後一個元素交換位置,不過也要維護相應的資訊即可。

刪除元素9:
在這裡插入圖片描述

class RandomizedCollection {

    private HashMap<Integer, ArrayList<Integer>
>valIndexsMap; private ArrayList<int[]> vals; // store the position in the map's value public RandomizedCollection() { valIndexsMap = new HashMap<>(); vals = new ArrayList<>(); } public boolean insert(int val) { boolean contain = !valIndexsMap.
containsKey(val); // ArrayList<Integer>indexs = valIndexsMap.get(val); // if(indexs == null){ // indexs = new ArrayList<>(); // } // indexs.add(vals.size()); ArrayList<Integer>indexs = valIndexsMap.computeIfAbsent(val, k -> new ArrayList<>()); indexs.add(vals.size()); vals.add(new int[]{val, indexs.size()-1}); return contain; } public boolean remove(int val) { if(!valIndexsMap.containsKey(val)) return false; ArrayList<Integer>indexs = valIndexsMap.get(val); int removeIndex = indexs.get(indexs.size() - 1); indexs.remove(indexs.size()-1); if(indexs.isEmpty()) valIndexsMap.remove(val); if(removeIndex < vals.size()-1){ // exchange // 將最後一個元素放在 removeIndex位置 vals.get(removeIndex)[0] = vals.get(vals.size()-1)[0]; vals.get(removeIndex)[1] = vals.get(vals.size()-1)[1]; valIndexsMap.get(vals.get(removeIndex)[0]).set(vals.get(removeIndex)[1], removeIndex); } vals.remove(vals.size()-1); return true; } public int getRandom() { return vals.get((int)(Math.random() * vals.size()))[0]; } }

這裡注意Java8computeIfAbsent用法:

類似下面的用法

Object key = map.get("key");
if (key == null) {
    key = new Object();
    map.put("key", key);
}
//上面的操作可以簡化為一行,若key對應的value為空,會將第二個引數的返回值存入並返回
Object key2 = map.computeIfAbsent("key", k -> new Object());

具體用法舉例:

import java.util.*;

public class Test {

    public static void main(String[] args){
        Map<String, List<String>> map = new HashMap<>();
        List<String> list;

        list = map.get("list-1");
        if (list == null) {
            list = new LinkedList<>();
            map.put("list-1", list);
        }
        list.add("one");
        //使用 computeIfAbsent 可以這樣寫
        list = map.computeIfAbsent("list-1", k -> new ArrayList<>());
        list.add("one");
    }
}