NC刷题笔记6-堆

本博客文章(学习笔记)导航 (点击这里访问)
在这里插入图片描述

NC51 合并k个已排序的链表

import java.util.  ;
public class Solution {
    public ListNode mergeKLists(ArrayList<ListNode> lists){
        ListNode res=new ListNode(0);
        ListNode result=res;
        PriorityQueue<ListNode> queue=new PriorityQueue<ListNode>((a,b)->{
            return a.val-b.val;
        });
        for(ListNode t:lists){
            if(t!=null) queue.offer(t);
        }
        while(!queue.isEmpty()){
            ListNode temp=queue.poll();
            result.next=temp;
            result=result.next;
            temp=temp.next;
            if(temp!=null) queue.offer(temp);
        }
        return res.next;
    }
}

NC82 滑动窗口最大值

描述
给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。
例如,如果输入数组 {2,3,4,2,6,2,5,1} 及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为 {4,4,6,6,6,5}; 针对数组 {2,3,4,2,6,2,5,1} 的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
窗口大于数组长度或窗口长度为0的时候,返回空。
数据范围:1 ≤ n ≤ 10000,0 ≤ size ≤ 10000,数组中每个元素的值满足0 ≤∣val∣≤10000
要求:空间复杂度 O(n),时间复杂度 O(n)

示例1  输入:[2,3,4,2,6,2,5,1],3  返回值:[4,4,6,6,6,5]
示例2  输入:[9,10,9,-7,-3,8,2,-6],5  返回值:[10,10,9,8]
示例3  输入:[1,2,3,4],5  返回值:[]
思路:
	优先队列
	1 先放size-1个
	2 从第size个开始放,没放一次就移除过界元素
import java.util.  ;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size) {
        PriorityQueue<int[]> queue=new PriorityQueue<int[]>((a1,a2)->{
            return a1[0]==a2[0]?a1[1]-a2[1]:a2[0]-a1[0];
        });
        ArrayList<Integer> res=new ArrayList<Integer>();
        if(num.length==0||size==0) return res;
        for(int i=0;i<size-1;i++){
            queue.offer(new int[]{num[i],i});
        }
        for(int i=size-1;i<num.length;i++){
            queue.offer(new int[]{num[i],i});
            while(queue.peek()[1]<(i-size+1)){
                queue.poll();
            }
            res.add(queue.peek()[0]);
        }
        return res;
    }
}

NC88 寻找第K大

描述
有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。
给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。
要求:时间复杂度O(nlogn),空间复杂度O(1)
数据范围:0≤n≤1000,1≤K≤n,数组中每个元素满足0≤val≤10000000
示例1
输入:[1,3,5,2,2],5,3
返回值:2
示例2
输入:[10,10,9,9,8,7,5,6,4,3,4,2],12,3
返回值:9
说明:
去重后的第3大是8,但本题要求包含重复的元素,不用去重,所以输出9
思路 快速排序
import java.util.  ;
 
public class Solution {
    public int findKth(int[] a, int n, int K) {
        quicksort(a,0,a.length-1);
        return a[K-1];
    }
    public void quicksort(int[] a,int left,int right){
        int l=left,r=right,povit=a[(l+r)/2];
        while(l<r){
            while(a[l]>povit) l++;
            while(a[r]<povit) r--;
            if (l >= r) break;
            int temp=a[l];
            a[l]=a[r];
            a[r]=temp;
            if(a[l]==povit) r--;
            if(a[r]==povit) l++;
        }
        if(l==r){
            l++;
            r--;
        }
        if(l<right) quicksort(a,l,right);
        if(r>left) quicksort(a,left,r);
    }
}

NC119 最小的K个数

描述
给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。
数据范围:100000≤k,n≤10000,数组中每个数的大小0≤val≤1000
要求:空间复杂度 O(n),时间复杂度 O(nlogn)

示例1
输入:[4,5,1,6,2,7,3,8],4 
返回值:[1,2,3,4]
说明:返回最小的4个数即可,返回[1,3,2,4]也可以        

示例2
输入:[1],0
返回值:[]

示例3
输入:[0,1,2,1,2],3
返回值:[0,1,1]
思路:
	优先队列
	选择大顶堆,把最大的弹出来
import java.util.  ;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        PriorityQueue<Integer> q=new PriorityQueue<Integer>((a,b)->b-a);
        for(int i=0;i<input.length;i++){
            q.offer(input[i]);
            while(q.size()>k) q.poll();
        }
        ArrayList<Integer> res=new ArrayList<Integer>();
        while(!q.isEmpty()) res.add(q.poll());
        return res;
    }
}

NC131 数据流中的中位数

描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
数据范围:数据流中数个数满足1≤n≤1000  ,大小满足1≤val≤1000 
进阶: 空间复杂度 O(n) , 时间复杂度 O(nlogn)
示例1  输入:[5,2,3,4,1,6,7,0,8]  返回值:"5.00 3.50 3.00 3.50 3.00 3.50 4.00 3.50 4.00 "
说明:数据流里面不断吐出的是5,2,3...,则得到的平均数分别为5,(5+2)/2,3...   
示例2  输入:[1,1,1]  返回值:"1.00 1.00 1.00 "
思路:
	小顶堆:放较大的数
	大顶堆:放较小的数
import java.util.  ;
public class Solution {
    PriorityQueue<Integer> minQ=new PriorityQueue<>();
    PriorityQueue<Integer> maxQ=new PriorityQueue<>((a,b)->b-a);
    public void Insert(Integer num) {
        if(maxQ.isEmpty()){
            maxQ.offer(num);
        }else if(maxQ.size()==minQ.size()){
            if(maxQ.peek()>=num){
                maxQ.offer(num);
            }else{
                minQ.offer(num);
                maxQ.offer(minQ.poll());
            }
        }else if(maxQ.size()>minQ.size()){
            if(num>maxQ.peek()){
                minQ.offer(num);
            }else{
                minQ.offer(maxQ.poll());
                maxQ.offer(num);
            }
        }
    }

    public Double GetMedian() {
        if(maxQ.size()==minQ.size()) return (maxQ.peek()+minQ.peek())/2.0;
        return maxQ.peek()/1.0;
    }
}

NC251 多数组第 K 小数

描述
给定两个升序的数列 arr1 和 arr2 ,和一个整数 target ,请你找出两个数列中第 K 小的值。
数据范围:两个数列的长度都满足1≤n≤10^6,数列中的值都满足1≤val≤10^9,给定整数大小满足1≤target≤len(arr1)+len(arr2) 

示例1
输入:[1,2,3,4],[1,3,4],2
返回值:1
说明:两个数列中数升序排列是 1 1 2 3 3 4,故第二小的是 1 

示例2
输入:[1,2,3,4],[1,3,4],7
返回值:4
思路1:
	优先队列 空间复杂度 O(1) 时间复杂度O(nlog(n))
思路2:
	排序 空间复杂度 O(n) 时间复杂度 O(n)
思路3:
	合并数组 空间复杂度 O(1) 时间复杂度O(1)
思路1import java.util.  ;
public class Solution {
    public int findKthNum (int[] arr1, int[] arr2, int target) {
        PriorityQueue<Integer> q=new PriorityQueue<Integer>((a,b)->b-a);
        for(int i:arr1){
            q.offer(i);
            while(q.size()>target) q.poll();
        }
        for(int i:arr2){
            q.offer(i);
            while(q.size()>target) q.poll();
        }
        return q.peek();
    }
}
思路2import java.util.  ;
public class Solution {
    public int findKthNum (int[] arr1, int[] arr2, int target) {
        List<Integer> list=new ArrayList<>();
        for (int arr:arr1){
            list.add(arr);
        }
        for (int arr:arr2){
            list.add(arr);
        }
        Collections.sort(list);
        int i1 = list.get(target-1);
        return i1;
    }
}
思路3import java.util.  ;
public class Solution {
    public int findKthNum (int[] arr1, int[] arr2, int target) {
        int i=0;
        int l=0,r=0;
        while(l<arr1.length && r<arr2.length){
            if(arr1[l]<=arr2[r]){
                i++;
                if(i==target) return arr1[l];
                l++;
            }else{
                i++;
                if(i==target) return arr2[r];
                r++;
            }
        }
        while(l<arr1.length){
            i++;
            if(i==target) return arr1[l];
            l++;
        }
        while(r<arr2.length){
             i++;
             if(i==target) return arr2[r];
             r++;
        }
        return 0;
    }
}

NC252 多数组中位数

描述
给定两个升序的数组 arr1 和 arr2 ,求两个数组合并后的下中位数
注意:下中位数指在两个数组的数个数在偶数时取更小的
数据范围:两个数组的长度都满足1≤n≤10^6 ,数组中的所有值都满足0≤val≤10^9

示例1
输入:[1,2,3],[3,4,5]
返回值:3

示例2
输入:[1,2,3],[4,5]
返回值:3
思路:
	合并数组
import java.util.  ;
public class Solution {
    public int getUpMedian (int[] arr1, int[] arr2) {
        int num=arr1.length+arr2.length;
        if(num%2==1) num=num+1;
        return findKthNum(arr1,arr2,num/2);
    }
    public int findKthNum (int[] arr1, int[] arr2, int target) {
        int i=0;
        int l=0,r=0;
        while(l<arr1.length && r<arr2.length){
            if(arr1[l]<=arr2[r]){
                i++;
                if(i==target) return arr1[l];
                l++;
            }else{
                i++;
                if(i==target) return arr2[r];
                r++;
            }
        }
        while(l<arr1.length){
            i++;
            if(i==target) return arr1[l];
            l++;
        }
        while(r<arr2.length){
             i++;
             if(i==target) return arr2[r];
             r++;
        }
        return 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CandyDingDing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值