涉及算法:非递归的dfs
题目大意:
求出一个长度为10^n+n-1的序列,其中包含了所有的n位数(一共10^n个数,从00000(n个0)~10^n-1)
题目分析:由于序列长度的限制,我们想要一个一个的写出0000(n个0)~10^n-1所有的数,是不可能的。由于10^n+n-1比我们所需要输出的数的个数只多n-1,所以基本上我们所求的序列每一位都要表示一个数,即第i个数的前n-1位是第i-1个数的后n-1位,而第一个数由于前面没有数字,所以第1个数就只能用一个n位数表示,这样序列的长度为n+10^n-1。我们在求第i个数的时候,要保证该数在前面i-1个数都没有出现过。
这个题目我一共用了三种方式来写,一种是最常见也最容易理解的递归的dfs,但是由于递归的次数太多,当n=4时就会产生StackOverFlowError。第二种是用stack来实现的非递归dfs,这个也不行,提交到判别系统中会MLE,最后只能参考别人的,不用stack的非递归,张见识了。
首先给出能够AC代码
package com.solo.dfs;
import java.util.Arrays;
import java.util.Scanner;
public class Main_1780_2
{
static int maxn=1000010;
static int vis[]=new int[maxn];
static char ans[]=new char[maxn];
static int nnow[]=new int[maxn];
static int n;
static int mod,end;
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
n=in.nextInt();
while (n!=0)
{
Arrays.fill(vis, 0);
Arrays.fill(ans, 0, n, '0');
end=(int) Math.pow(10, n)+n-1;
mod=(int) Math.pow(10, n-1);
vis[0]=1;
dfs();
n=in.nextInt();
}
}
public static void dfs()
{
int pos=n;int now=0;int i=0;
nnow[pos-1]=0;
while (pos<end)
{
now=nnow[pos-1]%mod;
for(;i<10;i++)
{
if(vis[now*10+i]==0)
{
vis[now*10+i]=1;
ans[pos]=(char)(i+'0');
nnow[pos]=now*10+i;
pos++;
i=0;
break;
}
}
if(i==10)
{
pos--;
vis[nnow[pos]]=0;
i=nnow[pos]%10+1;
}
}
for (int j = 0; j < end; j++)
{
System.out.print(ans[j]);
}
System.out.println();
}
}
*********************************************************************************************************************************
没有AC的代码也贴出来给大家看看,虽然不能AC,但是可以用来看看递归dfs和非递归dfs的区别,非递归dfs的实现方式又有哪些不同
//递归的dfs
//递归次数太多会造成StackOverflowError
public class Main_1780
{
static int maxn=1000000+10;
static int ans[]=new int[maxn];
static int vis[]=new int[maxn];
static int end,mod;
static int n;
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
n=in.nextInt();
end=(int) Math.pow(10, n)+n-1;
mod=(int) Math.pow(10, n-1);
for (int i = 0; i < n; i++)
{
ans[i]=0;
}
vis[0]=1;
dfs(n,0);
for (int i = 0; i < end; i++)
{
System.out.print(ans[i]);
}
}
public static boolean dfs(int pos,int now)//pos:序列的第i个位置,now:第pos位前的n-1位组成的n-1位数
{
if(pos==end)
{
return true;
}
for (int i = 0; i < 10; i++)
{
if(vis[now*10+i]==1) continue;
vis[now*10+i]=1;
ans[pos]=i;
if(dfs(pos+1, (now*10+i)%mod))
{
return true;
}
vis[now*10+i]=0;
}
return false;
}
}
//stack实现的非递归dfs
//MLE
public class Main_1780_3
{
static int maxn=1000010;
static int vis[]=new int[maxn];
static int ans[]=new int[maxn];
static int n;
static int mod,end;
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
n=in.nextInt();
while (n!=0)
{
Arrays.fill(vis, 0);
mod=(int) Math.pow(10, n);
end=(int) Math.pow(10, n)+n-1;
Arrays.fill(ans, 0,n,0);
dfs(new Node(0,n-1));
n=in.nextInt();
}
}
static class Node
{
Queue<Integer> adjNodes = new LinkedList<Integer>();//node
int now;//node所对应的n位数字
int pos;//node所放置的位置
public Node(int now,int pos)
{
this.now=now;
this.pos=pos;
for(int i=0;i<=9;i++)
{
adjNodes.offer(i);
}
}
}
static void dfs(Node u)
{
int pos;
Stack<Node> stack=new Stack<Node>();
Node v;
vis[u.now]=1;
stack.push(u);
while (!stack.isEmpty())
{
u=stack.peek();
Integer i=u.adjNodes.poll();
if(i==null)
{
vis[u.now]=0;
stack.pop();
}
else {
if (vis[(u.now*10+i)%mod]==0)
{
pos=u.pos+1;
vis[(u.now*10+i)%mod]=1;
ans[pos]=i;
if(pos==end-1) break;
stack.push(new Node((u.now*10+i)%mod, pos));
}
}
}
for (int i = 0; i <end ; i++)
{
System.out.print(ans[i]);
}
System.out.println();
}
}