关注下方公众号,分享硬核知识

作者 | 小K

出品 | 公众号:小K算法 (ID:xiaok365)

01

故事起源

有N堆纸牌编号为1~N,每堆有若干张,但纸牌总数必为N的倍数。可在任一堆上取若干张移动。

移牌规则:

  • 编号为1的堆上取的纸牌只能移到编号为2的堆上

  • 编号为N的堆上取的纸牌只能移到编号为N-1的堆上

  • 其他堆上取的纸牌可向左右相邻堆移动

问最少要移动几次可使每堆上纸牌一样多?

02

小规模分析

2.1

一堆纸牌

如果只有一堆纸牌,那就不用移动,也就是移动0次。

2.2

两堆纸牌

如果有两堆纸牌,一种情况是两堆已经一样多了,那就不用移动,最少0次。

另一种情况是不一样多,那只需要将多的移动到少的使两堆一样,最少1次。

2.3

三堆纸牌

如果三堆已经一样多,即都为平均数,那就不用移动。

另外的情况就是有一堆为平均数,或者0堆为平均数,当然肯定不可能只有两堆为平均数。

如果为下面这种情况,移动1次可以完成。

如果为下面这种情况,移动2次可以完成。

多列举几种不同的情况,你就会发现,三堆纸牌无论哪种情况,移动次数都在0~2次就可以完成。
那N堆纸牌是不是移动次数也在0~(N-1)次就可以完成呢?继续往下分析。

2.4

小规模总结

根据上面的分析,三堆纸牌移动的次数在0~2。那什么原因导致移动的次数不同呢?

总结:

  • 0次:3堆都为平均数

  • 1次:第一堆或者第三堆为平均数

  • 2次:其它情况

为1次时,有一堆为平均数不用移动,那这时和两堆也没有区别啊,三堆可以分解成两堆+一堆,到这里小K已经隐约感觉到了有子问题的存在。

03

分割子问题

想象这种场景,N堆纸牌,从中间某位置分开,左右两边都刚好够分,那么把每一边都看成整体时,一定不会有互相移动。因为如果你从左边移x张到右边,你必然还会从右边移x张回来,属于多余操作。
这样两边其实可以看成两个完全独立的子问题。

根据上面的规则,可以先将一个大问题分为多个不可再分割的子问题。

到这里我们已经成功向前推进了一步,接下来思考每个子区间的情况。

04

子问题分析

4.1

不可再分性

对于一个不可再分割的子区间,从任意位置切一刀,都无法再分割。

也就是任意位置切一刀,一定是一边均摊后小于平均数,另一边均摊后大于平均数。

现在我们要想办法让它能继续分割,即通过移动使得两边变成刚好够分。
如果不考虑移动次数肯定可以做到,那能否通过一次移动使子区间可以分割开呢?

4.2

均摊后大于平均数(充分性)

从左开始扫描每一堆纸牌,如果大于平均数,就把多余的移到右边相邻的堆上。这样左右两边都是刚好够分的情况,即通过一次移动就把该区间分割成两个更小的子区间。

4.3

均摊后小于平均数(充分性)

从左开始扫描每一堆纸牌,如果小于平均数,就继续向右扫描,这时判断整个左区间是否够分,直到扫描到。
区间[1,i+1]均摊后大于平均数(只有扫到末尾才可能刚好等于平均数),这时只需从上移动区间[1,i]还缺少的x个到上,使得区间[1,i]刚好够分,这样一次移动也能把区间分割成两个更小的子区间。

4.4

X堆最少移动X-1次(必要性)

通过一次移动可将区间一分为二,对于一个有X堆纸牌的子区间,一定能通过X-1次将它分割为全部均等的X堆。那最少一定要X-1次吗,还能否更少?

不论在哪个位置移动,每移动一次,只会改变相邻的两堆纸牌的数量,所以只能影响左右两个区间是否可分割。
即移动一次最多一分为二,不可能一分为三,那么有X堆的子区间最少也得移动X-1次。

05

算法及实现

5.1

算法思想

分析到这里问题的本质规律已经找出来了,先将整个区间分割开,然后对于每一个不可再分割的子区间,设有X堆纸牌,按上述方法移动X-1次可使得每堆都相等。
我们不需要真正去移动,只需要求出最少的次数。所以如果初始区间可以分割为Y个子区间,那么整个区间最少移动就是N-Y次。

5.2

代码实现

int main() {int n, a[100], sum = 0, interval = 0;cin >> n;for (int i = 0; i < n; ++i) {cin >> a[i];sum += a[i];}int avg = sum / n, last = -1;sum = 0;for (int i = 0; i < n; ++i) {sum += a[i];if (sum == (i - last) * avg) {interval++;sum = 0;last = i;}}cout << n - interval << endl;return 0;
}

06

总结

估计最后给大家的感觉就是:编码一分钟,思考两小时,哈哈。
实现代码非常简单,但思考过程并不简单,需要找出问题的本质规律,要证明算法的正确性,这个还是有一些思考量在里面的。大家跟着小K的思路多思考,勤用脑,总有一天你会感叹:原来都是套路啊,哈哈。

本文原创作者:小K,一个思维独特的写手。
文章首发平台:微信公众号【小K算法】。

如果喜欢小K的文章,请点个关注,分享给更多的人,小K将持续更新,谢谢啦!

关注下方公众号,分享硬核知识

关注我,涨知识

原创不易,感谢分享

转发,点赞,在看

往期精彩回顾

图解算法:冒泡排序

巴什博弈:取石子游戏

逻辑面试题:猴子搬香蕉

分享给更多朋友,转发,点赞,在看

算法面试题:均分纸牌相关推荐

  1. [Z]谷歌(Google)算法面试题

    谷歌(Google)算法面试题 1.谷歌面试题:给定能随机生成整数 1 到 5 的函数,写出能随机生成整数 1 到 7 的函数. 回答:此题的关键是让生成的 1 到 7 的数出现概率相同. 只要我们可 ...

  2. 200 道算法面试题集锦!Python 实现,含华为、BAT 等校招真题!

    点击上方"AI有道",选择"置顶"公众号 重磅干货,第一时间送达 春招临近,无论是要找工作的准毕业生,还是身在职场想要提升自己的程序员,提升自己的算法内功心法. ...

  3. 常见的js算法面试题收集,es6实现

    1.js 统计一个字符串出现频率最高的字母/数字 let str = 'asdfghjklaqwertyuiopiaia'; const strChar = str => {let string ...

  4. twitter java_Twitter算法面试题详解(Java实现)

    最近在网上看到一道Twitter的算法面试题,网上已经有人给出了答案,不过可能有些人没太看明白(我也未验证是否正确),现在给出一个比较好理解的答案.先看一下题目. 图1 先看看图图1.可以将方块看做砖 ...

  5. prim算法_历时两月,终拿字节跳动offer,算法面试题分享「带答案」

    欢迎关注专栏<Java架构筑基>--专注于Java技术的研究与分享! Java架构筑基​zhuanlan.zhihu.com Java架构筑基--专注于Java技术的研究与分享! 后续文章 ...

  6. java面笔试_java笔试手写算法面试题大全含答案

    java笔试手写算法面试题大全含答案 1.统计一篇英文文章单词个数. public class WordCounting { public static void main(String[] args ...

  7. 【机器学习算法面试题】四.深度神经网络中激活函数有哪些?

    欢迎订阅本专栏:<机器学习算法面试题> 订阅地址:https://blog.csdn.net/m0_38068876/category_11810806.html [机器学习算法面试题]一 ...

  8. 66 道前端算法面试题附思路分析助你查漏补缺

    大家好,我是漫步. 今天来分享一篇干货,前端关于算法的分析不多,下文列举了66道前端算法面试题,希望对你有所帮助. 作者:Eno_Yao https://segmentfault.com/a/1190 ...

  9. 一周刷爆LeetCode,算法da神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记

    一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记 教程与代码地址 P1 出圈了!讲课之外我们来聊聊 ...

  10. 微软的100道算法面试题(终结版)

    前言 数据结构与算法的重要性已不言而喻,最近,我整理出十大经典排序算法.五大常用算法总结,今天特意整理出微软面试的100题,若有不足之处,欢迎指正!由于篇幅过长,前30道题目写在上一篇,大家可以进我的 ...

最新文章

  1. jieba(结巴)常用方法
  2. linux内核网络协议栈--linux协议栈调用流程(七)
  3. python调用所有函数_python打印所有函数调用以了解脚本
  4. c语言指针实验报告总结,c语言指针实验报告
  5. 虚拟机下Linux网络配置
  6. java客户端运行hadoop_JAVA客户端连接部署在docker上的hdfs
  7. Matplotlib(三) rcParams 自定义样式控制
  8. html5表单新增的输入类型,HTML5之表单新增类型介绍
  9. Mac 键盘符号整理
  10. python 怎么算l2范数_数学推导+纯Python实现机器学习算法13:Lasso回归
  11. linux 指定库名 登录mysql_linux终端mysql用户操作只看这篇够了
  12. 关于使用swiper心得
  13. html email template
  14. 模型评估方法【附python代码】(信息准则:赤池信息量准则AIC、贝叶斯信息准则BIC)
  15. 1919:【02NOIP普及组】选数
  16. 解决给word中表格设置“跨页断行”后出现大片空白
  17. 本地RTMP流媒体服务器搭建拉流简易版
  18. 2022-2028全球电脑备份软件行业调研及趋势分析报告
  19. 768位RSA算法遭破解,1024位目前安全
  20. 分享本地html项目给其他人访问

热门文章

  1. Ruby 学习笔记6
  2. CentOS 5.8/6.7若干优化
  3. SVN 与CVS 和VSS的区别
  4. 解题报告 noi 2005 智慧珠游戏(BT 搜索)
  5. C# MD5加密与解密
  6. loadrunner- winsock 函数 一览表
  7. labview 快捷键
  8. 调用天气接口获取天气预报
  9. java新手笔记18 类比较
  10. Basic INFO: InstallShield 2012安装过程