数据结构:Map set - 习题(三)

news/2025/2/25 21:51:28

一、只出现一次的数字

题目链接https://leetcode.cn/problems/single-number/description/

描述:

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

解析:我们创建一个set,如果set中没有这个元素我们就将这个元素放入set中,如果set中存在这个元素我们就将这个元素在set中移除。最后我们set中的元素就是只出现一次的元素,因此我们可以在遍历一遍数组查看是哪个元素。

java">class Solution {
    public int singleNumber(int[] nums) {
       Set<Integer> set = new HashSet<>();
       for(int i = 0;i < nums.length;i++){
        if(!set.contains(nums[i])){
            set.add(nums[i]);
        }else{
            set.remove(nums[i]);
        }
       }

       for(int i = 0;i < nums.length;i++){
        if(set.contains(nums[i])){
            return nums[i];
        }
       }
       return -1;
    }
}

 但是上述方法并不是最最快的解法,我们最快的解法是利用位运算的方式,我们利用异或的方式来解决:我们依次得到所有的元素进行异或,我们创建一个变量n=0,而0^1 = 1,当我们遇到相同的元素时 1^1 = 0,因此我们遇到没有重复的元素时,经过异或就能得到这个只出现一次的元素:1^1^2=2

java">class Solution {
    public int singleNumber(int[] nums) {
        int n = 0;
        for(int num : nums){
            n^=num;
        }
        return n;
    }
}

 二、随机链表的复制

习题链接https://leetcode.cn/problems/copy-list-with-random-pointer/description/

描述:

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。

 这道题,我们想要直接拷贝我们发现这其实时不可以,因为我们发现当我们拷贝完后发现,我们的next和random所指向的就不是我们拷贝完后的结点了。同时我们也可以发现我们的random的指向的下一个结点是跳跃的指向,自己本身或者指向的是空。

既让是这样,我们可以利用我们的Map,Map里存放的是<Node,Node>,我们根据我们的链表将拷贝后结点的val值存放到新的结点中,然后我们在根据我们拷贝到Map的结点值将对应的next和random拷贝到新的结点当中 

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

 三、宝石与石头

习题链接https://leetcode.cn/problems/jewels-and-stones/description/

描述:

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

字母区分大小写,因此 "a" 和 "A" 是不同类型的石头。

解析:我们可以利用set,把宝石中的每个字符放到set中,然后遍历石头的所有字符,每遍历一个字符就到set中查看是否存在,如果存在就让count++; 

java">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);
            set.add(ch);
        }
        int count = 0;
        for(int i = 0;i < stones.length();i++){
            char ch = stones.charAt(i);
            if(set.contains(ch)){
                count++;
            }
        }
        return count;
    }
}

四、旧键盘 

习题链接https://www.nowcoder.com/questionTerminal/f88dafac00c8431fa363cd85a37c2d5e

描述:

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


解析:我们知道Set是天然去重的因此我们可以将错误键盘打印出来的结果放到set1中,这样set1中的结果就是我们好的键,之后我们在遍历我们原本要打印的结果,如果set1中不存在并且set2中不存在就将这个字符打印并存入set2中

java">import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String str1 = in.nextLine();
            String str2 = in.nextLine();
            fun(str1,str2);
        }
    }

    public static void fun(String str1,String str2){
        Set<Character> set1 = new HashSet<>();
        for(char ch : str2.toUpperCase().toCharArray()){
            set1.add(ch);
        }
        Set<Character> set2 = new HashSet<>();
        for(char ch : str1.toUpperCase().toCharArray()){
            if(!set1.contains(ch) && !set2.contains(ch)){
                System.out.print(ch);
                set2.add(ch);
            }
        }

    }
}

好了,今天的讲解就到这里了,还请大家多多关注,我们下一篇见! 


http://www.niftyadmin.cn/n/5865973.html

相关文章

kotlin 知识点一 变量和函数

在Kotlin中定义变量的方式和Java 区别很大&#xff0c;在Java 中如果想要定义一个变 量&#xff0c;需要在变量前面声明这个变量的类型&#xff0c;比如说int a表示a是一个整型变量&#xff0c;String b表 示b是一个字符串变量。而Kotlin中定义一个变量&#xff0c;只允许在变量…

目标检测之FAST RCNN论文简读

前言 FAST RCNN是RCNN的改进版&#xff0c;针对RCNN的一些痛点进行了修改。 FAST RCNN 论文传送门 摘要 This paper proposes a Fast Region-based Convolutional Network method (Fast R-CNN) for object detection. Fast R-CNN builds on previous work to efficiently c…

【Rust中级教程】2.7. API设计原则之灵活性(flexible) Pt.3:借用 vs. 拥有、`Cow`类型、可失败和阻塞的析构函数及解决办法

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 2.7.1. 借用(Borrowed) vs. 拥有(Owned) 针对Rust中几乎每一个函数、trait和类型&#xff…

Rust 中的内部可变性与 `RefCell<T>`

一、为什么需要内部可变性&#xff1f; 通常&#xff0c;Rust 编译器通过静态分析确保&#xff1a; 同一时刻只能存在一个可变引用&#xff0c;或任意多个不可变引用&#xff1b;引用始终保持有效。 这种严格的借用规则使得许多内存错误在编译阶段就能被捕获&#xff0c;但也…

golang性能分析之pprof

在 Go 语言中&#xff0c;使用 pprof 进行性能分析是优化代码的常用手段。以下简要介绍操作步骤&#xff1a; 1. 导入 pprof 包 在代码中导入 net/http/pprof 包&#xff08;即使你不需要 HTTP 服务&#xff09;&#xff0c;它会自动注册性能分析相关的路由&#xff1a; impo…

steam_api.dll丢失3分钟修复指南,解决Steam游戏无法运行

你是不是刚下载好 Steam 游戏&#xff0c;激动双击图标&#xff0c;结果弹出一句 “steam_api.dll 没有被指定在 windows 上运行”&#xff1f;本文提供 3 种安全修复方案&#xff0c;详解 steam_api.dll 文件下载避坑技巧 正确存放路径&#xff0c;推荐一键修复工具&#xff…

体育数据系统是怎么开发的

体育数据系统的开发通常包括多个环节&#xff0c;涉及数据采集、处理、存储和展示等方面。下面是开发一个体育数据系统的主要步骤&#xff1a; 1. 需求分析与规划 确定目标&#xff1a;明确系统的目标&#xff0c;比如实时比赛数据跟踪、球员统计、比赛分析等。 确定用户群体…

CSS实现图片缺角效果

效果&#xff1a; 源码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>123</title…