首页 > 试题广场 >

关联容器map设计

[编程题]关联容器map设计
  • 热度指数:759 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 48M,其他语言96M
  • 算法知识视频讲解
关联容器map保存<key, value>数据,能通过key快速存储或查找记录请设计一个map,能够满足以下要求:
1. map的容量size是一个固定值N,即map最多保存N个<key, value>记录
2. map insert一个<key, value>前,首先判断这个key是否已经在map中存在:
   1) 如果存在:记这个已存在的记录为<key, old_value>,若old_value<value,则old_value更新为value;否则,不做更新
   2) 如果不存在:
       若size<N,则执行map的insert,保存这个<key, value>,且size+=1;
       若size==N,先淘汰掉一个更新时间最早的记录,再执行map的insert,保存这个<key, value>,size保持为N不变。
说明:记录的更新时间默认为其被insert进map的时间,之后的某一时刻T,如果这个记录的value被更新,那么,该记录的更新时间就变为T。

输入描述:
第一行是map的最大size N(N<=200000),之后每一行都为"Key Value",其中Key为一个字符串(长度<16),Value为无符号整数(unsigned int),Key和Value之间用空格分隔。


输出描述:
输出为map insert的过程中被淘汰掉的记录(不输出value被更新的记录),每行为"Key Value", 和输入文件的"Key Value"格式相同。
示例1

输入

2
10_123_50_A0 1566918054
10_123_50_A1 1566918054
10_123_50_A1 1566918055
10_123_50_A3 1566918055
10_123_50_A4 1566918056

输出

10_123_50_A0 1566918054
10_123_50_A1 1566918055

备注:
1.程序首先从标准输入读入第1行,取得map的size大小N,并以N为参数初始化或者构造map;
2.然后再逐行读取标准输入,依次insert进map,在insert过程中,如果发生淘汰map中已有记录的情况,就把这个被淘汰的记录输出到标准输出。
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = Integer.parseInt(in.nextLine());
        int curSize = 0;
        LinkedHashMap<String, Long> map = new LinkedHashMap<>();
        while(in.hasNext()){
            String curInput = in.nextLine();
            String[] stringArray = curInput.split(" ");
            String curKey = stringArray[0];
            long curValue = Long.parseLong(stringArray[1]);
            if(map.containsKey(curKey)){
                if(map.get(curKey) < curValue){
                    map.remove(curKey);
                    map.put(curKey, curValue);
                }
            }else{
                if(curSize < n){
                    curSize++;
                }else{
                    for(String s : map.keySet()){
                        System.out.println(s+" "+map.get(s));
                        map.remove(s);
                        break;
                    }
                }
                map.put(curKey, curValue);
            }
        }
    }
}


发表于 2020-08-01 14:58:11 回复(0)
import java.util.*;

/**
 * LRU 算法 LinkHashMap 或者 hashMap + Queue
 */

public class Main {

     public static void main(String[] args) {


        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        sc.nextLine();

        //记录数据
        LinkedHashMap<String , Long> LRUhashMap = new LinkedHashMap<>();

        while (sc.hasNext()){

            //输入k - v
            String[] insert = sc.nextLine().split(" ");
            String key = insert[0];
            String value = insert[1];

            if(LRUhashMap.containsKey(key)){
                if(LRUhashMap.get(key)-Long.valueOf(value) < 0){
                    LRUhashMap.remove(key);
                    LRUhashMap.put(key,Long.valueOf(value));
                }
            }else{
                if(LRUhashMap.size() < N){ //空间剩余
                    LRUhashMap.put(key,Long.valueOf(value));
                }else if(LRUhashMap.size() == N){ //空间不足
                    for(String s : LRUhashMap.keySet()){
                        System.out.println(s + " " + LRUhashMap.get(s));
                        LRUhashMap.remove(s);
                        LRUhashMap.put(key,Long.valueOf(value));
                        break;
                    }
                }
            }
        }
    }
}

编辑于 2020-08-12 16:24:50 回复(2)
C++可以利用unordered_map和list实现LRU
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n=0;
    cin>>n;
    string s;
    unsigned int x;
    unordered_map<string,list<pair<string,unsigned int>>::iterator> mp;
    list<pair<string,unsigned int>> l;
    while(cin>>s>>x)
    {
        auto mpIt=mp.find(s);
        if(mpIt!=mp.end())
        {
            auto lIt = mpIt->second;
            unsigned int old = lIt->second;
            if(old<x)
            {
                l.erase(lIt);
                l.push_front({s,x});
                mp[s]=l.begin();
            }
        }
        else
        {
            if(l.size()>=n)
            {
                cout<<l.back().first<<' '<<l.back().second<<endl;
                mp.erase(l.back().first);
                l.pop_back();
            }
            l.push_front({s,x});
            mp[s]=l.begin();
        }
    }
    return 0;
}
发表于 2020-09-25 18:50:42 回复(0)
感觉这题有问题。   原题“先淘汰掉一个更新时间最早的记录
以下输出中应该保留后面两个,而不是前面两个

您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为0.00%

用例:
2
10.123.50.100 1
10.123.50.101 2
10.123.50.102 3
10.123.50.103 4

对应输出应该为:

10.123.50.100 1
10.123.50.101 2

你的输出为:

10.123.50.102 3
10.123.50.103 4

------------------------------ 以下是代码
importjava.util.*;
 
publicclassMain{
     
    publicstaticvoidmain(String args[]){
        Map<String,String> map =null;
        intmapLength =0;
        Scanner in =newScanner(System.in); //注意 这里不是通过静态获取或工厂获取,而是通过生产新的实例,在构造方法时绑定系统输入
        in.useDelimiter("\n"); //Scanner 默认碰到折行和空格next, 这里指定只有折行时next  window 环境下为\r
         
        while(in.hasNext()){
            String s = in.next();
            if(mapLength ==0){
                mapLength = Integer.parseInt(s);
                map =newLinkedHashMap<String,String>(mapLength);
                continue;
            }
             
            String[] arr = s.split(" ");
            String key = arr[0];
            String value = arr[1];
             
            //以链表的形式来维护数据的先后顺序, 排在链表后面的则更新时间越靠后
             
            if(map.size() ==0){
                map.put(key,value);
            }elseif(map.containsKey(key)){//发现已存在
                if(Integer.parseInt(key) > Integer.parseInt(map.get(key))){ //若新值大于老值,则更新处理, 同时更新时间顺序对应的链表调整
                    map.remove(key); //通过先删后插,保证链表更新顺序有序
                    map.put(key,value);
                }
            }elseif(map.size() == mapLength){ //发现链表已满,且不是重复值,删除掉最早的一个
                //这里移除掉第一个,即移除更新时间最早的那个
                for(String keys : map.keySet()){
                    map.remove(keys);
                    break;
                }
                 
                map.put(key,value);
            }elseif(map.size() < mapLength){
                map.put(key,value);
            }
             
        }
         
        //输出
        for(String key : map.keySet()){
            System.out.println(key+" "+map.get(key));
        }
         
         
    }
}

发表于 2020-12-15 15:49:04 回复(0)
c++为啥一直80%段错误,实在是感觉没毛病,太离谱了这题
#include <bits/stdc++.h>

using namespace std;
#define ll long long int
#define angel 0x3f3f3f3f
#define maxn 400050
#define pb push_back

int cnt,in[maxn];
map<string,unsigned int>Map;
string change[maxn];
map<string,int>inverse;
queue<int>q;

int main()
{
    int n;
    scanf("%d",&n);
    string x;
    unsigned int y;
    int sum=0;
    cnt=0;
    while(cin>>x>>y)
    {
        int dir=inverse[x];
        if(in[dir]==0)
        {
            if(sum<n)
            {
                Map[x]=y;
                change[++cnt]=x;
                inverse[x]=cnt;
                q.push(cnt);
                in[cnt]=1;
                sum++;
            }
            else
            {
                int now;
                while(!q.empty())
                {
                    now=q.front();
                    if(in[now]==1)
                        break;
                    q.pop();
                }
                in[now]=0;
                string tmp=change[now];
                cout<<tmp<<" "<<Map[tmp]<<endl;
                Map.erase(tmp);
                Map[x]=y;
                change[++cnt]=x;
                inverse[x]=cnt;
                q.push(cnt);
                in[cnt]=1;
            }
        }
        else
        {
            in[dir]=0;
            change[++cnt]=x;
            inverse[x]=cnt;
            in[cnt]=1;
            q.push(cnt);
            Map[x]=y;
        }
    }
    return 0;
}


发表于 2020-09-10 20:33:53 回复(0)
LRU 实现
import java.util.*;
public class Main{
    /*
     LRU 实现
     容量不足则将最少使用的剔除掉
    */
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int capa = sc.nextInt();
        DList lru = new DList(capa);
        while(sc.hasNext()){
            String key = sc.next();
            long val = sc.nextLong();
            lru.put(key, val);
        }
    }
}
class DList{
    int count;
    int capa;
    Map<String, Node> map;
    Node head;
    Node tail;
    public DList(int capa){
        map = new HashMap<>();
        count = 0;
        this.capa = capa;
        head = new Node("", -1);
        tail = new Node("", -1);
        head.next = tail;
        tail.pre = head;
    }

    public void put(String key, long val){
        Node node = map.get(key);
        if(node == null){
            node = new Node(key, val);
            map.put(key, node);
            Node reNode = addNewNode(node);
            if(reNode != null){
                map.remove(reNode.key);
                System.out.println(reNode.key + " " + reNode.val);
            }
            return;
        }
        if(node.val < val){
            node.val = val;
            moveToHead(node);
        }
    }

    public Node addNewNode(Node node){
        moveToHead(node);
        if(count == capa){
            return removeTail();
        }
        count++;
        return null;
    }

    public void moveToHead(Node node){
        if(node.pre != null){
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
        node.next = head.next;
        node.pre = head;
        head.next.pre = node;
        head.next = node;
    }

    private Node removeTail(){
        if(count == 0){
            return null;
        }
        Node temp = tail.pre;
        temp.pre.next = tail;
        tail.pre = temp.pre;
        temp.pre = null;
        temp.next = null;
        return temp;
    }
}
class Node{
    String key;
    long val;
    Node pre;
    Node next;
    public Node(String key, long val){
        this.key = key;
        this.val = val;
    }
}

发表于 2020-08-11 16:45:29 回复(0)
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        LRUMap<String, Long> map = new LRUMap<>(n, 0.75f, true);
        while (sc.hasNext()) {
            String key = sc.next();
            long value = sc.nextLong();
            if (map.containsKey(key)) {
                if (value > map.get(key)) {
                    map.put(key, value);
                }
            } else {
                map.put(key, value);
            }
        }
    }
}


class LRUMap<String, Long> extends LinkedHashMap<String, Long> {
    int max;

    public LRUMap(int initialCapacity, float loadFactor, boolean accessOrder) {
        super(initialCapacity, loadFactor, accessOrder);
        max = initialCapacity;
    }

    protected boolean removeEldestEntry(Map.Entry<String, Long> eldest) {
        if (size() > max) {
            System.out.println(eldest.getKey() + " " + eldest.getValue());
        }
        return size() > max;
    }
}

----来源zhx2020已提交的代码
发表于 2020-07-31 16:52:21 回复(0)