`

对一组数排列,包含相同元素

    博客分类:
  • java
阅读更多

题目:{3,2,2,6,7,8}排序输出,7不在第二位,68不在一起。

 

 

分析思考:

 

1.编写输出全部元素的排序组合,6位数共有6!个排序方式,即720个

 

2.由于有两个2,即重复元素,则最终将会有重复的排序方式,输出的个数720/2! = 360个,再去掉与7和68的限制相关的组合

 

 

全部元素排序

第一个位置有6种情况,取一个数放在第一位上,则第二位剩下5个元素,依次递归到最后一个元素,则得出一个排列组合。

按此方法,将全部排列输出

/**
	 * 分组排序
	 * @param source
	 */
	public static void group(int source[]) {
		for (int i = 0; i < source.length; i++) {

			int[] target = new int[source.length];

			// 第一个数有source.length种情况
			int first = source[i];

			int sourceStart = 0;
			target[sourceStart] = first;

			//通过下标移除已经选择的元素
			int[] leaveCollection = removeSelectIndex(i, source);
			groupNext(leaveCollection, sourceStart + 1, target,source.length);
		}
	}
	
	/**
	 * 通过下标移除已经选择的元素
	 * @param index
	 * @param source
	 * @return
	 */
	static int[] removeSelectIndex(int index , int[] source){
		int [] leaveCollection = new int[source.length -1];
		int leaveIndex = 0;
		for(int i = 0 ;i < source.length ;i++){
			if(index != i){
				leaveCollection[leaveIndex++] = source[i];
			}
		}
		return leaveCollection;
	}
	
	/**
	 * 第二个数有剩余source.length-1 种情况,第三个数从剩余中取,source.length-2种情况
	 * 
	 * @param source
	 * @param sourceStart
	 * @param target
	 */
	static void groupNext(int[] nextCollection, int sourceStart, int[] target,int sourceLength) {
		for (int l = 0; l < nextCollection.length; l++) {
			int second = nextCollection[l];

			target[sourceStart] = second;

			if (sourceStart + 1 < sourceLength) {
				// 递归下一位
				int[] copyOf = Arrays.copyOf(target, target.length);
				
				int[] source = removeSelectIndex(l, nextCollection);
				groupNext(source, sourceStart + 1, copyOf,sourceLength);
			} else {
				// 循环结束,输出结果
				println(target);
			}
		}
	}

 

由于有重复元素,在取剩下需要排序的集合时,不能用值去集合中删除,如在{22678}中删除2的元素,则剩下{678},通过下标移除是最好的方法。

 

 

删除不符合题意的组合

1.println(target)中,自行将7和68的限制去掉

 

2.由于有22存在,则在720个排列当中,有一半是重复的。需要把这些数据删除。最简单的做法通过Map,往Map中put进相同的元素,达到去重效果。

	static void println(int target[]) {
		StringBuffer bf = new StringBuffer();
		for (int i : target) {
			bf.append(i);
		}

		String value = bf.toString();
		
		if (value.indexOf("7") == 1)// except 7 in second position
			return;

		if (value.indexOf("68") != -1 || value.indexOf("86") != -1)// except adjoining
			return;

		rs.put(value, value);
	}

 

 

算法分析

 

解法二:

这种排序做法很早就看到过,通过将元素拼成两个数,再依次递增。判断输出结果:

 

public static void sort(String[] args) {
		// {3,2,2,6,7,8},其中7不能放在第二个位置,6和8不能相邻,打印所有的排列

		List<String> list = new ArrayList<String>();
		for (int i = 223678; i <= 876322; i++)
			list.add(i + "");

		int size = 0;// all size

		for (String s : list) {
			if (s.indexOf("0") != -1 || s.indexOf("1") != -1
					|| s.indexOf("4") != -1 || s.indexOf("5") != -1
					|| s.indexOf("9") != -1)// except 0,1,4,5,9
				continue;

			if (s.indexOf("2") == -1 || s.indexOf("3") == -1
					|| s.indexOf("6") == -1 || s.indexOf("7") == -1
					|| s.indexOf("8") == -1
					|| s.indexOf("2", s.indexOf("2") + 1) == -1)// contain all
				// 3,2,2,6,7,8
				continue;

			if (s.indexOf("7") == 1)// except 7 in second position
				continue;

			if (s.indexOf("68") != -1 || s.indexOf("86") != -1)// except
				// adjoining 6,8
				continue;
			size++;

			 System.out.println(s);
		}

		// System.out.println("All size --> " + size);// All size --> 198
	}

 

结果出来也是正确的。

 

但此算法循环的次数是876322-223678次=600000次,并且每次大约有10次的字符串indexOf操作,最终耗时500ms左右

 

而排序组合解法中,总共循环的次数为720次,耗时在15-50ms之间。

 

 

 

 

 

分享到:
评论
3 楼 yangkai 2010-02-02  
yangkai 写道
您好,对于你的排列组合,我个人认为有点复杂!
这里我有一个简单高效的算法:(如有问题请指正)

package com.ibm.common.arithmetic;

public class TraceBackSort {
	public static void main(String[] args) {
		TraceBackSort tc = new TraceBackSort();
		
                char a[] = {'3','2','2','6','7','8'};
		long start = System.currentTimeMillis();
		tc.perm(a, 0);
		long end = System.currentTimeMillis();
		System.out.println(end - start);
	}

	private void _swap(char[] a, int i, int j) {
		char temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

	public void perm(char[] a, int node) {
		int len = a.length;
		if (node == len) {
			String nodeStr = String.valueOf(a);
			if (nodeStr.charAt(1) != '7'
					&& !(nodeStr.matches("^\\d[68][86]\\d*$"))) {
				System.out.println(nodeStr);
			}
		} else {
			for (int i = node; i < len; i++) {
				_swap(a, node, i);
				perm(a, node + 1);
				_swap(a, node, i);
			}
		}
	}
}


2 楼 yangkai 2010-02-02  
您好,对于你的排列组合,我个人认为有点复杂!
这里我有一个简单高效的算法:(如有问题请指正)

package com.ibm.common.arithmetic;

public class TraceBackSort {
	public static void main(String[] args) {
		TraceBackSort tc = new TraceBackSort();
		
                char a[] = {'3','2','2','6','7','8'};
		long start = System.currentTimeMillis();
		tc.perm(a, 0);
		long end = System.currentTimeMillis();
		System.out.println(end - start);
	}

	private void _swap(char[] a, int i, int j) {
		char temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

	public void perm(char[] a, int node) {
		int len = a.length;
		if (node == len) {
			String nodeStr = String.valueOf(a);
			if (nodeStr.charAt(1) != '7'
					&& !(nodeStr.matches("^\\d[68][86]\\d*$"))) {
				System.out.println(nodeStr);
			}
		} else {
			for (int i = node; i < len; i++) {
				_swap(a, node, i);
				perm(a, node + 1);
				_swap(a, node, i);
			}
		}
	}
}

1 楼 yongyuan.jiang 2009-10-16  
一个同事给出另外一种思路。
5位先排序,再将重复的元素插入。

其实5位120次,再插入1位,结果依然是720次。

不过递归6位是否与5位有性能差别。还没去验证。

最终跑出来结果一样。

HashMap改由HashSet,虽然jdk HashSet源码是用HashMap事先的。但是结果却发现Set更加快。

package jyy.suanfa.zuhe;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Sort {

	public static void main(String[] args) {
		long l = 0;

		int time = 100;
		for (int i = 0; i < time; i++) {
			l += main1(null);
		}
		System.out.println("平均时间:"+l / time);
	}

	public static StringBuffer[] group(int[] source) {
		int length = 1;
		int count = 0;
		for (int i = 2; i <= source.length; i++) {
			length = length * i;
		}
		StringBuffer[] sbs = new StringBuffer[length];
		if (source.length <= 1) {
			sbs[count++] = new StringBuffer(String.valueOf(source[0]));
			return sbs;
		} else {
			for (int i = 0; i < source.length; i++) {
				int[] s = new int[source.length - 1];
				for (int j = 0; j < i; j++) {
					s[j] = source[j];
				}
				for (int j = i + 1; j < source.length; j++) {
					s[j - 1] = source[j];
				}
				StringBuffer[] reslut = group(s);
				for (int j = 0; j < reslut.length; j++) {
					StringBuffer sb = new StringBuffer(String
							.valueOf(source[i]));
					sb.append(reslut[j]);
					sbs[count++] = sb;
				}
			}
		}
		return sbs;
	}

	public static long main1(String[] args) {
		long first = System.nanoTime();
		int[] source = { 3, 2, 6, 7, 8 };
		StringBuffer[] group = group(source);
		Set<String> set = insert(group);

		long end = System.nanoTime();
		System.out.println("耗时:" + (end - first) + " nanoTime");
		return (end - first);
	}

	public static Set<String> insert(StringBuffer[] source) {
		Set<String> set = new HashSet<String>();
		for (int i = 0; i < source.length; i++) {
			StringBuffer sb = source[i];
			if (sb.indexOf("68") < 0 && sb.indexOf("86") < 0) {
				if (sb.charAt(0) == '7') {
					for (int j = 1; j <= sb.length(); j++) {
						StringBuffer temp = new StringBuffer(sb);
						set.add(temp.insert(j, '2').toString());
					}
				} else if (sb.charAt(1) == '7') {
					StringBuffer temp = new StringBuffer(sb);
					set.add(temp.insert(0, '2').toString());
					temp = new StringBuffer(sb);
					set.add(temp.insert(1, '2').toString());
				} else {
					for (int j = 0; j <= sb.length(); j++) {
						StringBuffer temp = new StringBuffer(sb);
						set.add(temp.insert(j, '2').toString());
					}
				}
			} else {
				int offset = sb.indexOf("68");
				if (offset < 0) {
					offset = sb.indexOf("86");
				}
				StringBuffer temp = new StringBuffer(sb);
				StringBuffer s = temp.insert(offset + 1, '2');
				if (sb.charAt(1) == '7') {
					continue;
				}
				set.add(s.toString());
			}
		}
		return set;
	}
}

相关推荐

    基于python的TXT解析器 parser 包含各个版本的代码 见注释

    每遍历一个元素(CA组合有效信息),就compile()和findall(),从该元素中提取数字组合(在compile()的参数中添加()就能够使提取的内容成为一组数据),然后通过dict自带函数setdefault()添加索引,并可以设置索引值...

    c程序设计习题参考(谭浩强三版)习题参考解答

    9.5请分析以下一组宏所定义的输出格式: 68 9.6请设计输出实数的格式。实数用“6.2f”格式输出。 69 9.7分别用函数和带参的宏,从3个数中找出最大数。 70 9.8试述“文件包含”和程序文件的连接(link)的概念,二者...

    数据结构实验

    如何计算一个三元组表表示的稀疏矩阵对角线元素之和以及两个三元组表表示的稀疏矩阵的乘积? 实验5:二叉树的建立及遍历 (第十三周星期三7、8节) 一 、实验目的 1.学会实现二叉树结点结构和对二叉树的基本操作。...

    Python寻找两个有序数组的中位数实例详解

    2.如果我们去掉其中一个数组比中位数小的k个数,再去掉另一个数组中比中位数大的k个数,得到的合并子数组的中位数和原来的中位数相同。 eg:[1,2,3],[1,2,3] =&gt; [1,1,2,2,3,3] 根据定理去除元素[2,3],[1

    蓝点被必做的算法经典题java.c/c++

    java经典算法题例。参赛必做。 【程序14】  题目:两个乒乓球队进行比赛,各出三人。...【程序30】写一个方法,用二分查找法判断任意整数在任意整数数组里面是否存在,若存在就返回它在数组中的索引位置,不存在返回-1

    java源码包2

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    Java使用递归算法求交错幂集(源代码)

    交错幂集(Alternating Power Set)是一个集合的概念,通常不是数学中的标准术语,但我们可以理解为在求一个集合的幂集时,对每一个子集的元素顺序进行交错排列。然而,在常规情况下,幂集并不考虑子集中元素的顺序...

    200个经典C程序源码(包括基础篇+数据结构篇+数值计算与趣味数学篇+图形篇+系统篇+常见试题解答篇).zip

    025 寻找相同元素的指针 026 阿拉伯数字转换为罗马数字 027 字符替换 028 从键盘读入实数 029 字符行排版 030 字符排列 031 判断字符串是否回文 032 通讯录的输入输出 033 扑克牌的结构表示 034 用“结构”...

    基于CNN、特征螺旋排列、奇异值分解、Hankel矩阵的故障诊断方法.zip

    **卷积层**是CNN的基本构建块,它通过使用一组可学习的滤波器(或称为卷积核)对输入图像进行扫描。每个滤波器在图像上滑动(卷积),并以局部区域(感受野)内的像素值与滤波器权重进行逐元素乘法后求和,生成一个...

    javascript入门笔记

    特点:将 a 和 b 先转换为二进制,按位操作,对应位置上的两个数字,相同时,该位整体结果为0,不同时,该位的整体结果为 1 使用场合:快速交换两个数字 5 ^ 3 101 011 ========== 110 结果为 6 练习: ...

    C语言程序设计标准教程

    比较详实 第四章: 数组 数 组  数组在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来。... 是对每一行的第一列元素赋值,未赋值的元素取0值。 赋值后各元素的值为: 1 ...

    关于C的精粹包含至少200个C语言小程序

    025 寻找相同元素的指针 026 阿拉伯数字转换为罗马数字 027 字符替换 028 从键盘读入实数 029 字符行排版 030 字符排列 031 判断字符串是否回文 032 通讯录的输入输出 033 扑克牌的结构表示 034 用“结构”...

    XML轻松学习手册--XML肯定是未来的发展趋势,不论是网页设计师还是网络程序员,都应该及时学习和了解

    一个文档结构树包含根元素,根元素是最顶级的元素,(就是紧接着XML声明语句后的第一个元素)。看例子: &lt;filelist&gt; &lt;title&gt;... &lt;author&gt;... 上面的例子分三级结构排列成"树"状,其中的就是根元素。在XML...

    python 颜色分类

    # 原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 # 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 # 输入示例 # [2,0,2,1,1,0] # 输出示例 # [0,0,1,1,2,2] #...

    Excel公式与函数大辞典.宋翔(带书签高清文字版).pdf

    1.6.3 创建对多个工作表中相同单元格区域的三维引用 30 1.6.4 更新跨工作簿引用的公式 31 1.7 审核公式 31 1.7.1 使用公式错误检查器 32 1.7.2 定位特定类型的数据 33 1.7.3 追踪单元格之间的关系 33 1.7.4 ...

    C++ set的使用方法详解

    set容器所包含的元素的值是唯一的,集合中的元素按一定的顺序排列。 我们构造set集合的目的是为了快速的检索,不可直接去修改键值。 set的一些常见操作: begin() 返回指向第一个元素的迭代器 clear() 清除所有...

    200个经典C程序【源码】

    025 寻找相同元素的指针 026 阿拉伯数字转换为罗马数字 027 字符替换 028 从键盘读入实数 029 字符行排版 030 字符排列 031 判断字符串是否回文 032 通讯录的输入输出 033 扑克牌的结构表示 034 用“结构”...

    200个C程序.rar

    025 寻找相同元素的指针 026 阿拉伯数字转换为罗马数字 027 字符替换 028 从键盘读入实数 029 字符行排版 030 字符排列 031 判断字符串是否回文 032 通讯录的输入输出 033 扑克牌的结构表示 034 用“结构”...

    数据结构第五章作业答案参考(C语言)

    2.对称矩阵的压缩存储:以行序为主序存储下三角中的元素,包括对角线上的元素。二维下标为( i, j ),存储空间的一维下标为k,给出k与 i, j (i)的关系k=( ) (1, j , 0*(n+1)/2)。 A.i*(i-1)/2+j-1 B.i*(i+1)/2+j...

    计算机二级公共基础知识

    链式存储结构就是在每个结点中至少包含一个指针域,用指针来体现数据元素之间逻辑上的联系。 1.2.2 线性结构和非线性结构 根据数据结构中各数据元素之间前后件关系的复杂程度,一般将数据结构分为两大类型:线性结构...

Global site tag (gtag.js) - Google Analytics