您的位置:首页 > 编程语言 > Java开发

java 实现排列组合Permutation and Combination和链式不相邻排列组合和环形不相邻排列

2017-10-01 22:03 1276 查看
常用的排列组合公式:
P (n,m)=n!/(n-m)!
C(n,m)=n!/(m!(n-m)!)
C(n,m)=C(n,n-m)
P(n,m)=P(m,m)*C(n,m)

import java.util.ArrayList;
import java.util.List;
public class PermutationCombination
{
public static void main(String[] args)
{
PermutationCombination perm = new PermutationCombination();
List<Character> data = new ArrayList<Character>();
data.add('a');
data.add('b');
data.add('c');
data.add('d');
List<List<Character>>result=new ArrayList<List<Character>>();
for(int i = 1; i <= data.size(); i++)
{
perm.permutation(data,new ArrayList<Character>(),i,result);
}
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result.get(i).size();j++)
{
System.out.print(result.get(i).get(j));
}
System.out.println();
}
System.out.println("################the split line of the permutation and combination ##########################");
PermutationCombination comb=new PermutationCombination();
List<Character>data2=new ArrayList<Character>();
data2.add('a');
data2.add('b');
data2.add('c');
data2.add('d');
List<List<Character>>result2=new ArrayList<List<Character>>();
for(int i=1;i<=data.size();i++)
{
comb.combination(data2, new ArrayList<Character>(), data2.size(), i, result2);
}
for(int i=0;i<result2.size();i++)
{
for(int j=0;j<result2.get(i).size();j++)
{
System.out.print(result2.get(i).get(j));
}
System.out.println();
}
}

/**
* the function is used to get permutation according to the formula P(n,m)=n!/(n-m)! note that(m<=n)
* @param data the source data
* @param workspace Customize a temporary space to store each qualified value
* @param k the number need permutation p(n,k)
*/
public <E> void permutation(List<E> data,List<E> workspace, int k,List<List<E>>result)
{
List<E> copyData;
List<E> copyTarget;
if(workspace.size() == k)
{
result.add(workspace); /*we need a return in order to deal with data after permutation*/
// for(E i : workspace) /*instead just print the result*/
// {
// System.out.print(i);
// }
// System.out.println();
}
for(int i=0; i<data.size(); i++)
{
copyData = new ArrayList<E>(data);
copyTarget = new ArrayList<E>(workspace);
copyTarget.add(copyData.get(i));
copyData.remove(i);
permutation(copyData, copyTarget,k,result);
}
}

/**
* according the formula C(n,m)=n!/(m!(n-m)!) and C(n,m)=C(n,n-m) note that (m<=n)
* 把数据的第一个元素添加到工作空间中,判断工作空间的大小,如果小于k,则需要继续递归,但此时,传入递归函数的
* 参数需要注意:假设当前插入的节点的下标是i,因为是顺序插入的,所以i之前的所有数据都应该舍去,只传入i之后的未使用过的数据。
* 因此在传参之前,应该对copyData作以处理
* (when the first element is added to the data in the working space, determine the size of the space,
* if less than k, you need to continue recursion, but this time, parameter recursive function to note:
* assuming the insertion of the subscript node is i, because it is the order of insertion,
* so all data before I should give up. Only after the incoming i unused data.
* Therefore, copyData should be handled before passing arguments)
* @param data the source data
* @param workSpace Customize a temporary space to store each qualified value
* @param k k in C(n,k)
*/
public <E> void combination(List<E> data, List<E> workSpace, int n, int k, List<List<E>>result)
{
List<E> copyData;
List<E> copyWorkSpace;
if(workSpace.size() == k)
{
result.add(workSpace); /*we need a return in order to deal with data after combination*/
// for(Object c : workSpace) /*instead just print the result*/
// {
// System.out.print(c);
// }
// System.out.println();
}
for(int i = 0; i < data.size(); i++)
{
copyData = new ArrayList<E>(data);
copyWorkSpace = new ArrayList<E>(workSpace);
copyWorkSpace.add(copyData.get(i));
for(int j = i; j >= 0; j--)
{
copyData.remove(j);
}
combination(copyData, copyWorkSpace, n, k,result);
}
}
}
链式不相邻组合:是指从A={1,2,3,…,n}中选取m个不相邻的组合个数

例如,n=4,m=2,有组合{1,3},{2,4},{1,4}
定理:从A={1,2,3,…,n}中取m个不相邻组合,其组合数为C(n−m+1,m)

链式不相邻排列:P(m,m)*C(n-m+1,m)

环形不相邻排列:A={1,2,3,…,n}围成一圈,选取m个不相邻的组合个数

例如,n=4,m=2,有组合{2,4}{1,3}{4,1}{3,1}

假设n=6,m=3, A={1,2,3,4,5,6},第一次选择,有6个位置,可以分为两种情况:

第一种 剩下的数中不同时包含两个端点,假设选择2,则1,3不能选,只剩下{4,5,6}, 这个一个大小为3的链式不相邻问题。

第二种 剩下的数中同时包含两个端点,假设选择3,则剩下{1,5,6},其中1和5可以相邻,1和6不可相邻。所以可以等价于{5,6,1}的链式不相邻的问题。
对于n个元素,先随便选择一个,有n中可能,则剩下的问题是 从(n-3)个元素中选择(m-1)个不相邻的组合问题,即A(n-m-1, m-1)

package com.copycat.acmcoder;
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
scanner.close();
if(m>(n/2))
{
System.out.println(0);
}
else
{
long sum=n;
for(int j=m+1;j<=2*m-1;j++)
{
sum=sum*(n-j);
}
System.out.println(sum);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: