问题描述:

给定一个非负数列,每次从中取出一个数字,而这个数字左右两边邻居值乘积作为本次取数的得分。被取出数字之后,剩余组成新的数列,且相对位置不变,如果最后这个数字没有左邻居或者右邻居,则补1即可。求,这些数字被取完,所有得分的总和最大是多少

例如下图

:这个题目是同学出的,传说是,三星实习生转正的测试题目,其实,如果没有左邻居或者右邻居是补 1, 还是补 0, 我不清楚,现在是按照补 1,计算。

问题分析:

(1)首先理解一个事情,就是把整个数列看做一个整体,那么最优解值,一定是最后一个数字 i 的得分是1(i 是未知的),加上以 i 为分界线,左右两个区间的最优解(有点像二分法)。这个不难理解,最后就剩下一个数字时,很显然,把两边的最优解加上最后一个 ,就是整体的最优解。这样一来就满足了动态规划的两个基本条件:

最优子结构:每个区间都符合这样解的结构。

重叠子问题:左右区间又生成左右区间,构成重叠问题。

(2)问题:最后被取走的数字i 是哪一个?因为已经知道区间内的所有数字,那么就可以枚举(遍历)这些数字,找到最优的那个 i 。这类问题一般称区间 dp 。

(3)问题:左右小区间的最优解如何确定?那么现在就是,从最小区间开始计算,通俗的讲,先计算长度2的小区间,然后依次增加区间的长度。每次计算时,小区间就像一个滑动窗口,例如从长度为2的小区间作为一个窗口,从左向右依次滑动,求出所有小区间的最优解保存到dp[l][r]中。可以看出计算过程是自底向上的。所以dp[l][r]只用到了上三角的空间(l<r)。

(4)dp状态转换方程:

dp方程式为:dp[left][right] = max(dp[left][right], nums[left] * nums[right] + dp[left][i] + dp[i][right])

dp[left][right],表示区间 left-->right 的最优解(不包括,left 和 right 两个边界)

nums[left] * nums[right],表示最后一个被取出的数字的得分,为什么要乘上两个边界值那?因为它是最后一个被取出来的,整体来看,最后就剩下一个,就是乘上两个1,在子区间内,就是乘上两边的边界值了。

max(dp[left][right], nums[left] * nums[right] + dp[left][i] + dp[i][right]),表示从区间内开始枚举 i,计算出本次区间的最优解。

Python3实现(时间复杂度O(n3),空间复杂度O(n2)):

# @Time   :2018/7/14
# @Author :LiuYinxing
# 解题思路 区间动态规划# 题目大意,给定一个数组,每次删除一个数字,并把这个数字相邻的两个数的积作为本次得分,如果左右没有相邻的数字,则补 1 。
# 求这个数列的最大得分是多少?class Solution:def maxScore(self, Nums):nums = [1] + Nums + [1]  # 首尾添加[1],方便计算n = len(nums)dp = [[0] * n for _ in range(n)]  # 初始化dpfor k in range(2, n):  # k 确定一个滑动窗口的大小,从2开始for left in range(0, n - k):  # 滑动窗口,从左向右滑动,确定区间的开始(left)、结束(right)位置right = left + kfor i in range(left + 1, right):  # 开始枚举,区间内选择一个数字,并使其得分最高dp[left][right] = max(dp[left][right],nums[left] * nums[right] + dp[left][i] + dp[i][right])return dp[0][n - 1]if __name__ == '__main__':nums = [3, 1, 5, 8]solu = Solution()print(solu.maxScore(nums))

欢迎指正哦。

算法题 - 数列最高得分相关推荐

  1. 【经典算法题】多边形三角剖分的最低得分

    [经典算法题]多边形三角剖分的最低得分 Leetcode 1039 多边形三角剖分的最低得分 题目描述:Leetcode 1039 多边形三角剖分的最低得分 分析 本题的考点:动态规划. 分析如下: ...

  2. 四道微软面试经典算法题

    比较经典的四个算法题,目前只收集到相关的思路和个别题目的解法,不断更新中 1.一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现.0是例外,可以反复出现. 请设计一个算法, ...

  3. 一道看完答案你会觉得很沙雕的「动态规划算法题」

    这道算法题其实并不难,如果你把文章从头到尾看完的话基本上能看懂,但如果你看到最后的话大概率会说一句:这是什么沙雕题目?! 题目来源于 LeetCode 第 877 号问题:石子游戏. 为了更好理解,我 ...

  4. 递增的整数序列链表的插入_每日算法题 | 剑指offer 链表专题 (5)链表中倒数第k个节点...

    点击上方"Jerry的算法和NLP",选择"星标"公众号 重磅干货,第一时间送达 题目 链表中倒数第k个节点 题目要求 输入一个链表的头结点,从尾到头反过来打印 ...

  5. 力扣高频算法php_互联网公司最常见的面试算法题有哪些?

    很多时候,你即使提前复习了这些最常见的面试算法题,你依旧无法通过算法面试! 为什么?你在提前准备复习的时候,在网上找了半天相应题目的分析文章,但你看了就是不懂. 你在面试的时候,卡壳了,一时间忘了怎么 ...

  6. 经典算法题每日演练——第十题 树状数组

    原文:经典算法题每日演练--第十题 树状数组 有一种数据结构是神奇的,神秘的,它展现了位运算与数组结合的神奇魅力,太牛逼的,它就是树状数组,这种数据结构不是神人是发现不了的. 一:概序 假如我现在有个 ...

  7. python全排序算法题_Python的100道经典算法题(1)

    按照c语言的100道经典算法题,自己原创写的,就得是自己的练习题了 [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位.十位.个位的数 ...

  8. java经典100例算法题_10道java经典算法题,每一题都能帮你提升java水平!

    JAVA经典算法题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析:兔子 ...

  9. 装饰器python的通俗理解_2道极好的Python算法题 | 带你透彻理解装饰器的妙用

    今天我分享两道非常好的算法题,大家耐心看完两道算法题之后,注意精华在最后,我相信大家对装饰器的理解又会更上一层楼. 1.斐波那契数列 1).这个序列非常有名,我非常喜欢这个序列(有同学问我为啥,偷偷告 ...

最新文章

  1. 点到面的战略和银行共生关系的文献总结
  2. CentOS 初体验四: 阿里云服务器开启8080端口
  3. Go使用HTTPClient发送Get Post请求
  4. android按钮在容器下方,使用flex布局解决安卓手机上固定在底部的按钮,在键盘弹起后挡住input输入框的问题...
  5. 计算机网络原理关于实验中几个指令使用的复习——网络层
  6. 从有理数到实数和数的连续体
  7. 为什么你的发行版仍然在使用“过时的”Linux 内核? | Linux 中国
  8. 开发人员学Linux(13):CentOS7安装配置IT设备监控系统Zabbix
  9. mysql 临时列可以判断,mysql数据库常用命令
  10. 2021大数据白皮书 附下载
  11. python 微信小程序签到系统_简易微信小程序签到功能
  12. 好物推荐:眼科OCT影像自动分割工具推荐
  13. 计操实验 多级反馈队列C语言
  14. 名帖232 张雨 行书《行书帖选》
  15. caffe的安装配置(CUDA7.5+VS2013)
  16. 职称论文发表的字数不够怎么办
  17. 威哥android视频百度云,威哥带你手把手开发Android电商项目视频教程
  18. 项目章程的主要内容#软考高级信息系统项目管理师/高项读书笔记#3
  19. 清理android桌面
  20. 【Hi3559AV100 Camera】Hi3559AV100 环境搭建

热门文章

  1. html制作企业官网
  2. Matlab符号处理工具箱简介
  3. NOI-C语言编程基础之循环控制——买房子
  4. 051 <css语法> 学习之: 常用标签(input等)
  5. ubuntu16.04 ns2安装教程
  6. RL强化学习算法90行代码快速实战 DQN代码分层讲解
  7. 如何用分布式Pollard-Rho法对椭圆曲线离散对数问题(ECDLP)进行攻击(上)
  8. 条形码组件Spire.Barcode 教程:在Java中扫描条形码
  9. 17款响应式布局框架
  10. 清华出版社人工智能科学丛书:统计学习理论与方法