算法面试真题详解:石子归并

简介: 算法面试真题详解:石子归并

有一个石子归并的游戏。最开始的时候,有n堆石子排成一列,目标是要将所有的石子合并成一堆。合并规则如下:

  1. 每一次可以合并相邻位置的两堆石子
  2. 每次合并的代价为所合并的两堆石子的重量之和
    求出最小的合并代价。

在线评测地址:领扣题库官网

样例 1:

输入: [3, 4, 3]
输出: 17

样例 2:

输入: [4, 1, 1, 4]
输出: 18

解释:

  1. 合并第二堆和第三堆 => [4, 2, 4], score = 2
  2. 合并前两堆 => [6, 4],score = 8
  3. 合并剩余的两堆 => [10], score = 18

算法:区间DP

这是一道区间DP问题,我们需要用区间表示状态来递推。

更多DP算法真题详解,点此免费查看

设s是表示石头重量的数组,设fi是将s[i,...,j]的石头合并成一个所需的最少能量,那么这个最少能量按照最后一步合并的分界线可以分为以下几种情况:
1、最后一步是s[i]和s[i+1,...,j]合并,此时需要的最少能量是fi+1+sum(s[i]...s[j]),第一项是合并后者需要的能量,第二项是最后一次合并所需要的能量。s[i]自己只有一个石头,不需要合并
2、最后一步是s[i,i+1]和s[i+2,...,j]合并,此时需要的最少能量是fi+fi+2+sum(s[i]...s[j]),第一项是合并前两个石头需要的能量,第二项是合并后半区间石头需要的能量,最后一项是最后一次合并需要的能量;
从上面我们可以看出一个规律,fi应该是所有区间分法中前一半区间的石头合并需要的总能量加上后半区间的总能量再加上最后一次合并需要的能量

  • 求得A的前缀和
  • 区间长度从2开始枚举,
  • 根据上诉思路可得递推式
  • dpl =min(dpl, dpl + dpj + 1 + sum_a[r + 1] - sum_a[l])
  • 记得初始化dpl为一个较大值
  • 结果存在dp0中

复杂度分析

  • 时间复杂度O(n^3)

    • 区间dp的复杂度
  • 空间复杂度O(n^2)

    • dp数组的大小
public class Solution {
    /**
     * @param A: An integer array
     * @return: An integer
     */
    public int stoneGame(int[] A) {
        int size = A.length;
        if (A == null || size == 0) {
            return 0;
        }
        
        int[][] dp = new int[size][size];
        int[] sum_a = new int[size + 1];
        //前缀和
        for (int i = 0; i < size; i++) {
            sum_a[i + 1] = sum_a[i] + A[i];
        }
        // 长度从2开始即可,因为长度为1的时候结果是0,dp初始化的时候默认就是0,没必要赋值
        for (int len = 2; len <= size; len++) {
            // i枚举的是正在枚举的区间的左端点
            for (int i = 0; i + len - 1 < size; i++) {
                // 正在枚举的区间左端点是i,右端点是i + size - 1
                int l = i, r = i + len - 1;
                // 在求最小的时候,需要初始化成一个很大的数,然后不断更新
                dp[l][r] = Integer.MAX_VALUE;
                for (int j = l; j < r; j++) {
                    //递推式
                    dp[l][r] = Math.min(dp[l][r], dp[l][j] + dp[j + 1][r] + sum_a[r + 1] - sum_a[l]);
                }
            }
        }
        
        return dp[0][size-1];
    }
}

更多题解参考:九章官网solution

相关文章
|
26天前
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
66 16
|
6月前
|
负载均衡 NoSQL 算法
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
这篇文章是关于Java面试中Redis相关问题的笔记,包括Redis事务实现、集群方案、主从复制原理、CAP和BASE理论以及负载均衡算法和类型。
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
|
4月前
|
算法 Java 数据库
美团面试:百亿级分片,如何设计基因算法?
40岁老架构师尼恩分享分库分表的基因算法设计,涵盖分片键选择、水平拆分策略及基因法优化查询效率等内容,助力面试者应对大厂技术面试,提高架构设计能力。
美团面试:百亿级分片,如何设计基因算法?
|
4月前
|
算法 前端开发 Java
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
这篇文章总结了单链表的常见面试题,并提供了详细的问题分析、思路分析以及Java代码实现,包括求单链表中有效节点的个数、查找单链表中的倒数第k个节点、单链表的反转以及从尾到头打印单链表等题目。
53 1
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
|
4月前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
4月前
|
算法 Java 数据库
美团面试:百亿级分片,如何设计基因算法?
40岁老架构师尼恩在读者群中分享了关于分库分表的基因算法设计,旨在帮助大家应对一线互联网企业的面试题。文章详细介绍了分库分表的背景、分片键的设计目标和建议,以及基因法的具体应用和优缺点。通过系统化的梳理,帮助读者提升架构、设计和开发水平,顺利通过面试。
美团面试:百亿级分片,如何设计基因算法?
|
4月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
149 2
|
5月前
|
机器学习/深度学习 JavaScript 算法
面试中的网红虚拟DOM,你知多少呢?深入解读diff算法
该文章深入探讨了虚拟DOM的概念及其diff算法,解释了虚拟DOM如何最小化实际DOM的更新,以此提升web应用的性能,并详细分析了diff算法的实现机制。
|
4月前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
40 0
|
6月前
|
搜索推荐 算法
十大排序算法-快排-希尔-堆排-归并-冒泡-桶排-选择-插入-计数-基数
十大排序算法-快排-希尔-堆排-归并-冒泡-桶排-选择-插入-计数-基数