【数据结构】Map和Set

目录

一、Map

1.1 Map常用方法

1.2 Map注意事项

1.3 Map的遍历

二、Set

2.1 Set常用方法

2.2 Set注意事项

2.3 Set的遍历

三、题目练习

3.1 从给定的数据中,找出第一个重复的数据

3.2 去除给定的数据中重复的数据

3.3 统计重复的数据出现的次数

3.4 只出现一次的数据

3.5 复制带随机指针的链表

3.6 宝石与石头

3.7 坏键盘打字

3.8 前K个高频单词


一、Map

1.1 Map常用方法

Map是一个接口类,没有继承Collection。存储的是键值对,键一定是唯一的,不能重复。

方法说明
V get(Object key)返回key对应的value
V getOrDefault(Object key, V defaultValue)返回key对应的value, key 不存在,返回默认值
V put(K key, V value)设置key对应的value
V remove(Object key)删除key对应的映射关系
Set<K> keySet()返回所有key的不重复集合
Collection<V> values()返回所有value的可重复集合
Set<Map.Entry<K, V>> entrySet()返回所有的key-value映射关系
boolean containsKey(Object key)判断是否包含key
boolean containsValue(Object value)判断是否包含value

1.2 Map注意事项

  • Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
  • Map中存放键值对的Key是唯一的, value是可以重复的
  • Map中的Key可以全部分离出来,存储到Set中来进行访问(因为Key不能重复)。
  • Map中的value可以全部分离出来,存储在Collection的任何-个子集合中(value可能有重复)。
  • Map中键值对的Key不能直接修改, value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行重新插入
  • key可以为null。value也可以为null

1.3 Map的遍历

借助Set<Map.Entry<K, V>> entrySet()

方法说明
K getKey()返回entry中的key
V getValue()返回entry中的value
V setValue(V value)将键值对中的value替换为指定value
        Set<Map.Entry<Integer,Integer>> entrySet = hashmap.entrySet();
        for(Map.Entry<Integer,Integer> entry : entrySet){
            int a = entry.getKey();
            System.out.println(entry);
        }

二、Set

2.1 Set常用方法

方法说明
boolean add(E e)添加元素,但重复元素不会被添加成功
void clear()清空集合
boolean contains(Object 0)判断o是否在集合中
Iterator<E> iterator()返回迭代器
boolean remove(Object o) .删除集合中的0
int size()返回set中元素的个数
boolean isEmpty()检测set是否为空,空返回true, 否则返回false
Object[] toArray() 将set中的元素转换为数组返回
boolean containsAll(Collection<?> c)集合c中的元素是否在set中全部存在,是返回true, 否则返回true
boolean addAl(Collection<? extends将集合c中的元素添加到set中,可以达到去重的效果

2.2 Set注意事项

  • Set是继承自Collection的一 个接口类
  • Set中只存储了key, 并组要求key一定要唯一
  • Set最大的功能就是对集合中的元素进行去重
  • Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  • 插入的值可以为null

2.3 Set的遍历

    public static void main(String[] args) {
        HashSet<Integer> set = new HashSet<>();
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(4);
        Iterator<Integer> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

三、题目练习

3.1 从给定的数据中,找出第一个重复的数据

    public int func(int[] nums){
        Set<Integer> hashSet = new HashSet<>();
        for(int i=0;i<nums.length;i++){
            if(hashSet.contains(nums[i])){
                return nums[i];
            }
            hashSet.add(nums[i]);
        }
        return -1;
    }

3.2 去除给定的数据中重复的数据

    public void func2(int[] nums){
        Set<Integer> hashSet = new HashSet<>();
        for(int i=0;i<nums.length;i++){
            hashSet.add(nums[i]);
        }
        System.out.println(hashSet);
    }

3.3 统计重复的数据出现的次数

    public void fun3(int[] nums){
        Map<Integer,Integer> hashmap = new HashMap<>();
   
        for (int i = 0; i < nums.length; i++) {
            if(hashmap.containsKey(nums[i])){
                // 如果在hashmap中存在,就更新次数
                int count = hashmap.get(nums[i]);
                count = count+1;
                hashmap.put(nums[i],count);
            }else{
                // 不存在,就放入hashmap中,值是1
                hashmap.put(nums[i],1);
            }
        }
        Set<Map.Entry<Integer,Integer>> entrySet = hashmap.entrySet();
        // 遍历hashmap
        for(Map.Entry<Integer,Integer> entry : entrySet){
            int a = entry.getKey();
            System.out.println(entry);
        }
    }

3.4 只出现一次的数据

力扣

class Solution {
    public int singleNumber(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for(int i=0;i<nums.length;i++){
            // 如果已经出现,就从set中移除该元素
            if(set.contains(nums[i])){
                set.remove(nums[i]);
            }else{
                set.add(nums[i]);
            }
        }
        // set剩下的元素就是只出现一次的元素
        Iterator<Integer> it = set.iterator();
        
        while(it.hasNext()){
            return it.next();
        }
        return -1;
    }
}

3.5 复制带随机指针的链表

力扣

class Solution {
    public Node copyRandomList(Node head) {
        Map<Node,Node> map = new HashMap<>();
        Node cur = head;
        while(cur != null){
            // 将新节点和旧节点的对应关系存储到map中
            Node node = new Node(cur.val);
            map.put(cur,node);
            cur = cur.next;
        }
        cur = head;
        while(cur != null){
            // 得到新节点
            // 从map中得到新节点和旧节点 根据旧节点的next和random属性修改新节点的属性
            Node node = map.get(cur);
            node.next = map.get(cur.next);
            node.random = map.get(cur.random);
            cur = cur.next;
        }
        return map.get(head);
    }
}

3.6 宝石与石头

力扣

class Solution {
    public int numJewelsInStones(String jewels, String stones) {
        Set<Character> set = new HashSet<>();
        for(int i =0;i<jewels.length();i++){
            char ch = jewels.charAt(i);
            // 对jewels中的字符进行去重
            if(!set.contains(ch)){
                set.add(ch);
            }
        }
        int sum = 0;
        for(int i =0;i<stones.length();i++){
            char ch = stones.charAt(i);
            // stones中的字符如果在set中出现,sum++
            if(set.contains(ch)){
                sum++;
            }
        }
        return sum;
    }
}

3.7 坏键盘打字

旧键盘 (20)__牛客网

import java.util.*;
public class Main{
    public static void func(String str1,String str2){
        // 先将字符串转成大写的字符数组
        char[] ch1 = str1.toUpperCase().toCharArray();
        char[] ch2 = str2.toUpperCase().toCharArray();
        // ch1是正常的输入
        // ch2是实际的输入
        Set<Character> set1 = new HashSet<>();
        for(char ch:ch2){
            // 统计ch2中出现的不重复的字符 ,这些字符都是好的按键
            if(!set1.contains(ch)){
                set1.add(ch);
            }
        }
        Set<Character> set2 = new HashSet<>();
        for(char ch:ch1){
            // 如果字符没有在好的按键集合里,就加到set2中,加之前要判断是否已经存在,如果存在,就不用再add了
            if(!set1.contains(ch)){
                if(!set2.contains(ch)){
                    set2.add(ch);
                    System.out.print(ch);
                 
                }
            }
        }
    }
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        String str1 = scanner.nextLine();
        String str2 = scanner.nextLine();
        func(str1,str2);
    }
}

3.8 前K个高频单词

力扣

  • 先统计每个单词的出现次数
  • 建立一个小根堆,重写compare方法。存在两种情况,第一种是两个词的出现次数一样,比较单词的首字母的AscII码值。第二种情况是两个词的出现次数不一样
  • topK思想。
class Solution {
    public List<String> topKFrequent(String[] words, int k) {
        int c = k;
        HashMap<String,Integer> hashmap = new HashMap<>();
        // 统计每个单词的出现次数
        for(String str:words){
            if(!hashmap.containsKey(str)){
                hashmap.put(str,1);
            }else{
                int count = hashmap.get(str);
                hashmap.put(str,count+1);
            }
        }
        // 建立一个小根堆,重写compare方法
        PriorityQueue<Map.Entry<String,Integer>> queue = new PriorityQueue<>(new Comparator<Map.Entry<String,Integer>>(){
            @Override
            public int compare(Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2){
                if(o1.getValue().equals(o2.getValue())){
                    return o2.getKey().compareTo(o1.getKey());
                }
                return o1.getValue()-o2.getValue();
            }
        });
        // topK的思想
        for(Map.Entry<String,Integer> entry : hashmap.entrySet()){
            if(k >0){
                queue.offer(entry);
                k--;
            }else{
                Map.Entry<String,Integer> peek = queue.peek();
                int tmp = peek.getValue().compareTo(entry.getValue());
                if(tmp < 0){
                    queue.poll();
                    queue.offer(entry);
                }else if(tmp == 0){
                    if(peek.getKey().compareTo(entry.getKey()) >0 ){
                        queue.poll();
                        queue.offer(entry);                       
                    }
                }
            }
        }
        List<String> result = new ArrayList<>();
        for(int i=0;i<c;i++){
            result.add(queue.poll().getKey());
        }
        Collections.reverse(result);
        return result;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘减减

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值