leetcode演算法執行個體---組合和枚舉問題__演算法

來源:互聯網
上載者:User

給定一列數(未排序)和一列目標值, 找出唯一的一個組合和等於目標值的組合, 數組中的數不能重複使用.

演算法思路: 使用遞迴.

對數組排序, 從小到大;
令i = 起始下標(初始為0), 對於每一個數,
如果它等於目標值, 則在緩衝結果中加入此數並將緩衝結果加入輸出隊列, 隨後在緩衝結果中刪除此數;
如果它小於目標值, 則在緩衝結果中加入此數並遞迴調用此演算法, 目標值更新為差值, 起始下標為i;
如果它大於目標值, 演算法返回.
對於2.2的理解: 如果這個數小於目標值, 由於演算法是迴圈遞迴, 那麼起始的下標必定不能小於i(否則出現重複情況)
代碼如下:

import java.util.Arrays;import java.util.Collections;import java.util.LinkedHashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;/** * 將手續約作為一筆交易,如果拼湊不出來,則拆分剩餘明細中金額最大的那筆交易 * @author kenan.zhang * @date 2017-08-23 */public class Calc {    public static void recursion(List<Integer> sourceList,LinkedList<Integer> tmpList,List<LinkedList<Integer>> resultList,Integer targetValue,int startIndex){        for (int i = startIndex; i < sourceList.size(); i++) {            Integer currentValue = sourceList.get(i);            if(currentValue <= targetValue){                if(currentValue.equals(targetValue)){                    tmpList.add(currentValue);                    resultList.add(new LinkedList<Integer>(tmpList));                    tmpList.remove(currentValue);                    break;                }else if(currentValue < targetValue){                    tmpList.add(currentValue);                    recursion(sourceList, tmpList, resultList, targetValue-currentValue, i+1);                    tmpList.remove(currentValue);                    //只取第一個合格資料群組                    if(resultList.size() == 1){                        //從來源資料列表中去掉已經使用過的資料                        sourceList.removeAll(resultList.get(0));                        break;                    }                }            }else{                break;            }        }    }    public static Map<Integer,LinkedHashMap<Integer,List<Integer>>> getResult(List<Integer> sourceList,List<Integer> targetValues){        Collections.sort(sourceList);        Collections.sort(targetValues);        int startIndex = 0;        List<Integer> remainTargetValues = new LinkedList<Integer>();        Map<Integer,LinkedHashMap<Integer,List<Integer>>> resultMap = new LinkedHashMap<Integer,LinkedHashMap<Integer,List<Integer>>>();        for(int i=0;i<targetValues.size();i++){            Integer currentValue = targetValues.get(i);            List<LinkedList<Integer>> resultList = new LinkedList<LinkedList<Integer>>();            LinkedList<Integer> tmpList = new LinkedList<Integer>();            recursion(sourceList, tmpList, resultList,currentValue, startIndex);            if(resultList.size() == 0){                remainTargetValues.add(currentValue);                resultMap.put(currentValue, null);            }else{                LinkedHashMap<Integer,List<Integer>> res = new LinkedHashMap<Integer,List<Integer>>();                //為了區分該匯總交易是否通過某筆交易明細拆分拼湊而來:如果子map的key為Integer.MAX_VALUE,否則對應的是被拆分的交易明細                res.put(Integer.MAX_VALUE, resultList.get(0));                resultMap.put(currentValue, res);            }        }        //對最大的一筆交易進行拆分        int lastIndex = sourceList.size()-1;        Integer lastValue = sourceList.get(lastIndex);        for(int i=0;i<remainTargetValues.size();i++){            Integer targetValue = remainTargetValues.get(i);            List<Integer> myTmpList = new LinkedList<Integer>();            Integer gap = lastValue - sourceList.get(i);            if(gap >= 0){                myTmpList.add(sourceList.get(i));                myTmpList.add(targetValue-sourceList.get(i));                Collections.sort(myTmpList);                LinkedHashMap<Integer,List<Integer>> res = new LinkedHashMap<Integer,List<Integer>>();                //為了區分該匯總交易是否通過某筆交易明細拆分拼湊而來:如果子map的key為Integer.MAX_VALUE,否則對應的是被拆分的交易明細                res.put(lastValue, myTmpList);                resultMap.put(targetValue, res);                sourceList.set(lastIndex, gap);            }else{                System.out.println(sourceList);                for(int k=remainTargetValues.size()-1;k<sourceList.size();k++){                    myTmpList.add(sourceList.get(k));                }                myTmpList.add(lastValue);                LinkedHashMap<Integer,List<Integer>> res = new LinkedHashMap<Integer,List<Integer>>();                //為了區分該匯總交易是否通過某筆交易明細拆分拼湊而來:如果子map的key為Integer.MAX_VALUE,否則對應的是被拆分的交易明細                res.put(lastValue, myTmpList);                resultMap.put(targetValue, res);            }        }        return resultMap;    }    //重載    public static Map<Integer,LinkedHashMap<Integer,List<Integer>>> getResult(Integer[] source,Integer[] target){        List<Integer> sourceList = new LinkedList<Integer>();        sourceList.addAll(Arrays.asList(source));        LinkedList<Integer> targetValues = new LinkedList<Integer>(Arrays.asList(target));        return getResult(sourceList, targetValues);    }    public static void main(String[] args) {        Integer[] source = new Integer[]{69, 35, 29, 26, 18, 12, 46, 92, 96, 75, 58, 34, 110};        Integer[] target = new Integer[]{104,44,58,61,73,260,100};        Map<Integer,LinkedHashMap<Integer,List<Integer>>> resultMap = getResult(source, target);        System.out.println("結果resultMap是:"+resultMap);        List<Integer> sourceList = new LinkedList<Integer>();        sourceList.addAll(Arrays.asList(source));        LinkedList<Integer> targetValues = new LinkedList<Integer>(Arrays.asList(target));        Map<Integer,LinkedHashMap<Integer,List<Integer>>> resultMap2 = getResult(sourceList, targetValues);        System.out.println("結果resultMap2是:"+resultMap2);    }}

改進版:

import java.math.BigDecimal;import java.util.Collection;import java.util.Collections;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;/** * 將手續約作為一筆交易,如果拼湊不出來,則拆分剩餘明細中金額最大的那筆交易 * 該方案理論上可能存在需要拆分多筆交易的情況 * @author kenan.zhang * @date 2017-08-23 */public class Calculator2 {    public static void recursion(List<Map<String,Object>> detailList,LinkedList<Map<String,Object>> tmpList,LinkedList<Object> resultList,Map<String,Object> targetSummary,int startIndex){        for (int i = startIndex; i < detailList.size(); i++) {            Map<String,Object> currentDetail = detailList.get(i);            BigDecimal summaryMoney = (BigDecimal) targetSummary.get("summaryMoney");            BigDecimal detailMoney = (BigDecimal) currentDetail.get("detailMoney");            if(detailMoney.compareTo(summaryMoney) != 1){                if(detailMoney.compareTo(summaryMoney) == 0){                    tmpList.add(currentDetail);                    resultList.add(new LinkedList<Map<String,Object>>(tmpList));                    tmpList.remove(currentDetail);                    resultList.add(targetSummary);                    //從來源資料列表中去掉已經使用過的資料                    detailList.removeAll((Collection<?>) resultList.get(0));                    break;                }else if(detailMoney.compareTo(summaryMoney) == -1){                    tmpList.add(currentDetail);                    targetSummary.put("summaryMoney", summaryMoney.subtract(detailMoney));                    recursion(detailList, tmpList, resultList, targetSummary, i+1);                    //值還原                    targetSummary.put("summaryMoney", ((BigDecimal)(targetSummary.get("summaryMoney"))).add(detailMoney));                    tmpList.remove(currentDetail);                    //只取第一對合格資料,第一個元素代表詳細資料列表,第二個元素代表對應的摘要資料                    if(resultList.size() == 2){                        //從來源資料列表中去掉已經使用過的資料                        detailList.removeAll((Collection<?>) resultList.get(0));                        break;                    }                }            }else{                break;            }        }    }    public static LinkedList<Object> getResult(Map<String,List<Map<String,Object>>> sourceData){        List<Map<String,Object>> detailList = sourceData.get("detail");        List<Map<String,Object>> summaryList = sourceData.get("summary");        DetailValueComparator detailComparator = new DetailValueComparator();        SummaryValueComparator summaryComparator = new SummaryValueComparator();        Collections.sort(detailList,detailComparator);        Collections.sort(summaryList,summaryComparator);        int startIndex = 0;        List<Map<String,Object>> remainSummaryList = new LinkedList<Map<String,Object>>();        LinkedList<Object> returnList = new LinkedList<Object>();        for(int i=0;i<summaryList.size();i++){            Map<String,Object> currentSummary = summaryList.get(i);            LinkedList<Object> resultList = new LinkedList<Object>();            LinkedList<Map<String,Object>> tmpList = new LinkedList<Map<String,Object>>();            recursion(detailList, tmpList, resultList,currentSummary, startIndex);            if(resultList.size() == 0){                remainSummaryList.add(currentSummary);            }            returnList.addAll(resultList);        }        Collections.sort(detailList,detailComparator);        for(int i=0;i<remainSummaryList.size();i++){            //對最大的一筆交易進行拆分            int lastIndex = detailList.size()-1;            Map<String,Object> lastDetail = detailList.get(lastIndex);            Map<String,Object> targetSummary = remainSummaryList.get(i);            LinkedList<Map<String,Object>> myTmpList = new LinkedList<Map<String,Object>>();            BigDecimal lastDetailMoney = (BigDecimal) lastDetail.get("detailMoney");            BigDecimal summaryMoney = (BigDecimal) targetSummary.get("summaryMoney");            BigDecimal sum = new BigDecimal(0);            //待刪除列表            List<Map<String,Object>> listToRemove = new LinkedList<Map<String,Object>>();            for(int j=0;j<detailList.size();j++){                myTmpList.add(detailList.get(j));                Object t = detailList.get(j).get("detailMoney");                BigDecimal detailMoney = new BigDecimal(t.toString());                listToRemove.add(detailList.get(j));                sum = sum.add(detailMoney);                if(!less(sum, summaryMoney)){                    listToRemove.remove(detailList.get(j));                    myTmpList.remove(detailList.get(j));                    Map<String,Object> m = new HashMap<String,Object>();                    //gap代表拼湊的金額                    BigDecimal gap = summaryMoney.subtract(sum.subtract(detailMoney));                    m.put("detailMoney", gap);                    m.put("ifBorrow", "yes");                    //被拆交易的序號                    m.put("borrowSerial", lastDetail.get("serialNo"));                    myTmpList.add(m);                    returnList.add(myTmpList);                    returnList.add(targetSummary);                    //更新被拆分交易的金額                    lastDetail.put("detailMoney", lastDetailMoney.subtract(gap));                    detailList.removeAll(listToRemove);                    if(equal(sum, summaryMoney)){                        detailList.remove(lastDetail);                    }                    //重新排序,保證每次取到最大的交易明細進行拆分                    Collections.sort(detailList, detailComparator);                    break;                }            }        }        return returnList;    }    public static boolean greater(BigDecimal d1,BigDecimal d2){        return d1.compareTo(d2)==1;    }    public static boolean equal(BigDecimal d1,BigDecimal d2){        return d1.compareTo(d2)==0;    }    public static boolean less(BigDecimal d1,BigDecimal d2){        return d1.compareTo(d2)==-1;    }    public static void main(String[] args) {        Map<String,List<Map<String,Object>>> sourceData = new HashMap<String,List<Map<String,Object>>>();        List<Map<String,Object>> detailList = new LinkedList<Map<String,Object>>();        Map<String, Object> m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(69));        m1.put("serialNo", 69);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(35));        m1.put("serialNo", 35);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(29));        m1.put("serialNo", 29);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(26));        m1.put("serialNo", 26);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(18));        m1.put("serialNo", 18);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(12));        m1.put("serialNo", 12);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(46));        m1.put("serialNo", 46);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(92));        m1.put("serialNo", 92);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(96));        m1.put("serialNo", 96);        detailList.add(m1);        m1 = new HashMap<String, Object>();        m1.put("detailMoney", new BigDecimal(75));        m1.put("serialNo", 75);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.