整數的分解方法

騰訊 2017春招真題java

題目

以下示例:
1:共0種分解方法;
2:共0種分解方法;
3:3=2+1 共1種分解方法;
4:4=3+1=2+1+1 共2種分解方法;
5:5=4+1=3+2=3+1+1=2+2+1=2+1+1+1 共5種分解方法
6:6=5+1=4+2=4+1+1=3+2+1=3+1+1+1=2+2+1+1=2+1+1+1+1 共7種分解方法
以此類推,求一任意整數num有幾種分解方法?
輸入一個數字(1到90),輸出該整數的分解方法個數
如:
輸入:2——輸出:0
輸入:3——輸出:1
輸入:5——輸出:5數組

分析

爲保證輸出的惟一性,保持降序排列
列表分析3~7的分解狀況:code

當前數 分解狀況以1結尾 分解狀況以2結尾 分解狀況以3結尾 分解狀況總數
3 ① 2+1 --- --- 1
4 ① 3+1
② 2+1+1
(②是將3進一步分解)
---
(2+2不算,分解出來的數不能都相等)
--- 2
5 ① 4+1
② 2+2+1
③ 3+1+1
④ 2+1+1+1
(②--④是將4進一步分解,此時4=2+2也算)
① 3+2 --- 5
6 ① 5+1
② 4+1+1
③ 2+2+1+1
④ 3+1+1+1
⑤ 2+1+1+1+1
⑥ 3+2+1
(②--⑥是將5進一步分解)
① 4+2 ---
(3+3不算)
7
7 ① 6+1
② 3+3+1
③ 5+1+1
④ 4+1+1+1
⑤ 2+2+1+1+1
⑥ 3+1+1+1+1
⑦ 2+1+1+1+1+1
⑧ 3+2+1+1
⑨ 4+2+1
(②--⑨是將5進一步分解)
① 5+2
② 3+2+2
(②是將5進一步分解,且只取5的分解狀況中結尾數>=2的,才能保證降序排列)
① 4+3 12

總結分解方法:table

  • 對於數num,按照分解狀況的結尾數字考慮:以1結尾,以2結尾,...,以Math.floor((num - 1) / 2)結尾,每種結尾都先進行一次分解(以7爲例,以1結尾時分解成6+1,以2結尾分解成5+2,以3結尾分解成4+3)
  • 對於第一次分解出的兩個數(num1,num2),進一步分解num1,且只在num1 > 2*num2 時分解num1(不然沒法保證降序,例:5=3+2,3繼續分解出2+1,則5=2+1+2不是降序)
  • 若num1是偶數,計算分解狀況時+1(例:5=4+1,進一步分解4時,要考慮4=2+2)
  • 保證num1進一步分解的結尾的數>=num2(例:7=5+2,進一步分解5時,只能將5分解成3+2,若分解成任意以1結尾的狀況,如4+1,則7=4+1+2不是降序)


    所以,咱們運用動態規劃的方法,從3開始往大數分析,構造二維數組,橫座標表示當前分析的數,縱座標表示當前分解狀況結尾的數

解答

解法1:(我)

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()){
            int num = sc.nextInt();
            int result = 0;

            int[][] arr = new int[num+1][];
            for(int i = 3; i <= num; i++){
                int columnNum = (int)Math.floor((i-1)/2d);
                arr[i] = new int[columnNum];
                for(int j = 0; j < columnNum; j++){
                    arr[i][j] = 1;
                    int num2 = j + 1;
                    int num1 = i - num2;
                    if(num1 > 2 * num2){//只有這種狀況才分解
                        if(num1 % 2 == 0){//num1是偶數,計算分解狀況時+1
                            arr[i][j]++;
                        }
                        //計算數1的分解狀況
                        for (int k = j; k < arr[num1].length; k++){
                            arr[i][j] += arr[num1][k];
                        }

                    }
                }

            }
//            輸出整個二維數組的狀況
//            for(int i = 3; i <= num; i++){
//                for(int j = 0; j < arr[i].length;j++){
//                    System.out.println("arr["+i+"]["+j+"] is: "+arr[i][j]);
//                }
//            }
            if(num == 1 || num == 2) result = 0;
            else{
                for(int i = 0; i < arr[num].length;i++){
                    result += arr[num][i];
                }
            }
            System.out.println(result);
        }
    }
}
相關文章
相關標籤/搜索