百度笔试:回家有n个台阶,每次至少走一个,但是要求每步和之前两步走的台阶数目不能一样,请问有多少种不同的解法,答案对10^9+7取模。

回家有n个台阶,每次至少走一个,但是要求每步和之前两步走的台阶数目不能一样,请问有多少种不同的解法,答案对10^9+7取模。

输入两个整数n,m,n表示台阶数目,m表示单步最大跨越的台阶数目。

思路:老实说这题不难,但是想全A还是有点难,全A肯定要动态规划,而且是三维的动态规划,但是我觉得面试的时候也不会考这么难,所以三维的动态规划的方法就不写了,下面写了两个方法,一个是递归的,一个是记忆化搜索(带备忘录的递归)。

1、递归

就是递归每次需要传入上一次的值last和上上次的值lastlast,然后遍历可以跳跃的值1~m,如果不是last和lastlast就可以继续递归,否则跳过,代码如下:

public static int res=0;
public static void dfs1(int index,int n,int m,int last,int lastlast){
		if(index==n)
		{
			res++;
			res=res%1000000007;
		}
		if(index>n)
			return ;
		for(int i=1;i<=m;i++){
			if(i!=lastlast&&i!=last){
				dfs1(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast	
			}	
		}	
	}

2、带备忘录的递归

大家都知道,递归的低效率是由于重复计算了很多子问题,因此想到把子问题保存在哈希表里面,每次递归时直接查询,如果哈希表里面没有才继续往下算,代码如下:

public static HashMap<String,Integer> map;
	public static int dfs(int index,int n,int m,int last,int lastlast){
		if(index==n)
		{
			return 1;	
		}
		if(index>n)
			return 0;
		String str=index+","+last+","+lastlast;
		if(map.containsKey(str))
			return map.get(str);
		int lastres=0;
		for(int i=1;i<=m;i++){
			if(i!=lastlast&&i!=last){
				lastres+=dfs(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast
			}	
		}
		lastres=lastres%1000000007;
		map.put(str,lastres);
		return lastres;
	}

最后把两个代码放在一起,方便大家比较:

public static int res=0;
	public static HashMap<String,Integer> map;
	public static int dfs(int index,int n,int m,int last,int lastlast){
		if(index==n)
		{
			return 1;	
		}
		if(index>n)
			return 0;
		String str=index+","+last+","+lastlast;
		if(map.containsKey(str))
			return map.get(str);
		int lastres=0;
		for(int i=1;i<=m;i++){
			if(i!=lastlast&&i!=last){
				lastres+=dfs(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast
			}	
		}
		lastres=lastres%1000000007;
		map.put(str,lastres);
		return lastres;
	}
	public static void dfs1(int index,int n,int m,int last,int lastlast){
		if(index==n)
		{
			res++;
			res=res%1000000007;
		}
		if(index>n)
			return ;
		for(int i=1;i<=m;i++){
			if(i!=lastlast&&i!=last){
				dfs1(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast	
			}	
		}	
	}
	public static void print(List<List<Integer>> tmp){
		for(List<Integer> a:tmp){
			for(Integer a1:a)
				System.out.print(a1+" ");
			System.out.println();
		}		
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		//int n=70;
		//int m=4;
		int n=sc.nextInt();
		int m=sc.nextInt();
		map=new HashMap<>();
		System.out.println("带备忘录的:");
		System.out.println(dfs(0,n,m,0,0));
		dfs1(0,n,m,0,0);	
		System.out.println("不带备忘录的");
		System.out.println(res);
		
	}

猜你喜欢

转载自blog.csdn.net/qq_35590091/article/details/108403940