力扣刷题-1642.可以到达的最远建筑

题目

题解

第一个题解,不使用堆排序,卡在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;
}

要点

  1. 使用贪心算法,【n个】梯子用在【之前走过的】和【现在正在走的】中最大的【n个】阶梯差,然后判断砖块数是否大于等于剩下的阶梯差之和。

  1. 记录最大的n个阶梯差使用最小堆数据结构,每次比较替换n个中最小的那个然后更新最小堆。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

东东咚咚东

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

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

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

打赏作者

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

抵扣说明:

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

余额充值