春招冲刺百题计划|堆

news2024/12/26 11:53:03

Java基础复习

  1. Java数组的声明与初始化
  2. Java ArrayList
  3. Java HashMap
  4. Java String 类
  5. Java LinkedList
  6. Java Deque继承LinkedList
  7. Java Set
  8. Java 队列
  9. 优先队列:第二题用到了

第一题:215. 数组中的第K个最大元素

在这里插入图片描述
可以直接使用Arrays.sort()快排,然后return nums[n-k];
或者手动实现快速选择的内容:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
在这里插入图片描述

class Solution {
    int quickselect(int[] nums, int l, int r, int k) {
        if (l == r) return nums[k];
        int x = nums[l], i = l - 1, j = r + 1; //选最左边的为基准。
        while (i < j) {
            do{ 
                i++; 
            }while(nums[i] < x);//左边的都小于x
            do{
                j--;
            }while(nums[j] > x);//右边的都大于x
            if (i < j){
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
        }
        if (k <= j) return quickselect(nums, l, j, k); //一趟排序后,基准比第k大的大,那么在基准左边找。
        else return quickselect(nums, j + 1, r, k);//否则在基准右边找。
    }
    public int findKthLargest(int[] _nums, int k) {
        int n = _nums.length;
        return quickselect(_nums, 0, n - 1, n - k);
    }
}

另一种解法就是堆排序:参考:https://pdai.tech/md/algorithm/alg-sort-x-heap.html
逻辑结构是完全二叉树,存储结构是数组。之间的联系如下:
在这里插入图片描述算法实现步骤就是, ① 初始化堆: 将数列a[1…n]构造成最大堆。 ② 交换数据: 将a[1]和a[n]交换,使a[n]是a[1…n]中的最大值;然后将a[1…n-1]重新调整为最大堆。 接着,将a[1]和a[n-1]交换,使a[n-1]是a[1…n-1]中的最大值;然后将a[1…n-2]重新调整为最大值。 依次类推,直到整个数列都是有序的。

    public static void maxHeapDown(int[] a, int start, int end) {
        int c = start;            // 当前(current)节点的位置
        int l = 2*c + 1;        // 左(left)孩子的位置
        int tmp = a[c];            // 当前(current)节点的大小

        for (; l <= end; c=l,l=2*l+1) {
            // "l"是左孩子,"l+1"是右孩子
            if ( l < end && a[l] < a[l+1])
                l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
            if (tmp >= a[l])
                break;        // 调整结束
            else {            // 交换值
                a[c] = a[l];
                a[l]= tmp;
            }
        }
    }

    /*
     * 堆排序(从小到大)
     *
     * 参数说明: 
     *     a -- 待排序的数组
     *     n -- 数组的长度
     */
    public static void heapSortAsc(int[] a, int n) {
        int i,tmp;

        // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个(最大)二叉堆。
        for (i = n / 2 - 1; i >= 0; i--)
            maxHeapDown(a, i, n-1);

        // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
        for (i = n - 1; i > 0; i--) {
            // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
            tmp = a[0];
            a[0] = a[i];
            a[i] = tmp;
            // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
            // 即,保证a[i-1]是a[0...i-1]中的最大值。
            maxHeapDown(a, 0, i-1);
        }
    }

提交代码:

class Solution {
    public static void heapSortAsc(int[] a, int n){

        for(int i=n/2-1; i>=0; i--){
            maxHeapDown(a, i, n-1);
        }
        for (int i = n - 1; i > 0; i--) {
            // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
            int tmp = a[0];
            a[0] = a[i];
            a[i] = tmp;
            // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
            // 即,保证a[i-1]是a[0...i-1]中的最大值。
            maxHeapDown(a, 0, i-1);
        }

    }
    public static void maxHeapDown(int[] a, int start, int end) {
        int c = start;            // 当前(current)节点的位置
        int l = 2*c + 1;        // 左(left)孩子的位置
        int tmp = a[c];            // 当前(current)节点的大小

        for (; l <= end; c=l,l=2*l+1) {
            // "l"是左孩子,"l+1"是右孩子
            if ( l < end && a[l] < a[l+1])
                l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
            if (tmp >= a[l])
                break;        // 调整结束
            else {            // 交换值
                a[c] = a[l];
                a[l]= tmp;
            }
        }

    }
    public int findKthLargest(int[] _nums, int k) {
        int n = _nums.length;
        heapSortAsc(_nums, n);
        return _nums[n-k];
    }
}

第二题:373. 查找和最小的 K 对数字

在这里插入图片描述
以下写法超出内存限制:

class Solution {
     public static void heapSortAsc(int[][] a, int n){
        for(int i=n/2-1; i>=0; i--){
            maxHeapDown(a, i, n-1);
        }
        for (int i = n - 1; i > 0; i--) {
            // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
            int[] tmp = a[0];
            a[0] = a[i];
            a[i] = tmp;
            // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
            // 即,保证a[i-1]是a[0...i-1]中的最大值。
            maxHeapDown(a, 0, i-1);
        }
    }
    public static void maxHeapDown(int[][] a, int start, int end) {
        int c = start;            // 当前(current)节点的位置
        int l = 2*c + 1;        // 左(left)孩子的位置
        int[] tmp = a[c];            // 当前(current)节点的大小

        for (; l <= end; c=l,l=2*l+1) {
            // "l"是左孩子,"l+1"是右孩子
            if ( l < end && (a[l][0] + a[l][1]) < (a[l+1][0] + a[l+1][1]))
                l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
            if ((tmp[0]+tmp[1]) >=  (a[l][0] + a[l][1]))
                break;        // 调整结束
            else {            // 交换值
                a[c] = a[l];
                a[l] = tmp;
            }
        }

    }
    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        
        int n = nums1.length*nums2.length;
        int[][] a = new int[n][2];
        int idx = 0;
        for(int i=0; i<nums1.length; i++){
            for(int j=0; j<nums2.length; j++){
                a[idx][0] = nums1[i];
                a[idx++][1] = nums2[j];
            }
        }
        heapSortAsc(a, n);
        List<List<Integer>> results = new ArrayList<List<Integer>>();   
        for(int i=0; i<k; i++){
                List<Integer> tmp = new ArrayList<Integer>();
                tmp.add(a[i][0]);
                tmp.add(a[i][1]);
                results.add(tmp);
        }
        return results;

    }
}

参考:灵茶山艾府的题解
在这里插入图片描述
觉得这样的大神,每次写得代码都很简洁。哭唧唧。我和这篇的问题,就在于,我使用的代码的堆,没办法随时调整。

class Solution {
    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        List<List<Integer>> ans = new ArrayList<>(k); // 预分配空间
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
        pq.add(new int[]{nums1[0] + nums2[0], 0, 0});
        while (ans.size() < k) {
            int[] p = pq.poll();
            int i = p[1];
            int j = p[2];
            ans.add(List.of(nums1[i], nums2[j]));
            if (j == 0 && i + 1 < nums1.length) {
                pq.add(new int[]{nums1[i + 1] + nums2[0], i + 1, 0});
            }
            if (j + 1 < nums2.length) {
                pq.add(new int[]{nums1[i] + nums2[j + 1], i, j + 1});
            }
        }
        return ans;
    }
}

这里自己仿照源码写了一份优先队列

class Solution {
    class MyPriorityQueue{
        //仿照源码编写自己的
        private int[][] queue;
        private int size;
        MyPriorityQueue(){
            queue=new int[0][0];
            size = 0;
        }
        private int Mycompare(int[] a, int[] b){
            return a[0]-b[0];
        }
        public void offer(int[] e){
            int i = size;
            if (i >= queue.length)
                queue = Arrays.copyOf(queue, i+1);
                size = i + 1;
                if (i == 0)//队列原来为空,这是插入的第一个元素
                    queue[0] = e;
                else
                    siftUp(i, e);//调整
        }

        private void siftUp(int k, int[] x) { //找到x该待的位置
            while (k > 0) {
                int parent = (k - 1) >>> 1;//parentNo = (nodeNo-1)/2
                int[] e = queue[parent];
                if (Mycompare(x, e) >= 0) break;
                queue[k] = e;
                k = parent;
            }
            queue[k] = x;
        }

        public int[] peek() {
            if (size == 0)
                return null;
            return queue[0];//0下标处的那个元素就是最小的那个
        }

        public int[] poll() {
            if (size == 0)
                return null;
            int s = --size;
            int[] result = queue[0];//0下标处的那个元素就是最小的那个
            int[] x = queue[s]; //最后一个叶子结点
            queue[s] = null;
            if (s != 0) //队列不为空要调整
                siftDown(0, x);//调整
            return result;
        }

        private void siftDown(int k, int[] x) {
            int half = size >>> 1; //size/2
            while (k < half) {
                //首先找到左右孩子中较小的那个,记录到c里,并用child记录其下标
                int child = (k << 1) + 1;//leftNo = parentNo*2+1
                int[] c = queue[child];
                int right = child + 1;
                if (right < size && Mycompare(c, queue[right]) > 0)
                    c = queue[child = right];
                if (Mycompare(x, c) <= 0)
                    break;
                queue[k] = c;//然后用c取代原来的值
                k = child;
            }
            queue[k] = x;
        }
        
    }


    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        List<List<Integer>> ans = new ArrayList<>(k); // 预分配空间
        MyPriorityQueue pq = new MyPriorityQueue();
        pq.offer(new int[]{nums1[0] + nums2[0], 0, 0});
        while (ans.size() < k) {
            int[] p = pq.poll();
            int i = p[1];
            int j = p[2];
            ans.add(List.of(nums1[i], nums2[j]));
            if (j == 0 && i + 1 < nums1.length) {
                pq.offer(new int[]{nums1[i + 1] + nums2[0], i + 1, 0});
            }
            if (j + 1 < nums2.length) {
                pq.offer(new int[]{nums1[i] + nums2[j + 1], i, j + 1});
            }
        }
        return ans;
    }
}

第三题:264. 丑数 II

在这里插入图片描述
首先明确一下质因子是什么?
质因子(或质因数)在数论里是指能整除给定正整数的质数。
只有两个正因数(1和它本身)的自然数即为质数。(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97…)
仔细想想还是不难的,就是用小顶堆,弹出一个x,添加2x,3x,5x进去。

class Solution {
    int[] NUMS = new int[]{2, 3, 5};
    class MyPriorityQueue{
        //仿照源码编写自己的
        private long[] queue;
        private int size;
        MyPriorityQueue(){
            queue=new long[0];
            size = 0;
        }
        private long Mycompare(long a, long b){
            return a-b;
        }
        public void offer(long e){
            int i = size;
            if (i >= queue.length)
                queue = Arrays.copyOf(queue, i+1);
                size = i + 1;
                if (i == 0)//队列原来为空,这是插入的第一个元素
                    queue[0] = e;
                else
                    siftUp(i, e);//调整
        }

        private void siftUp(int k, long x) { //找到x该待的位置
            while (k > 0) {
                int parent = (k - 1) >>> 1;//parentNo = (nodeNo-1)/2
                long e = queue[parent];
                if (Mycompare(x, e) >= 0) break;
                queue[k] = e;
                k = parent;
            }
            queue[k] = x;
        }

        public long peek() {
            return queue[0];//0下标处的那个元素就是最小的那个
        }

        public long poll() {
            int s = --size;
            long result = queue[0];//0下标处的那个元素就是最小的那个
            long x = queue[s]; //最后一个叶子结点
            queue[s] = -1;
            if (s != 0) //队列不为空要调整
                siftDown(0, x);//调整
            return result;
        }

        private void siftDown(int k, long x) {
            int half = size >>> 1; //size/2
            while (k < half) {
                //首先找到左右孩子中较小的那个,记录到c里,并用child记录其下标
                int child = (k << 1) + 1;//leftNo = parentNo*2+1
                long c = queue[child];
                int right = child + 1;
                if (right < size && Mycompare(c, queue[right]) > 0)
                    c = queue[child = right];
                if (Mycompare(x, c) <= 0)
                    break;
                queue[k] = c;//然后用c取代原来的值
                k = child;
            }
            queue[k] = x;
        }
        
    }
    public int nthUglyNumber(int n) {
        //我目前的思路就是得到一组序列,长度为n,就是从1开始算,找到第n个满足条件的就行。
        int[] result = new int[n+1];
        result[1] = 1;
        if(n==1){
            return result[n];
        }
        int sum=2;
        MyPriorityQueue queue = new MyPriorityQueue();
        Set<Long> had = new HashSet<>();
        queue.offer(2); had.add(2l);
        queue.offer(3); had.add(3l);
        queue.offer(5); had.add(5l);
        while(sum<=n){
            long tmp = queue.poll();
            result[sum] = (int)tmp;
            for(int i=0; i<NUMS.length; i++){
                if(!had.contains(tmp*NUMS[i])){
                    had.add(tmp*NUMS[i]);
                    queue.offer(tmp*NUMS[i]);
                }
            }
            sum++;
        }
        return result[n];
    }
}

第四题:218.天际线问题

在这里插入图片描述
算术评级是9,我就看一看,凑个热闹。
莫名想接雨水,但是接雨水好像是维护一个单调队列。
后期有时间再补。先把简单题和中等题搞明白。o(╥﹏╥)o。

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

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

相关文章

数据库第六次

视图 salary decimal(10,2) not null default 0 comment ‘工资’, address varchar(200) not null default ‘’ comment ‘通讯地址’, dept_id int comment ‘部门编号’ ); create index idx_name on emp(emp_name); create index idx_birth on emp(birth); create index…

MySQL-日志-优化

目录 介绍一下mysql 的日志 redo log 和binlog 的区别及应用场景 redo log 和 binlog 在恢复数据库有什么区别? redo log 是怎么实现持久化的? redo log除了崩溃恢复还有什么其他作用? &#xff08;顺序写&#xff09; redo log 怎么刷入磁盘的知道吗&#xff1f; 两阶…

2024西安铁一中集训DAY2 ---- 模拟赛(最小生成树 + AC自动机 + 模拟 + rmq)

文章目录 比赛成绩题解A. 江桥的生成树&#xff08;MST&#xff09;B. 江桥的神秘密码&#xff08;AC自动机&#xff0c;ST表&#xff09;C. 江桥的字符距离D. 江桥的防御力测试&#xff08;rmq&#xff0c;乱搞&#xff09; 比赛成绩 估测&#xff1a;60 100 100 0 260 实…

FastAPI 学习之路(四十九)WebSockets(五)修复接口测试中的问题

其实代码没有问题&#xff0c;但是我们忽略了一个问题&#xff0c;就是在正常的开发中&#xff0c;肯定是遇到过这样的情况&#xff0c;我们频繁的有客户端链接&#xff0c;断开连接&#xff0c;需要统一的管理这些链接&#xff0c;那么应该如何管理呢。其实可以声明一个类去管…

218.贪心算法:分发糖果(力扣)

核心思想 初始化每个学生的糖果数为1&#xff1a; 确保每个学生至少有一颗糖果。从左到右遍历&#xff1a; 如果当前学生的评分高于前一个学生&#xff0c;则当前学生的糖果数应比前一个学生多一颗。从右到左遍历&#xff1a; 如果当前学生的评分高于后一个学生&#xff0c;则…

01对话系统---文字渐出和停顿效果

实现代码 using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; using System.Text.RegularExpressions; using System;/// <summary> /// 增加文本时间停顿功能 /// 增加文字渐出&#xff0c;&#xff08;单个字符逐渐显现&a…

Unity免费领场景多人实时协作地编2人版局域网和LAN联机类似谷歌文档协同合作搭建场景同步资产设置编辑付费版支持10人甚至更多20240709

大家有没有用过谷歌文档、石墨文档、飞书文档等等之类的协同工具呢&#xff1f; Blender也有类似多人联机建模的插件&#xff0c; Unity也有类似的多人合作搭建场景的插件啦。 刚找到一款免费插件&#xff0c;可以支持2人局域网和LAN联机地编。 付费的版本支持组建更大的团队。…

从汇编层看64位程序运行——静态分析和动态分析入门

大纲 GDBIDA总结参考资料 之前一直谈各种相对宏观的工具怎么使用&#xff0c;比如Flink、RabbitMQ等。最近想聊聊比较微观的技术&#xff0c;用各种“显微镜”去看看运行在系统层的二进制码是什么样子。当然二进制码比较难以记忆&#xff0c;于是我会从二进制码的助记符——汇编…

IOS上微信小程序密码框光标离开提示存储密码解决方案

问题&#xff1a; ios密码框输入密码光标离开之后会提示存储密码的弹窗 解决方案 1、在苹果手机上面把 “自动填充密码”关闭&#xff0c;但是苹果这个默认开启&#xff0c;而且大部分客户也不会去自己关闭。 2、欺骗苹果手机&#xff0c;代码实现。 先说解决思路&#xf…

java内部类的本质

定义在类内部&#xff0c;可以实现对外部完全隐藏&#xff0c;可以有更好的封装性&#xff0c;代码实现上也往往更为简洁。 内部类可以方便地访问外部类的私有变量&#xff0c;可以声明为private从而实现对外完全隐藏。 在Java中&#xff0c;根据定义的位置和方式不同&#xf…

mmaction2的GPU环境配置记录RTX3090,cuda12.2,ubuntu22.04版本

1、配置镜像源 最重要的一个步骤,先看下镜像源地址,如果镜像源有问题,所有的包安装都会有问题 镜像源地址获取地址:选择对应的ubuntu版本号,将里面的镜像源地址复制出来,更新到服务器 ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirro…

【web]-sql注入-bestdb

打开页面后&#xff0c;如图 查看源代码&#xff0c;发现有段注释&#xff0c;尝试sql注入 <!-- $sql "SELECT * FROM users WHERE id $query OR username \"$query\"";--> 1、尝试万能密码 1 or 11# / admin&#xff0c; 提示F…

Linux磁盘-MBRGPT

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux磁盘涉及到的命令不是很多&#xff0c;但是在实际运维中的作用却很大&#xff0c;因为Linux系统及业务都会承载到硬盘上…

2024年新一代WebOffice内嵌网页组件——猿大师办公助手

背景 WebOffice控件这个中间件软件产品已存在二十余年&#xff0c;在国内众多大中小型企业、各级政府机关、科研机构和学校等事业单位的OA、ERP、文档系统、云盘等信息化B/S系统中得到了大量使用&#xff0c;为我国的信息化事业也做出了不小贡献。随着操作系统、浏览器及Offic…

随笔一、泰山派RK3566开发板调试串口波特率修改

摘要&#xff1a;立创泰山派RK3566开发板默认调试串口波特率是1500000bps&#xff0c;一般串口助手工具没有此波特率&#xff0c;为适应各种调试环境需要&#xff0c;打算修改调试串口波特率为115200bps 需要修改三个部分 1. uboot引导部分 修改tspi_linux_sdk/u-boot/config…

面试项目 | 带你玩转大学生智能汽车项目

文章目录 前言智能车系统介绍1.从智能车说起2.整体系统结构3.经验之谈 系统分层设计1.分层与模块化2.整个系统的总体设计控制与图像层嵌入式平台层 机械与硬件设计部分1.硬件布线2.电机H桥3.机械这块简单说几句吧 嵌入式平台软件搭建1.从任务调度说起大循环调度定时任务调度实时…

[吃瓜教程]南瓜书第6章软间隔与支持向量回归

1.软间隔支持向量机的模型 之前讨论的支持向量机的一个重要的假设前提是它的数据集是线性可分的。然而在现实任务中&#xff0c;线性不可分的情形才是最常见的&#xff0c;因此需要允许支持向量机犯错。这就是接下来要说的软间隔的支持向量机。 2.软间隔支持向量机的策略 从…

PropertySourcesPropertyResolver

SpringBoot应用中涉及配置相关的东西&#xff0c;例如配置文件、环境变量、系统变量等都是基于类ApplicationServletEnvironment的构造器开启的&#xff0c;如下其抽象父类AbstractEnvironment构造器&#xff1a; public abstract class AbstractEnvironment{private final Mu…

TypeError: load() got an unexpected keyword argument ‘loader‘

定义函数 get_yaml_data用来读取 login_data.yml 文件并打印其内容。 import yamldef get_yaml_data(path):with open(path,moder,encodingutf-8)as f:data yaml.load(f,loader yaml.FullLoader)return dataif __name____main__:pathr..\config\desired_caps.ymlprint(get_y…

7 月12日学习打卡--栈和队列的相互转换

hello大家好呀&#xff0c;本博客目的在于记录暑假学习打卡&#xff0c;后续会整理成一个专栏&#xff0c;主要打算在暑假学习完数据结构&#xff0c;因此会发一些相关的数据结构实现的博客和一些刷的题&#xff0c;个人学习使用&#xff0c;也希望大家多多支持&#xff0c;有不…