【笔试题】一个无重复面值的找零算法的思路与实现【方案2】

来源:互联网 发布:时间序列数据回归 编辑:程序博客网 时间:2024/05/01 15:11

给出升序排列的N个数字,比如1, 2, 3, 7, 70
找出无法被这组数字组成的最小正整数。(这组数字中每个数字最多使用一次)
(1)简单描述你的算法和思路。
(2)用C/C++实现
(3)分析你的代码的时间复杂度和空间复杂度

解题思路:
这个问题类似于一个硬币找零问题的升级版。现存在一堆面值为V1, V2, V3, ...的硬币,每种面值的硬币只有一枚,现在需要为顾客找出总值为sum的零钱。问不能被找零的sum的最小值是多少?


方案2:

  • 算法概述

  1. 从最小的面值开始计算,依次加入后面的面值算出当前可以组合出的所有总额。如{1, 3, 5},首先1可以组成{1},加上3可以组成{1, 3, 4}...
  2. 每次遍历求出组合的可能总额后,可以预先进行一些判断,判断组合中小于等于最大的面值的总额种类是不是与最大面值相等,如果不相等说明已存在不可找零的总额。例如使用最小的两个面值1,3组成总额{1, 3, 4},小于等于最大面值3的总额只有两种,则说明1到3是不连续的自然数,因此已存在不能被找零的总额(遍历查找可知为2)。
  3. 在遍历完所有面值之后,查看形成的总额集合是不是连续的,如对{1, 2, 3, 7, ...}进行遍历,由于4不存在,所以不能组成的最小值便是4。
  • 实现
方案二用java进行了实现。(貌似不符合题意= =, anyway, 只是为了回忆下java)
import java.util.ArrayList;import java.util.Collections;public class ChangeAlgorithm {  public static void main(String args[]) {  Integer[] values = {1, 2,3,7, 20};//the face value of the moneyArrayList<Integer> sumList = new ArrayList<Integer>(); //the sum values//loops to calculate all possible sum valuesfor(int i=0;i<values.length;i++){//try to find all possible sum values with the first 'i' face valuesint size=sumList.size();for(int j=0;j<size;j++){Integer item=values[i]+sumList.get(j);if(sumList.indexOf(item)==-1){sumList.add(item);}   }if(sumList.indexOf(values[i])==-1){sumList.add(values[i]);}Collections.sort(sumList);//if the number of possible sum values are not equal to the face value if(!values[i].equals(sumList.indexOf(values[i])+1)){break;}}//find the impossible sum value for(int i=0;i<sumList.size();i++){if(sumList.get(i)!=i+1){System.out.println((i+1)+" is the minimum.");break;}}          }   }
  • 复杂度
todo