开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第33天,点击查看活动详情
✨欢迎关注🖱点赞🎀收藏⭐留言✒
🔮本文由京与旧铺原创,csdn首发!
😘系列专栏:算法学习
💻首发时间:🎞2022年12月27日🎠
🀄如果觉得博主的文章还不错的话,请三连支持一下博主哦
🎧作者是一个新人,在很多方面还做的不好,欢迎大佬指正,一起学习哦,冲冲冲
⭐️1739. 放置盒子⭐️
🔐题目详情
难度困难
有一个立方体房间,其长度、宽度和高度都等于 n 个单位。请你在房间里放置 n 个盒子,每个盒子都是一个单位边长的立方体。放置规则如下:
- 你可以把盒子放在地板上的任何地方。
- 如果盒子
x需要放置在盒子y的顶部,那么盒子y竖直的四个侧面都 必须 与另一个盒子或墙相邻。
给你一个整数 n ,返回接触地面的盒子的 最少 可能数量*。*
示例 1:
输入:n = 3
输出:3
解释:上图是 3 个盒子的摆放位置。
这些盒子放在房间的一角,对应左侧位置。
示例 2:
输入:n = 4
输出:3
解释:上图是 3 个盒子的摆放位置。
这些盒子放在房间的一角,对应左侧位置。
示例 3:
输入:n = 10
输出:6
解释:上图是 10 个盒子的摆放位置。
这些盒子放在房间的一角,对应后方位置。
提示:
1 <= n <= 109
💡解题思路
解题思路: 贪心思想+数学推理题
想要占地板数最少,那么需要靠墙角进行方块的放置,因为墙角天然提供了两个侧面的消耗,这是这道题贪心的一个点吧,并且以类阶梯放置时,所占地面的方块数最少,下面我们来进行找规律。
地面上盒子数为时,最多可以放个盒子。
地面上盒子数为时,最多可以放个盒子。
地面上盒子数为时,最多可以放个盒子,不妨将这种放置情况称为完整的阶梯堆,以下简称阶梯堆。
地面上盒子数为时,最多可以放个盒子,相比于上一个阶梯堆,多了个地面盒子,多了个盒子上限。
地面上盒子数为时,最多可以放个盒子,相比于上一个阶梯堆,多了个地面盒子,多了个盒子上限。
地面上盒子数为时,最多可以放个盒子,相比于上一个阶梯堆,多了个地面盒子,多了个盒子上限,形成了一个完整放置的阶梯堆。
地面上盒子数为时,最多可以放个盒子,相比于上一个阶梯堆,多了个地面盒子,多了个盒子上限。
地面上盒子数为时,最多可以放个盒子,相比于上一个阶梯堆,多了个地面盒子,多了个盒子上限。
地面上盒子数为时,最多可以放个盒子,相比于上一个阶梯堆,多了个地面盒子,多了个盒子上限。
地面上盒子数为时,最多可以放个盒子,相比于上一个阶梯堆,多了个地面盒子,多了个盒子上限,并且形成了一个新的阶梯堆。
通过这些举例,我们可以看出一些规律,当地面放置的盒子数为,,,...,时,最多放置的盒子堆是一个阶梯堆。
地面盒子为时,即(等差数列求和),所对应盒子的上限为(裂项相消):
因为从顶端往下数,每层的盒子数为,,,...,。
利用裂项相消计算得:
最终。
根据变化规律,在阶梯堆基础上添加地面盒子数个,盒子上限会增加。【不妨称作添加规律】
对于本题我们可以算出最大阶梯堆的地面盒子数量不妨设为,然后再将剩余的盒子以以上【添加规律】模拟计数得出,即可的最终所占的地面盒子数。
🔑源代码
Java代码1:
class Solution {
public int minimumBoxes(int n) {
int maxN = 0;
int ans = 0;
int k = 1;
while (k * (1 + k) / 2 + maxN <= n) {
maxN += k * (1 + k) / 2;
k++;
}
//k多记了1
k--;
//x
ans = k * (1 + k) / 2;
k = 1;
//基于阶梯堆,每增加一块地面盒子,上限增加k(k从1递增)
while (maxN < n) {
maxN += k;
ans++;
k++;
}
return ans;
}
}
Java代码2:
class Solution {
public int minimumBoxes(int n) {
int maxN = 1;
int ans = 0;
int k = 1;
while (maxN <= n) {
k++;
maxN = (int) ((long) k * (1 + k) * (2 + k) / 6);
}
//k多记了1
k--;
maxN = (int) ((long) k * (1 + k) * (2 + k) / 6);
//x
ans = k * (1 + k) / 2;
k = 1;
//基于阶梯堆,每增加一块地面盒子,上限增加k(k从1递增)
while (maxN < n) {
maxN += k;
ans++;
k++;
}
return ans;
}
}
C++代码1:
class Solution {
public:
int minimumBoxes(int n) {
int ans = 0;
int k = 1;
int maxN = 0;
while (maxN + k * (1 + k) / 2 <= n)
{
maxN += k * (1 + k) / 2;
k++;
}
//k多加1
--k;
ans = k * (1 + k) / 2;
k = 1;
while (maxN < n)
{
ans++;
maxN += k;
k++;
}
return ans;
}
};
C++代码2:
class Solution {
public:
int minimumBoxes(int n) {
int ans = 0;
int k = 1;
int maxN = 1;
while (maxN <= n)
{
k++;
maxN = (int) ((long) k * (k + 1) * (k + 2) / 6);
}
//k多加1
--k;
maxN = (int) ((long) k * (k + 1) * (k + 2) / 6);
ans = k * (1 + k) / 2;
k = 1;
while (maxN < n)
{
ans++;
maxN += k;
k++;
}
return ans;
}
};
C语言代码1:
int minimumBoxes(int n){
int ans = 0;
int k = 1;
int maxN = 0;
while (maxN + k * (1 + k) / 2 <= n)
{
maxN += k * (1 + k) / 2;
k++;
}
//k多加1
--k;
ans = k * (1 + k) / 2;
k = 1;
while (maxN < n)
{
ans++;
maxN += k;
k++;
}
return ans;
}
C语言代码2:
int minimumBoxes(int n){
int ans = 0;
int k = 1;
int maxN = 1;
while (maxN <= n)
{
k++;
maxN = (int) ((long) k * (k + 1) * (k + 2) / 6);
}
//k多加1
--k;
maxN = (int) ((long) k * (k + 1) * (k + 2) / 6);
ans = k * (1 + k) / 2;
k = 1;
while (maxN < n)
{
ans++;
maxN += k;
k++;
}
return ans;
}
🌱总结
本题主要有两个难点,一个是贪心思维,知道从墙角下手,第二个就是数学规律推理,找出盒子变化规律。
参考资料: leetcode.cn/problems/bu…