`
luzitian
  • 浏览: 26892 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

把一个数字分离成不同的数字的和

阅读更多

一道有趣的题目,把一个整数num拆分成n个整数的合,要求这n个整数各不相同,不能有重复,如num为10,则有以下几种情况:

1 9
2 8
3 7
4 6
1 2 7
1 3 6
1 4 5
1 2 3 4

我想了一个算法,不知正确与否,希望各位大牛来拍砖。

分析:

首先,把10拆分成两个数,因为各个数不能相同,所以只当第一个数为4时为止,即

1 9
2 8
3 7
4 6

其次,再把10拆分1和9,对9采用上面的拆法,9会被拆成如下:

1 8
2 7
3 6
4 5

因为各数字不能重复出现,所以把1 8这对去掉,所以10被拆成如下:

1 2 7
1 3 6
1 4 5

再次,再把10拆分成1、2和7,对7采用上面的拆法,7会被拆成如下:

1 6
2 5
3 4
1 2 4

因为拆分出的数字中不能含有1、2所以只留下3 4这对数字,所以10被拆成如下:

1 2 3 4

最后,再把10拆分成1、2、3和4,由于4拆分出的两个数字必须大于3,这是不可能的,所以已经无法继续拆分。至此10的拆分结束。

 

从上面的分析可以看出,最后一步都是把经过前面拆分后剩下的数值拆分成两个数,而前面的拆分则是拆分出1或1、2或1、2、3……,由此写出了第一个程序:

package calc.printsum;
import junit.framework.TestCase;
/**
 * 打印和为num的所有情况,并且每行中不能有重复数字 
 */
public class PrintResult1 extends TestCase {
	public void test() {
		int num = 10;
	                // i <= Math.ceil(num / 2)
                                //因为i再大就会打出重复数字了
		for (int i = 1; i <= Math.ceil(num / 2); i++) {
			splitNum(i, num - sumToN(i));
//			System.out.println("------------");
		}
	}

	/**
	 * @param start
	 * @param num
	 */
	private void splitNum(int start, int num) {
		if (start > num) {
			return;
		}
		for (int i = start; i <= Math.ceil(num / 2) && i != (num - i); i++) {
			// 打出从1到start的数字
			printSerial(start);
			// 把剩下的num分成两半
			System.out.print(i + " ");
			System.out.println(num - i);
		}
	}

	/**
	 * 顺序打印1到n
	 * @param n
	 */
	private void printSerial(int n) {
		for (int i = 1; i < n; i++) {
			System.out.print(i + " ");
		}
	}

	/**
	 * 计算1到n的总和
	 * @param n
	 * @return
	 */
	private int sumToN(int n) {
		int sum = 0;
		for (int i = 1; i < n; i++) {
			sum += i;
		}
		return sum;
	}
}

函数printSerial由于是i<n所以当i=1时是不会打印任何东西的,所以splitNum的for循环中当start是1时实际上只执行了“把剩下的num分成两半”的两句打印语句,这正是我们想要的。

 

分析此类可以发现存在两个问题:

1、sumToN实际上是不需要的,我们完全可以充分利用先计算过的结果,从而无须每次都从头到尾计算前n个数的和;

2、如果把System.out.println("------------");这一句的注释打开,可以看到在最后一组数字后面还打多了两次------------,如下:

1 2 3 4
------------
------------
------------

于是有了修改后的PrintResult2:

package calc.printsum;
import junit.framework.TestCase;
/**
 * 打印和为num的所有情况,并且每行中不能有重复数字
 */
public class PrintResult2 extends TestCase {
	public void test() {
		int num = 10;
		int sum = 0;
		// i <= Math.ceil(num / 2)
                                //因为i再大就会打出重复数字了
		for (int i = 1; i <= Math.ceil(num / 2); i++) {
                                                // sum利用了上次计算的结果
			sum += (i - 1);
			// 由i > (num - sum) / 2演变而来,当i再增大时num-sum的值已经无法继续拆分成两个不同于前i个数字的数字之合了
			if (2 * i > (num - sum)) {
				break;
			}
			splitNum(i, num - sum);
//			System.out.println("------------i:" + i + " sum:" + sum
//					+ " (num - sum) / 2:" + (num - sum) / 2);
		}
	}

	/**
	 * 把num按从start开始分离成两个不同的数相加
	 * @param start
	 * @param num
	 */
	private void splitNum(int start, int num) {
		if (start >= num) {
			return;
		}
		for (int i = start; i <= Math.ceil(num / 2) && i != (num - i); i++) {
			// 打出从1到start的数字
			printSerial(start);
			// 把剩下的num分成两半
			System.out.print(i + " ");
			System.out.println(num - i);
		}
	}

	/**
	 * 顺序打印1到n
	 * 
	 * @param n
	 */
	private void printSerial(int n) {
		for (int i = 1; i < n; i++) {
			System.out.print(i + " ");
		}
	}
}

这是我对这个题目的思考过程,有错误的地方欢迎大牛批评指出。

分享到:
评论

相关推荐

    java 字母数字分离

    java 字母数字分离 字母大小写互换 将数字排在字母的后面

    用汇编语言将字符串中的字母和数字分开存储

    ### 任务分析:字母和数字分离 在给出的代码示例中,主要目标是读取一个混合包含字母和数字的字符串,并将其拆分为两个独立的字符串:一个仅包含所有数字,另一个仅包含所有字母。这涉及到几个关键步骤: 1. **...

    Linux字母数字分离

    Linux 字母数字分离是指在 Linux 环境下,使用 Shell 命令或编程语言来将文件中的字母和数字分离,并对数字进行求和操作。该操作可以用于数据处理、数据分析和数据统计等领域。 在 Linux 环境下,可以使用 Shell ...

    1088 分离整数的各个数.cpp

    给定一个整数n(1≤n≤100000000),要求从个位开始分离出它的每一位数字。从个位开始按照从低位到高位的顺序依次输出每一位数字。 【输入】 输入一个整数,整数在1到100000000之间。 【输出】 从个位开始按照从低位...

    可以分离EXCEL中的数字和文字

    可以分离EXCEL中的数字和文字,很难得的用法。

    Excel分离汉字、字母和数字

    其中,对数据进行精细的处理,如分离混合文本中的汉字、字母和数字,是常见的需求之一。以下是对给定文件标题“Excel分离汉字、字母和数字”以及其描述、标签、部分内容所涉及的知识点的详细解析。 ### Excel分离...

    易语言正则表达式分离汉字英文数字

    在处理字符串时,易语言提供了正则表达式这一强大的工具,可以用来进行复杂的文本匹配和处理,包括分离汉字、英文和数字。 正则表达式(Regular Expression)是模式匹配的一种表示方式,能够有效地描述一组字符串的...

    excel如何分离不同位数的字母与数字.docx

    我们的目标是将字母部分和数字部分分离开,分别放在B列和C列。 步骤1:提取字母部分 - 在B1单元格中,输入一个与A1单元格相同但仅包含字母的部分。例如,如果A1是"12ab34",则在B1单元格输入"a"。 - 点击B1单元格的...

    数字转换成金额大写

    2. **分离整数部分和小数部分**:将数字拆分成整数和小数两部分,分别处理。 3. **整数部分转换**:从个位到亿位,依次转换每个数字。这里可以使用数组或哈希表存储对应的中文大写字符。如果位数不足,前面需要补零...

    excel如何分离不同位数的字母与数字.pdf

    以下是一个详细的方法,教你如何在Excel中分离不同位数的字母与数字。 首先,打开一个包含这种混合数据的工作表。假设我们有一列数据在A列,从A1开始,其中每条记录都是由一个字母和一组数字组成,如"A123"、"B4567...

    将数字与字母分开的程序

    标题中的“将数字与字母分开的程序”是一个编程任务,主要目标是编写一个软件或脚本,能够识别字符串中的数字和字母,并将它们分离。在编程领域,这通常涉及到字符串处理和字符检测。 描述中提到的“利用STRTOINT...

    matlab分离字符串和数字的测试数据

    测试matlab分离字符串和数字的测试数据,可用来测试matlab分离数字和字符串的代码

    gis字段计算器提取数字和中文

    GIS是一个用于捕获、管理、分析和显示地理数据的系统,而字段计算器是GIS软件中的一个功能,它允许用户执行预定义的逻辑脚本来对字段中的数据进行操作,例如提取数据或者进行数据转换。 在GIS的字段计算器中,可以...

    电子功用-数字电视的彩色分离器

    在电子工程领域,数字电视的彩色分离器是一个关键组件,它负责从复合视频信号中提取出红、绿、蓝三原色信号,从而实现彩色图像的还原和处理。本资料详细探讨了这一技术,旨在为相关专业人士提供深入理解。 彩色电视...

    数位分离1

    在本篇文章中,我们将深入探讨如何实现数位分离,并通过一个具体的编程示例来说明其执行过程和实现方式。 首先,数位分离的基本概念涉及到将一个数字拆分为单独的数字元素,通常是指拆分为它的各个数位。在不同的...

    基于FPGA的通信信号数字滤波分离技术.pdf

    本篇论文“基于FPGA的通信信号数字滤波分离技术”深入探讨了如何利用FPGA实现通信信号的数字滤波与分离,这对于提升通信系统性能有着重要的理论和实际意义。 首先,本论文以现代软件无线电信道化理论和FPGA技术为...

    分离数字字母汉字符号-易语言.zip

    "分离数字字母汉字符号"这个任务涉及到字符串操作和字符处理,这是一个常见的编程需求,尤其在数据清洗、文本分析和格式转换等方面。在这个场景下,我们使用的是"易语言",一种中国本土开发的、面向对象的、组件式的...

    实验七时分复用数字基带通信系统.doc

    数字终端模块是实验七时分复用数字基带通信系统的核心部分,它的工作原理是将时分复用信号分离成两路数据信号,并将其转换成串行数据信号和并行数据信号。数字终端模块的输入端包括时分复用基带信号输入点、抽样后的...

    数字信号处理课程设计3-题目三:利用数字滤波器实现信号分离.docx

    例如,对于第一路调幅信号,其载波频率为250Hz,可以通过设计一个适当的低通滤波器来分离出该信号;对于第二路调幅信号,其载波频率为500Hz,可以通过设计一个带通滤波器来分离;而对于第三路调幅信号,其载波频率为...

    vhdl 数字频率计

    1. 模块化设计:vhdl 数字频率计采用模块化设计思想,通过分离不同的模块来实现对频率的测量。这种设计方法可以使得系统更加灵活、可靠和易维护。 2. 数字频率计的组成:vhdl 数字频率计主要由三个模块组成:计数器...

Global site tag (gtag.js) - Google Analytics