Java一道经典算法题!!!求解!

TKD03072010 2011-04-26 07:51:01
整数的分划问题。
如,对于正整数n=6,可以分划为:
6
5+1
4+2, 4+1+1
3+3, 3+2+1, 3+1+1+1
2+2+2, 2+2+1+1, 2+1+1+1+1
1+1+1+1+1+1
现在的问题是,对于给定的正整数n,编写算法打印所有划分。
用户从键盘输入 n (范围1~10)
程序输出该整数的所有划分。
...全文
492 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
carefreedom 2011-07-10
  • 打赏
  • 举报
回复
这个算法好精巧。。
lg_asus 2011-05-03
  • 打赏
  • 举报
回复
厉害,看半天没看懂
whut_lcy 2011-04-27
  • 打赏
  • 举报
回复
LZ偷懒哥
TKD03072010 2011-04-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 keeya0416 的回复:]

我在4楼的代码不是分治
思路是 n 最大能填充够一个长度为 n 、值均为 1 的数组
考虑到重复
所以在填充的时候让数组递减
Java code

if (index <= arr.Length && remnant == 0)
{
for (int i = 0; i < index - 1……
[/Quote]
Thank you very much!
java爱好者 2011-04-27
  • 打赏
  • 举报
回复
分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。
对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。
将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
keeya0416 2011-04-27
  • 打赏
  • 举报
回复
我在4楼的代码不是分治
思路是 n 最大能填充够一个长度为 n 、值均为 1 的数组
考虑到重复
所以在填充的时候让数组递减

if (index <= arr.Length && remnant == 0)
{
for (int i = 0; i < index - 1; i++)
{
System.out.print(arr[i] + " + ");
}
System.out.println(arr[index - 1]);
}

这段代码路判断,当需要填充的数字为 0 时,即为填充完毕,开始输出。其实index <= arr.Length 这个条件可以不要,因为 n 最大能填充够一个长度为 n 、值均为 1 的数组,所以这个总是成立的。

for (int i = 1; i <= remnant && i <= maxNum; i++)
{
arr[index] = i;
divideNumber(arr, index + 1, i, remnant - i);
}

这段代码的意思是,当剩余的数字大于0,将可以添入的合法数字枚举填入,分别进入数组下一个序号的填充步骤,因为填充数字的规则是不变的,所以用了递归,并没有分治。合法的数字是满足 小于等于 剩余数字 和 下于等于上一数字填充时的值以满足数组递减的性质(那个值是当前数组中的非0最小值)。
下边这个是用分治做的,楼主也可以看下

public static void solve(int i){
innerSolve(i, i, 1, "");
}

private static void innerSolve(int tatol, int n, int min, String result){
if (n == 0){
System.out.println(tatol + " = " + result.substring(1));
}
else if (n >= min){
innerSolve(tatol, n - min, min, result + "+" + min);
innerSolve(tatol, n, min + 1, result);
}
}
rorom 2011-04-27
  • 打赏
  • 举报
回复
这个思路应该是挺清晰的
TKD03072010 2011-04-27
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 afgasdg 的回复:]

分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。
对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。
将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的……
[/Quote]
谢谢!看来递归这块 还得再花时间研究研究!
mintdo 2011-04-27
  • 打赏
  • 举报
回复
我是打酱油的!
lw372289iuei2010 2011-04-27
  • 打赏
  • 举报
回复
正在思考中
TKD03072010 2011-04-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 keeya0416 的回复:]

引用 4 楼 keeya0416 的回复:
Java code


public static void divideNumber(int n)
{
int[] arr = new int[n];
divideNumber(arr, 0, 6, 6);
}

//往数组中填充数字, index为待添位, maxNum 为能填入的……

6
5+1
4+2, 4……
[/Quote]
哥们 有QQ吗?想向你再讨教一下!
TKD03072010 2011-04-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 keeya0416 的回复:]

引用 4 楼 keeya0416 的回复:
Java code


public static void divideNumber(int n)
{
int[] arr = new int[n];
divideNumber(arr, 0, 6, 6);
}

//往数组中填充数字, index为待添位, maxNum 为能填入的……

6
5+1
4+2, 4……
[/Quote]
非常感谢你的解答,但是思路 我还是不能理解,呵呵
keeya0416 2011-04-26
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 keeya0416 的回复:]
Java code


public static void divideNumber(int n)
{
int[] arr = new int[n];
divideNumber(arr, 0, 6, 6);
}

//往数组中填充数字, index为待添位, maxNum 为能填入的……
[/Quote]
6
5+1
4+2, 4+1+1
3+3, 3+2+1, 3+1+1+1
2+2+2, 2+2+1+1, 2+1+1+1+1
1+1+1+1+1+1
这里可以看出填充数组的话,填入的数字是递减的
我在 4 楼写的就是这个思路
keeya0416 2011-04-26
  • 打赏
  • 举报
回复


public static void divideNumber(int n)
{
int[] arr = new int[n];
divideNumber(arr, 0, 6, 6);
}

//往数组中填充数字, index为待添位, maxNum 为能填入的最大值, remnant 为剩余数字
public static void divideNumber(int[] arr, int index, int maxNum, int remnant)
{
if (index <= arr.Length && remnant == 0)
{
for (int i = 0; i < index - 1; i++)
{
System.out.print(arr[i] + " + ");
}
System.out.println(arr[index - 1]);
}
else
{
for (int i = 1; i <= remnant && i <= maxNum; i++)
{
arr[index] = i;
divideNumber(arr, index + 1, i, remnant - i);
}
}
}
TKD03072010 2011-04-26
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 yewuqing007 的回复:]

Java code
public class t11 {
public static void fun(int[] str, int n, int m) {
if (n == 0) {
for (int i = 0; i <= m - 1; i++) {
if (i == (m - 1))
……
[/Quote]
感谢你的解答,能说一下你的思想,或加一些注释吗?
devin_jia 2011-04-26
  • 打赏
  • 举报
回复
public class t11 {
public static void fun(int[] str, int n, int m) {
if (n == 0) {
for (int i = 0; i <= m - 1; i++) {
if (i == (m - 1))
System.out.println(str[i]);
else
System.out.print(str[i] + " ");
}
} else {
for (int i = n; i >= 1; i--) {
if (m == 0 || i <= str[m - 1]) {
str[m] = i;
fun(str, n - i, m + 1);
}
}
}
}

public static void main(String[] args) {
fun(new int[6], 6, 0);
}
}
做一门精致,全面详细的 java数据结构与算法!!!让天下没有难学的数据结构,让天下没有难学的算法,不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发???总之你知道的,不知道的,我们都讲,并且持续更新,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱话不多说,牛不多吹,我们要讲的本门课程内容:稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问、八皇后问算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧