Map与Set高频面试算法题(只出现一次的数字,复制带随机指针的链表,宝石与石头,旧键盘,前k个高频单词)(Java实现)

简介: 给一个非空整数数组,只有一个元素出现了一次,剩余的元素都出现了两次,,请找出那个只出现一次的数字

LeetCode 136  只出现一次的数字

题目链接:只出现一次的数字


题目:

image.png

给一个非空整数数组,,只有一个元素出现了一次,剩余的元素都出现了两次,,请找出那个只出现一次的数字

方法一:


我们知道0异或任何数等于任何数,两个相等的数字异或为0,所以我们可以采用位运算,将所有的数依次异或,得到的数就是只出现一次的元素


代码展示:

class Solution {
    public int singleNumber(int[] nums) {
        int ret = 0;
        for(int i = 0;i < nums.length;i++){
            ret = ret ^ nums[i];
        }
        return ret;
    }
}


方法二:


我们可以往HashSet中依次存放元素,因为set中不能存放重复元素,所以当某个元素插入失败时,说明set中已有该元素,将该元素从set中删掉,最后set中剩余的元素就是只出现一次的元素


代码展示:

class Solution {
    public int singleNumber(int[] nums) {
        Set<Integer> s = new HashSet<>();
        for(int i = 0;i < nums.length;i++){
            if(!s.add(nums[i])){
                s.remove(nums[i]);
            }
        }
        Object[] array = s.toArray();
        return (int)array[0]; 
    }
}


LeetCode 138 复制带随机指针的链表

题目链接:复制带随机指针的链表


题目:

image.png

示例:

微信图片_20221030133116.png


方法:


可以使用HashMap,K为原链表的结点,V为与K相对应的新节点,先复制完结点,再链接新结点,新结点要链接next和random指针域 ,链接方法如下:


next链接的方法:map.get(cur).next = map.get(cur.next),cur为遍历原链表的结点

random链接的方法:map.get(cur).random = map.get(cur.random)

代码展示:

class Solution {
    public Node copyRandomList(Node head) {
        Node cur = head;
        Map<Node,Node> m = new HashMap<>();
        while(cur != null){
            Node newNode = new Node(cur.val);
            m.put(cur,newNode);
            cur = cur.next;
        }
        cur = head;
        while(cur != null){
            m.get(cur).next = m.get(cur.next);
            m.get(cur).random = m.get(cur.random);
            cur = cur.next;
        }
        return m.get(head);
    }
}

leetCode 771 宝石与石头

题目链接:宝石与石头


题目:

image.png

给你一个字符串 jewels 代表石头中宝石的类型,另有一个字符串 stones 代表你拥有的石头,stones 中每个字符代表了一种你拥有的石头的类型,求你拥有的石头中有多少是宝石。

方法:


我们可以借助HashSet,将宝石依次插入到set中,再依次遍历每个石头,判断宝石中是否包含该石头,如果包含则计数+1 ,返回最终计数


代码展示:

class Solution {
    public int numJewelsInStones(String jewels, String stones) {
        Set<Character> s = new HashSet<>();
        for(int i = 0;i < jewels.length();i++){
            s.add(jewels.charAt(i));
        }
        int count = 0;
        for(int i = 0;i < stones.length();i++){
            if(s.contains(stones.charAt(i))){
                count++;
            }
        }
        return count;
    }
}


旧键盘打字

题目链接:旧键盘


题目:


旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。


输入描述:

image.png



输出描述:

image.png



注意:输出要求英文字母大写,所以我们在输入时直接将字符串准换成大写,求转换大写后的坏键


方法:


我们可以将实际输出的字符保存到HashSet中,然后依次将应该输出的字符往set中插入,如果插入成功说明该键是坏键,直接输出该键


代码展示:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String s1 = sc.nextLine().toUpperCase();//应该输出的
        String s2 = sc.nextLine().toUpperCase();//实际输出的
        Set<Character> s = new HashSet<>();
        for(int i = 0;i < s2.length();i++){
            s.add(s2.charAt(i));
        }
        for(int i = 0;i < s1.length();i++){
            if(s.add(s1.charAt(i))){
                System.out.print(s1.charAt(i));
            }
        }
        System.out.println();
    }
}


LeetCode 692 前K个高频单词

题目链接:前K个高频单词


题目:


给一个单词列表words和一个整数k,返回前k个出现次数最多的单词


注意:返回的单词应该按单词的出现频率依次排序,如果不同的单词具有相同的出现频率,则按照字典序排序


示例:

image.png


方法:使用Top-k思想解决


先使用HashMap统计各个单词以及对应的出现次数

map中存放的是K-V键值对,将前k个键值对插入到优先级队列中,键值对对应的类型为Map.Entry<K,V>

往优先级队列中插入键值对时,需要创建比较器类,使Map.Entry<K,V>类型可以比较大小

插入前k个后,后面插入的N-K个键值对需要和堆顶元素比较,如果比堆顶元素大则删除堆顶元素,插入该键值对

插入完所有的键值对后,使用依次从优先级队列中删除后往List中添加

因为堆顶元素是最小的,而题目要求是按照频率高往低输出,故List中保存的顺序是与题目要求相反的

将List中的内容逆置后返回

分析如何创建比较器类及重写compare的方法 :


我们往优先级队列中插入的是键值对,类型为Map.Entry<String,Integer>,我们要的前K个高频,从次数上看,是小堆的方式,堆顶元素出现的次数是最低的,后面的N-k个元素与堆顶元素比较时,次数大于堆顶元素时替换堆顶元素,从字典序上看,是大堆的方式,当元素出现的次数相同时,堆顶元素应为字典序大的


代码展示:

//比较器类
class KVCmp implements Comparator<Map.Entry<String,Integer>>{
    public int compare(Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2){
        if(o1.getValue() > o2.getValue()){
            return 1;
        }
        if(o1.getValue()==o2.getValue() && o2.getKey().compareTo(o1.getKey())>0){
            return 1;
        }
        if(o1.getValue()==o2.getValue() && o2.getKey().compareTo(o1.getKey())==0){
            return 0;
        }
        return -1;
    }
}
class Solution {
    public List<String> topKFrequent(String[] words, int k) {
        Map<String,Integer> m = new HashMap<>();
        //统计次数
        for(int i = 0;i < words.length;i++){
            m.put(words[i],m.getOrDefault(words[i],0)+1);
        }
        //new比较器类
        KVCmp cmp = new KVCmp();
        //创建优先级队列,传入比较器
        PriorityQueue<Map.Entry<String,Integer>> p = new PriorityQueue<>(cmp);
        Set<Map.Entry<String,Integer>> s = m.entrySet();
        int i = 0;
        //将键值对插入到优先级队列中
        for(Map.Entry<String,Integer> kv : s){
            //前k个直接插入
            if(i < k){
                p.offer(kv);
                i++;
            }else {
                //后面的经过比较后再插入
                if(cmp.compare(kv,p.peek()) > 0){
                    p.poll();
                    p.offer(kv);
                }
            }
        }
        List<String> ret = new ArrayList<>();
        //往list中插入键值对的V,也就是单词
        for(i = 0;i < k;i++){
            ret.add(p.poll().getKey());
        }
        Collections.reverse(ret);//逆置
        return ret;
    }
    }





相关文章
|
10月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
5月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
1121 35
|
10月前
|
存储 缓存 监控
上网行为监控系统剖析:基于 Java LinkedHashMap 算法的时间序列追踪机制探究
数字化办公蓬勃发展的背景下,上网行为监控系统已成为企业维护信息安全、提升工作效能的关键手段。该系统需实时记录并深入分析员工的网络访问行为,如何高效存储和管理这些处于动态变化中的数据,便成为亟待解决的核心问题。Java 语言中的LinkedHashMap数据结构,凭借其独有的有序性特征以及可灵活配置的淘汰策略,为上网行为监控系统提供了一种兼顾性能与功能需求的数据管理方案。本文将对LinkedHashMap在上网行为监控系统中的应用原理、实现路径及其应用价值展开深入探究。
233 3
|
5月前
|
存储 算法 搜索推荐
《数据之美》:Java数据结构与算法精要
本系列深入探讨数据结构与算法的核心原理及Java实现,涵盖线性与非线性结构、常用算法分类、复杂度分析及集合框架应用,助你提升程序效率,掌握编程底层逻辑。
|
10月前
|
人工智能 算法 NoSQL
LRU算法的Java实现
LRU(Least Recently Used)算法用于淘汰最近最少使用的数据,常应用于内存管理策略中。在Redis中,通过`maxmemory-policy`配置实现不同淘汰策略,如`allkeys-lru`和`volatile-lru`等,采用采样方式近似LRU以优化性能。Java中可通过`LinkedHashMap`轻松实现LRUCache,利用其`accessOrder`特性和`removeEldestEntry`方法完成缓存淘汰逻辑,代码简洁高效。
466 0
|
5月前
|
存储 算法
算法入门:专题一:双指针(有效三角形的个数)
给定一个数组,找出能组成三角形的三元组个数。利用“两边之和大于第三边”的性质,先排序,再用双指针优化。固定最大边,左右指针从区间两端向内移动,若两短边之和大于最长边,则中间所有组合均有效,时间复杂度由暴力的O(n³)降至O(n²)。
|
5月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
9月前
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
603 58
|
8月前
|
机器学习/深度学习 算法 Java
Java实现林火蔓延路径算法
记录正在进行的森林防火项目中林火蔓延功能,本篇文章可以较好的实现森林防火蔓延,但还存在很多不足,如:很多参数只能使用默认值,所以蔓延范围仅供参考。(如果底层设备获取的数据充足,那当我没说)。注:因林火蔓延涉及因素太多,如静可燃物载量、矿质阻尼系数等存在估值,所以得出的结果仅供参考。
308 5
|
8月前
|
存储 负载均衡 算法
我们来说一说 Java 的一致性 Hash 算法
我是小假 期待与你的下一次相遇 ~
426 1