LeeCode 01-坐上公交的最晚时间
问题描述:给你一个下标从 0 开始长度为 n 的整数数组 buses ,其中 buses[i] 表示第 i 辆公交车的出发时间。同时给你一个下标从 0 开始长度为 m 的整数数组 passengers ,其中 passengers[j] 表示第 j 位乘客的到达时间。所有公交车出发的时间互不相同,所有乘客到达的时间也互不相同。
给你一个整数 capacity ,表示每辆公交车 最多 能容纳的乘客数目。
每位乘客都会排队搭乘下一辆有座位的公交车。如果你在 y 时刻到达,公交在 x 时刻出发,满足 y <= x 且公交没有满,那么你可以搭乘这一辆公交。最早 到达的乘客优先上车。
返回你可以搭乘公交车的最晚到达公交站时间。你 不能 跟别的乘客同时刻到达。
注意:数组 buses 和 passengers 不一定是有序的。
示例:
示例 1:
输入:buses = [10,20], passengers = [2,17,18,19], capacity = 2
输出:16
解释:
第 1 辆公交车载着第 1 位乘客。
第 2 辆公交车载着你和第 2 位乘客。
注意你不能跟其他乘客同一时间到达,所以你必须在第二位乘客之前到达。
示例 2:
输入:buses = [20,30,10], passengers = [19,13,26,4,25,11,21], capacity = 2
输出:20
解释:
第 1 辆公交车载着第 4 位乘客。
第 2 辆公交车载着第 6 位和第 2 位乘客。
第 3 辆公交车载着第 1 位乘客和你。
提示:
n == buses.length
m == passengers.length
1 <= n, m, capacity <= 105
2 <= buses[i], passengers[i] <= 109
buses 中的元素 互不相同 。
passengers 中的元素 互不相同 。
本人做法:
int latestTimeCatchTheBus(int buses, int busesSize, int passengers, int passengersSize, int capacity) {
/*
总思路
- 排序 将buses,passages数组从小到大排序
- 最晚时间到达 即
1> 选择到达时间最晚的公交 即下标为N-1的数组
2> 按照乘客到达的时间从早到晚依次将busessize-1量公交车乘客安排完毕
3> 继续安排最后一辆公交车的乘客
/
/
子问题一 排序 冒泡排序
1.依次比较i i+1两个元素的大小
1.1 若i > i + 1,返回1
1.2 若i < i + 1,交换二者位置
2.循环 n - 1 n - 1次 /
/
问题二 安排乘客
1.从下标i = 0 i<busesSize-2 外层,j = 0 内层 开始
2.若(buses + i)>*(passengers + j) - j+1 z+1
z==capacity或乘客不符合条件 i + 1
*/int time; //最晚到达时间
int lasttime; //原本最后一位乘客的抵达时间for(int j = 0; j < busesSize - 1; j++) { //公交车抵达时间排序
for(int i = 0; i < busesSize - 1 - j; i++) {
if((buses + i) < (buses + i + 1)) {continue;
}
else {int z = *(buses + i); *(buses + i) = *(buses + i + 1); *(buses + i + 1) = z;
}
}
}
for(int j = 0; j < passengersSize - 1; j++) { //乘客到达时间排序
for(int i = 0; i < passengersSize - 1 - j; i++) {
if((passengers + i) < (passengers + i + 1)) {continue;
}
else {int z = *(passengers + i); *(passengers + i) = *(passengers + i + 1); *(passengers + i + 1) = z;
}
}
}
int j1 = 0;
int i = 0;
int q = capacity;
for(i = 0; i <= busesSize-2; i++){ //除最后一辆车外安排好其余乘客 j表示倒数第二辆车的最后一位乘客下标
for(q = capacity; q > 0; q—){if(*(passengers + j1) < *(buses + i)){ //如果乘客到达时间小于公交车到达时间 j1++; } else{ break; }
}
}
int j = j1 - 1;if(passengersSize - j1 >=capacity){
for(int c = capacity; c > 0; c—){if(*(passengers + j + c) - 1 != *(passengers + j + c - 1)){ time = *(passengers + j + c) - 1; break; } else if(c == 1){ time = *(passengers + j + 1) - 1; //极端情况,安排乘客抵达时间在第一个乘客前 break; }
}
}return time;
}
官方解答:
int compare(const void a, const void b) {
return ((int)a - (int)b);
}
int latestTimeCatchTheBus(int buses, int busesSize, int passengers, int passengersSize, int capacity) {
qsort(buses, busesSize, sizeof(int), compare); //公交车到达时间排序
qsort(passengers, passengersSize, sizeof(int), compare); //乘客到达时间排序
int pos = 0; //第pos位乘客上车
int space = 0; //公交车容量
for (int i = 0; i < busesSize; i++) {
int arrive = buses[i]; //第i(从0开始计数)量车情况
space = capacity; //每辆公交车初始容量为capacity
while (space > 0 && pos < passengersSize && passengers[pos] <= arrive) {
//乘客上车条件:如果剩余容量>0,还有乘客未走,以及乘客抵达时间<=公交车到达时间
//反之若不满足任意条件,即,该辆公交车容量已满,或已经没有乘客,或乘客到达时间晚于公交车时间,跳出循环,转为下一辆车
space--;
pos++;
//在比较完下标为0的乘客时,pos = 1,已经指向下一位乘客数组下标,所以比到最后一位时,pos的值也会比下标大1,代表走了第几位(1开始计数)乘客
}
}
pos--; //指向最后一位上车乘客的元素
int lastCatchTime = space > 0 ? buses[busesSize - 1] : passengers[pos];
//space也可代表最后一辆公交车的剩余容量情况
while (pos >= 0 && passengers[pos] == lastCatchTime) {
pos--;
lastCatchTime--;
}
return lastCatchTime;
}
代码解读:
qsort — 用于数组排序的函数 英语quick sort快速排序
一、头文件
include
二、格式
int cmp(const void a,const void b) {
return (int)a-(int)b;
}
qsort(num, n, sizeof(int), cmp);
包含四个参数(数组名, 数组长度,数组元素数据类型所占字节,排序原则)
使用方法:
定义一个函数cmp(自命名),通过cmp返回的参数确定排序规则,其中cmp函数的参数需要以(const void a,consi void b)的形式定义,表示a,b变量的数据类型未知,在return返回时,用强制类型转换转换为int型,(int)a - (int)b 表示递增顺序,同理,(int)b - (int)a 表示递减顺序
排序原则:
根据要排序数组元素数据类型的不同,可分为四种
1.int型
int cmp(const void a,const void b) {
return (int)a-(int)b;
}
2.double型
int cmp(const void a,const void b) {
return (double)a>(double)b?1:-1;
}
需要注意浮点数会存在精度损失的问题,所以我们需要通过比较,来返回1或-1,以确定是增序还是降序。
3.char型
int cmp(const void a,const void b) {
return (char)a-(char)b;
}
4.结构体型
struct node{
int i;
double j;
char k;
};
int cmp(const void a,const void b) {
return ((node)a).i-((node)b).i;
}
深度剖析:
void qsort(void base, //指向了待排序数组的第一个元素
size_t num, //待排序的元素个数
size_t size, //每个元素的大小,单位是字节
int ( cmp)(const void, const void) //指向一个函数,这个函数可以比较2个元素的大小
);
返回类型void:我们改变的是数列的排序,实际只需要进行内存的操作,所以不需要返回值。
void base:表示应传入初始地址,至于为什么是void类型,它不知道我们会传入什么数据,而void类型就像一个垃圾桶一样什么地址都可以仍进去,所以只能用void类型。
size_t num:num数量,表示应传入的元素个数
size_t width:width宽度,表示应传入的每个元素占的字节大小
int (cmp)(const void , const void *):
应传入一个比较函数地址,用于比较两个数据的大小,因为传入的数据类型是不确定的,所以我们需要自己定义一个比较函数传到qsort比较函数里面去,以便它知道怎么样去比较两个数据的大小。
qsort可以排序任意类型的数据
比较2个整数的大小,> < ==
比较2个字符串的大小,strcmp
比较2个结构体数据(学生:张三,李四)指定比较的标准
const void a
关键字 const
作用:用const修饰的变量或对象的值不能再被改变
根据数据类型的不同分为:
1.修饰普通变量
const int n=5;
注意:用const修饰变量时,一定要给变量初始化,否则之后不能再进行赋值
int const n=5;
两种情况,n的值都不能再被改变
2.修饰指针
1>常量指针:指针指向的内容是常量
const int n;
int const n;
注意:仅仅指 指针指向的内容为常量,相当于,常量指针指向哪个变量,哪个变量的值不能被改变,但是不能通过这个指针改变变量的值,但还是可以通过其他的引用来改变变量的值 【存疑-那常量指针的意义在哪】
int a=5;
const int n=&a;
a=6;
2>指针常量:指针自己是常量,即只能指向一个地址,但指向的内容可以改变
int a=5;
int p=&a;
int const n=&a;
p=8;
区分指针常量,常量指针:字面翻译
const int n; 先常量后指针,常量指针
int* const n=&a; 先指针后常量,指针常量,指针(是)常量
(int)a-(int)b
(int*)a :强制类型转换,将a的数据类型强制转换成整型指针
强制类型转换:(type_name) expression 即 (要转换的目标类型)被转换的变量或表达式
学习心得:
循环条件有顺序,eg:while (pos >= 0 && passengers[pos] == lastCatchTime) 判断完第一个条件符合后才进行第二个条件
所以必要的边界条件先写,再写后面的逻辑约束条件