春招冲刺百题计划|堆

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.mfbz.cn/a/796770.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

修正版头像上传组件

修正版头像上传组件 文章说明核心源码展示运行效果展示源码下载 文章说明 在头像剪切上传一文中&#xff0c;我采用div做裁剪效果&#xff0c;感觉会有一些小问题&#xff0c;在昨天基于canvas绘制的功能中改进了一版&#xff0c;让代码变得更简洁&#xff0c;而且通用性相对高…

ChatGPT使用姿势

使用上的痛点 用的不好&#xff1a;你经常会感觉到 ChatGPT 回答的好空&#xff0c;没有太多参考价值无处去用&#xff1a;有了 GPT 之后&#xff0c;发现自己好像并没有什么好问的&#xff0c;不知道可以用 GPT 来干嘛。 如何使用AI 核心心法&#xff1a;GPT 生成的答案质量…

纯技术分享:淘宝商品详情原数据接口参数解析

item_get_app-获得淘宝app商品详情原数据 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_s…

【机器学习】使用决策树分类器预测汽车安全性的研究与分析

文章目录 一、决策树算法简介决策树的结构分类和回归树 (CART)决策树算法术语决策树算法直觉 二、属性选择度量信息增益熵 基尼指数计算分割基尼指数的步骤 三、决策树算法中的过度拟合避免过度拟合的方法 四、导入库和数据可视化探索性数据分析重命名列名查看数据集的总结信息…

WAF基础介绍

WAF 一、WAF是什么&#xff1f;WAF能够做什么 二 waf的部署三、WAF的工作原理 一、WAF是什么&#xff1f; WAF的全称是&#xff08;Web Application Firewall&#xff09;即Web应用防火墙&#xff0c;简称WAF。 国际上公认的一种说法是&#xff1a;Web应用防火墙是通过执行一…

小零食,大智慧!连锁零食店如何选择收银?收银系统源码

近几年专业的散装零食店非常的火热&#xff0c;像百草味、良品铺子、大嘴零食、来伊份等都大受欢迎。而传统超市的散装零食区则是日益冷落&#xff0c;小超市多数干脆放弃了散装。 休闲零食作为快消品的一类&#xff0c;是大家工作闲暇、生活休闲的必备食品。随着人们生活质量…

前端状态管理工具pinia:pinia是什么?相较于Vuex,pinia有什么优势,如何手动添加pinia到Vue3项目中

1.什么是pinia? Pinia是Vue的最新状态管理工具&#xff0c;是Vuex的替代品。 2.相较于Vuex,pinia有什么优势? 1.提供更加简单的API(去掉了mutation) 倘若你学习过vuex&#xff0c;你一定会发现很多很多不合理的地方,实现一个功能可能要在state定义数据&#xff0c;在muta…

【前端】零基础学会编写CSS

一、什么是CSS CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种是一种用来为结构化文档&#xff08;如 HTML 文档&#xff09;添加样式&#xff08;字体、间距和颜色等&#xff09;的计算机语言&#xff0c;能够对网页中元素位置的排版进行像素级别的精…

前端练习小项目——方向感应名片

前言&#xff1a;在学习完HTML和CSS之后&#xff0c;我们就可以开始做一些小项目了&#xff0c;本篇文章所讲的小项目为——方向感应名片 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 在开始学习之前&#xff0c;先让我们看一…

卷积神经网络——LeNet——FashionMNIST

目录 一、文件结构二、model.py三、model_train.py四、model_test.py 一、文件结构 二、model.py import torch from torch import nn from torchsummary import summaryclass LeNet(nn.Module):def __init__(self):super(LeNet,self).__init__()self.c1 nn.Conv2d(in_channe…

基于SSM的校园一卡通管理系统的设计与实现

摘 要 本报告全方位、深层次地阐述了校园一卡通管理系统从构思到落地的整个设计与实现历程。此系统凭借前沿的 SSM&#xff08;Spring、Spring MVC、MyBatis&#xff09;框架精心打造而成&#xff0c;旨在为学校构建一个兼具高效性、便利性与智能化的一卡通管理服务平台。 该系…

liunx硬盘分区挂载笔记

NAME: 设备名称。 MAJ : 主设备号和次设备号。 RM: 只读标志&#xff08;0 表示可读写&#xff0c;1 表示只读&#xff09;。 SIZE: 设备的总大小。 RO: 只读状态&#xff08;0 表示可读写&#xff0c;1 表示只读&#xff09;。 TYPE: 设备类型&#xff08;disk 表示物理磁盘设…

C 语言结构体

由于近期项目需求,需使用到大量的指针与结构体&#xff0c;为更好的完成项目&#xff0c;故对结构体与指针的内容进行回顾&#xff0c;同时撰写本博客&#xff0c;方便后续查阅。 本博客涉及的结构体知识有&#xff1a; 1.0&#xff1a;结构体的创建和使用 2.0: typedef 关…

怎样在 C 语言中进行类型转换?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; &#x1f4d9;C 语言百万年薪修炼课程 通俗易懂&#xff0c;深入浅出&#xff0c;匠心打磨&#xff0c;死磕细节&#xff0c;6年迭代&#xff0c;看过的人都说好。 文章目…

记一次 .NET某上位视觉程序 离奇崩溃分析

一&#xff1a;背景 1. 讲故事 前段时间有位朋友找到我&#xff0c;说他们有一个崩溃的dump让我帮忙看下怎么回事&#xff0c;确实有太多的人在网上找各种故障分析最后联系到了我&#xff0c;还好我一直都是免费分析&#xff0c;不收取任何费用&#xff0c;造福社区。 话不多…

快速读出linux 内核中全局变量

查问题时发现全局变量能读出来会提高效率&#xff0c;于是考虑从怎么读出内核态的全局变量&#xff0c;脚本如下 f open("/proc/kcore", rb) f.seek(4) # skip magic assert f.read(1) b\x02 # 64 位def read_number(bytes):return int.from_bytes(bytes, little,…

每日一练:奇怪的TTL字段(python实现图片操作实战)

打开图片&#xff0c;只有四种数字&#xff1a;127&#xff0c;191&#xff0c;63&#xff0c;255 最大数字为255&#xff0c;想到进制转换 将其均转换为二进制&#xff1a; 发现只有前2位不一样 想着把每个数的前俩位提取出来&#xff0c;组成新的二进制&#xff0c;然后每…

c++ 多边形 xyz 数据 获取 中心点方法,线的中心点取中心值搞定 已解决

有需求需要对。多边形 获取中心点方法&#xff0c;绝大多数都是 puthon和java版本。立体几何学中的知识。 封装函数 point ##########::getCenterOfGravity(std::vector<point> polygon) {if (polygon.size() < 2)return point();auto Area [](point p0, point p1, p…

AI绘画Midijourney操作技巧及变现渠道喂饭式教程!

前言 盘点Midijourney&#xff08;AIGF&#xff09;热门赚米方法&#xff0c;总有一种适合你之AI绘画操作技巧及变现渠道剖析 【表情包制作】 首先我们对表情包制作进行详细的讲解&#xff1a; 当使用 Midjourney&#xff08;AIGF&#xff09; 绘画来制作表情包时&#xff…

ensp防火墙综合实验作业+实验报告

实验目的要求及拓扑图&#xff1a; 我的拓扑&#xff1a; 更改防火墙和交换机&#xff1a; [USG6000V1-GigabitEthernet0/0/0]ip address 192.168.110.5 24 [USG6000V1-GigabitEthernet0/0/0]service-manage all permit [Huawei]vlan batch 10 20 [Huawei]int g0/0/2 [Huawei-…