您的位置:首页 > 娱乐 > 八卦 > 武汉光谷建设_上海迪士尼乐园官网_象山seo外包服务优化_桂林最新消息今天

武汉光谷建设_上海迪士尼乐园官网_象山seo外包服务优化_桂林最新消息今天

2025/5/2 7:59:33 来源:https://blog.csdn.net/Qiang_san/article/details/144791916  浏览:    关键词:武汉光谷建设_上海迪士尼乐园官网_象山seo外包服务优化_桂林最新消息今天
武汉光谷建设_上海迪士尼乐园官网_象山seo外包服务优化_桂林最新消息今天

前言

本博客会分享Leetcode3218. 切蛋糕的最小总开销 I解题思路,这是12月25日的每日一题。文章第二部分会分享一下自己的解题思维过程,如何通过刷题提升自己的算法能力。

3218. 切蛋糕的最小总开销 I - 力扣(LeetCode)

在这里插入图片描述

看完题目的第一反应,这道题应该是用贪心算法进行解题。可以想到满足最终答案res有以下公式:
r e s = ∑ C u t ∗ ( C o t O p p o s i t e S i d e + 1 ) res=\sum{Cut}*(CotOppositeSide+1) res=Cut(CotOppositeSide+1)
Cut指切蛋糕的花销,CotOppositeSide指异侧已经切了的刀数。根据样例中的动图:

  • 第一刀,沿垂直线0切时:Cut=5,CotOppositeSide=0
  • 第二刀,沿水平线0切时:Cut=1,CotOppositeSide=1
  • 以此类推…

在这里插入图片描述

对于某一刀花销Cut是一定的,所以CotOppositeSideres是正相关。要想使答案尽可能的小,就得尽量让较大的Cut对应较小的CotOppositeSide。结合题目中给的数据范围,一开始我想到用堆维护当前Cut的最大值,并且需要回溯去分别计算水平最大值优先或者垂直最大值优先的结果,最后再输出最小值。但是实际上并不需要,直接同时考虑全局下的花销最大值即可,也就有了如下的代码:

int minimumCost(int m, int n, vector<int>& horizontalCut, vector<int>& verticalCut) {priority_queue<pair<int,bool>,vector<pair<int,bool>>,less<>> q;for(int i=0;i<horizontalCut.size();i++){q.push({horizontalCut[i],true});}for(int i=0;i<verticalCut.size();i++){q.push({verticalCut[i],false});}int hori=0,vert=0;int res=0;while(!q.empty()){auto tmp=q.top();q.pop();if(tmp.second){res+=tmp.first*(vert+1);hori++;}else{res+=tmp.first*(hori+1);vert++;}}return res;}

这段代码能过这道题,甚至困难难度的3219. 切蛋糕的最小总开销 II - 力扣(LeetCode)也能勉强过。代码时间复杂度为O(mlogm+nlogn+(n+m)log(m+n)),仍有优化的空间

学习题解

优化自己的代码

如果只是单纯的维护Cut的最大值,没有必要使用堆去维护,每次出堆都会需要再次调整堆,导致了不必要的时间开销。只需要对数组进行排序,然后再用双指针控制此时Cut是最大值即可,这样处理之后算法的时间复杂度降低到了O(mlogm+nlogn).优化后得到了如下的代码:

int minimumCost(int m, int n, vector<int>& horizontalCut, vector<int>& verticalCut) {sort(horizontalCut.begin(),horizontalCut.end(),greater());sort(verticalCut.begin(),verticalCut.end(),greater());int hor=0,ver=0;auto it_hor=horizontalCut.begin(),it_ver=verticalCut.begin();int res=0;while(it_hor!=horizontalCut.end() || it_ver!=verticalCut.end()){//注意处理指针已经到数组最后的情况if(it_hor!=horizontalCut.end() && it_ver!=verticalCut.end()){if(*it_hor>(*it_ver)){res+=(*it_hor)*(ver+1);it_hor++;hor++;}else{res+=(*it_ver)*(hor+1);it_ver++;ver++;}}else if(it_hor!=horizontalCut.end()){res+=(*it_hor)*(ver+1);it_hor++;}else{res+=(*it_ver)*(hor+1);it_ver++;}}return res;}

学习新算法

在看题解的时候,关注都灵神的题解,用的是最小生成树的 Kruskal 算法。自然而然就会驱使自己去学习这个此前没有学习过的算法,加之有这道题的背景,学习新算法的时候就更容易理解新算法的思想,能更快掌握新的算法。至此,总结出如下的刷算法题的思维导图:

在这里插入图片描述

谢谢你的阅读!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com