第一讲,整数划分 JAVA 代码(分治实现之一)

来源:互联网 发布:淘宝店铺怎么设置包邮 编辑:程序博客网 时间:2024/06/10 03:21

整数划分问题相信很多人都做过,题意是这样的:

将正整数n表示成一系列正整数之和,

n=n1+n2+,,,,,+nk(其中n1>=n2>=......>=nk>=1,k>1)

例如:正整数6有如下11种不同的划分,

6=1+1+1+1+1+1
6=1+1+1+1+2
6=1+1+1+3
6=1+1+2+2
6=1+1+4
6=1+2+3
6=1+5
6=2+2+2
6=2+4
6=3+3
6=6


这道题网上搜一大把解题方法,什么回溯法,动态规划等等都可以解出来,昨晚突然想到一个新的解题思路(可能网上已经有人发表过了,不过确实是自己突然发现的,如有雷同,纯属巧合O(∩_∩)O~):

这道题的麻烦之处在于解题过程很容易产生重复的情况,不过只要按照下面的做法就不会出现重复的现象,

当对正整数N划分,有如下划分情况:

N=1+1+........+1

N=1+1+......+2

......

N=1+(N-1)

N=N

接下来如果对N+1(这里用M代替N+1)进行划分时,则在N划分的所有情况前面都加1即

 


M=1+1+1+........+1

M=1+1+1+......+2

.......

M=1+N

 


加完之后对每一个新的表达式做如下操作:

步骤1.当表达式的个数小于等于2个时(如:3=1+2表达式的个数为2个),该表达式不作处理,判断下一个表达式,否则执行步骤2

步骤2.当表达式的个数大于2个时,对表达式的前两个数字求和(如:5=1+2+3,则前两个数即为1和2,),如果和小于等于第三个数字时,则构造新的表达式,即将当前表达式的前两个数字合并,其他的保持一致:

如原来的表达式为:M=x1+x2+x3+....xn

则新的表达式为:M=(x1+x2) + x2+x3...+n

如果和大于第三个数字,如:7=2+2+3,前两个数字的和为4,大于第三个数字。则不作处理,跳到步骤1,判断下一个表达式

 


当全部的表达式(只包括前一个数字的表达式前面加1的那些表达式,不包括这个过程生成的新表达式)都执行完以上步骤之后,最终结果就只差一个了,即本身等于本身的情况,再加上该种情况即可

 


说的很不清楚,来点实际的吧:

如5的划分情况为:

5=1+1+1+1+1
5=1+1+1+2
5=1+1+3
5=1+2+2
5=1+4
5=2+3
5=5


现在求6的划分,则首先第一步,在5的每个表达式的前面都加1,则得到:

6=1+1+1+1+1+1
6=1+1+1+1+2
6=1+1+1+3
6=1+1+2+2
6=1+1+4
6=1+2+3
6=1+5


接着第二步,按顺序对每个表达式执行之前说的步骤1和步骤2。

1.对于表达式:6=1+1+1+1+1+1,满足步骤1,执行步骤2,因为前两个数相加1+1=2大于第三个数1,所以不作处理,继续判断表达式2

2.对于表达式:  6=1+1+1+1+2,6=1+1+1+3 同样不作处理,继续下一个表达式

3.对于表达式:  6=1+1+2+2,前两个求和:1+1=2等于第三个数,所以满足条件,生成新的有效表达式:6=2+2+2,继续下一个表达式

4.对于表达式:  6=1+1+4 , 6=1+2+3,同理,可以生成新的表达式:6=2+4,6=3+3

5.对于表达式:  6=1+5 不满足步骤1中的条件

6.全部表达式遍历完毕,结束,加上自身等于自身的情况,即:6=6

最终的结果就为:

6=1+1+1+1+1+1
6=1+1+1+1+2
6=1+1+1+3
6=1+1+2+2
6=1+1+4
6=1+2+3
6=1+5
6=2+2+2
6=2+4
6=3+3
6=6


终于写完了,其实思路很简单,但是要说清楚可真麻烦,根据这种思路,代码就可以写了,不过代码也不是很好写的,我这里用了最简单明了的代码完成以上功能,代码写的很不上档次,空间复杂度太高,有时间再优化,欢迎大牛拍砖!


[java]
import java.util.ArrayList; 
import java.util.List; 
 
public class IntegerSplit { 
    private List<int[]> result = new ArrayList<int[]>(); 
    public void split(int m) { 
        //初始化  
 
        result.add(new int[]{1,1}); 
        result.add(new int[]{2}); 
        if (m == 1) { 
            System.out.println("1=1"); 
            System.out.println("一共有:1种"); 
            return ; 
        } else { 
            for (int i = 3; i <= m; i++) { 
                int size=result.size(); 
                for(int j=0;j<size;j++){ 
                    int[] ca=result.get(j); 
                    int[] newca=new int[ca.length+1];            
                    newca[0]=1; 
                    System.arraycopy(ca, 0, newca, 1, ca.length); 
                    ca=null; 
                    ca=newca; 
                    result.set(j, ca); 
                    int[] cs=merger(ca); 
                    if(cs!=null){ 
                        result.add(cs.clone()); 
                    } 
                } 
                result.add(new int[]{i}); 
                 
            } 
        } 
        //打印结果  
        for(int[] ca:result){ 
            System.out.print(m+"="); 
            for(int p=0;p<ca.length-1;p++){ 
                System.out.print(ca[p]+"+"); 
            } 
            System.out.print(ca[ca.length-1]); 
            System.out.println(); 
        } 
        System.out.println("一共有:"+result.size()+"种"); 
         
    } 
    //合并  
    public int[] merger(int[] ca) { 
        if (ca.length <= 2) 
            return null; 
        if (ca[0] + ca[1] <= ca[2]) { 
            int[] rca = new int[ca.length - 1]; 
            rca[0] = ca[0] + ca[1] ; 
            System.arraycopy(ca, 2, rca, 1, ca.length - 2); 
            return rca; 
        } 
        return null; 
    } 
    public static void main(String[] args) { 
        new IntegerSplit().split(10); 
    } 

import java.util.ArrayList;
import java.util.List;

public class IntegerSplit {
 private List<int[]> result = new ArrayList<int[]>();
 public void split(int m) {
  //初始化

  result.add(new int[]{1,1});
  result.add(new int[]{2});
  if (m == 1) {
   System.out.println("1=1");
   System.out.println("一共有:1种");
   return ;
  } else {
   for (int i = 3; i <= m; i++) {
    int size=result.size();
    for(int j=0;j<size;j++){
     int[] ca=result.get(j);
     int[] newca=new int[ca.length+1];   
     newca[0]=1;
     System.arraycopy(ca, 0, newca, 1, ca.length);
     ca=null;
     ca=newca;
     result.set(j, ca);
     int[] cs=merger(ca);
     if(cs!=null){
      result.add(cs.clone());
     }
    }
    result.add(new int[]{i});
    
   }
  }
  //打印结果
  for(int[] ca:result){
   System.out.print(m+"=");
   for(int p=0;p<ca.length-1;p++){
    System.out.print(ca[p]+"+");
   }
   System.out.print(ca[ca.length-1]);
   System.out.println();
  }
  System.out.println("一共有:"+result.size()+"种");
  
 }
 //合并
 public int[] merger(int[] ca) {
  if (ca.length <= 2)
   return null;
  if (ca[0] + ca[1] <= ca[2]) {
   int[] rca = new int[ca.length - 1];
   rca[0] = ca[0] + ca[1] ;
   System.arraycopy(ca, 2, rca, 1, ca.length - 2);
   return rca;
  }
  return null;
 }
 public static void main(String[] args) {
  new IntegerSplit().split(10);
 }
}
输出:


[java]
10=1+1+1+1+1+1+1+1+1+1 
10=1+1+1+1+1+1+1+1+2 
10=1+1+1+1+1+1+1+3 
10=1+1+1+1+1+1+2+2 
10=1+1+1+1+1+1+4 
10=1+1+1+1+1+2+3 
10=1+1+1+1+1+5 
10=1+1+1+1+2+2+2 
10=1+1+1+1+2+4 
10=1+1+1+1+3+3 
10=1+1+1+1+6 
10=1+1+1+2+2+3 
10=1+1+1+2+5 
10=1+1+1+3+4 
10=1+1+1+7 
10=1+1+2+2+2+2 
10=1+1+2+2+4 
10=1+1+2+3+3 
10=1+1+2+6 
10=1+1+3+5 
10=1+1+4+4 
10=1+1+8 
10=1+2+2+2+3 
10=1+2+2+5 
10=1+2+3+4 
10=1+2+7 
10=1+3+3+3 
10=1+3+6 
10=1+4+5 
10=1+9 
10=2+2+2+2+2 
10=2+2+2+4 
10=2+2+3+3 
10=2+2+6 
10=2+3+5 
10=2+4+4 
10=2+8 
10=3+3+4 
10=3+7 
10=4+6 
10=5+5 
10=10 
一共有:42种 

10=1+1+1+1+1+1+1+1+1+1
10=1+1+1+1+1+1+1+1+2
10=1+1+1+1+1+1+1+3
10=1+1+1+1+1+1+2+2
10=1+1+1+1+1+1+4
10=1+1+1+1+1+2+3
10=1+1+1+1+1+5
10=1+1+1+1+2+2+2
10=1+1+1+1+2+4
10=1+1+1+1+3+3
10=1+1+1+1+6
10=1+1+1+2+2+3
10=1+1+1+2+5
10=1+1+1+3+4
10=1+1+1+7
10=1+1+2+2+2+2
10=1+1+2+2+4
10=1+1+2+3+3
10=1+1+2+6
10=1+1+3+5
10=1+1+4+4
10=1+1+8
10=1+2+2+2+3
10=1+2+2+5
10=1+2+3+4
10=1+2+7
10=1+3+3+3
10=1+3+6
10=1+4+5
10=1+9
10=2+2+2+2+2
10=2+2+2+4
10=2+2+3+3
10=2+2+6
10=2+3+5
10=2+4+4
10=2+8
10=3+3+4
10=3+7
10=4+6
10=5+5
10=10
一共有:42种

另外加多一段只求划分总数,不求过程的代码:


[java]
public class ZSHF { 
    public static int q(int n,int m){ 
        if(n<1||m<1)return 0; 
        if(n==1||m==1)return 1; 
        if(n<m)return q(n,n); 
        if(n==m)return q(n,m-1)+1; 
        return q(n,m-1)+q(n-m,m); 
    } 
    public static void main(String[] args) { 
        int number=10; 
        int result=q(number,number); 
        System.out.println("对整数"+number+"的划分一共有:"+result+"种"); 
     
    } 

public class ZSHF {
 public static int q(int n,int m){
  if(n<1||m<1)return 0;
  if(n==1||m==1)return 1;
  if(n<m)return q(n,n);
  if(n==m)return q(n,m-1)+1;
  return q(n,m-1)+q(n-m,m);
 }
 public static void main(String[] args) {
  int number=10;
  int result=q(number,number);
  System.out.println("对整数"+number+"的划分一共有:"+result+"种");
 
 }
}
输出结果:


[java]
对整数10的划分一共有:42种 

 

0 0