`
viking.liu
  • 浏览: 53924 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

无重复数组合

阅读更多
无重复数的组合问题
就是集合的所有非空子集

比如 {1,2,3}
的组合结果是
{1},{2},{3}
{1,2}{1,3}{2,3}
{1,2,3}
组合跟关键字的排列顺序无关

利用全排列算法求解
全排列算法可以求出集合所有的子集排列
所以 组合就是全排列的一个子集
1
2
3
12
13
21
23
31
32
123
132
213
231
312
321
一共是15个

取其中的长度为分别为1,2,3的递增序列就ok了
长度为1的: 1  2  3
长度为2的: 12 13 23
长度为3的: 123
因为组合是无序的,所以其他的舍弃

全排列参考
http://viking-liu.iteye.com/admin/blogs/1198952
一般的算法书上都有

package com.viking.divide;

public class Combination {
	public static void main(String[] args) {

		int[] a = { 1, 2, 3 ,4};
		System.out.println(perm(a, 0));
	}

	public static int perm(int[] a, int begin) {

		int count = 0;
		String path = "";
		for (int i = 0; i < begin - 1; i++) {
			if (a[i] > a[i + 1]) {
				return 0;
			}
			path += a[i] + " ";
		}
		if (begin > 0) {
                        // 输出有序的子集 就是组合的所有结果
			System.out.println(path + a[begin - 1]);
			count = 1;
		}
		if (begin == a.length) {
			return count;
		}

		for (int i = begin; i < a.length; i++) {
			swap(a, begin, i);
			count += perm(a, begin + 1);
			swap(a, begin, i);
		}
		return count;
	}

	public static void swap(int[] a, int begin, int end) {
		int temp = a[begin];
		a[begin] = a[end];
		a[end] = temp;
	}
}




上面这个算法的问题是求了在判断已排的序列是有有序时,从头开始,其实没有这个必要
因为每次递归都在判断,只要判断最后序列两个是否有序就ok了。
具体优化如下:
package com.viking.divide;

public class Combination {
	public static void main(String[] args) {
		int[] a = { 5, 2, 3, 4 };
		System.out.println(perm(a, 0));
	}

	public static int perm(int[] a, int begin) {
		int count = 0;	
		if (begin > 0) {
			if (begin > 1 && a[begin - 1] < a[begin - 2]) {
				//已排好数列无序
				return 0;
			}		
			for (int i = 0; i < begin; i++) {
				System.out.print(a[i] + " ");
			}
			System.out.println();
			count = 1;
		}
	
		for (int i = begin; i < a.length; i++) {
			swap(a, begin, i);
			count += perm(a, begin + 1);
			swap(a, begin, i);
		}
		return count;
	}

	public static void swap(int[] a, int begin, int end) {
		int temp = a[begin];
		a[begin] = a[end];
		a[end] = temp;
	}
}





上面的问题解决了判断序列是否有序时,减少比较次数。
但是整个全排列的交换次数很多,而且很多是没有意义的交换,
那么什么样的交换没有意义呢?
比如
3 21
3已经排好了,那么排21,2和1的交换就是没有意义的
因为组合只输出升序,无论 321 还是 312 最终都只有一个 3输出
所以要避免这种没有意义的交换

接着优化
package com.viking.divide;

public class Combination2 {
	public static void main(String[] args) {

		int[] a = { 4, 2, 3, 1 };
		System.out.println(perm(a, 0));		
	}
public static int c=0;
	public static int perm(int[] a, int begin) {
		int count = 0;
		if (begin > 0) {
			for (int i = 0; i < begin; i++) {
				System.out.print(a[i] + " ");
			}
			System.out.println();
			count = 1;
		}

		for (int i = begin; i < a.length; i++) {
			if (begin == 0 || a[begin - 1] < a[i]) {
				// 组合数没有顺序,所以用从小到大进行输出
				// 如果交换后不是升序,那么就不用交换,这样可以减少没有必要的交换
				swap(a, begin, i);
				count += perm(a, begin + 1);
				swap(a, begin, i);
			}
		}
		return count;
	}

	public static void swap(int[] a, int begin, int end) {	
		if (begin != end) {                   
			int temp = a[begin];
			a[begin] = a[end];
			a[end] = temp;
		}
	}
}



可以在每种方法中加入交换计数器c 计算组合的交换次数
最后一种的交换次数比前面两中方法的交换次数少很多

如果不是很理解,应该先理解全排列的算法
上面方法都是基于全排列算法改进的
求组合更好的方法。。。。
分享到:
评论

相关推荐

    C#生成2位或N位不重复字母数字组合

    在C#编程中,生成不重复的字母数字组合是一项常见的任务,特别是在密码生成、验证码创建或者唯一标识符的生产场景中。本篇文章将详细讲解如何使用C#来生成指定长度的不重复字母数字组合,包括两位及任意N位的情况。 ...

    易语言组合6位不重复数字

    这可能是为了实现某种特定的验证或者筛选机制,比如检查生成的数字是否满足某个条件(比如能被某个数整除)或者计算特定组合的总和。 易语言的源码文件中,可能会包含以下几个关键部分: 1. 数字集合定义:初始化0-...

    C#生成不重复字母数字组合的随机数

    在C#编程中,生成不重复的字母数字组合是一个常见的需求,这可能涉及到密码生成、唯一标识符创建或数据加密等多个领域。在这种情况下,我们通常会利用C#的内置类和方法来实现这一功能。标题提到的是“C#生成不重复...

    java有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

    通过运行上述代码,我们可以得到所有的不同三位数组合: - 123, 132, 142, 143, 213, 214, 231, 234, 241, 243, 312, 314, 321, 324, 341, 342, 412, 413, 421, 423, 431, 432 共有24个不同的组合。 ### 三、结论 ...

    易语言组合6位不重复数字源码

    至于动态规划,虽然在这个问题上不如前两种方法直观,但也可以通过构建一个状态数组来存储已生成的组合,避免重复生成。不过,对于较小规模如6位的数字组合,回溯法和DFS通常是更高效的选择。 易语言作为编程工具,...

    有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

    有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?字数不够,字数不够,字数不够,字数不够,字数不够,字数不够

    python 有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少?(源码)

    # 题目:有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少? # 分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。

    有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数.docx

    标题中的问题旨在探究如何使用1、2、3、4这四个数字来组成没有重复数字的三位数,并且描述中提供了算法思路,即通过三个嵌套的for循环配合一个if语句来实现。在这个Java程序中,`EleventhNumberRange` 类用于解决这...

    题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

    总结,这个问题是关于使用C语言编程解决一个排列组合问题,通过三重循环生成所有可能的三位数,同时利用条件判断保证数字的唯一性。这个过程体现了程序设计基础、数据结构基础和C语言语法等多方面的知识。

    c程序100例 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

    在C#编程中,我们经常会遇到需要解决排列组合问题,比如本题所示的例子:如何用1、2、3、4这四个数字组成互不相同且无重复数字的三位数,并计算总数以及列举出所有可能的组合。这个问题属于组合数学中的全排列问题,...

    C语言重复数全排列的代码

    每个排列占1行,各字符之间无空格分隔,每行由换行符结束。各行之间不必排序,但同一个排列不得重复输出。 【输入样例】 AABB 【输出样例】 AABB ABAB ABBA BABA BAAB BBAA

    C#输出不重复数字源码

    在这个解决方案中,"可定义输出个数"意味着用户可以设置要生成的不重复数字组合的数量。这可以通过在递归函数外部维护一个计数器来实现,每当输出一个组合时,计数器加1,当达到预设数量时,停止递归。 在给出的`...

    计算数字排列组合,任意数字的组合。

    2. **组合的计算**:组合的总数用组合数C(n, r)表示,即从n个不同元素中不重复地取出r个元素的组合数。组合数的计算公式为C(n, r) = n! / [r!(n-r)!]。 3. **算法实现**:在编程中,常用递归或动态规划方法实现排列...

    没有重复出现的数字的数字符号串的全体

    在编译原理中,正规式是一...通过这种方式,我们可以构造出一套规则来描述这类字符串,并通过正规式的操作和组合来生成任意长度的无重复数字的字符串正规式。这对于编译器设计和文本处理算法具有重要的理论和实践价值。

    java m取n 重复 不重复 排列组合 for循环嵌套递归

    System.out.println(chs.length + "取" + n + "不重复的排列组合个数为" + total); } ``` ##### 3.2 重复排列组合 ```java // 重复排列组合 public static int loop(int start, int end, char[] chs, String msg, ...

    重复数字统计器 .e文件

    《重复数字统计器.e文件详解》 在信息技术领域,数据处理和分析是至关重要的环节,尤其是在大数据时代。本文将深入探讨“重复数字统计器...在实际应用中,用户应根据自身需求调整和优化这种组合,以最大化其潜在价值。

    易语言源码易语言组合6位不重复数字源码.rar

    易语言源码易语言组合6位不重复数字源码.rar 易语言源码易语言组合6位不重复数字源码.rar 易语言源码易语言组合6位不重复数字源码.rar 易语言源码易语言组合6位不重复数字源码.rar 易语言源码易语言组合6位不...

    输出n个数字的全排列(可重复)

    1、输入n个数(不重复),求n个数字的全排列 如:n=3 全排列的数字为 1 2 3 则输出 123 132 213 231 321 312 2、输入n和k(n》=k)求n个数字的(n,k)排列 如n=3,k=2 输入的三个数位1 2 3 则输出 12 13 21 23 31...

    1234组成不相同的三位数个数

    有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

    易语言取元素组合数

    组合数,也称为二项式系数,在组合数学中占有重要地位,通常表示为C(n, k),表示从n个不同元素中不重复地选择k个元素的方法数。 在编程中,计算组合数通常涉及到递归或动态规划。易语言的源码实现可能包括这两种...

Global site tag (gtag.js) - Google Analytics