经过编程解决一道求和获取最小值的选择题。

此为原题

解决思路:从四个数组中各取出一个值,并且每一个数组中取得值索引的位置不能重复,而后将拿到的索引获取对应数组元素的值,求和,放到集合,再排序,获取最小值。至少用到循环或迭代。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

相关文章
相关标签/搜索