深度优先解决排列九位数的问题

这篇博客由IT新手撰写,介绍了使用深度优先解决将9张编号卡片放入9个编号盒子的排列问题。通过简化问题和递归思想,解释了如何实现所有可能的放法,最后给出了代码实现的思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

萌新深夜写一篇有关于深度优先的博客,萌新刚刚走进IT大门,简直毫无技术可言,说的不对的请指教。

所谓深度优先,我的理解它是离不开递归的,而递归这种神才用的东西,想必要把它捋顺还是很可怕的一件事,就好比大学刚开始学C语言老师给我们玩一个汉诺塔的游戏,总的来说,递归是不需要真正捋清楚里面的每一层是怎么实现的,你只需要知道   “当下应该如何思考 ”,而不需要考虑“下一步是如何做到的”。

比如在这里我介绍一个深度优先的例子:假如有编号为1-9的卡片和编号为1-9的盒子,现在需要将这九张卡片分别放入9个盒子中,并且每个盒子有且只有一张卡片,那么一共有多少种放法呢?并且告诉我所有的放法?

是不是咋一看好像并不是很难,这里深夜先介绍一种大神的算法,首先9张卡片放到9个盒子实际上就是对一个不重复的九位数进行排列,这是不是和小学初中学的那种排列方式差不多呢,接下来我们要找规律了,9个数字的排列组合如何才是重复的呢?这里我们用到了字符串的分割的方法(Split),将123456789当成一个不重复的九位数,那么

string str="123456789";

将str按这个字符串中的每一个字符来分割的话,所得到的字符串的数量应该是2,当然前提是这个九位数是不重复的,如果重复会出现什么结果呢,比如:

string str1="123456589";

按5来分割的话会得到蓝色区域的部分,也就是分割后的长度为3,这就是重复和不重复的区别了,

static bool IsNoneRepeat(string str)
        {
            for (int i = 0; i < str.Length; i++)
            {
                if (str.Split(new char[] { str[i]}).Length != 2)
                {
                    return false;
                }
            }
            return true;
        }

        一下子又跑远了,没办法每次看完大神的代码总觉得惭愧,深夜还需要好好学习,回到我们刚才说的深度优先,还记得刚才说的重点吗,深度优先就是递归,讲究的是当前该如何做,那么我们把这个问题简化一下,假如是三张卡片三个盒子的时候,现在深夜拿着三张卡片站在第一个盒子面前,盒子都是按照顺序排列的,深夜此时有一种购物的心理,我拿着九张卡呢,那么这一号盒子我要不要买呢,你要是和深夜一样有这种心理的话就自己打自己脑袋一下吧,开个玩笑,继续,深夜将手中的1卡片放到里面,此时一定有钻牛角尖的同学要问了,深夜可不可以先放卡片2,当然可以了,只是便于我们写代码和描述,咱们还是先按照顺序来吧,一会你就知道你的牛角尖钻的有点上天。

        此时深夜到了第二个盒子面前,手上还有2和3数字的卡片,本着按顺序好写代码的原理深夜果断又把卡片2放到了二号盒子中了,那么到了三号盒子面前的时候深夜此时只有3卡片了,于是放进去,当深夜傻不拉几的想去四号盒子的时候,发现根本没有四号盒子手中也没有卡片了,那么就完成了第一种放法。(1、2、3)

按照思维是不是觉得已经结束了,那就大错特错了,我们还要继续考虑别的放法,可是手中已经没有卡片了啊,怎么办呢,本着没有的东西就去抢回来的原理(开玩笑,未成年人自动忽略),深夜果断把三号盒子中的卡片拿了回来,可是此时三号盒子我们刚才已经放过了一次,刚抢回来的我才不会再往里放呢,于是深夜又开始打起了二号盒子的主意,深夜把卡片2也从二号盒子“抢”了出来,那么深夜现在就有两张卡片,分别是2和3,深夜这次机智的把卡片3放到了二号盒子中,然后走向了三号盒子,并且把手中最后一张卡片2放到了三号盒子中。深夜果然还是比较傻的,又走向了四号盒子,一片空空荡荡,没盒子没卡片,那么第二种放法又有了。(1、3、2)


按照深夜的“按照顺序好写代码”“没有就去抢”“刚放过的又想骗我放一次”的逻辑,那么可以完成所有的放法,它们分别是:(1、2、3)(1、3、2)(2、1、3)(2、3、1)(3、1、2)(3、2、1)

罗里吧嗦半天,有人会问,老铁,代码怎么写啊,好吧接下来我们来说一下代码。

首先如何往盒子中按顺序的放卡片呢,其实用一个for循环就可以解决了

for(int i=1;i<=n;i++)
{
    box[index]=i;//将卡片i放到第index个盒子中
}

“没有就去抢”怎么知道自己是没有呢,定义一个数组,card[n]来记录是否有这张卡片

    for (int i = 1; i <= n; i++)
            {
                if (card[i-1]==0)
                {
                    box[index] = i;//这句相当于第一张牌放进第一个盒子中
                    card[i-1] = 1;//第一张牌已经被使用了
                }
            }

将这个方法封装成一个方法。然后就好办了把,前面说到递归,相比大部分的朋友已经知道怎么做了,我就不多说了

全部源代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 深度优先
{
    class Program
    { 
        private static int[] card=new int[9];//用来标记哪些牌已经使用
        private static int[] box = new int[9];//用来表示盒子
        static void Main(string[] args)
        {
            DepthFirstSearch(0,card.Length);

        }
        static void DepthFirstSearch(int index,int n)
        {
            if (index == n)
            {
                PrintBox(box);
            }
            for (int i = 0; i < n; i++)
            {
                if (card[i]==0)
                {
                    box[index] = i;//这句相当于第一张牌放进第一个盒子中
                    card[i] = 1;//第一张牌已经被使用了
                    DepthFirstSearch(index + 1,n);
                    card[i] = 0;
                }
            }
            
        }
        static void PrintBox(int[] box)
        {
            for (int i = 0; i < box.Length; i++)
            {
                Console.Write(box[i]+" ");
            }
            Console.WriteLine();
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值