资讯专栏INFORMATION COLUMN

程序员的算法趣题Q50: 完美洗牌

xeblog / 3168人阅读

摘要:的结果与原书的结果不符。上一篇程序员的算法趣题欲速则不达程序员的算法趣题欲速则不达下一篇程序员的算法趣题同时结束的沙漏本系列总目录参见程序员的算法趣题详细分析和全解程序员的算法趣题详细分析和全解

目录

1. 问题描述

 2. 解题分析

2.1 思路1

2.2 思路2

3. 代码及测试

4. 后记


1. 问题描述

        问题:对2n张牌洗牌,并求当1<=n<=100时,一共有多少个n可以使得经过2(n-1)次洗牌后,恢复最初顺序?分两种情况考虑:

        Case1: 2(n-1)次洗牌后,牌恢复最初顺序

        Case2: 2(n-1)次洗牌后第一次恢复顺序

        Case2可以看作是case1的一种特殊情况。Case1的意思是,如果在m{其中m为2(n-1)的因子}次洗牌后回复最初顺序即可。

 2. 解题分析

2.1 思路1

        第一感是以下这个‘高大上’的想法:

        呃。。。虽说如此,群论只学了一丢丢。。。等我先把群论学一学再来看这条路能不能走通。本系列其实出现过好几道可以用群论来解决的问题。群论学习从开始到放弃经历过好多次了,这次带着问题去学习看看能不能走得远一些。 

2.2 思路2

        (没有别的更炫的法子时)蛮干就是了。。。

        针对每一个n,从初始状态(初始状态是什么并不重要)开始,以迭代的方式进行以上permutation操作,并判断是否回到了最初状态。

        算法流程如下:

3. 代码及测试

# -*- coding: utf-8 -*-"""Created on Sat Oct  9 19:33:11 2021@author: chenxy"""# import sysimport time# import datetime# import math# import random# from   typing import List# from   queue import Queue# from   collections import deque# import itertools as itimport numpy as npN = 100ok_list = []tStart = time.perf_counter()for n in range(1,N+1):    start = np.arange(2*n)    p     = np.zeros_like(start)    for k in range(n):        p[2*k]   = start[k]        p[2*k+1] = start[n+k]    # print(p)        cur = start    cnt = 0    # recover = False    while 1:        cur = cur[p]        cnt = cnt + 1        if np.array_equal(cur, start):            # print(n, cur, start, cnt)            if (2*(n-1) % cnt) == 0:            # if (2*(n-1)) == cnt:                # print(n, cur, start, cnt)                # recover = True                ok_list.append(n)                break        if cnt > 2*(n-1):            break    # if recover:        # ok_list.append(n)tCost  = time.perf_counter() - tStart        print("length of ok_list = {0}, tCost = {1:6.3f}(sec)".format(len(ok_list),tCost))print(ok_list)            

case1运行结果:

length of ok_list = 46, tCost =  0.046(sec)
[1, 2, 3, 4, 6, 7, 9, 10, 12, 15, 16, 19, 21, 22, 24, 27, 30, 31, 34, 36, 37, 40, 42, 45, 49, 51, 52, 54, 55, 57, 64, 66, 69, 70, 75, 76, 79, 82, 84, 87, 90, 91, 96, 97, 99, 100]

case2运行结果(注释掉 "if (2*(n-1) % cnt) == 0:",打开 “ if (2*(n-1)) == cnt:)":

length of ok_list = 45, tCost =  0.059(sec)
[2, 3, 4, 6, 7, 9, 10, 12, 15, 16, 19, 21, 22, 24, 27, 30, 31, 34, 36, 37, 40, 42, 45, 49, 51, 52, 54, 55, 57, 64, 66, 69, 70, 75, 76, 79, 82, 84, 87, 90, 91, 96, 97, 99, 100]

        尴尬。。。case2的结果与原书的结果不符。想不出哪里不对,哪个小伙伴看出来毛病来了请不吝指教^-^

4. 后记

        两个遗留事项:

        (1) 基于群论的解决方法

        (2) case2的结果不对

        嗯,我一定会回来的。。。

        上一篇:程序员的算法趣题Q49: 欲速则不达

        下一篇:程序员的算法趣题Q51: 同时结束的沙漏

        本系列总目录参见:程序员的算法趣题:详细分析和Python全解

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/122179.html

相关文章

  • 序员算法趣题Q49: 欲速则不达

    摘要:本文先考虑深度优先搜索。深度优先搜索算法流程如下最后,将初始化为,初始化,和分别初始化为适当的全零数组,然后调用到最终退出后所得到的即为所求结果。 目录 1. 问题描述 2. 解题分析 3. 代码及测试 4. 后记 1. 问题描述 2. 解题分析         本题是要找最长路径,应该...

    BlackMass 评论0 收藏0
  • 序员算法趣题Q54: 偷懒算盘

    摘要:且听下回分解基于动态规划策略的优化解法参见程序员的算法趣题偷懒的算盘上一篇程序员的算法趣题同数包夹程序员的算法趣题同数包夹本系列总目录参见程序员的算法趣题详细分析和全解程序员的算法趣题详细分析和全解 目录 1. 问题描述 2. 解题分析 3. 代码及测试 4. 后记 1. 问题描述   ...

    wangzy2019 评论0 收藏0
  • 序员算法趣题Q22: 不缠绕纸杯电话

    摘要:假设有几个小朋友以相同间隔围成圆周,要结对用纸杯电话相互通话。如果绳子交叉,很有可能会缠绕起来,所以结对的原则是不能让绳子交叉。如下所示运行结果上一篇异或杨辉三角形下一篇禁止右转本系列总目录参见程序员的算法趣题详细分析和全解 目录 1. 问题描述 2. 解题分析 3. 代码及测试 1. 问...

    MoAir 评论0 收藏0
  • 序员算法趣题Q46: 唯一OX序列

    摘要:可以在遍历所有矩阵时,对各种出现的次数进行计数,最后计数值为的个数即为所求结果。上一篇排序交换次数的最少化排序交换次数的最少化本系列总目录参见程序员的算法趣题详细分析和全解程序员的算法趣题详细分析和全解 目录 1. 问题描述 2. 解题分析 3. 代码及测试 4. 后记 1. 问题描述 ...

    y1chuan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<