經過編程解決一道求和獲取最小值的選擇題。

此爲原題

解決思路:從四個數組中各取出一個值,並且每一個數組中取得值索引的位置不能重複,而後將拿到的索引獲取對應數組元素的值,求和,放到集合,再排序,獲取最小值。至少用到循環或迭代。java

通過初步嘗試,代碼以下算法

package demo;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * desc:從裝有四個元素的數組中,只能從0,1,2,3個位置各取出一個元素,使相加的和最小。  70
 * @author lisha 2017年8月21日 下午12:50:42
 */
public class SumArrayMinTest {
	
	private static int arr0[]=new int[]{15,19,26,19};
	private static int arr1[]=new int[]{18,23,17,21};
	private static int arr2[]=new int[]{21,22,16,23};
	private static int arr3[]=new int[]{24,18,19,17};
	
	public static void main(String[] args) {
		
		int temp = 0;
		
		int[] arr=new int[]{0,1,2,3};
		List<Integer> list=new ArrayList<>();
		List<Integer> posList=new ArrayList<>();
		List<Integer> result=new ArrayList<>();
		list.add(0);
		list.add(1);
		list.add(2);
		list.add(3);
		
		for (int i = 0; i < list.size(); i++) {
			//temp+=arr0[i]; //取第一個數組第一個元素
			posList=delElement(list, list.get(i)); //去掉已使用的位置
			//第二個數組內取值
			for (int j = 0; j < posList.size(); j++) {
				//temp+=arr1[list.get(j)];//獲取第二個數組內第一個元素
				posList=delElement(list, list.get(i));
				posList=delElement(list, list.get(j));
				for (int j2 = 0; j2 < posList.size(); j2++) {
					//temp+=arr2[list.get(j2)];//獲取第三個數組內第一個元素
					posList=delElement(list, list.get(i));
					posList=delElement(list, list.get(j));
					posList=delElement(list, posList.get(j2));
					for (int j3 = 0; j3 < posList.size(); j3++) {
						//temp+=arr3[list.get(j3)];//獲取第三個數組內第一個元素
						result.add(temp);
						//temp=0;
					}
				}
			}
		}
		
		System.out.println("result大小爲:"+result.size());
		/*for (Integer i:result) {
			System.out.println(i);	
		}*/
	}
	
	/**
	 * 
	 * author:lisha 2017年8月21日 下午1:36:51
	 * desc:去掉已經使用的位置
	 */
	public static List<Integer> delElement(List<Integer> l,int element){
		List<Integer> list=new ArrayList<>();
		List<Integer> ll=new ArrayList<>();
		list.addAll(l);
		for (int i = 0; i < list.size(); i++) {
			if(list.get(i)==element){
				list.remove(i);
				i--;
			}
		}
		ll.add(element);
		ll.addAll(list);
		System.out.println(ll.size()+"---"+ll.toString());
		//System.out.println(list.size()+"---"+list.toString());
		return list;
	}
}
輸出結果以下:
…………
4---[2, 0, 1, 3]
4---[0, 1, 2, 3]
4---[3, 0, 1, 2]
4---[2, 0, 1, 3]
4---[1, 0, 2, 3]
4---[3, 0, 1, 2]
4---[2, 0, 1, 3]
4---[3, 0, 1, 2]
result大小爲:108

囧,不對呀。四個裝有四個元素的數組各取出一個,位置不重複。按排列組合算應該是432*1 共24種狀況,按循環嵌套方式未能實現。。。。。放棄。。apache

換一種思路,解決問題的關鍵在於如何拿到四個數組各取一個值索引不能重複的排列組合。網上資料查找排列組合方式的算法。數組

完整解決方法以下,上代碼:優化

package demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.map.HashedMap;

/**
 * url參考文檔:http://blog.csdn.net/leixingbang1989/article/details/47761171
 * desc: 將一個集合按順序全排列組合,運用排列組合從每一個數組不一樣的索引位置各取一個值,使和最小
 * @author lisha 2017年8月21日 下午4:38:15
 */
public class FullPermutation {//求全排列組合
    private int n;  
    private List<String> resultList=new ArrayList<>();
    
    //從下列四個數組中不一樣數組位置各取出一個值,使相加的和最小
	private static int arr0[]=new int[]{15,19,26,19};
	private static int arr1[]=new int[]{18,23,17,21};
	private static int arr2[]=new int[]{21,22,16,23};
	private static int arr3[]=new int[]{24,18,19,17};
	
    public FullPermutation ()  
    {  
        this.n=0;  
    }  
    public  void listAll(List<String> candidate,String prefix)  
    {  
          
        if(candidate.isEmpty())  
        {  
            //System.out.println(prefix);  
            this.n++;  
            this.resultList.add(prefix);
        }  
        for(int i=0;i<candidate.size();i++)  
        {  
            @SuppressWarnings("unchecked")
			List<String> temp=new LinkedList<String>(candidate);//轉換成linkList,移除一個對象是在不影響原來隊列的基礎上的  
            String s1=prefix+temp.remove(i);//用於保存排列組合生成的結果  
            listAll(temp,s1);//注意,這裏temp和s1都是全新的集合和字符串,並非一直對一個集合來進行操做  
              
        }  
          
    }  
    public int getN() {  
        return n;  
    }  
    public void setN(int n) {  
        this.n = n;  
    }  
    
    public List<String> getResultList() {
		return resultList;
	}
	public void setResultList(List<String> resultList) {
		this.resultList = resultList;
	}
	
	//求不一樣排列組合位置和的最小值,輸出
	public static void arrayPosToSum(List<String> list){
		List<Integer> sumList=new ArrayList<Integer>();
		Map<String,Integer> map=new HashMap<String,Integer>();//用於存儲最小值和對應數組取值的位置
		for (int i = 0; i < list.size(); i++) {
			int sum=0;
			String str=list.get(i);
			for (int j = 0; j < str.length(); j++) {
				int index=Integer.valueOf(str.substring(j, j+1));
				switch(j){
				case 0:
					sum+=arr0[index];
					break;
				case 1:
					sum+=arr1[index];
					break;
				case 2:
					sum+=arr2[index];
					break;
				case 3:
					sum+=arr3[index];
					break;
				}
			}
			
			sumList.add(sum);
			map.put(str, sum);
			
		}
		
		Collections.sort(sumList);
		//輸出最小值和對應數組中的取值位置
		for(String key:map.keySet()){
			if(map.get(key)==sumList.get(0)){
				System.out.println("取值位置index="+key+"---最小值value="+map.get(key));
			}
		}
		
		
	}
	
	public static void main(String[] args) {  
        String []arr={"0","1","2","3"};  
        FullPermutation f=new FullPermutation();  
        f.listAll(Arrays.asList(arr), "");
        System.out.println("全部的排列個數:"+f.getN());  
        arrayPosToSum(f.getResultList());
    }  
  
}
輸出結果以下:

全部的排列個數:24
取值位置index=0321---最小值value=70
取值位置index=1023---最小值value=70

此次對了,發現還有兩種選擇方法能夠使成本獲取最小值70. 0312的含義是從四個數組中依次拿取數組一第1個,數組2第4個,數組3第2個,數組4第3個位置的元素。this

問題解決。url

總結:花費了好幾個小時的時間,剛開始以爲很簡單的問題,用程序實現起來仍是有點兒難度的。感謝網上提供的資料。程序還能夠進行不少優化,歡迎建議和意見。.net

相關文章
相關標籤/搜索