本博客文章(学习笔记)导航 (点击这里访问)
![在这里插入图片描述](https://img-blog.csdnimg.cn/fe463387c4ab4c1c85662c7f78ceff23.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATuKCgg==,size_20,color_FFFFFF,t_70,g_se,x_16)
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)
思路1:
import 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();
}
}
思路2:
import 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;
}
}
思路3:
import 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;
}
}