典型递归问题

1 把一个数组里的数进行组合全部列出,比如1和2列出来为1,2,12,21

1.1 伪码

  • 初始化input,visited,result
  • 算法开始,从数组input的不同位置开始,执行下面伪码:
go(input,visited,result,i){
	//先对visited进行深拷贝
	visited[i]=true;
	result.add(input[i]);
	打印出result;
	for循环,如果visited里面存在fasle项,就go(input,visited,result,false项的地址);
	result.remove(result.size() - 1);
}

1.2 代码实现

public static void main(String args[]) {
		// 获取输入
		Scanner s = new Scanner(System.in);
		String str = s.nextLine();
		String[] temp = str.split("\\s+");
		int[] input = new int[temp.length];
		for (int i = 0; i < temp.length; ++i) {
			input[i] = Integer.valueOf(temp[i]);
		}
		ArrayList<Integer> result = new ArrayList<Integer>();
		// 算法
		boolean[] visited = new boolean[input.length];// 用于标记元素是否被访问
		for (int i = 0; i < input.length; ++i) {
			go(input, visited, result, i);
			result.remove(result.size() - 1);//第一个添加的数,只能这样删除
		}
	};

	public static void go(int[] input, boolean[] visited, ArrayList<Integer> result, int i) {
		boolean myVisited[] = new boolean[visited.length];// 用于实现深拷贝
		System.arraycopy(visited, 0, myVisited, 0, visited.length);
		myVisited[i] = true;
		result.add(input[i]);
		display(result);
		// 继续递归
		for (int k = 0; k < myVisited.length; ++k) {
			// 看是否还有没被访问的元素(都是按地址从小到大访问的)
			if (myVisited[k] == false) {
				// result.add(input[i]);//没加一个数就打印一次
				// display(result);
				go(input, myVisited, result, k);
				result.remove(result.size() - 1);
			}
		}
		// 每个标记都被访问完
		// result.remove(result.size()-1);
	}

	public static void display(ArrayList<Integer> result) {

		for (int iterator : result) {
			System.out.print(iterator);
		}
		System.out.println();
	}

2 试用递归的方法编程计算非波那契数列的通项f(n),已知f1=1,f2=1,以后每项都是前两项的和。

2.1 伪码

简单,不写了。

2.2 代码实现

package temp;

import java.util.Scanner;

public class temp {
	private static final int F1=1;
	private static final int F2=1;
	
	public static void main(String args[]) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int result=f(n);
		System.out.println(result);
	};
	
	public static int f(int n){
		if(n==1){
			return F1;
		}else if(n==2){
			return F2;
		}
		else{
			return f(n-2)+f(n-1);
		}
	}

}

3 一个字符串中可能包含a~z中的多个字符,如有重复,如String data=“aadfasdfdfadflkfasf”,求出现次数最多的那个字母及次数,如有多个重复的则都求出。

  这道题与递归毫无关系(不知道Jav程序员面试宝典那本书为什么要把这道题放在那个地方)。

3.1 思路

  这道题,简单,我想到了用hashMap存储结果,因为放入重复的key时,后放的那个会覆盖已经有的那个key

3.2 代码实现

注意:Map类型的遍历,先取出它的keySet,再根据keySet遍历Map。

public class temp2 {
	public static void main(String args[]) throws IOException {
		// 获取输入
		Scanner s = new Scanner(System.in);
		String str = s.nextLine();
		LinkedHashMap<Character, Integer> resultMap = new LinkedHashMap<Character, Integer>();
		for (int i = 0; i < str.length(); ++i) {
			// 如果resultMap中没有当前字符的信息,就添加
			Integer temp = resultMap.get(str.charAt(i));
			if (temp == null) {
				resultMap.put(str.charAt(i), 1);
			} else {
				resultMap.put(str.charAt(i), temp + 1);
			}
		}
		// 查找最大值
		LinkedHashMap<Character, Integer> realResult=findMax( resultMap);
		//打印出结果
		Set<Character> set=realResult.keySet();
		for(Character temp:set){
			System.out.println(temp+"出现的次数:"+realResult.get(temp));
		}
		
	}

	public static LinkedHashMap<Character, Integer> findMax(LinkedHashMap<Character, Integer> resultMap){
		Set<Character> set=resultMap.keySet();
		LinkedHashMap<Character, Integer> realResult=new LinkedHashMap<Character, Integer>();
		int max=0;
		Character c=null;
		for(Character temp:set){
			if(resultMap.get(temp)>max){
				max=resultMap.get(temp);
				c=temp;
			}
		}
		//将结果存入realResult
		realResult.put(c, max);
		//查找重复最大的
		for(Character temp:set){
			if(resultMap.get(temp)==max){
				c=temp;
				realResult.put(c, max);
			}
		}
		return realResult;
				
	}
}

4 利用1、2、2、3、4这5个数字,用java写一个main函数,打印出所有不同的排列,如12234,21234(不能存在重复,比如出现两个12234)

4.1 思路

  • 将1,2,2,3,4看成5个不同的字符A,B,C,D,E进行排列
  • 利用set集合不能放重复元素的特性,去掉相同的排列

4.2 代码实现

public class temp2 {
	private static int size = 5;
	public static int[] input = new int[size];// 放在这里是为了避免递归时,频繁传递参数input
	private static HashSet<String> realSet = new HashSet<String>();// 用于去重,放在这里是为了避免递归时,频繁传递参数input

	public static void main(String args[]) throws IOException {
		// 初始化一些数据
		Scanner scn = new Scanner(System.in);// 用于接受1 2 2 3 4
		String str = scn.nextLine();
		String[] temp = str.split("\\s+");
		for (int i = 0; i < size; ++i) {
			input[i] = Integer.valueOf(temp[i]);
		}

		boolean[] visited = new boolean[size];
		for (int i = 0; i < size; i++) {
			go(visited, i, "");
		}
		// 打印出结果
		for (String iterator : realSet) {
			System.out.println(iterator);
		}
	}

	public static void go(boolean[] visited, int i, String resultStr) {
		// 深拷贝visited与resultStr
		boolean[] myVisited = new boolean[size];
		char[] myResultChar = new char[resultStr.length()];
		System.arraycopy(visited, 0, myVisited, 0, size);
		System.arraycopy(resultStr.toCharArray(), 0, myResultChar, 0, resultStr.length());
		String myResultStr = new String(myResultChar);
		// 访问第i个元素
		myVisited[i] = true;
		myResultStr += input[i];
		for (int k = 0; k < myVisited.length; ++k) {
			if (myVisited[k] == false) {
				go(myVisited, k, myResultStr);
			}
		}
		
		//是否所有的元素都被访问了
		boolean isAllVisited = true;
		for (int k = 0; k < myVisited.length; ++k) {
			if (myVisited[k] == false) {
				isAllVisited = false;
				break;
			}
		}
		if (isAllVisited) {
			realSet.add(myResultStr);
		}
	}

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值