对n个不同正数进行排列,一共有多少种排列方式

import java.util.Scanner;

public class NumberGroup {

	public static void main(String[] args) {

		System.out.println("请输入一个正数");
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		int[] a = new int[n];
		int[] b = new int[a.length];
		System.out.println("请输入"+ n +"个正数");
		for(int i=0; i<a.length; i++) {
			a[i] = scan.nextInt();
		}
		
		for(int i=0; i<a.length; i++) {		
			numberGroup(a[0], a, 0, b);
		}
		
	}

	public static void numberGroup(int num, int[] a, int count, int[] b) {
		b[count] = num;
		count++;

		if (count >= a.length) {                             //递归的出口
			for (int i = 0; i < b.length; i++) {
				System.out.print(b[i] + " ");
				if (i == b.length - 1)
					System.out.println();
			}

			// b[count - 1] = 0;
			return;
		}

		for (int i = 0; i < a.length; i++) {
			if (!jiancha(b, a[i])) {
				numberGroup(a[i], a, count, b);
				qingchu(count, b);                                      //关键
			}
		}

	}

	public static boolean jiancha(int[] b, int x) {
		for (int i = 0; i < b.length; i++) {
			if (b[i] == x) {
				return true;
			}
		}
		return false;
	}

	public static void qingchu(int count, int[] b) {

		for (int j = count; j < b.length; j++) {
			b[j] = 0;
		}

	}

}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
思路: 1. 子集树:对于每个元素,有选和不选两可能,可以看成是一棵二叉树,遍历这棵树,记录下每个叶子结点的和,若有满足条件的叶子结点,则找到了一个解。 2. 排列树:排列树是在子集树的基础上,将每个元素看成是可重复的,即可以出现多次,因为要考虑到重复元素的情况,所以需要加上一个限制条件,即每个元素在当前排列中出现的次数不能超过原集合中该元素的个数。 代码: 1. 子集树 ```c++ #include<iostream> using namespace std; int n, k, a[100], ans[100], cnt; void dfs(int x, int sum) { // x表示当前处理到哪个元素,sum表示当前所选元素的和 if (x == n + 1) { // 遍历到叶子结点 if (sum == k) { // 找到一个解 cnt++; cout << "Solution " << cnt << ": "; for (int i = 1; i <= n; i++) { if (ans[i] == 1) cout << a[i] << " "; } cout << endl; } return; } ans[x] = 0; // 不选当前元素 dfs(x + 1, sum); ans[x] = 1; // 选当前元素 dfs(x + 1, sum + a[x]); } int main() { cin >> n >> k; for (int i = 1; i <= n; i++) { cin >> a[i]; } dfs(1, 0); if (cnt == 0) cout << "No solution!" << endl; return 0; } ``` 2. 排列树 ```c++ #include<iostream> using namespace std; int n, k, a[100], ans[100], cnt, num[100]; void dfs(int x, int sum) { // x表示当前处理到哪个元素,sum表示当前所选元素的和 if (x == n + 1) { // 遍历到叶子结点 if (sum == k) { // 找到一个解 cnt++; cout << "Solution " << cnt << ": "; for (int i = 1; i <= n; i++) { for (int j = 1; j <= ans[i]; j++) { // 输出每个元素出现的次数 cout << a[i] << " "; } } cout << endl; } return; } for (int i = 0; i <= num[x]; i++) { // 枚举当前元素出现的次数 ans[x] = i; dfs(x + 1, sum + i * a[x]); // 更新当前和 } } int main() { cin >> n >> k; for (int i = 1; i <= n; i++) { cin >> a[i]; } sort(a + 1, a + n + 1); // 排序,以方便后面处理重复元素 int j = 1; num[1] = 1; for (int i = 2; i <= n; i++) { // 计算每个元素在原集合中出现的次数 if (a[i] == a[j]) num[j]++; else { j++; a[j] = a[i]; num[j] = 1; } } n = j; // 更新元素个数 dfs(1, 0); if (cnt == 0) cout << "No solution!" << endl; return 0; } ``` 思路树图: 1. 子集树 ``` 1 / \ 2 2 / \ / \ 3 3 3 3 / \ / \ / \ / \ 4 4 4 4 4 4 4 4 ``` 2. 排列树 ``` 1(0) / | \ 1(1) 1(2) 1(3) / \ / \ / \ 2(0) 2(1) 2(0) 2(1) 2(0) 2(1) / \ / \ / \ / \ / \ / \ 3(0) 3(1) 3(0)3(1)3(0)3(1)3(0)3(1)3(0)3(1) ``` 其中,数字表示当前处理的元素下标,括号中的数字表示该元素当前已经选择的次数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值