【贪心数学困难题】1739. 放置盒子

news2024/11/15 19:44:36

⭐️前面的话⭐️

本篇文章介绍【贪心数学困难题】1739. 放置盒子题解,展示语言java。

📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
📆首发时间:🌴2023年1月31日🌴
✉️坚持和努力一定能换来诗与远方!
💭推荐书籍:📚《算法》,📚《算法导论》
💬参考在线编程网站:🌐牛客网🌐力扣
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
🍭作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


📌导航小助手📌

  • ⭐️1739. 放置盒子⭐️
    • 🔐题目详情
    • 💡解题思路
    • 🔑源代码
  • 🌱总结


⭐️1739. 放置盒子⭐️

1739. 放置盒子

🔐题目详情

难度困难

有一个立方体房间,其长度、宽度和高度都等于 n 个单位。请你在房间里放置 n 个盒子,每个盒子都是一个单位边长的立方体。放置规则如下:

  • 你可以把盒子放在地板上的任何地方。
  • 如果盒子 x 需要放置在盒子 y 的顶部,那么盒子 y 竖直的四个侧面都 必须 与另一个盒子或墙相邻。

给你一个整数 n ,返回接触地面的盒子的 最少 可能数量*。*

示例 1:

img

输入:n = 3
输出:3
解释:上图是 3 个盒子的摆放位置。
这些盒子放在房间的一角,对应左侧位置。

示例 2:

img

输入:n = 4
输出:3
解释:上图是 3 个盒子的摆放位置。
这些盒子放在房间的一角,对应左侧位置。

示例 3:

img

输入:n = 10
输出:6
解释:上图是 10 个盒子的摆放位置。
这些盒子放在房间的一角,对应后方位置。

提示:

  • 1 <= n <= 109

💡解题思路

解题思路: 贪心思想+数学推理题

想要占地板数最少,那么需要靠墙角进行方块的放置,因为墙角天然提供了两个侧面的消耗,这是这道题贪心的一个点吧,并且以类阶梯放置时,所占地面的方块数最少,下面我们来进行找规律。

地面上盒子数为 1 1 1时,最多可以放 1 1 1个盒子。
1

地面上盒子数为 2 2 2时,最多可以放 2 2 2个盒子。

2
地面上盒子数为 3 3 3时,最多可以放 4 4 4个盒子,不妨将这种放置情况称为完整的阶梯堆,以下简称阶梯堆。

3
地面上盒子数为 4 4 4时,最多可以放 5 5 5个盒子,相比于上一个阶梯堆,多了 1 1 1个地面盒子,多了 1 1 1个盒子上限。
4

地面上盒子数为 5 5 5时,最多可以放 7 7 7个盒子,相比于上一个阶梯堆,多了 2 2 2个地面盒子,多了 1 + 2 1+2 1+2个盒子上限。
5
地面上盒子数为 6 6 6时,最多可以放 10 10 10个盒子,相比于上一个阶梯堆,多了 3 3 3个地面盒子,多了 1 + 2 + 3 1+2+3 1+2+3个盒子上限,形成了一个完整放置的阶梯堆。
6
地面上盒子数为 7 7 7时,最多可以放 11 11 11个盒子,相比于上一个阶梯堆,多了 1 1 1个地面盒子,多了 1 1 1个盒子上限。
7

地面上盒子数为 8 8 8时,最多可以放 13 13 13个盒子,相比于上一个阶梯堆,多了 2 2 2个地面盒子,多了 1 + 2 1+2 1+2个盒子上限。
8

地面上盒子数为 9 9 9时,最多可以放 16 16 16个盒子,相比于上一个阶梯堆,多了 3 3 3个地面盒子,多了 1 + 2 + 3 1+2+3 1+2+3个盒子上限。
9
地面上盒子数为 10 10 10时,最多可以放 16 16 16个盒子,相比于上一个阶梯堆,多了 4 4 4个地面盒子,多了 1 + 2 + 3 + 4 1+2+3+4 1+2+3+4个盒子上限,并且形成了一个新的阶梯堆。
10

通过这些举例,我们可以看出一些规律,当地面放置的盒子数为 1 1 1 1 + 2 1+2 1+2 1 + 2 + 3 1+2+3 1+2+3,…, 1 + 2 + 3 + . . . + i 1+2+3+...+i 1+2+3+...+i时,最多放置的盒子堆是一个阶梯堆。

地面盒子为 1 + 2 + 3 + . . . + i 1+2+3+...+i 1+2+3+...+i时,即 i × ( 1 + i ) 2 \frac{i\times(1+i)}{2} 2i×(1+i)(等差数列求和),所对应盒子的上限为 m a x N maxN maxN(裂项相消):

1 + ( 1 + 2 ) + ( 1 + 2 + 3 ) + . . . + ( 1 + 2 + 3 + . . . + i ) = ∑ i = 1 i i × ( 1 + i ) 2 1+(1+2)+(1+2+3)+...+(1+2+3+...+i)=\sum_{i=1}^{i}{\frac{i\times(1+i)}{2}} 1+(1+2)+(1+2+3)+...+(1+2+3+...+i)=i=1i2i×(1+i)

因为从顶端往下数,每层的盒子数为 1 1 1 1 + 2 1+2 1+2 1 + 2 + 3 1+2+3 1+2+3,…, 1 + 2 + 3 + . . . + i 1+2+3+...+i 1+2+3+...+i

利用裂项相消计算得:

∑ i = 1 i i × ( 1 + i ) 2 = ∑ i = 1 i ( i × ( 1 + i ) 2 × [ ( i + 2 ) − ( i − 1 ) ] 3 ) = ∑ i = 1 i ( i ( i + 1 ) ( i + 2 ) 6 − ( i − 1 ) i ( i + 1 ) 6 ) = 1 6 ∑ i = 1 i [ i ( i + 1 ) ( i + 2 ) − ( i − 1 ) i ( i + 1 ) ] = [ ( 1 × 2 × 3 ) − ( 0 × 1 × 2 ) + ( 2 × 3 × 4 ) − ( 1 × 2 × 3 ) + . . . + i ( i + 1 ) ( i + 2 ) − ( i − 1 ) i ( i + 1 ) ] = 1 6 [ i ( i + 1 ) ( i + 2 ) − ( 0 × 1 × 2 ) ] = i ( i + 1 ) ( i + 2 ) 6 \begin{aligned} \sum_{i=1}^{i}{\frac{i\times(1+i)}{2}}&=\sum_{i=1}^{i}({\frac{i\times(1+i)}{2}}\times\frac{[(i+2)-(i-1)]}{3})\\ &=\sum_{i=1}^{i}(\frac{i(i+1)(i+2)}{6}-\frac{(i-1)i(i+1)}{6})\\ &=\frac{1}{6}\sum_{i=1}^{i}[i(i+1)(i+2)-(i-1)i(i+1)]\\ &=[(1\times2\times3)-(0\times1\times2)+(2\times3\times4)-(1\times2\times3)+...+i(i+1)(i+2)-(i-1)i(i+1)]\\ &=\frac{1}{6}[i(i+1)(i+2)-(0\times1\times2)]\\ &=\frac{i(i+1)(i+2)}{6}\\ \end{aligned} i=1i2i×(1+i)=i=1i(2i×(1+i)×3[(i+2)(i1)])=i=1i(6i(i+1)(i+2)6(i1)i(i+1))=61i=1i[i(i+1)(i+2)(i1)i(i+1)]=[(1×2×3)(0×1×2)+(2×3×4)(1×2×3)+...+i(i+1)(i+2)(i1)i(i+1)]=61[i(i+1)(i+2)(0×1×2)]=6i(i+1)(i+2)

最终 m a x N = i ( i + 1 ) ( i + 2 ) 6 maxN=\frac{i(i+1)(i+2)}{6} maxN=6i(i+1)(i+2)

根据变化规律,在阶梯堆基础上添加地面盒子数 j j j个,盒子上限会增加 1 + 2 + 3 + . . . + j = j × ( 1 + j ) 2 1+2+3+...+j=\frac{j\times(1+j)}{2} 1+2+3+...+j=2j×(1+j)。【不妨称作添加规律】

对于本题我们可以算出最大阶梯堆的地面盒子数量不妨设为 x = 1 + 2 + . . . + k = k × ( 1 + k ) 2 x=1+2+...+k=\frac{k\times(1+k)}{2} x=1+2+...+k=2k×(1+k),然后再将剩余的盒子以以上【添加规律】模拟计数得出 y y y,即可的最终所占的地面盒子数 a n s = x + y ans=x+y ans=x+y

🔑源代码

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;
}

🌱总结

本题主要有两个难点,一个是贪心思维,知道从墙角下手,第二个就是数学规律推理,找出盒子变化规律。

优化参考:
1

class Solution {
    public int minimumBoxes(int n) {
        int x = (int) Math.cbrt(6L * n);
        int ans = x * (x + 1) / 2;
        int maxN = (int) ((long) x * (x + 1) * (x + 2) / 6);
        if (maxN > n) {
            maxN -= ans;
            ans -= x;
        }
        return ans + (int) Math.ceil((-1 + Math.sqrt(1 + 8 * (n - maxN))) / 2);
    }
}
class Solution {
public:
    int minimumBoxes(int n) {
        int x = cbrt(6L * n);
        int ans = x * (x + 1) / 2;
        int max_n = (long) x * (x + 1) * (x + 2) / 6;
        if (max_n > n) {
            max_n -= ans;
            ans -= x;
        }
        return ans + ceil((-1 + sqrt(1 + 8 * (n - max_n))) / 2);
    }
};

参考资料:
https://leetcode.cn/problems/building-boxes/solution/mei-xiang-ming-bai-yi-ge-dong-hua-miao-d-8vbe/

觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!

1-99

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/190407.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20份可视化大屏模板,直接套用真香(文末附源码)

最近有不少小伙伴问我&#xff1a;有没有数据可视化大屏模板&#xff0c;而且要B格很高的。 这不&#xff0c;立马安排。特地给大家准备了20张精美、炫酷而且十分实用的可视化大屏模板&#xff0c;涉及机械、加工、零售、银行、交通等行业。 只要你有数据就能够迅速套用到模板…

Spring-IOC/DI配置管理第三方bean

Spring-IOC/DI配置管理第三方bean 1&#xff0c;IOC/DI配置管理第三方bean 1.1 案例:数据源对象管理 本次案例将使用咱们前面提到过的数据源Druid(德鲁伊)和C3P0来配置学习下。 1.1.1 环境准备 学习之前&#xff0c;先来准备下案例环境: 创建一个Maven项目 pom.xml添加依…

代码随想录day52 动态规划

代码随想录day52 动态规划 题1143.最长公共子序列 1&#xff0c;本题和最长重复子数组的区别在于本题不要求连续&#xff0c;那么当遇到元素不相同时不能重头开始累计&#xff0c;而应该取前面情况中的最大值。 2&#xff0c;dp数组依然为dp[i][j]&#xff1a;长度为[0, i -…

提取页码去重再编号

实例需求&#xff1a;A列为档号数据&#xff0c;由多段数字组成&#xff0c;使用减号作为分隔符&#xff0c;最后一段数字代表页数&#xff0c;注意页数是不连续的&#xff0c;倒数第二段数字是代表档案中的第几本&#xff0c;每个档案都是从1开始。现在需要在B列创建“卷内顺序…

A股level2行情数据接口可以获取可转债数据吗?

可以的&#xff0c;究竟如何通过level2行情获取可转债数据&#xff1f; level2行情数据接口数据包括每只股票每3秒的快照数据&#xff0c;每10秒的快照数据毫秒级差别推送数据&#xff0c;收集多个逐笔成交数据和逐笔委托数据。 通过数据提供商获取即时收集数据和盘后数据。数…

七、请求和响应

请求和响应 web框架本质就是处理用户发起的请求&#xff0c;然后返回响应结果。请求&#xff0c;和响应就是框架中的数据流。 请求 当页面被请求时&#xff0c;django会创建一个HttpRequest对象&#xff0c;该对象包含关于请求的元数据。然后django加载适当的视图&#xff0…

[NOI Online 2021 入门组] 切蛋糕

题目描述: Alice、Bob 和 Cindy 三个好朋友得到了一个圆形蛋糕&#xff0c;他们打算分享这个蛋糕。 三个人的需求量分别为 a,b,c现在请你帮他们切蛋糕&#xff0c;规则如下&#xff1a; 每次切蛋糕可以选择蛋糕的任意一条直径&#xff0c;并沿这条直径切一刀&#xff08;注意…

【C++】模板进阶:非类型的模板参数与模板的特化

一、非类型模板参数 模板参数分类&#xff1a;类型形参与非类型形参。 类型形参&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之后的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将…

GMP调度模型

GMP的发展: go 1.1版本之前时候过使用的是GM模型全局队列的模式。GM模型全局队列的模式M&#xff1a;1 内核线程&#xff1a;协程新建一个协程G的时候会放入全局队列中&#xff0c;每次执行一个协程G的时候&#xff0c;内核线程M会从全局队列中获取一个协程G执行,因为内核线程…

Dataset and DataLoader 加载数据集

文章目录7、Dataset and DataLoader 加载数据集7.1 Revision7.1.1 Manual data feed 手动数据输入7.1.2 Epoch, Batch-Size, Iterations7.2 DataLoader 数据加载器7.3 Dataset 数据集7.3.1 import7.3.2 class7.3.3 DataLoader7.4 Example: Diabetes Dataset7.4.1 Prepare datas…

【微服务】Seata的部署和集成

Seata的部署和集成一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务二、微服务集成seata1.引入依赖2.修改配置文件三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取nacos配置一、部署Sea…

【Redis】.net core 3.1 Redis安装和简单使用

Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。 简单来说&#xff0c;就是一个键值对数据库。 Redis支持的…

DynaSLAM-5 DynaSLAM中Mask R-CNN部分源码解析(Ⅳ)

目录 1.ROIAlign层 2.Mask分支 3.整体框架回顾 1.ROIAlign层 在上文中&#xff0c;我们现在手里已经有了正负样本数据以及它们对应的标签。接下来我们就要进行预测的操作了&#xff01; 但在预测之前&#xff0c;还有些小问题&#xff1a; ①每个ROI大小也不一样&#xff0c…

Biotin-SS-Sulfo-NHS;CAS:325143-98-4;生物素-二硫键-磺酸-活性酯

名称&#xff1a;生物素-二硫键-磺酸-活性酯 英文名称&#xff1a;Biotin-SS-Sulfo-NHS CAS:325143-98-4 分子式&#xff1a;C19H27N4NaO9S4 分子量&#xff1a;606.67 外观&#xff1a;白色固体或粘稠液体&#xff0c;取决于分子量大小 溶剂&#xff1a;溶于大部分有机溶…

JVM自动内存管理核心知识速览

目录运行时数据区程序计数器Java虚拟机栈本地方法栈Java堆方法区运行时常量池直接内存对象对象的创建类加载检查分配内存指针碰撞&#xff08;Bump The Pointer&#xff09;空闲列表&#xff08;Free List&#xff09;内存分配并发问题初始化值设置对象头执行init方法对象的内存…

一、Qt汽车仪表盘之绘制背景-绘制饼图

一、绘图坐标系分析 1、坐标系平移 1、从原来的坐标系中心移动到矩形仪表盘中心&#xff0c;相对应的坐标会发生变化。 2、了解绘制饼图的含义 &#xff08;1&#xff09;坐标系平移之后坐标变化 &#xff08;2&#xff09;绘制第一个饼图效果 第一个饼图&#xff1a;坐标…

[COMST 2022] 元宇宙的安全隐私问题

A Survey on Metaverse: Fundamentals, Security, and Privacyhttps://ieeexplore.ieee.org/abstract/document/9880528摘要元宇宙&#xff0c;作为下一代互联网的一个不断发展的范式&#xff0c;旨在建立一个完全沉浸式、超时空、自我维持的虚拟共享空间&#xff0c;供人类玩耍…

进销存ERP源码/ 进销存APP源码/小程序ERP系统/Thinkphp+Uniapp全开源销售进库出入库

框架&#xff1a;ThinkPHP5.0.24 uniapp 包含:服务端php全套开源源码&#xff0c;uniapp前端全套开源源码&#xff08;可发布H5/android/iod/微信小程序/抖音小程序/支付宝/百度小程序&#xff09; 注&#xff1a;这个是全开源&#xff0c;随便你怎么开&#xff0c;怎么来&…

JUC并发编程之SynchronousQueue的底层原理

作者简介&#xff1a;专注于研究Linux内核、Hotspot虚拟机、汇编语言、JDK源码、各大中间件源码等等喜欢的话&#xff0c;可以三连关注~SynchronousQueue是什么在JDK源码中JUC包下的并发编程阻塞/同步队列实现各种花样&#xff0c;但是队列的实现无非是。先进先出&#xff0c;后…

程序员必备的Linux命令——文件及目录命令

Linux命令就是我们对Linux系统进行管理的操作指令。类似于我们操作windows系统中可视化的各种操作动作。 在Linux系统中&#xff0c;我们任何东西都被认做是文件&#xff0c;比如cpu、内存、键盘以及用户全是文件。Linux命令类似于之前的DOS命令。 Linux系统中命令分为两种&a…