C语言 | Leetcode C语言题解之第295题数据流的中位数

题目:

题解:

typedef struct Heap
{
    int* array;   //存放堆的数组
    int  capacity;//数组的容量
    int  len;     //已存数组的大小
}Heap;
                                                        /*大小根堆切换开关*/
int  HeapLen(Heap* hp);                                 //heap获取当前的堆大小
void HeapSwap(int* pLeft, int* pRight);                 //heap交换父子结点的数值
bool HeapEmpty(Heap* hp);                               //heap判空
bool HeapFull(Heap* hp);                                //heap判满
int  HeapGetTop(Heap* hp);                              //heap获取堆顶
void HeapInsert(Heap* hp, int  dat,bool isMax);         //heap向堆的尾部插入1个元素
void HeapDelete(Heap* hp,bool isMax);                    //heap删除堆顶
void HeapAdjustDown(Heap* hp, int parent,bool isMax);   //heap向下调整
void HeapAdjustUp(Heap* hp, int child,bool isMax);      //heap向上调整
Heap* CreateHeap(int size);                             //heap创建
void heapFree(Heap* hp);                                //heap释放空间

int HeapLen(Heap* hp)
{
    return hp->len;
}

bool HeapEmpty(Heap* hp)          //判空
{
    if (HeapLen(hp) == 1)
    {
        return true;
    }
    return false;
}

bool HeapFull(Heap* hp)          //判满
{
    if (hp->capacity == hp->len)
    {
        return true;
    }
    return false;
}


void HeapSwap(int* pLeft, int* pRight)//交换数值
{
    //交换堆中的父子结点
    int  temp;
    temp    = *pLeft;
    *pLeft  = *pRight;
    *pRight = temp;
}

int HeapGetTop(Heap* hp)
{
    return hp->array[1];
}



Heap* CreateHeap(int size)
{
    Heap* heap = (Heap*)malloc(sizeof(Heap));
    int   heapLen = size + 1;//长度比size的长度大1才行
    //给堆申请空间,初始化
    heap->array = (int*)malloc(sizeof(int) * heapLen);
    heap->capacity  = heapLen;     //容量
    heap->len       = 1;           //当前大小
    return heap;
}

void HeapAdjustDown(Heap* hp, int parent ,bool isMax)//向下调整
{
    //标记左右孩子中最小孩子
    int child = 2 * parent;            //左孩子为2*parent  右孩子为 2*parent +1
    int len  = hp->len;
    while (child < len)
    {
        if(isMax)
        {
            //大根堆 选最大的
            //有右子树时 ,找左右孩子中最大的孩子 
            if ((child + 1 < len) && hp->array[child] < hp->array[child + 1])
                child = child + 1;

            //最大孩子大于双亲时 ,孩子与双亲数值交换,否则说明已经调好,不用继续
            if (hp->array[child] > hp->array[parent])
            {
                HeapSwap(&hp->array[child], &hp->array[parent]);
                parent = child;
                child = parent << 1;
            }
            else
                return;
        }
        else
        {
            //小根堆  选最小的
            //有右子树时 ,找左右孩子中最小的孩子 
            if ((child + 1 < len) && hp->array[child] > hp->array[child + 1])
                child = child + 1;

            //最小孩子小于双亲时 ,孩子与双亲数值交换,否则说明已经调好,不用继续
            if (hp->array[child] < hp->array[parent])
            {
                HeapSwap(&hp->array[child], &hp->array[parent]);
                parent = child;
                child = parent << 1;
            }
            else
                return;
        }
    }
}




void HeapAdjustUp(Heap* hp, int child,bool isMax)//向上调整
{
    //得到父母结点的位置
    int parent = child / 2;
    while (child > 1)
    {
        if(isMax)
        {
            //大根堆选择大的
            //循环迭代从child当前位置一直迭代到0位置即对顶
            if (hp->array[child] > hp->array[parent])
            {
                HeapSwap(&hp->array[child], &hp->array[parent]);
                child = parent;
                parent = child/2;
            }
            else
                return;
        }
        else
        {
            //小根堆选择小的
            //循环迭代从child当前位置一直迭代到0位置即对顶
            if (hp->array[child] < hp->array[parent])
            {
                HeapSwap(&hp->array[child], &hp->array[parent]);
                child = parent;
                parent = child/2;
            }
            else
                return;
        }
    }
}

void HeapDelete(Heap* hp,bool isMax)//删除堆顶
{
    if (HeapEmpty(hp))
        return;

    //用最后一个元素覆盖堆顶,相当于删除堆顶
    hp->array[1] = hp->array[hp->len - 1];
    hp->len--;//删除最后一个元素 heap长度变短
    HeapAdjustDown(hp, 1,isMax);//对第一个元素进行调整
}



void HeapInsert(Heap* hp, int  dat,bool isMax)
{
    if (HeapFull(hp))
    {
        //扩容
        hp->capacity <<= 1; 
        hp->array = (int *) realloc(hp->array, hp->capacity * sizeof(int));
    }
    int child = 0;
    int parent = 0;
    //插入到最后一个元素的下一个位置
    hp->array[hp->len++] = dat;
    //调整刚插入元素,
    //因为插入的是堆的尾部,需要堆向上调整
    HeapAdjustUp(hp, hp->len - 1,isMax);
}


void heapFree(Heap* hp)
{
    free(hp->array);
    free(hp);
}

typedef struct 
{
    //左边是 最大堆   右边是小根堆
    //0 1 3              5 7 9 
    Heap* maxLHeap;
    Heap* minRHeap; 
} MedianFinder;


MedianFinder* medianFinderCreate() 
{
    MedianFinder* newMedian = (MedianFinder* )malloc(sizeof(MedianFinder));
    newMedian->maxLHeap = CreateHeap(128);
    newMedian->minRHeap = CreateHeap(128);
    return newMedian;
}

void medianFinderAddNum(MedianFinder* obj, int num)
{
    //检查
    int leftHeapLen = obj->maxLHeap->len;
    int rightHeapLen = obj->minRHeap->len;

    if (leftHeapLen <= rightHeapLen)
    {
        //插入左边的最小堆


        //检查当前值 是否大于 右边的最小堆的堆顶值
        if (!HeapEmpty(obj->minRHeap))
        {
            if (num > obj->minRHeap->array[1])
            {
                //保存当前右边最小堆堆顶值 需要准备移动到 左边 最大堆中
                int  moveValue = obj->minRHeap->array[1];

                //将当前值放到 右边的最小堆 的堆顶
                obj->minRHeap->array[1] = num;
                HeapAdjustDown(obj->minRHeap, 1, false);

                //插入到左边最大堆中
                HeapInsert(obj->maxLHeap, moveValue, true);

                //直接结束了
                return;
            }
        }

        //这里检查 num是小于右边的 最小堆 的堆顶值的
        HeapInsert(obj->maxLHeap, num, true);
    }
    else
    {
        //插入右边的最大堆


        //检查当前值 是否小于 左边的最大堆的堆顶值
        if (!HeapEmpty(obj->maxLHeap))
        {
            if (num < obj->maxLHeap->array[1])
            {
                //保存当前左边最大堆堆顶值 需要准备移动到 右边 最小堆中
                int  moveValue = obj->maxLHeap->array[1];

                //将当前值放到 左边的最da堆 的堆顶
                obj->maxLHeap->array[1] = num;
                HeapAdjustDown(obj->maxLHeap, 1, true);

                //插入到右边最小堆中
                HeapInsert(obj->minRHeap, moveValue, false);

                //直接结束了
                return;
            }
        }
        //这里检查 num是大于左边的 最大堆 的堆顶值的
        HeapInsert(obj->minRHeap, num, false);
    }


}

double medianFinderFindMedian(MedianFinder* obj)
{
    if (obj->maxLHeap->len == obj->minRHeap->len)
    {
        return (double)(obj->minRHeap->array[1] + obj->maxLHeap->array[1]) / 2;
    }

    return (double)obj->maxLHeap->array[1];

}

void medianFinderFree(MedianFinder* obj) 
{
    heapFree(obj->maxLHeap);
    heapFree(obj->minRHeap);
    free(obj);
}

/**
 * Your MedianFinder struct will be instantiated and called as such:
 * MedianFinder* obj = medianFinderCreate();
 * medianFinderAddNum(obj, num);
 
 * double param_2 = medianFinderFindMedian(obj);
 
 * medianFinderFree(obj);
*/
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【1】项目代码完整且功能都验证ok,确保稳定可靠运行后才上传。欢迎下载使用!在使用过程中,如有问或建议,请及时私信沟通,帮助解答。 【2】项目主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 【3】项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 【4】如果基础还行,或热爱钻研,可基于此项目进行二次开发,DIY其他不同功能,欢迎交流学习。 【注意】 项目下载解压后,项目名字和项目路径不要用中文,否则可能会出现解析不了的错误,建议解压重命名为英文名字后再运行!有问私信沟通,祝顺利! 基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip
好的,我可以帮你解答这个问目描述: 给定一个 n x n 的网格,每个单元格都有一个正整数,代表从该点出发的初始能量。你的初始位置是左上角,即 (0,0) ,目标位置是右下角,即 (n-1,n-1)。你只能向右或向下走。在你走过某个单元格时,你需要用掉那个单元格中的能量(即:如果你在单元格(i,j)上,那么你需要用掉 grid[i][j] 的能量)。如果你没有足够的能量,那么你不能继续前进。你的目标是在保持最小初始能量的情况下,找到一条从左上角到右下角的路径,使得沿路径所需的能量最小化。 注意:当你经过某个单元格时,你需要跟踪你通过该单元格所剩余的能量(如果剩余能量为正数,则保留,否则将其归零)。 解思路: 本可以使用动态规划来解决。我们定义 dp[i][j] 表示从左上角到 (i, j) 位置所需要的最小初始能量。显然,dp[0][0] = grid[0][0]。 对于第一行和第一列,由于我们只能向右或向下走,因此我们可以得到: dp[0][j] = max(dp[0][j-1], grid[0][j]) dp[i][0] = max(dp[i-1][0], grid[i][0]) 对于其他位置,我们可以通过向右或向下移动到达该位置。因此,我们可以得到: dp[i][j] = min(max(dp[i-1][j], dp[i][j-1]) - grid[i][j], 0) + grid[i][j] 由于最终状态是 dp[n-1][n-1],因此我们可以得到最终的答案为 max(dp[n-1][n-1], 1)。 代码实现: ```c int calculateMinimumHP(int** dungeon, int dungeonSize, int* dungeonColSize){ int m = dungeonSize, n = dungeonColSize[0]; int dp[m][n]; dp[0][0] = dungeon[0][0]; for (int j = 1; j < n; j++) { dp[0][j] = max(dp[0][j-1], dungeon[0][j]); } for (int i = 1; i < m; i++) { dp[i][0] = max(dp[i-1][0], dungeon[i][0]); } for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = min(max(dp[i-1][j], dp[i][j-1]) - dungeon[i][j], 0) + dungeon[i][j]; } } return max(dp[m-1][n-1], 1); } ``` 这就是使用完整的c语言完成leetcode第1514的代码实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值