经典算法之全排列(详集)

我总结了全排列的各种题解,若有不全之处还请各位大大们慷慨指出.


1. 全排列之取球游戏

问题描述:

  m球中取n个球,共有多少种取法


解题思路:

  用递归思想解题.乍眼一看貌似递归无下手之处,其实每一个球只有两种情况:要么取, 要么不取. 若用m表示球的个数,n表示需要取的球的总数,那么当前球取则return fun(m - 1, n - 1) ; 不取则 return fun(m - 1, n);


代码实现:

github上相关代码:https://github.com/striner/javaCode/blob/master/Take%20the%20ball

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

//全排列练习

//1.取球游戏 m球中取n个球,共有多少种取法
public class Main {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int m = input.nextInt();    //共有m个球
		int n = input.nextInt();    //取n个球
		int num = fun(m, n);        //共有num种取法
		System.out.println(num);
		input.close();
	}

	public static int fun(int m, int n) {

		if (n == 0) return 1;   //m个球中取0个球,只有一种取法
		if (m == n) return 1;   //m个球中取m个球,只有一种取法
		
		//假设有一个球做了标记,那么它就有两种取法: 取 或 不取
		return fun(m - 1, n - 1) + fun(m - 1, n);
	}
}


运行结果:



2. 全排列之字符串数组组合计数问题

问题描述:

  求出输入字符串数组的全排列结果


解题思路:

  用ArrayList<>集合存放每一种可能的排列.用fun(str.substring(0, i) + str.substring(i + 1))递归,将每一次的str.charAt(i)提取出来并拼到下一次递归的排列结果之前.


代码实现:

github上相关代码:https://github.com/striner/javaCode/blob/master/An%20array%20of%20strings%20of%20Full%20Permutation

//2. 字符串数组全排列  组合计数问题
//求出输入字符串数组的全排列结果
class Main1 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String str = input.nextLine();
		List<String> list = fun(str);

		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
		input.close();
	}

	public static List<String> fun(String str) {

		List<String> list = new ArrayList<>();
		if (str.length() == 1) {
			list.add(str);
			return list;
		}
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			List<String> t = fun(str.substring(0, i) + str.substring(i + 1));
			for (int j = 0; j < t.size(); j++) {
				list.add("" + c + t.get(j));
			}
		}
		return list;
	}
}


运行结果:




3.全排列之字符串数组组合计数问题(数组实现)

问题描述:

  求出输入字符串数组的全排列结果


解题思路:

  通过数组中每一个元素与其后面元素一一交换实现


代码实现:

github上相关代码:https://github.com/striner/javaCode/blob/master/An%20array%20of%20strings%20of%20Full%20Permutation%20By%20Arrays

//3. 用数组实现字符串数组的全排列
//通过数组中每一个元素与其后面元素一一交换实现
class Main2 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String str = input.nextLine();
		char[] arr = str.toCharArray();
		fun(arr, 0);
		
		input.close();
	}

	public static void fun(char[] arr, int index) {   //arr:待排数据   index: 考虑的当前位置(数组下标)

		if (index == arr.length - 1) {
			System.out.println(String.valueOf(arr));
			return;
		}
		
		for (int i = index; i < arr.length; i++) {
			char ch = arr[i]; arr[i] = arr[index]; arr[index] = ch;     //试探
			fun(arr, index + 1);
			ch = arr[i]; arr[i] = arr[index]; arr[index] = ch;      //回溯
		}
	}
}


运行结果:



4. 全排列之固定数目的组合问题

问题描述:

   输入一串字符串数组,并中取3个数输出所有的可能结果


解题思路:

  由于所需取出的球数仅为3种,可以直接暴力破解. 后文会介绍取出不定球数或球数很多时的解法.


代码实现:

github上相关代码:https://github.com/striner/javaCode/blob/master/The%20combinatorial%20problem%20of%20fixed%20number

//4. 固定数目的组合问题  组合枚举循环暴力法
//输入一串字符串数组,并中取3个数输出所有的可能结果
class Main3 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String string = input.nextLine();
		char[] ch = string.toCharArray();
		fun(ch);
		
		input.close();
	}

	public static void fun(char[] ch) {

		for (int i = 0; i < ch.length; i++) {
			for (int j = i + 1; j < ch.length; j++) {
				for (int k = j + 1; k < ch.length; k++) {
					System.out.println("" + ch[i] + ch[j] + ch[k]);
				}
			}
		}
	}
}


运行结果:




5. 全排列之不定数目的组合问题

问题描述:

  从输入的字符数组中取n个字母,都有哪些取法


解题思路:

  采用组合枚举递归法解题,并用ArrayList对每种排列结果进行存储.


代码实现:

github上相关代码:https://github.com/striner/javaCode/blob/master/Variable%20number%20of%20combinatorial%20problems

//5. 不定数目的组合问题 组合枚举递归法
//从输入的字符数组中取n个字母,都有哪些取法
class Main4 {
	public static void main(String[] args) {
		 Scanner input = new Scanner(System.in);
		 String str = input.next();   
		 int n = input.nextInt();    //串str中取n个字母
		 List<String> list = fun(str, n);
		 for (int i = 0; i < list.size(); i++) {
			 System.out.println(list.get(i));
		 }
		 
		 input.close();
	}

	public static List<String> fun(String str, int n) {

		List<String> list = new ArrayList<>();
		if (n == 0) {
			list.add("");
			return list;
		}
		for (int i = 0; i < str.length(); i++) {
			char ch = str.charAt(i);
			List<String> t = fun(str.substring(i + 1), n - 1);
			for (int j = 0; j < t.size(); j++) {
				list.add("" + ch + t.get(j));
			}
		}
		return list;
	}
}


运行结果:




6. 全排列之组合重复问题

问题描述:

"AABBBC" 取3个,都有哪些取法


解题思路:

此题用data[]数组对每个元素的最大个数进行存储,用x[]来表示每个元素所取的个数,采用递归方式求得每一种结果并打印输出.


代码实现:

github上相关代码:https://github.com/striner/javaCode/blob/master/Repeat%20combination

//6. 组合重复
//"AABBBC" 取3个,都有哪些取法
class Main5 {
	public static void main(String[] args) {

		int[] data = {2, 3, 1};     //每个元素的最大个数 限制条件
		int[] x = new int[data.length];     //每个元素取几个
		
		fun(data, x, 0, 3);
	}

	public static void fun(int[] data, int[] x, int k, int goal) {  //k: 当前考虑的数的下标  goal:距离目标的剩余个数

		if (k == x.length) {
			if (goal == 0) 
				work(x);
			return;
		}
		
		for (int i = 0; i <= Math.min(data[k], goal); i++) {
			x[k] = i;
			fun(data, x, k + 1, goal - i);   //试探
		}
		x[k] = 0;   //回溯	
	}

	public static void work(int[] x) {

		for (int i = 0; i < x.length; i++) {
			for (int j = 0; j < x[i]; j++) {  //x[i]表示第i项的数最高出现几次
				System.out.print((char)('A' + i));
			}
		}
		System.out.println();
	}
}


运行结果:







猜你喜欢

转载自blog.csdn.net/striner/article/details/79690334
今日推荐