双非本科准备秋招(13.1)—— 力扣 栈、队列与堆

news2024/11/26 16:38:54

1、103. 二叉树的锯齿形层序遍历

昨天做的二叉树的层序遍历,把代码直接拿过来。

这个题要求的是一个Z型遍历,如下图。

        用一个变量f记录正反顺序,然后使用LinkedList记录答案,下图可以看到LinkedList继承了Deque,所以可以当作双端队列来用。

每次记录答案时,根据f的值选择调用offerLast和offerFirst方法。

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        LinkedBlockingQueue<TreeNode> q = new LinkedBlockingQueue<>();
        List<List<Integer>> list = new ArrayList<>();
        if(root == null) return list;
        q.offer(root);
        int cnt = 1;
        boolean f = true;

        while(!q.isEmpty()){
            LinkedList<Integer> L = new LinkedList<>();
            int temp = 0;
            for(int i = 0; i < cnt; i++){
                TreeNode t = q.poll();
                if(f) L.offerLast(t.val);
                else L.offerFirst(t.val);
                if(t.left != null){
                    q.offer(t.left);
                    temp++;
                }
                if(t.right != null){
                    q.offer(t.right);
                    temp++;
                }
            }
            cnt = temp;
            list.add(L);
            f = !f;
        }

        return list;
    }
}

2、23. 合并 K 个升序链表

        用优先队列来做,默认排序即可(小顶堆),最后处理一下答案,把队列q中的元素转移到新的链表上。

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue<Integer> q = new PriorityQueue<>();
        ListNode head = new ListNode();
        ListNode p = head;
        for(int i = 0; i < lists.length; i++){
            while(lists[i] != null){
                q.offer(lists[i].val);
                lists[i] = lists[i].next;
            }
        }
        while(!q.isEmpty()){
            ListNode t = new ListNode(q.poll());
            p.next = t;
            p = p.next;
        }
        return head.next;
    }
}

3、215. 数组中的第K个最大元素

堆这种数据结构就适合求前几个具有xx特性的元素问题,包括下一个题目和最后一个题目。

这个题用小顶堆做,我们可以手写一个堆的结构class MinHeap。

我们只需要把前k个元素加入堆(offer()方法),然后后面的元素只需要判断是否大于堆中的第一个元素即可,如果大于,就替换第一个元素(replace()方法)。

因为堆中第一个元素是k个中最小的,我们不断加入大的元素,那么最后是不是堆中只剩下最大的k个元素了,k个最大元素中最小的不就是堆的第一个元素嘛。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        MinHeap heap = new MinHeap(k);

        for(int i = 0; i < k; i++){
            heap.offer(nums[i]);
        }

        for(int i = k; i < nums.length; i++){
            if(nums[i] > heap.array[0]){
                heap.replace(nums[i]);
            }
        }

        return heap.array[0];
    }
}

public class MinHeap {
    int[] array;
    int size;

    public MinHeap(int capacity) {
        this.array = new int[capacity];
    }

    public void offer(int offerd){
        up(offerd);
        size++;   
    }

    public void up(int offerd){
        int child = size;
        while(child > 0){
            int parent = (child-1)/2;
            if(array[parent] > offerd){
                array[child] = array[parent];
            }
            else{
                break;
            }
            child = parent;
        }
        array[child] = offerd;
    }

    public void replace(int replaced){
        array[0] = replaced;
        down(0);
    }

    private void down(int parent) {
        int lc = parent*2+1;
        int rc = lc+1;
        int min = parent;
        if(lc < size && array[lc] < array[min]){
            min = lc;
        }
        if(rc < size && array[rc] < array[min]){
            min = rc;
        }
        if(min != parent){
            swap(min, parent);
            down(min);
        }
    }

    private void swap(int i, int j) {
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}

4、703. 数据流中的第 K 大元素

与上个题不能说一模一样,只能说完全一致。

需要注意add方法要判断一下堆是不是满了,因为初始化堆的时候有可能提供的元素个数小于k个,如果没满直接加入堆就好。

class KthLargest {
    MinHeap heap = null;
    public KthLargest(int k, int[] nums) {
        heap = new MinHeap(k);
        int len = Math.min(k, nums.length);
        for(int i = 0; i < len; i++){
            heap.offer(nums[i]);
        }
        for(int i = k; i < nums.length; i++){
            if(nums[i] > heap.array[0]){
                heap.replace(nums[i]);
            }
        }
    }
    
    public int add(int val) {
        if(heap.size < heap.array.length){
            heap.offer(val);
        }
        else if(val > heap.array[0]){
            heap.replace(val);
        }
        return heap.array[0];
    }
}

public class MinHeap {
    int[] array;
    int size;

    public MinHeap(int capacity) {
        this.array = new int[capacity];
        Arrays.fill(this.array, Integer.MIN_VALUE);
    }

    public void offer(int offerd){
        up(offerd);
        size++;   
    }

    public void up(int offerd){
        int child = size;
        while(child > 0){
            int parent = (child-1)/2;
            if(array[parent] > offerd){
                array[child] = array[parent];
            }
            else{
                break;
            }
            child = parent;
        }
        array[child] = offerd;
    }

    public void replace(int replaced){
        array[0] = replaced;
        down(0);
    }

    private void down(int parent) {
        int lc = parent*2+1;
        int rc = lc+1;
        int min = parent;
        if(lc < size && array[lc] < array[min]){
            min = lc;
        }
        if(rc < size && array[rc] < array[min]){
            min = rc;
        }
        if(min != parent){
            swap(min, parent);
            down(min);
        }
    }

    private void swap(int i, int j) {
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}

5、1047. 删除字符串中的所有相邻重复项

解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

读完解释后,感觉就是明示了栈的数据结构。

我们把a入栈,b入栈,b入栈,b和栈顶重复,b不入了并且弹出栈顶元素,这时候栈只剩下a,然后a入栈,a和栈顶重复,a不入了并且弹出栈顶元素,栈空了,然后c入栈,a入栈。

这时候我们依次弹出,得到ac,那么我们可以倒着遍历字符串,倒着入栈,结果都是一样的,不影响删除相邻重复的字母。

class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        for(int i = s.length()-1; i >= 0; i--){
            if(!stack.isEmpty() && stack.peek() == s.charAt(i)){
                stack.pop();
            }
            else{
                stack.push(s.charAt(i));
            }
        }
        String ans = "";
        while(!stack.isEmpty()){
            ans += stack.pop();
        }

        return ans;
    }
}

6、347. 前 K 个高频元素

        元素与元素的次数,让人联想到哈希表。存到哈希表后,对出现的次数进行排序,这应该是第一思路。

        前k个高频元素,有出现了前几个具有xx特性的这种要求,我们就会想到堆,在堆中只存放前k个高频元素,使用小顶堆,我们最后得到的就是前k个最高频的元素了。

        java中的ProrityQueue的底层就是堆,我就不用自己写的了。因为我们的堆中要存储数据和出现的次数,因此可以存个数组,下标0代表是什么数据,下标1代表出现的次数。        

        我们先加入到map中,然后遍历map集合,把cnt大于堆顶的元素替换掉原来的元素,也就是队列出队,这样就得到了前k个高频的元素了。

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        PriorityQueue<int[]> q = new PriorityQueue<>(k, (o1, o2) -> o1[1] - o2[1]);
        HashMap<Integer, Integer> map = new HashMap<>();

        for(int i = 0; i < nums.length; i++){
            int v = 0;
            if(map.containsKey(nums[i])){
                v = map.get(nums[i]);
            }
            map.put(nums[i], v+1);
        }

        for(Integer n : map.keySet()){
            int cnt = map.get(n);
            if(q.size() < k){
                q.offer(new int[]{n, cnt});
            }
            else if(cnt > q.peek()[1]){
                q.poll();
                q.offer(new int[]{n, cnt});
            }
        }

        int[] ans = new int[k];
        int j = 0;
        while(!q.isEmpty()){
            ans[j++] = q.poll()[0];
        }
        return ans;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1426131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【知识图谱--第一讲概论】

深度学习–连接主义 知识图谱–符号主义 表示 有属性图和RDF图两种 RDF由三元组表示&#xff1a;Subject - Predicate - Object 存储 图数据库 抽取 融合 推理 问答 图算法

Linux:进程信号的概念与产生原理

文章目录 信号的概念实践信号关于前台和后台进程的操作 操作系统与外设信号的产生signal系统调用 前面的篇章结束了信号量的话题&#xff0c;那么接下来引入的是信号的话题&#xff0c;信号和信号量之间没有任何关系&#xff0c;只是名字比较像 信号的概念 在生活中存在各种各…

linux麒麟系统安装mongodb7.0

1.mogedb下载 下载的是他tar包 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz wget -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz 也可以下载rpm包 2.将包上传至服务器并解压 #进入目录 并解压 cd /opt/ tar…

Linux ---- Shell编程之免交互

一、Here Document 多行重定向 1、Here Document定义 使用I/O重定向的方式将命令列表提供给交互式程序标准输入的一种替代品Here Document 是标准输 入的一种替代品&#xff0c;可以帮助脚本开发人员不必使用临时文件来构建输入信息&#xff0c;而是直接就地生产出一个文件…

技术科普 | 机器视觉5大关键技术及其常见应用

计算机视觉是指&#xff1a;让机器通过数字图像或视频等视觉信息来模拟人类视觉的过程&#xff0c;以达到对物体的理解、识别、分类、跟踪、重建等目的的技术。它是人工智能领域中的一个分支&#xff0c;涉及图像处理、模式识别、机器学习、深度学习等多个领域。 随着人工智能和…

7.2、子集求和问题与背包密码系统

7.2、子集求和问题与背包密码系统 一、数学描述 1.1、第一种描述 20 世纪 70 年代末&#xff0c;默克尔和赫尔曼首次尝试将密码系统建立在一个 NP-完全问题上。他们使用了以下数学问题的一个版本&#xff0c;该问题是对经典knapsack问题的概括。 子集和问题 假设你有一个正…

数据结构——链式二叉树(3)

本篇文章我们依然讲解链式二叉树的OJ题&#xff1b; 一、二叉树的层序遍历 层序遍历即从根节点开始一层一层的遍历。我们可以运用队列的先进先出特性实现&#xff01; //层序遍历 void a(BTNode* root) {Que qhead;Queueinit(&qhead);//先入队根节点if(root)QueuePush(&…

C#,计算几何,随机点集之三角剖分的德劳内(Delaunay)算法的源代码

一、三角剖分Delaunay算法简介 点集的三角剖分&#xff08;Triangulation&#xff09;&#xff0c;对数值分析&#xff08;比如有限元分析&#xff09;以及图形学来说&#xff0c;都是极为重要的一项预处理技术。尤其是Delaunay三角剖分&#xff0c;由于其独特性&#xff0c;关…

LeetCode: 160.相交链表(令人赞叹的优雅)

160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 目录 官方双指针解法&#xff1a; 博主的辣眼代码&#xff1a; 每日一表情包&#xff1a; 博主还未学习哈希表&#xff0c;所以介绍的是双指针法&#xff0c;此题的哈希表解法时O&#xff08;nm&#xff09;空O&…

MySQL窗口函数--lead()函数

lead()函数&#xff1a; 查询当前行向下偏移n行对应的结果 该函数有三个参数&#xff1a;第一个为待查询的参数列名&#xff0c;第二个为向下偏移的位数&#xff0c;第三个参数为超出最下面边界的默认值。 如下代码&#xff1a; 查询向下偏移 2 位的年龄 SELECT user_id,user…

JavaScript高级:深浅拷贝

目录 1 引言 2 浅拷贝 2.1 拷贝数组 1.2 拷贝对象 3 赋值操作和浅拷贝的比较 4 深拷贝 4.1 前置知识 --> 递归函数 4.2 使用递归实现深拷贝 4.3 js库中的lodash里面的cloneDeep内部实现深拷贝 4.4 利用JSON实现深拷贝 深浅拷贝只针对引用数据类型 1 引言 假如我们…

leetcode 19 , 118

19 .删除链表倒数第n个节点 思路1&#xff1a; 我首先想到的就是使用两个loop来进行解决&#xff1a; 遍历所有节点&#xff0c;得到需要删除节点的位置。再遍历一边所有节点&#xff0c;找到需要删除节点进行删除。 解决方案1&#xff1a; class Solution {public ListNod…

DevOps落地笔记-07|案例分析:如何有效管理第三方组件

上一讲主要介绍了如何通过代码预检查的方式提高入库代码的质量&#xff0c;将代码检查尽可能前置&#xff0c;降低修复问题的成本&#xff0c;从而提高交付软件的质量。除了代码本身的问题&#xff0c;依赖组件也是经常困扰开发者的一个问题。比如&#xff0c;依赖组件的某个版…

项目管理构建不只是Maven,还有更优越的它!

教程全文阅读请转至《项目管理构建不只是Maven,还有更优越的它&#xff01;》 Gradle简介 Gradle是一种现代化的构建工具&#xff0c;用于构建Java、C、Python、Android等项目。它是一种基于Groovy语言的自动化构建工具&#xff0c;可以自动化执行各种构建任务&#xff0c;例…

matlab基本操作

目录 1 清空workspace 2 清空命令行窗口 3 求字符的ASCII码 4 矩阵的表示 5 矩阵的转置 6 按列输出 7 求逆矩阵 8 创建零矩阵 9 生成随机数 10 生成空数组 11 生成单位矩阵 12 生成幻方矩阵 13 结构体 14 重复 15 点乘与叉乘 16 寻找符合条件的元素…

2024年1月份实时获取地图边界数据方法,省市区县街道多级联动【附实时geoJson数据下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

spring cache的使用(Redis)

要在Spring Boot应用中使用Redis作为缓存&#xff0c;你需要遵循一些步骤来配置和使用Redis。以下是使用Spring Cache抽象与Redis进行整合的详细说明&#xff1a; 1. 添加依赖 首先&#xff0c;需要在pom.xml中添加Spring Boot的Redis starter依赖以及缓存的starter依赖。这会…

vivado 与系统设计师接口

与系统设计师接口 作为迭代I/O和时钟规划过程的一部分&#xff0c;您可以交换有关AMD设备通过导出CSV文件和IBIS模型&#xff0c;与PCB或系统设计者进行引脚连接。根据PCB或设计规范的变化&#xff0c;您可能需要将引脚重新导入为如定义和配置I/O端口中所述。完成I/O和时钟中的…

如何在 Mac 中运行 Office 办公软件

虽然 Office 软件也有 Mac 版本的&#xff0c;但是有蛮多小伙伴用起来还是感觉不得劲&#xff0c;毕竟接触了太久的 Windows&#xff0c;所以想要使用 Windows 版本的 Office 软件。 今天就给大家介绍一下怎么在 Mac 电脑中运行 Windows 版本的办公软件&#xff0c;在这里就需…

【Qt】—— Qt Creator 创建项目

目录 &#xff08;一&#xff09;Qt Creator概览 &#xff08;二&#xff09;使⽤Qt Creator新建项⽬ &#xff08;一&#xff09;Qt Creator概览 从开始菜单或者快捷⽅式打开Qt Creator集成开发环境&#xff0c;启动之后看到类似下⾯的界⾯&#xff1a; 【解释说明】 菜单栏…