這是一個面試筆試題,要求在1個鐘以內完成,雖然我花了三天想辦法解決了,可是我仍是不可以在1個鐘以內回想起來寫出個人算法,由於算法很複雜,我不由以爲出這題的公司是否是想招天才。java
水果信息: 面試
李子,重量:4,價格:4500
蘋果,重量:5,價格:4700算法
橘子,重量:2,價格:2250
草莓,重量:1,價格:1100
甜瓜,重量:6,價格:4940數組
菠蘿,重量:2,價格:3900ui
西瓜,重量:6,價格:5800this
桃子,重量:3,價格:3700code
香蕉,重量:2,價格:3750
梨子,重量:3,價格:3600rem
個人解決辦法是用回溯法。回溯法有什麼用?以前我以爲除了能用來解決八皇后問題就沒什麼用處了。後來在我解決這個面試題的時候,我發現回溯法能夠解決排列組合中的組合問題,而這道面試題中要求水果不能重複,正好是一個組合問題。和通常組合不同的是,通常的組合的每一個組合元素個數是固定的,而這道面試題只要重量不超過規定的重量就算是一個組合。get
代碼:it
package test; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * 揹包最大承重爲20,算出裝滿水果後價格最高的組合,水果不能重複 */ public class Fruit { private static int maxWeight = 20; private String name; private int price; private int weight; public Fruit(String name, int weight, int price) { this.name = name; this.weight = weight; this.price = price; } public String getName() { return name; } public int getPrice() { return price; } public int getWeight() { return weight; } public static void printMaxPriceFruits(List<Fruit> fruitList) { System.out.println("最優解爲:"); List<List<Fruit>> maxPriceBagLists = best(fruitList); for (List<Fruit> bagList : maxPriceBagLists) { for (Fruit fruit : bagList) { System.out.print(fruit.getName() + " "); } int totalWeight = 0; int totalPrice = 0; for (Fruit fruit : bagList) { totalWeight += fruit.getWeight(); totalPrice += fruit.getPrice(); } System.out.print("weight:" + totalWeight + " " + "price:" + totalPrice); System.out.println(); } } /** * 用回溯法求出價格最高的組合 * * @param fruitList * 全部水果的集合 * @return 返回價格最高的組合 */ public static List<List<Fruit>> best(List<Fruit> fruitList) { // 初始化剩餘可裝重量 int remainWeight = maxWeight; // 用於回溯法的數組 int[] fruitArr = new int[fruitList.size()]; // 初始化水果選擇的起點 for (int i = 0; i < fruitArr.length; i++) { fruitArr[i] = -1; } // 存放水果組合的揹包集合 List<Fruit> bagList = new ArrayList<Fruit>(); // List<List<Fruit>> bagLists = new ArrayList<List<Fruit>>(); // 從第一種水果開始選擇 int k = 0; /* * 當有增長動做,此變量等於false(解鎖),當肯定組合則爲true(加鎖,肯定組合後會刪除最後一個元素繼續判斷, * 有可能刪除後的組合符合條件,可是這個組合不是最優解,由於這個組合以前能夠添加水果) */ boolean lock = false; while (true) { fruitArr[k] += 1; // 全部水果都試過都不能繼續添加進揹包,則肯定一個組合 if (fruitArr[k] >= fruitList.size()) { if (k > 0) { if (!lock) { List<Fruit> copyBagList = new ArrayList<Fruit>(); copyBagList.addAll(bagList); bagLists.add(copyBagList); // 打印組合 // for (Fruit fruit : bagList) { // System.out.print(fruit.getName() + " "); // } // int totalWeight = 0; // int totalPrice = 0; // for (Fruit fruit : bagList) { // totalWeight += fruit.getWeight(); // totalPrice += fruit.getPrice(); // } // System.out.print("weight:" + totalWeight + " " // + "price:" + totalPrice); // System.out.println(); // /////////////////////////////// lock = true; } remainWeight += bagList.get(bagList.size() - 1).getWeight();// 可承重增長 bagList.remove(bagList.size() - 1);// 揹包集合去掉最後一個水果 fruitArr[k] = -1;// 迴歸起點(這裏是回溯法的步驟,這個算法可省去這個步驟) k--;// 目標更新爲上一個水果,繼續搜索可能性 } else {// 若是回溯到揹包第一個水果,且任何水果都嘗試過了,則已經遍歷全部可能的組合,跳出循環 break; } } // 若是該水果能放入揹包 else if (fruitList.get(fruitArr[k]).getWeight() <= remainWeight) { bagList.add(fruitList.get(fruitArr[k]));// 添加進揹包集合 remainWeight -= fruitList.get(fruitArr[k]).getWeight();// 剩餘承重 lock = false; // 目標更新爲揹包的下一種水果 k++; // 若是全部水果都能裝入,則k++會溢出,說明揹包容量大於等於全部水果重量的合直接返回 if (k >= fruitArr.length) { bagLists.add(bagList); return bagLists; } // 設定下一個水果選擇的起點 fruitArr[k] = fruitArr[k - 1]; } } return maxPriceBagLists(bagLists); } /** * 計算最優解組合的集合 * * @param bagLists * 全部可能的組合 * @return 返回價格最高的組合 */ public static List<List<Fruit>> maxPriceBagLists(List<List<Fruit>> bagLists) { List<List<Fruit>> maxPriceBagLists = new ArrayList<List<Fruit>>(); int maxPrice = 0; for (List<Fruit> bagList : bagLists) { int totalPrice = -1; for (Fruit fruit : bagList) { totalPrice += fruit.getPrice(); } if (totalPrice == maxPrice) { maxPriceBagLists.add(bagList); } else if (totalPrice > maxPrice) { maxPrice = totalPrice; maxPriceBagLists.clear(); maxPriceBagLists.add(bagList); } } return maxPriceBagLists; } /** * @param args */ public static void main(String[] args) { Fruit li = new Fruit("李子", 4, 4500); Fruit ping = new Fruit("蘋果", 5, 4700); Fruit ju = new Fruit("橘子", 2, 2250); Fruit cao = new Fruit("草莓", 1, 1100); Fruit tian = new Fruit("甜瓜", 6, 4940); Fruit bo = new Fruit("菠蘿", 2, 3900); Fruit xi = new Fruit("西瓜", 6, 5800); Fruit tao = new Fruit("桃子", 3, 3700); Fruit xiang = new Fruit("香蕉", 2, 3750); Fruit pear = new Fruit("梨子", 3, 3600); List<Fruit> fruitList = new LinkedList<Fruit>(); fruitList.add(li); fruitList.add(ping); fruitList.add(ju); fruitList.add(cao); fruitList.add(tian); fruitList.add(bo); fruitList.add(xi); fruitList.add(tao); fruitList.add(xiang); fruitList.add(pear); Fruit.printMaxPriceFruits(fruitList); } }