整数全排列问题

原文:整数全排列

题目:

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;
      }
    }

点赞