阿里p7前端面试题蓝桥杯 ALGO-1004 无聊的逗 01背包+回溯 python,讲的真透彻

如何理解分割成两个等和的列表子集

为了确定是否能够得出两个等长木棍,我们就看在这些木棍中能否拼出总长度之和的一半这个数来,如果可以,这些木棍就能够分出两条等长的木棍。举个例子, 有4根木棍:4 2 9 2 木棍长度总和是4+2+9+2 = 17 。因为两根木棍长度之和必定是偶数,所以这些木棍要想拼出两根等长木棍是不可能的。但如果木棍长度是 4 2 9 3 长度总和是 18,就要看木棍列表中能否凑出18 / 2 = 9 这个数了。我们一眼望去可以发现,是能够凑出9这个数的,因此 4 2 9 3 这个木棍列表是能够分出两根的等长木棍的。

不知道我说到这里各位同学能否明白这道题的解决思路,如果不明白,我再举个例子。还是以 4 2 9 2 木棍为例,我们知道,这些木棍是不能分出两个等长木棍的。但如果我硬要得出两根等长木棍的最大长度是多少,该怎么办呢? 就要舍弃掉一些木棍了,舍弃谁好呢?我们一眼望去可以发现 舍弃了9后木棍列表变成 4 2 2 是可以凑成两根等长木棍的,木棍的长度是(4+2+2)/ 2 = 4。而4也是在 4 2 9 2 木棍列表中所能找到等长的单根的最大长度,所以4作为结果返回。

说到这里不知道同学们能不能区分开以上整体与部分的关系,如果可以我们继续,否则再倒回上面仔细琢磨一下。

思路

=================================================================

现在我们就知道该干啥了,就是要判断木棍列表能否凑出长度之和的一半(sum(Stick_list) / 2)这个数。细心的同学看到前面的两个一眼发现都加粗显示了,因为,可能肉眼看起来容易找到,但如果想告诉电脑该怎么发现并不容易

这里就要使用01背包思路来求解了。01背包是整道题的前置知识点。如果01背包不懂的朋友没关系,@代码随想录 在B站有非常详细的讲解视频,一次看不懂没关系,多看几遍,我也是看了四五遍才懂的,一定要理解每个步骤,理解完后会发现并没有你想的这么难。🔍🔍戳这里进入~

搞清楚01背包后,你会发现,判断木棍列表能否凑出长度之和一半这个数 还是不知道该如何下手。说实话让我想,我也想不出用01背包。

那你会不会说岂不是白学01背包了?当然不是,01背包应用是非常广的,你现在遇不到以后也会遇到,越早学越好。学了01背包,起码是不知道怎么做,如果告诉你思路你就能够做,但你学都没学的话,那跟你说了也不会。

我们看一下力扣这道题,可以说跟我们所要求的东西非常相似。

在这里插入图片描述

📮📮📮虽然我现在知道该怎么做,但我建议你还是跟着视频学好点,如果单纯看文字描述思考的话会比较枯燥而且较难理解。我是看leetcode官方题解视频学会的,也是看了四五遍才懂,所以推荐给大家。 🔑🔑leetcode官方视频题解

在这里插入图片描述

跟着他们学还是挺有意思的。


上面是分割线,当你看到这里的时候我默认当做你已经会了判断木棍列表能否凑出长度之和一半这个数

如果初始的木棍列表能够凑出长度之和一半这个数,那么我们就能直接返回结果。但如果不能的话我们就要在这个列表中删掉一些木棍再来看是否能够分成两根等长木棍,最后在这些可能的情况中返回木棍长度的最大值作为结果。

接着我们思考一下,如何在删掉一些木棍的列表中找出能够分成两根等长木棍的最大长度?

我最开始的思路是使用BFS让木棍列表按字典序由小到大逐步弹出一个元素,每弹一个匹配一次,当第一次匹配到的木棍列表的时候长度必然 (我的想法而已)最大,因为我是按字典序从小到大弹出元素的,每次将小的弹出,再弹大的,那如果找到第一次能够划分等长木棍的列表,应该就是木棍的最大长度了。比如:假设木棍 1 2 3 4 凑不出两根等长的木棍,我的思路就是弹出1 变成 234 然后匹配看234能否凑出等长木棍,不行的话弹出2变成134匹配,不行再弹出3 变成124匹配等等等,然后弹出12 13 14 23 24 34 这样逐个弹出并匹配。

感觉挺完美的,但一提交结果就拿了个50分。想了半天,头发也都快抓没了,就是想不出来,因此我也改了名,我本来叫李帅哥的,哎,说多都是泪。但最后调试打印长度总和的时候终于看到了问题所在。

我们先看个优化前的数据截图

在这里插入图片描述

左边列表是用来判断是否能够拼成两根等长木棍的,右边的那个数是长度总和。注意又是假设啊,假设图中两个红框的列表才能分成两根等长的木棍,那么一定是先出现的列表长度就越大吗?答案是否定的,存有五个数的列表未必会大过存有三个数的列表,可能数多的列表元素值更小。

既然知道了不能够直接返回第一个能够分成两根等长木棍的列表,那么我们就要遍历搜索找出能够分割成等长木棍的最大值了。

我的做法是:先将木棍列表降序排序,之后使用DFS得到木棍列表的每个子集,然后分别判断这个子集能够否分成两根等长的木棍,如果可以,比较得出最大值,最后返回结果,期间需要剪枝

剪枝还是挺有讲究的,没搞好分分钟超时。我们在遍历过程中需要让子集调用一个自定义的函数,这个函数是用来判断列表是否能够分出两根等长木棍的,但如果每有一个子集就要匹配一次的话,会消耗大量资源。因此在调用这个函数前,要进行一个判断:如果此列表总和大于已知的木棍之和最大值,以及这个列表总和是偶数(奇数的话必定不能分成两根等长木棍),才能调用那个函数。让列表降序排序再遍历是因为整体列表长度总和还是由高到低的,这样能较为容易的得到更大值,那么就能直接将子集中更小的值排除,而无需进行函数调用。

接着就是DFS的经典剪枝操作了,如果有数组used用来标记元素是否使用的话,就是,如果这个数使用过,可以直接跳过;如果这个数与前一个数相等且前一个数没有使用过的话,跳过。同时,要有个start标记起始位置,每走一层递归start+1。当然,这里不是排列而是组合(也就是说(2,1),(1,2)存在一个即可)可以不使用used数组,直接+1即可。

如果你看不懂我说的剪枝操作,没关系,做多一点回溯题即可,做多两条你就会发现,这类题型写法总是千变一律啊…

如果你想多了解回溯算法的剪枝思路,我还是推荐你看下@代码随想录的讲解视频,讲的确实不错。

忙乎了一天,终于把这篇文章给写完了,下面我们看下代码实现。

代码实现

===================================================================

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
img

现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。

分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算**

  • 23
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值