突发奇想想用C解决高中排列组合问题

题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

很简单的一道高中题目,用程序来也是很好实现的。话不多说,直接上代码。

#include<stdio.h>
 
int main()
{
    int i,j,k;
    printf("n");
    for(i=1;i<5;i++) { // 以下为三重循环
        for(j=1;j<5;j++) {
            for (k=1;k<5;k++) { // 确保i、j、k三位互不相同
                if (i!=k&&i!=j&&j!=k) { 
                    printf("%d,%d,%dn",i,j,k);
                }
            }
        }
    }
}

因为是三位数,而且四个数字还是连着的,所以只需要来一个三重循环,再把有相同数字的去掉就行。

那如果是一个六位数,十位数,显然循环套循环就不太方便了。

而且,如果数字是2、4、6、8,它甚至都不能用上述循环。

这就是我下面要解决的问题。既然基本思路就是循环套循环,那么能不能整一个n重循环呢?答案是肯定的,大家可以看看我的上一篇文章找零问题的一种遍历算法——“时钟模型”找零问题的一种遍历算法——“时钟模型”。里面提到了一种遍历算法,类似于时钟,它可用于连续数字的n重循环。当然大家就会问,万一不是连续数字呢?这其实很好解决,只需要一点映射的概念,比如有一个数组{2, 4, 6, 8},虽说它的元素不是连续的。但是它的下标永远是连续的呀。

有了上面的分析,我们就可以开始敲代码了。

首先得知道“时钟模型”

while(1){
        b[n-1]--;
        for(j=n-1;j>=1;j--){
            if(b[j]==-1){
                b[j-1]--;
                b[j]=m[j];//m[n-1]是存储b[n-1]初值的数组,此处未写出
            }
        }
        if(b[0]==-1) break;
	}

 其次就是如何将下标和数组元素对应,并输出。很简单,将一个元素都是顺序排列的数组代入上述代码,这就是普通的带有顺序的排列组合。再将带有目标数字的一个数组,以这样array1[array2[i]]的形式输出即可。附带代码便于理解。

void fun1()
{
    int array1[4] = {2, 4, 6, 8};
    fun2(array1);
}

void fun2(int array1[], n, m)
{   
    int array2[m],mm[m];
    for(int i=0;i<m;i++) array2[i] = mm[i] = n-1;
    while(1){
        for(int i=0;i<n;i++){
            printf("%d",array1[array2[i]]);
        }
        printf("n");
        array2[n-1]--;
        for(j=n-1;j>=1;j--){
            if(array2[j]==-1){
                array2[j-1]--;
                array2[j]=mm[j];
            }
        }
        if(array2[0]==-1) break;
    }
}

写到这,差不多基本原理都写完了。 其作为一道经典的高中题目,有时会有许多限制,比如组成的数字要从大到小,或者从小到大,二话不说直接上代码。

#include<stdio.h>

void onput1(int b[], int n, int ptr[], int m, int key);
void onput2(int b[], int n, int ptr[], int m, int key);
int dif(int array[], int n);//判断数组是否有重复元素
int mima(int array[], int n);//判断元素是否大于0 
void input();

int dif(int array[], int n)
{
	int ii,jj,md=0;
	for(ii=0;ii<n-1;ii++){
		for(jj=ii+1;jj<n;jj++){
			if(array[ii]==array[jj]) md=1;
		}
		if(md==1) break;
	}
	
	return !md;
}

int mima(int array[], int n)
{
	int md=1;
	for(int ii=0;ii<n;ii++){
		if(array[ii]>9 || array<0) md=0;
	}
	
	return md;
}

void onput1(int b[], int n, int ptr[], int m, int key)
{
	int mm[n],nn[n],sum=0;
	for(int k=0;k<n;k++){
		mm[k]=b[k];
	}
	while(1){
		for(int i=0;i<n;i++){
			nn[i]=ptr[b[i]];
		}
		if((key==0 ? dif(nn, n)) : 1 && ptr[b[0]]!=0){
			for(int i=0;i<n;i++){
	        	printf("%d",ptr[b[i]]);
			}
			printf("n");
			sum++;
		}
        b[n-1]--;
        for(int j=n;j>=1;j--){
            if(b[j]==-1){
                b[j-1]--;
                b[j]=mm[j];
            }
        }
        if(b[0]==-1) break;
	}
	printf("总共有%d种情况:",sum);
}

void onput2(int b[], int n, int ptr[], int m, int key)
{
	int mm[n],sum=0,result,l;
	for(int k=0;k<n;k++){
		mm[k]=b[k];
	}
	while(1){
		if(key==1){
			for(l=0;l<n-1;l++){
				if(ptr[b[l]]>=ptr[b[l+1]]) break;
			}
			if(l==n-1 && ptr[b[0]]!=0){
				for(int i=0;i<n;i++){
		        	printf("%d",ptr[b[i]]);
				}
				sum++;
				printf("n");
			}
		}else if(key==2){
			for(l=0;l<n-1;l++){
				if(ptr[b[l]]<=ptr[b[l+1]]) break;
			}
			if(l==n-1 && ptr[b[0]]!=0){
				for(int i=0;i<n;i++){
		        	printf("%d",ptr[b[i]]);
				}
				sum++;
				printf("n");
			}
		}
        b[n-1]--;
        for(int j=n;j>=1;j--){
            if(b[j]==-1){
                b[j-1]--;
                b[j]=mm[j];
            }
        }
        if(b[0]==-1) break;
	}
	printf("总共有%d种情况:",sum);
}

void input()
{
	int n,m,*ptr,key=0;
	printf("请输入需要数字的个数:");
	scanf("%d",&n);
	int array[n];
	printf("分别是:");
	for(int i=0;i<n;i++){
		scanf("%d",&array[i]);
	}
	printf("要组成几位数:");
	scanf("%d",&m);
	int b[m]; 
	ptr=array;
	for(int i=0;i<m;i++){
		b[i]=n-1;
	}
	if(dif(array, n) && mima(array, n)){
		printf("从小到大排列输入1n从大到小输入2n无重复数字输入0n需要重复数字输入3n-->");
		scanf("%d",&key);
		if(key==1){
			onput2(b, m, ptr, n, key);
		}else if(key==2){
			onput2(b, m, ptr, n, key);
		}else{
			onput1(b, m, ptr, n, key);
		}
	}else{
		printf("[ERROR]数据输入错误,请重新输入n");
		input(); 
	} 
}

main()
{
	input();
}

还有我运行的结果

  

 

 好了,我的分享到此结束了。如果你感兴趣的话,不如自己动手继续修饰这段代码,让它能够解决更多的关于高中排列组合的问题。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码

)">
< <上一篇

)">
下一篇>>