欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

典型递归问题

程序员文章站 2022-05-08 22:54:22
...

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);
		}
	}

}

相关标签: 递归