Python-思维专题1
前言这个专题会收录一些我认为有点思维难度的题甚至有些题目都不好理解希望你也能从解题的过程中获得乐趣。注1.收录的题目难度仅代表个人看法并且我的代码肯定也有很多可以提升的地方不喜勿喷但是改进意见我肯定会听的。2.会持续更新主要是我才写到这几道。一、翻牌游戏题目描述N 张扑克牌正面朝下扣在桌面上每轮都从第一张开始翻面。第一轮每隔一张将扑克牌翻面第二轮每隔两张将扑克牌翻面第三轮每隔三张将扑克牌翻面……依此规则玩下去。问题玩了 M 轮后扑克牌中连续正面朝上和朝下的最大张数分别是多少输入格式一行两个整数即 n、m。输出格式空格隔开的两个整数即连续正面朝上的最大张数、连续正面朝下的最大张数。样例输入数据 110 3输出数据 12 5提示无分析先给你分析一下题目说实话因为题目没理解清楚导致我重写了2遍。首先我给你讲一下翻牌的规则。我现在用样例输入举例假设0代表正面朝下1代表正面朝上那么最初始的牌面就是这样的[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]。然后进行第一轮翻拍第一轮的规则是从第一张开始每隔1张翻一次那么经过第一轮翻牌后的牌面会是这样的[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]。接下来进行第二轮翻盘模仿上一次就是从第一张开始每隔2张翻一次那么牌面会变成这样[0, 0, 1, 1, 1, 0, 0, 0, 1, 1]。以此类推经过3轮翻牌后牌面最终会变成这样[1, 0, 1, 1, 0, 0, 0, 0, 0, 1]。注第一张每次都要翻。然后我给你分析一下“连续正面朝上的最大张数、连续正面朝下的最大张数”是什么意思。假设有一组牌是这样排列的[1, 0, 1, 1, 0, 0, 0, 0, 0, 1]就是上面那个样例那么连续正面朝上的最大张数就是这个部分[1, 0,1, 1, 0, 0, 0, 0, 0, 1]连续正面朝下的最大张数就是这个部分[1, 0, 1, 1,0, 0, 0, 0, 0, 1]。但是这里还有一个非常重要的点那就是题目所判断的是最终牌面在这个例子中就是第3次翻牌后牌面中连续正面朝上的最大张数、连续正面朝下的最大张数千万不要搞错啦我就在这里跳过坑。那么游戏规则在这里就给大家讲清楚了。下面我们就开始解题。首先我们根据牌有向上和向下2种状态很容易想到用1和0来统计牌的不同状态就是我上面解析题目时的想法。然后先将初始的牌面用一个列表l来表示l中全是0因为题目说初始时全部牌都朝下然后这里其实可以用列表的复制创建但是代码中我用的是for循环再用for循环推出经过翻拍后的牌面。接下来就是我认为除了理解题目之外最难的一个部分了。如何实现寻找相连的部分其实就是和上一个数比较是否相等听起来很简单是吧但做起来还要考虑很多问题难。我先拿连续正面朝上的最大张数举例连续正面朝下的最大张数其实思路是一样的只是判断条件的不同因此我感觉这里也可以用函数来实现这部分功能可以少写一块代码但是我展示的代码中是重复2次做的先判断这个数是否为1第一个数不能忘记哦若为一x就加1我们用x来统计个数。然后这里要考虑一种特殊情况如果它是第一位数并且它不是1按道理它要执行和上一个数比较的程序但是由于它是第一个数它没法和上一个数作比较所以直接continue。随后每个数我们都需要和上一个数进行比较看它们是否都等于1若满足x加1。然后每当上面的条件都不满足时就用一个新的列表a来存储这一次x的值并且x重新归0然后重复以上操作。直到循环结束最后输出max(a)即可。但是这里还有一种特殊情况就是如果列表l总共就只有1个数呢它只执行一次循环之后那a岂不是空列表所以循环结束后在循环的外面还要将x再一次添加到a中来避免这种情况。终于讲完了bushi代码简化前n, m map(int, input().split()) l [] a [] b [] x 0 y 0 for i in range(n): l.append(0) for j in range(1, m 1): for k in range(0, n, j 1): if l[k] 0: l[k] 1 elif l[k] 1: l[k] 0 for q in range(len(l)): if l[q] 1: x 1 elif l[q] ! 1 and q 0: continue elif l[q] l[q - 1] 1: x 1 else: a.append(x) x 0 for e in range(len(l)): if l[e] 0: y 1 elif l[e] ! 0 and e 0: continue elif l[e] l[e - 1] 0: y 1 else: b.append(y) y 0 a.append(x) b.append(y) print(max(a), max(b))简化后def f(l, a): s [] x 0 for i in range(len(l)): if l[i] a: x 1 elif l[i] ! a and i 0: continue elif l[i] l[i - 1] a: x 1 else: s.append(x) x 0 s.append(x) return s n, m map(int, input().split()) l [0] * n for j in range(1, m 1): for k in range(0, n, j 1): if l[k] 0: l[k] 1 elif l[k] 1: l[k] 0 print(max(f(l, 1)), max(f(l, 0)))注简化只是写法变了行数少了但整体解题思路没变展示这个也只是想让大家拓宽思维。二、狐狸找兔子题目描述山顶有 n 个洞一只狐狸和一只兔子住在各自的洞里。狐狸一直想吃掉兔子。一天兔子对狐狸说“你想吃我有一个条件先把洞从 1-n 编上号你从 n 号洞出发先到1号洞找我第二次隔1个洞找我第三次隔2个洞找我以后依次类推次数不限到 n 号洞后又回到 1 号洞继续找。若能找到我你就可以饱餐一顿。不过在没有找到我以前不能停下来。”狐狸满口答应就开始找了。它从早到晚进了 m 次洞累得昏了过去也没找到兔子。请问兔子可能躲在哪些洞里输入格式一行两个正整数即 n、m。输出格式多行每行一个整数即兔子可能在的洞编号。按编号有小到大输出。样例输入数据 110 1000输出数据 12 4 7 9提示无分析这个在我看来相比于上一题就简单一点了所以我讲的也会简略一点写完上一题的分析其实就已经燃尽了多担待吧但是主要思路肯定会说的。这道题主要就是用for循环一个一个排查如果狐狸找过这个洞就将列表中的这个数变成0。这里要注意for循环查找的过程中会有一个环形结构每当找到n后就会从头开始所以要取模n。代码n, m map(int, input().split()) l [] ans 0 for i in range(1, n 1): l.append(i) for j in range(1, m 1): if ans j n: ans j else: ans (ans j) % n l[ans - 1] 0 for k in l: if k ! 0: print(k)