题目
题解
第一个题解,不使用堆排序,卡在70/77,超时
void refresh(int gap, int* max, int ladders, int* need){
int insert = ladders - 1;
while(insert >= 0 && max[insert] > gap) insert--;
if(insert < 0){
//本次的楼梯高度差不大于之间最大的n个任何一个
*need = *need + gap;
}else{
*need = *need + max[0];
for(int i = 0; i < insert; i++){
max[i] = max[i+1];
}
max[insert] = gap;
}
}
int furthestBuilding(int* heights, int heightsSize, int bricks, int ladders){
//梯子为0个的情况
if(ladders == 0){
int station = 0;
for(int i = 1; i < heightsSize; i++){
//目前正站在i-1建筑物上。
if(heights[i] <= heights[i-1]){
station++;
}else{
bricks -= (heights[i] - heights[i-1]);
if(bricks >= 0){
station++;
}else{
break;
}
}
}
return station;
}
//n把梯子存放包括当前在内需要跨越的最大n个高度
int* max = (int*)malloc(sizeof(int)*ladders);
for(int i = 0; i < ladders; i++){
max[i] = 0;
}
//使用完梯子之后还需要的砖块数
int* need = (int*)malloc(sizeof(int));
*need = 0;
int station = 0;
for(int i = 1; i < heightsSize; i++){
//目前正站在i-1建筑物上。
if(heights[i] <= heights[i-1]){
station++;
}else{
refresh(heights[i]-heights[i-1], max, ladders, need);
if(bricks >= *need){
station++;
}else{
break;
}
}
}
return station;
}
第二个题解,使用了堆排序后就过了
//堆结构
typedef struct Heap{
int* data;
int size;
}Heap;
//堆初始化
void initialHeap(Heap* h){
for(int i = (h->size-1)/2;i >= 1;i--){
//特殊情况:序号最大的非叶节点可能会没有右孩子
if (i == (h->size - 1) / 2 && i * 2 + 1 == h->size) {
if (h->data[i * 2] < h->data[i]) {
int temp = h->data[i];
h->data[i] = h->data[2 * i];
h->data[2 * i] = temp;
}
continue;
}
//其他调整调整
if(h->data[i*2]<h->data[i] && h->data[i*2]<=h->data[2*i+1]){
int temp = h->data[i];
h->data[i] = h->data[2*i];
h->data[2*i] = temp;
}else if(h->data[i*2+1]<h->data[i] && h->data[i*2+1]<=h->data[2*i]){
int temp = h->data[i];
h->data[i] = h->data[2*i+1];
h->data[2*i+1] = temp;
}
}
}
//更新堆
int renewHeap(Heap* h, int x){
if(x <= h->data[1]) return x;
int theMin = h->data[1];
h->data[1] = x;
//从上往下调整,把最小的放在根上
int index = 1; //目前正在调整的索引
while(index <= (h->size-1)/2){
//特殊情况:序号最大的非叶节点可能会没有右孩子
if (index == (h->size - 1) / 2 && index * 2 + 1 == h->size) {
if (h->data[index * 2] < h->data[index]) {
int temp = h->data[index];
h->data[index] = h->data[2 * index];
h->data[2 * index] = temp;
}
break;
}
//其他非叶结点的调整
if(h->data[index]<=h->data[2*index] && h->data[index]<=h->data[2*index+1]){ //该索引位置已经比左右两孩子的值都小了,无需调整
break;
}
if(h->data[index*2]<h->data[index] && h->data[index*2]<=h->data[2*index+1]){
int temp = h->data[index];
h->data[index] = h->data[2*index];
h->data[2*index] = temp;
index = index*2;
}else if(h->data[index*2+1]<h->data[index] && h->data[index*2+1]<=h->data[2*index]){
int temp = h->data[index];
h->data[index] = h->data[2*index+1];
h->data[2*index+1] = temp;
index = index*2+1;
}
}
return theMin;
}
void refresh(int gap, int* max, int ladders, int* need){
if(gap <= max[0]){
*need = *need + gap;
}else{
*need = *need + max[0];
int i = 1;
for( ; i < ladders; i++){
if(max[i] < gap){
max[i-1] = max[i];
}else{
break;
}
}
max[i-1] = gap;
}
}
int furthestBuilding(int* heights, int heightsSize, int bricks, int ladders){
//梯子为0个的情况
if(ladders == 0){
int station = 0;
for(int i = 1; i < heightsSize; i++){
//目前正站在i-1建筑物上。
if(heights[i] <= heights[i-1]){
station++;
}else{
bricks -= (heights[i] - heights[i-1]);
if(bricks >= 0){
station++;
}else{
break;
}
}
}
return station;
}
//ladders把梯子存放包括当前在内需要跨越的最大ladders个高度
//声明一个堆,其中堆的大小是ladders+1,因为索引为0的位置不用,实际存放的数据还是ladders个。
Heap* h = (Heap*)malloc(sizeof(Heap));
h->size = ladders+1;
h->data = (int*)malloc(sizeof(int)*h->size);
//往堆内填充初试数据
for(int i = 0;i < ladders;i++){
h->data[i+1] = 0;
}
//初始化堆
initialHeap(h);
//使用完梯子之后还需要的砖块数
int* need = (int*)malloc(sizeof(int));
*need = 0;
int station = 0;
for(int i = 1; i < heightsSize; i++){
//目前正站在i-1建筑物上。
if(heights[i] <= heights[i-1]){
station++;
}else{
//更新堆
*need += renewHeap(h,heights[i] - heights[i-1]);
if(bricks >= *need){
station++;
}else{
break;
}
}
}
return station;
}
要点
使用贪心算法,【n个】梯子用在【之前走过的】和【现在正在走的】中最大的【n个】阶梯差,然后判断砖块数是否大于等于剩下的阶梯差之和。
记录最大的n个阶梯差使用最小堆数据结构,每次比较替换n个中最小的那个然后更新最小堆。