原文:整数全排列
题目:
n种不同面值的硬币存放在数组A中,现在需要找零钱给用户,找零金额为m,求最少硬币数找零方式
输入、输出描述
输入:
A为不同面值硬币构成的非负整数数组,n=length(A),m为待找零钱的总金额数
输出:
最少硬币数找零方式,按面值金额从小到大排序,若无解:返回长度为1的数组,且素组的元素为-1
Example
输入:
A:1,3,5 n:3 m:19
输出:
1,3,5,5,5
解题思路:
使用递归算法。
设一组整数为digit = {d1, d2, d3, ...., dn},记该数组的全排列为A(digit),由于每一种排列的第一位数有n种情况,A(digit)就等于sum( A(digit-{di}) ),其中di属于{d1, d2, d3, ...., dn},digit-{di}表示digit数组去掉元素di之后的数组,依次类推下去。以digit={1,2,3}为例进行说明:
{1,2,3}的全排列可以分为3个子数组的全排列:
- 1+{2,3}的全排列:123 132
- 2+{1,3}的全排列:213 231
- 3+{1,2}的全排列:312 321
为了避免重复的排列结果,可以用HashSet保存每次排列的结果,最后将所有结果按照数值大小进行排序。
代码:
import java.util.*;
public class Main {
//交换数组里的两个元素
public void swap(int i,int j,int[] digit){
if(i!=j){
int temp;
temp = digit[i];
digit[i] = digit[j];
digit[j] = temp;
}
}
//将整数数组转换成数字
public int arrayToNum(int[] digit) {
int num = 0;
int xishu = 1;
for (int i = digit.length-1; i >=0; i--) {
num += digit[i]*xishu;
xishu *= 10;
}
return num;
}
//为了避免元素重复,将每次的排列结果插入一个HashSet里
Set<Integer> temp = new HashSet<>();
public void numArrange(int[] digit,int i){
if(i == (digit.length-1)){
temp.add(arrayToNum(digit));//将排列结果插入HashSet
}else{
int j;
for(j=i;j<digit.length;j++){
swap(i,j,digit);
numArrange(digit,i+1);
swap(i,j,digit);
}
}
}
public int[] solution(int[] digit,int n) {
numArrange(digit, 0);
int length = temp.size();
int[] result = new int[length];
int index = 0;
for (int i : temp) {
result[index++] = i;
}
Arrays.sort(result);//排序
return result;
}
}