0
点赞
收藏
分享

微信扫一扫

HashMap和HashSet相关oj题

祈澈菇凉 2022-04-04 阅读 30

OJ题地址:
136. 只出现一次的数字
138. 复制带随机指针的链表
771. 宝石与石头
牛客:旧键盘打字
692. 前K个高频单词

目录

只出现一次的数字

复制带随机指针的链表

宝石与石头

旧键盘打字

前k个高频单词


只出现一次的数字

思路:
1.利用HashSet,遍历数组,如果HashSet中未包含该元素则进行添加,若包含该元素就进行移除
2.利用异或运算(^),相同为0,不同为1,这样就找出只出现一次的元素

思路2的实现:

//思路2:利用异或^,时间复杂度O(N),空间复杂度O(1)
class Solution {
    public int singleNumber(int[] nums) {
        int temp = 0;
        for(int num : nums){
            temp ^= num;
        }
        return temp;
    }
}

思路1的实现:

//思路1:相同add,不同remove,迭代器输出
class Solution {
    public int singleNumber(int[] nums) {
        HashSet<Integer> set = new HashSet<>();
        for(int num : nums){
            if(!set.contains(num)){
                set.add(num);
            }
            else
            {
                set.remove(num);
            }
        }
        Iterator it = set.iterator();
        return (int)it.next();
    }
}

复制带随机指针的链表

思路:利用HashMap<已有节点的地址,新生成节点的地址>,接着利用已有节点的指向来操作新节点。

class Solution {
    public Node copyRandomList(Node head) {
        //利用HashMap<已有节点的地址,生成的新节点的地址>
        HashMap<Node,Node> hashMap = new HashMap<>();
        Node cur = head;
        //设置每个已有节点和新节点之间key-value关系
        while(cur != null){
            Node temp = new Node(cur.val);//val域
            hashMap.put(cur,temp);//设置key-value
            cur = cur.next; //cur继续向后走
        }
        cur = head;//指向首节点
        while(cur != null){
            //进行连接
            hashMap.get(cur).next = hashMap.get(cur.next);
            hashMap.get(cur).random = hashMap.get(cur.random);
            cur = cur.next;
        }
        //返回新链表的首位置
        return hashMap.get(head);
    }
}

宝石与石头

思路:利用HashSet存储宝石的种类,遍历每一个石头去寻找宝石,如果找到宝石,那宝石的个数加1

class Solution {
    public int numJewelsInStones(String jewels, String stones) {
        Set<Character> set = new HashSet<>();
        //存储宝石
        for(char ch : jewels.toCharArray()){
            set.add(ch);
        }
        int count = 0;
        //在石头中找宝石
        for(char ch : stones.toCharArray()){
            if(set.contains(ch)){
                count++;
            }
        }
        return count;
    }
}

旧键盘打字

思路:利用HashSet存储真实(real)文字的每一个字符,接着去遍历应该(ideal)输入的文字,如果Set中不包含该字符,则进行输出(但是该字符可能会有多个,会重复输出,因此需要去判断

import java.util.*;
public class Main{
    public static void func(String ideal , String real){
        //set1存储真实的文字字符
        Set<Character> set1 = new HashSet<>();
        for(char ch : real.toUpperCase().toCharArray()){
            set1.add(ch);
        }
        
        //set2存储坏了的键盘字符
        Set<Character> set2 = new HashSet<>();        
        for(char ch : ideal.toUpperCase().toCharArray()){
            //ideal中可能会有重复的,重复输出
            if(!set1.contains(ch)&&!set2.contains(ch)){
                System.out.print(ch);
                set2.add(ch);
            }
            //为啥不直接拿set2去接收去重?
            //是因为全部接收输出顺序就会发生改变
        }
    }
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        //应该输入的文字(ideal)
        String ideal = scanner.nextLine();
        //现实输入的文字
        String real = scanner.nextLine();
        func(ideal,real);
    }
}

前k个高频单词

思路:首先利用HashMap<String,Integer>记录每个字符串出现的次数,接着再利用优先队列建立k小堆,最终逆序输出结果。

class Solution {
       public List<String> topKFrequent(String[] words, int k) {

        //1.利用HashMap去统计
        HashMap<String,Integer> hashMap = new HashMap<>();
        for(String str : words){
            if(!hashMap.containsKey(str)){
                hashMap.put(str,1);
            }
            else{
                hashMap.put(str,hashMap.get(str)+1);
            }
        }

        //2.利用优先队列进行排序       
        //出现问题了:此时优先队列无法比较(这是个Entry类),利用匿名类实现compre()
        PriorityQueue<Map.Entry<String,Integer>> priorityQueue =
                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() - o2.getValue() == 0){
                            return o2.getKey().compareTo(o1.getKey());
                        }
                        //==的情况需要判断字典序
                        return o1.getValue() - o2.getValue();
                    }
                });

        //hashMap.entrySet()的返回类型是Set<Map.Entry<K, V>>
        for(Map.Entry<String,Integer> entry : hashMap.entrySet()){
            //建立小堆
            if(priorityQueue.size() < k){
                priorityQueue.offer(entry);
            }
            else{
                //num存放的是堆顶
                Map.Entry<String,Integer>  num = priorityQueue.peek();
                //比较元素大小
                if(num.getValue() < entry.getValue()){
                    priorityQueue.poll();
                    priorityQueue.offer(entry);
                }//比较字典序
                else if(num.getValue() == entry.getValue()){
                    if(num.getKey().compareTo(entry.getKey()) > 0){
                        priorityQueue.poll();
                        priorityQueue.offer(entry);
                    }
                }
            }
        }
        // 3.放入ArrayList里面,然后逆序就结束了
        ArrayList<String> arrayList = new ArrayList<>();
        while(priorityQueue.size() != 0){
            Map.Entry<String,Integer> entry = priorityQueue.poll();
            arrayList.add(entry.getKey());//从小到大排序了
        }
        //arrayList里面没有逆序方法,需要用Collections(工具类)类中的reverse()方法
        Collections.reverse(arrayList);
        return arrayList;
    }
}
举报

相关推荐

0 条评论