全排列算法

在这里插入图片描述
图片来自:https://www.cnblogs.com/sunriseblogs/p/9873013.html
排列代码


import java.math.BigInteger;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;



public class Main61 {
	public static int []a;
	public static int len;
	public static int count=0;
	public static void fun(int n) {
		if (n==len) {
			System.out.println(Arrays.toString(a));
		}else {
			for (int i = n; i <len; i++) {
				swap(i,n);
				fun(n+1);
				swap(n, i);
			}
		}
	}
	//交换下标x与y的值
	public static void swap(int x,int y) {
		int t=a[x];
		a[x]=a[y];
		a[y]=t;
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();//输入数组长度
		len=n;
		a=new int[n];
		for (int i = 0; i <n; i++) {
			a[i]=sc.nextInt();
		}
		fun(0);
	}
	
}

例题如下

A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
下图就是一种排法(如有对齐问题,参看p1.png)。

   A
  9 6
 4   8
3 7 5 2

这样的排法可能会有很多。

如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?

请你计算并提交该数字。

注意:需要提交的是一个整数,不要提交任何多余内容。

思路:把三角形的边当做一个长度为九的数组,全排列判断

a[0]+a[1]+a[2]+a[3];
a[3]+a[4]+a[5]+a[6];
a[6]+a[7]+a[8]+a[0];
是否相等
需要注意,每一种三边相等的组合都会有三种旋转的角度存在和三种旋转角度的镜像存在,所以六种中只取一种。结果除以6


import java.util.Arrays;
import java.util.Scanner;



public class Main61 {
	public static int []a={1,2,3,4,5,6,7,8,9};
	public static int count=0;
	public static void fun(int n) {
		if (n==9) {
			//System.out.println(Arrays.toString(a));
			int s1=a[0]+a[1]+a[2]+a[3];
			int s2=a[3]+a[4]+a[5]+a[6];
			int s3=a[6]+a[7]+a[8]+a[0];
			if (s1==s2&&s2==s3) {
				count++;
			}
		}else {
			for (int i = n; i <9; i++) {
				swap(i,n);
				fun(n+1);
				swap(n, i);
			}
		}
	}
	//交换下标x与y的值
	public static void swap(int x,int y) {
		int t=a[x];
		a[x]=a[y];
		a[y]=t;
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		fun(0);
		System.out.println(count/6);
	}
	
}


2020年3月12日11:16:47 以下为后期补充
用stack实现全排列,代码更为简洁,statck把两个数的交换swap(a,b)换成了添加一个数据,和删除这个数据,逻辑上还是相同的。

全排列一般有三种:
 1.  全部排列 可以重复使用数字
 2.  全部排列 不可以重复使用数字
 3.  部分排列 选取m个数字有多少种排列

import java.util.Stack;

public class Main03 {
	//递归 回溯 Stack实现全排列(可以重复使用数字)
	public static  Stack<Integer> stack=new Stack<Integer>();
	/**
	 * @param shu   待选择的数组
     * @param targ  要选择多少个次
     * @param cur   当前选择的是第几次
	 */
	public static void main(String[] args) {
		int shu[]={1,2,3};
		f(shu,3,0);;
	}
	public static void f(int shu[],int targ,int cur) {
		if (cur==targ) {
			System.out.println(stack);
			return ;
		}
		for (int i = 0; i < shu.length; i++) {
				stack.push(shu[i]);//添加数据
				f(shu, targ, cur+1);
				stack.pop();//删除后进数据
		}
	}

}

import java.util.Stack;

public class Main03 {
	//递归 回溯 实现全排列(不可以重复使用数字)
	public static  Stack<Integer> stack=new Stack<Integer>();
	/**
	 * @param shu   待选择的数组
     * @param targ  要选择多少个次
     * @param cur   当前选择的是第几次
	 */
	public static void main(String[] args) {
		int shu[]={1,2,3};
		f(shu,3,0);;
	}
	public static void f(int shu[],int targ,int cur) {
		if (cur==targ) {
			System.out.println(stack);
			return ;
		}
		for (int i = 0; i < shu.length; i++) {
			if (!stack.contains(shu[i])) {
				stack.push(shu[i]);//添加数据
				f(shu, targ, cur+1);
				stack.pop();//删除后进数据
			}
		}
	}

}

import java.util.Stack;

public class Main03 {
	//递归 回溯 实现全排列(选择targ个元素的排列方式)
	public static  Stack<Integer> stack=new Stack<Integer>();
	/**
	 * @param shu   待选择的数组
     * @param targ  要选多少个元素
     * @param has   当前有多少个元素
     * @param cur   当前选到的下标
	 */
	public static void main(String[] args) {
		int shu[]={1,2,3,4};
		f(shu,3,0,0);;
	}
	public static void f(int shu[],int targ,int has,int cur) {
		if (has==targ) {
			System.out.println(stack);
			return ;
		}
		for (int i = cur; i < shu.length; i++) {
			if (!stack.contains(shu[i])) {
				stack.push(shu[i]);//添加数据
				f(shu, targ,has+1,i);
				stack.pop();//删除后进数据
			}
		}
	}

}

原文地址


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值