拆数,给定两个正整数m,n(m >= n),将m拆成n个数相加...(游戏)

1. 问题

(网上看到的题目)
昨天去面试人家出了这样一道题,觉得挺简单的,但就是编不出来,只好麻烦各位高手了。
给定两个正整数m,n(m >= n),将m拆成n个数相加:m =a(1)+a(2)+...+a(n),使之满足:a(1)<a(2)<...<a(n);
列出所有的拆法。
例如:若m=7,n=3则只有一种拆法:7=1+2+4。

2. 解决代码

package com.clzhang.game;

/**
 * 问题:
 * 昨天去面试人家出了这样一道题,觉得挺简单的,但就是编不出来,只好麻烦各位高手了。
 * 给定两个正整数m,n(m >= n),将m拆成n个数相加:m =a(1)+a(2)+...+a(n),使之满足:a(1)<a(2)<...<a(n);
 * 列出所有的拆法。
 * 例如:若m=7,n=3则只有一种拆法:7=1+2+4。
 * @version 1.0
 * @author acer
 */
import java.util.*;

public class SplitInt {

    // 返回所有拆法中各最大数集合中的最大数
    private int getMax(int m, int n, int lastNum) {
        int total = 0;
        for (int i = 1; i < n; i++) {
            total += i;
        }
        if ((m - total) >= lastNum)
            return lastNum - 1;
        else
            return m - total;
    }

    // 返回当前数是否可能组成一种拆法
    private boolean isValidNum(int m, int n, int num) {
        int total = 0;
        if (num < n)
            return false;

        for (int i = 0; i < n; i++) {
            total += num--;
        }
        return total >= m;
    }

    /*
     * 计算拆分结果,递归调用 
     * @param m - 被拆数 
     * @param n - 拆分个数 
     * @param lastNum - 上一次拆分数值
     */
    public LinkedList<String> calu(int m, int n, int lastNum) {
        LinkedList<String> result = new LinkedList<String>();
        if (n == 1) {
            result.add(String.valueOf(m));
            return result;
        }

        int num = getMax(m, n, lastNum);
        while (isValidNum(m, n, num)) {
            LinkedList<String> lkl = calu(m - num, n - 1, num);
            for (int i = 0; i < lkl.size(); i++) {
                result.add(String.valueOf(num) + "+" + lkl.get(i));
            }
            num--;
        }
        return result;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入m值:");
        int m = scanner.nextInt();
        System.out.println("请输入n值:");
        int n = scanner.nextInt();
        scanner.close();
        
        AbstractList<String> list = new SplitInt().calu(m, n, m);
        if (list.size() == 0)
            System.out.println("没有解!");
        else {
            for (int i = 0; i < list.size(); i++)
                System.out.println("第 " + (i + 1) + " 种拆法:" + list.get(i));
        }
    }
    
}

3. 输出

请输入m值:
10
请输入n值:
3
第 1 种拆法:7+2+1
第 2 种拆法:6+3+1
第 3 种拆法:5+4+1
第 4 种拆法:5+3+2 

posted @ 2013-01-23 20:02  那些年的事儿  阅读(681)  评论(0编辑  收藏  举报