【腾讯面试题】熊出没
大家好,我是牛牛,终于又到了最爱的周五啦,大家是不是已经无心工作,就等着愉快的周末到来?
不瞒你说,牛牛也是这样!今天就给大家分享一道有趣的算法题,希望能给大家带来一个好心情~
01
故事起源
故事,要从住在森林里的大熊发现了一个装满苹果的山洞说起...
牛牛码特
13:14
85%
微信(116)
相亲相爱一家熊????
我发现一个山洞,里面有好多苹果????,看起来很好吃的样子~
不过我们只能从洞口和洞尾拿苹果,我们来比比看谁拿的苹果重量最大吧~
好啊好啊
那我们赶快去山洞吧!
熊熊们山洞之旅遇到的问题,归纳起来就是:给定一个装满苹果的山洞,只能从洞口和洞尾拿苹果,每轮两只熊交替拿,并且只能拿一个,谁拿的苹果总重量最大谁就获胜,那谁会是最终的赢家呢?
02
问题剖析
假定山洞里苹果的分布为:1KG,3KG,14KG,7KG。
直觉上来说,是不是我们每轮拿最大的,就一定赢?如果是这种策略,那么大熊第一轮拿7KG,此时的状况就变成了:
这时候很显然,二熊会拿最右边14KG的苹果:
现在山洞里只剩下1KG和3KG两个苹果,无论大熊拿哪一个,它手上苹果总重量,也没二熊的重。难道这是大熊的必输局?
那么,让我们换种拿法,重来一遍。
如果第一轮,大熊选择拿第一个苹果,那此时状态就变成了:
这个时候,二熊只能从3KG、7KG里面选,无论拿哪个,大熊第三轮拿到14KG都能获胜。因此,只要开局拿1KG,大熊就是必胜的。
所以说,每轮选最大这种策略行不通,我们还需要考虑到对后面苹果的影响。
相信经过这个分析,大家已经对题目比较清楚,甚至有点解题思路了吧?别着急,现在我们就一起来看看有哪些解决办法吧。
03
花式取苹果
深度优先递归法
我们可以把问题抽象出来,大熊第一轮去取苹果,是否能赢取决于两个因素:一个是取的苹果的重量,另一个是二熊对剩下的进行选择。再仔细一想,二熊面临的问题,其实和大熊开始时是一模一样的。这样思路就很明显了,我们可以用递归的方法去解决问题。
下面这张图,可以帮助我们辅助思考。
我们从最右边往左边看,每一轮都选择当前的最优解,整个流程走下来,就是递归的实际执行流程了。
经过上述分析,代码也很清晰明了:
func CanFistBearWin(nums []int) bool { return picker(0, len(nums)-1, nums) >= 0}
// i, j 表示当前子问题中,山洞左右从哪里开始func picker(i, j int, nums []int) int { if i == j { return nums[i] } head := nums[i] - picker(i+1, j, nums) end := nums[j] - picker(i, j-1, nums) return max(head, end)}
记忆化递归法
问题虽然解决了,但是跑了一下测试用例,发现用时100ms以上。这样看来,性能上是不是还有优化空间呢?
可以看到,图上是有重复子问题的,那我们完全可以将子问题的解答记录下来。等到后面再遇到的时候,直接返回结果,而不用再递归下去,这样就可以节约大量时间了。
动态规划法
在上面的分析中,我们已经把问题拆分为子问题,既然是子问题,又可以递归解决,那么就不由地会去想,能不能通过动态规划,递推解决?
依照惯例,我们需要一个dp数组,在上面的分析中不难看出,这个数组应该是二维的,dp[i][j]就表示左边起点为i,右边起点为j的山洞,在先手的情况下,熊熊能拿多少KG的苹果。
既然要用动态规划,那么一定要找到一个公式。我们前面分析过,如果大熊先手,是否能赢取决于两个因素:一个是取的苹果的重量,另一个是二熊对剩下的进行选择。
根据这两个因素,我们可以转化为下列公式:
dp[i][j] = Max(nums[i]-dp[i+1][j], nums[j]-dp[i]dp[j-1])
再结合下面的图来进行推导。我们还是以四个苹果为例,为苹果从左到右编上号。
0号位置对应的dp[0][0]就是其苹果的重量,我们从1号位置开始,对每个位置往前递推:
????红苹果配合代码食用更佳:
func CanFistBearWin(nums []int) bool { // 提前计算数组长度,避免反复消耗 length := len(nums) dp := make([][]int, length) // 子数组初始化 for i := 0; i < length; i++ { dp[i] = make([]int, length) // 左右在一个点的情况,取了这个苹果即可 dp[i][i] = nums[i] } // j表示山洞右侧位置 for j := 1; j < length; j++ { // i表示山洞左侧位置 for i := j-1; i >= 0; i-- { head := nums[i] - dp[i+1][j] end := nums[j] - dp[i][j-1] dp[i][j] = max(head, end) } } return dp[0][length-1] >= 0}果不其然,成功拿到了苹果,熊熊开心地跳起了舞
04
熊熊复盘
解决此类问题的核心思想,是将从洞两端选择苹果这个问题抽离出来,成为子问题。然后,在此基础上,我们建立了递归解法,根据实际运行的结果,使用记忆化搜索优化,提高了性能。
解决了问题就算完成任务了?我们的目标可是成为一名追求极致的工程师,当然会想还有没有其它解决方案。于是,我们将同一种抽象模型,从递归转换成递推,玩了把动态规划。
换个角度看问题,生命会展现出另一种美。生活中不是缺少美,而是缺少发现。算法也一样,同一个问题,学着用多个角度去思考、解决,你会发现它别样的魅力!
【腾讯面试题】熊出没相关推荐
- android获取指针空间大小_腾讯笔试题:浅谈计算机中cpu位数和指针
来一个腾讯笔试题 在刷题的时候看到了腾讯笔试题的这个问题 long a = (long)(((int *) 0) + 4);printf("%ld ",a); 请问输出 a 的值是 ...
- 腾讯面试题:char 和 varchar的最大长度是多少,以及他们之间的区别(看完你就能和面试官笑谈人生了)
title: 腾讯面试题:char 和 varchar的最大长度是多少,以及他们之间的区别(看完你就能和面试官笑谈人生了) tags: 面试常见题 腾讯面试题:char 和 varchar的最大长度是 ...
- 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了)
title: 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了) tags: 面试常见题 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了) 腾讯面试题:创建索 ...
- 腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
1.腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中? 思想:用数组来存这40亿个数,而且只能用bit来表示.why? ...
- 【转】IT名企面试:腾讯笔试题(2)
摘要:想要进入腾讯公司,面试笔试题是一定要有所准备的.那么这里我们总结了一些腾讯笔试题,例如:const的含义及实现机制等问题. 腾讯是国内数一数二的IT企业了.那么每年想要进入腾讯公司的应聘者也是络 ...
- 线性表11|单链表小结:腾讯面试题 - 数据结构和算法16
线性表11|单链表小结:腾讯面试题 让编程改变世界 Change the world by program 静态链表的删除操作 我们的故事还没结束,小C看到小A和2B这样非法的勾当,内心觉得很不爽,一 ...
- 程序员求助:腾讯面试题,64匹马8个跑道,多少轮选出最快的四匹
昨天,有网友私信我,说去阿里面试,彻底的被打击到了.问了为什么网上大量使用ThreadLocal的源码都会加上private static?他被难住了,因为他从来都没有考虑过这个问题.无独有偶,今天笔 ...
- java 2017腾讯面试题_腾讯2017刁难面试题,是不是大神就看你会做几题
原标题:腾讯2017刁难面试题,是不是大神就看你会做几题 一.今日头条2017笔试题(决策问题) 现在有两堆石子,小今与小条玩游戏,2个人都足够聪明,两个人规定:每次每人只能从其中一堆中取走1个或2个 ...
- python编辑距离正则匹配_详解一道腾讯面试题:编辑距离
原标题:详解一道腾讯面试题:编辑距离 来自公众号:labuladong 预计阅读时间:8 分钟 前几天在网上看到一份鹅场的面试题,算法部分大半是动态规划,最后一题就是写一个计算编辑距离的函数,今天就专 ...
- 腾讯面试题 你了解ReentrantLock吗?
腾讯面试题 你了解ReentrantLock吗? ReetrantLock是一个可重入的独占锁,主要有两个特性,一个是支持公平锁和非公平锁,一个是可重入. ReetrantLock实现依赖于AQS(A ...
最新文章
- 基于cnn的短文本分类_自然语言理解之(二)短文本多分类TextCNN实践
- BZOJ-2748: [HAOI2012]音量调节 (傻逼背包DP)
- HCP Anywhere:为HDS内容云锦上添花
- php 多组radiobutton,Tkinter多个Radiobutton组
- golang的一个简单小爬虫demo学习记录
- java多重继承用在什么地方_Java提高篇——Java实现多重继承
- Linux内核深入理解定时器和时间管理(7):相关的系统调用
- NCBI安装影响因子插件
- C++ gbk与utf8互转
- 程序员如何改善精神内耗?
- extjs 中formPanel提交到action后返回json数据到ext中,但是ext页面不进入sucess也不进入failure
- 无盘服务器0x00000124,知识分享电脑故障0x00000124导致蓝屏的原因和解决思路-电脑蓝屏原因...
- 站点能源低碳目标网,助力网络碳中和 | 华为发布站点能源十大趋势
- 【原创】VBA学习笔记(300)VBA 很多工作表函数都只对1维数组有用,用2维数组上经常报错!
- b站网页版倍速无效_看网课讲师太啰嗦太慢?在线视频课程效率低?教你自定义超倍速看
- [乐意黎原创]PHP抛PHP Startup:Unable to load dynamic library bcmath,Libmcrypt,mhash,mcrypt等警告及模块动态安装详解
- CyberWorld赛博世界是否能成为元宇宙核心力量
- VSCode下载很慢解决方法
- 关于“IT学子成长指导”专栏及文章目录
- 用C语言构建一个素数表
热门文章
- mac微软雅黑字体_【字体字重】常见设计稿字体对应字重
- oracle有一百个人围一圈报数,案例:Oracle创建表时报session超过最大值 ORA-00018 证明递归ses...
- 定期存款单的mysql编写程序_MySQL 调优和使用必读
- 【Java】“异常”详解
- 第1关:学习-用循环和数组实现输入某年某月某日,判断这一天一年的第几天
- 布局类型java_java – 我们可以为所有屏幕大小制作一种布局类型
- centos 7 php mysql apache_CentOS 7 搭建 Apache+MySQL+PHP
- spring boot+oracle数据库配置成功
- 求方程ax2+bx+c的根python_Python,计算 ax^2 + bx + c = 0的根
- android的天气和时钟部件,Android的天气和时钟部件