力扣(LeetCode)每日随机一题——1353.最多可以参加的会议数目[中等]

本文介绍了一个使用贪心策略和优先队列的编程题解,涉及如何在给定的会议时间表中选择最多可以参加的会议,同时关注了JavaPriorityQueue的使用和几个关键方法如computeIfAbsent、containsKey和addAll。
摘要由CSDN通过智能技术生成

一、题目

最多可以参加的会议数目

12
3

二、代码

没做出来呜呜😢

class Solution {

    // 贪心技术的活动安排问题-与标准活动安排问题不同的是前者在固定时间段都需占用,而本题只需要选择时间段内一天即可
    // 按开始时间和结束时间都排序...按开始选或结尾选-尝试了一下好像按尾选要容易些
    // 基本方向有,但具体思路没想出来,无法处理 在无论按头或按尾都发现若有多个相同值时如何挑选 的问题

    public int maxEvents(int[][] events) {
        return 0;
    }
}

三、题解

贪心+优先队列模拟

贪心:优先参加结束时间距离当前时间最近的会议~

class Solution {

    public int maxEvents(int[][] events) {

        // max 为最后一个会议结束的时间
        
        int ans = 0, max = -1;

        // 按会议结束时间升序排序
        // 当a-b为负数的时候表示a的优先级更高,故a-b表示值越小优先级越高

        PriorityQueue<Integer> queue = new PriorityQueue<>((a, b) -> a - b);	// 1

        // key -> 第 i 天, value -> 第 i 天开始的会议的结束时间
   
        Map<Integer, List<Integer>> map = new HashMap<>();
			
		// for用于遍历二维数组的行,从0开始,故循环体内的e[0]和e[1]分别表示e[i][0]和e[i][1]
        for (int[] e : events) {
        
        	// 将开始时间相同的所有会议的结束时间集合在一起
        	// "computeIfAbsent(e[0], k -> new ArrayList<>())"返回的是列表;这一部分,若出现新的开始时间,则建立一个新键及其新列表与其对应,并将当前结束时间添加到列表中;若map中已存在此开始时间,则在后面继续添加相对应的结束时间
        	// 这里的add为Map.Array.add();
            map.computeIfAbsent(e[0], k -> new ArrayList<>()).add(e[1]);	// 2

			// max 为最后一个会议结束的时间
            max = Math.max(e[1], max);

        }

        // 模拟:忘了的话可以跑一遍队列
        // 整体思路就是从1开始到最晚结束时间依次遍历一遍,然后挑选此时间要进行的会议;而队列的作用就是存储未进行的会议;挑选的判断条件就是挑选的时间不能小于此时的时间,因为队列中存储的是每个会议最晚进行时间,即,结束时间

        for (int i = 1; i <= max; i++) {

            if (map.containsKey(i)) {	// 3
            	// 队列在addAll进行插入操作时,已经将队列排至有序堆状态	5 
            	queue.addAll(map.get(i));	// 4
            }

			// 

			// peek() :返回队列头元素但不移除,如果队列为空,则返回null
            while (!queue.isEmpty() && queue.peek() < i) {
            	// poll() : 移除队列头的元素并且返回,如果队列为空则返回null
            	queue.poll();
            }
            if (!queue.isEmpty()) {

                ans++;
				// poll() : 移除队列头的元素并且返回,如果队列为空则返回null
                queue.poll();

            }

        }

        return ans;

    }

}

来源:力扣(LeetCode

四、总结

题解代码学习解析

1.优先级队列

① 优先级队列是一种特殊类型的队列,其中每个元素都与一个优先级值相关联。并且,元素根据其优先级提供服务。即,首先服务更高优先级的元素。但是,如果出现具有相同优先级的元素,则按照它们在队列中的顺序提供服务。
② Java中PriorityQueue的使用
优先队列相较于队列的区别就在于优先队列最先出队的总是优先级最高的元素
Java提供了PriorityQueue类实现优先队列,由于它实现了Queue接口,也可以通过Queue引用

Queue<Integer> priorityQueue = new PriorityQueue<>((a,b)->b-a);

不同于Queue,定义PriorityQueue时需要传入一个比较器Comparator(如上述代码中((a,b) -> b-a)),这个比较器将决定元素的优先级,决定方式类似于List的sort()方法,也就是当传入a,b时,如果a优先度更高,就会返回负数,如果b优先度高就返回正数,相等就返回0。上面的例子就是表示数值大的优先度更高
也可以不传入Comparator,这样的话它的元素就需要实现Comparable接口,例如

Queue<Integer> priorityQueue = new PriorityQueue<>();

Integer本身也实现了Comparable接口,比较方法如下

public static int compare(int x, int y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

因此上面的priorityQueue中数值小的优先度更高

实例:

Queue<Integer> priorityQueue = new PriorityQueue<>();
for(int i=0;i<10;i++){
	//  Math.random()函数是取[0,1)之间的随机数
    priorityQueue.add((int)(Math.random()*40+1));
}
System.out.println(String.format("list:%s", priorityQueue));
// list:[6, 8, 19, 18, 15, 35, 27, 40, 30, 36]

③ Java之Queue接口中add()/offer()、remove()/poll()、element()/peek()的区别
(1).add() 和 offer()
add() : 添加元素,如果添加成功则返回true,如果队列是满的,则抛出异常
offer() : 添加元素,如果添加成功则返回true,如果队列是满的,则返回false
区别:对于一些有容量限制的队列,当队列满的时候,用add()方法添加元素,则会抛出异常,用offer()添加元素,则返回false
(2).remove() 和 poll()
remove() : 移除队列头的元素并且返回,如果队列为空则抛出异常
poll() : 移除队列头的元素并且返回,如果队列为空则返回null
区别:在移除队列头元素时,当队列为空的时候,用remove()方法会抛出异常,用poll()方法则会返回null
(3).element() 和 peek()
element() :返回队列头元素但不移除,如果队列为空,则抛出异常
peek() :返回队列头元素但不移除,如果队列为空,则返回null
区别 :在取出队列头元素时,如果队列为空,用element()方法则会抛出异常,用peek()方法则会返回null

2.computeIfAbsent方法(返回值:返回的就是value值)

// 如果map中不存在等于"键"的k,则添加为"键"的k以及"对应的值",如果有,则不操作
        System.out.println("--------------mapComputeIfAbsent-----------------");
        Map mapComputeIfAbsent = new HashMap<String, String>();
        Object valueAbsent = mapComputeIfAbsent.computeIfAbsent("键", k -> "value");
        Object valueAbsent2 = mapComputeIfAbsent.computeIfAbsent("键", k -> "value2");
        System.out.println(mapComputeIfAbsent); //输出结果 {键=value}
        System.out.println(valueAbsent); //输出结果 value
        System.out.println(valueAbsent2); //输出结果 value

3.containKey(key)方法

Map类中的containKey(key)方法是判断该key在map中是否有key存在。如果存在则返回true,反之,返回false

4.addAll方法

Queue中的addAll(Collection c)方法将集合c中的元素都添加到队列中;如果c为空则抛出异常,如果c就是队列本身,也抛出异常

5.java优先队列PriorityQueue修改队列内元素排序问题

PriorityQueue队列是基于堆排序不断更新排序的,但前提是要插入(删除)数据,如果仅仅是修改已经稳定队列的值或内容,而不进行插入或者删除,那么,这个顺序是不会变的。
举个例子:

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

public class BankerClass {

 public static void main(String[] args)
 {
 	Queueq1=new PriorityQueue(com);
 	q1.add(new node(1, 5));
 	node team=new node(2, 2);
 	q1.add(team);
 	q1.add(new node(3, 9));
 	q1.add(new node(4, 7));
 	for(node no:q1)
 	{
 		System.out.println("id :"+ no.id +" value" +no.value);
 	}
 	System.out.println();
 	team.value=6;//修改了value,按道理不应该在第一,
 	for(node no:q1)
 	{
 		System.out.println("id :" +no.id " value" +no.value);
 	}
 	
 }
 static Comparatorcom=new Comparator() {

		@Override
		public int compare(node o1, node o2) {//基于value排序
			return o1.value-o2.value;
		}
	};
static class node
{
	int id;
	int value;
	public node(int id,int value)
	{
		this.value=value;
		this.id=id;
	}
}
}

输出为:
id :2 value2
id :1 value5
id :3 value9
id :4 value7

id :2 value6
id :1 value5
id :3 value9
id :4 value7

如果想更新排序,可以这样操作:移除后添加
q1.remove(team);
q1.add(team);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值