LintCode2016年8月22日算法比赛----将数组重新排序以构造最小值

将数组重新排序以构造最小值

题目描述

给定一个整数数组,请将其重新排序,以构造最小值。

样例

给定[3,32,321],通过将数组重新排序,可构造6个可能性的数字:

3+32+321=332321  
3+321+32=332132
32+3+321=323321
32+321+3=323213
321+3+32=321332
321+32+3=321323

其中,最小值为 321323,所以,将数组重新排序后,该数组变为 [321, 32, 3]

挑战

在原数组上完成,不使用额外空间。

分析:

问题的关键在于如何比较两个数字的大小,将小的数字放在高位,将大的数字放在低位,构造的新数字就应当最小的。但此处比较数字大小不是一般的方式那种比较。比如比较321和3,首先321的从左数第一位是3,与单个数字3相等,那么接下来该怎么比较呢?如果把3放在高位,把321放在低位,那么组成的数字是3321,比把321放在高为构成的数字3213大,显然这里应该判断321比3小,怎么个小法?既然321第一位跟三相等,那么接着比较下一位,发现单个数字3已经到了最后一位,那么把321剩下的数字21和3来进行比较,发现2比3小,所以321小于3。按照这个思路,调用Collections.sort()函数,构造一个新的比较器,在比较器中实现上述比较方法。按位比较,显然需要将数字转换为字符串,这样比较容易提取各个位的数字。

Java算法实现

public class Solution {
    /**
     * @param nums n non-negative integer array
     * @return a string
     */
    public String minNumber(int[] nums) {
        // Write your code here
        List<String>list=new ArrayList<>();
		for(int i=0;i<nums.length;i++){
				//将所有数字转化为字符串
				list.add(String.valueOf(nums[i]));
		}
		
		Collections.sort(list,new Comparator<String>() {
			//新的比较器,实现新方式的大小比较
			@Override
			public int compare(String str1, String str2) {
				// TODO Auto-generated method stub
				int i=0;
				for(i=0;i<str1.length()&&i<str2.length();i++){
					if(str1.charAt(i)<str2.charAt(i)){
						//如果当前位已经比较出了大小,直接返回比较结果
						return -1;
					}
					else if(str1.charAt(i)>str2.charAt(i)){
						return 1;
					}
				}
				if(i==str1.length()&&i==str2.length()){
					//已经比较到了两个字符串的结尾
					return 0;
				}
				else{
					if(i<str2.length()){
						//还没有比较到str2的结尾,用str2剩下的字符与str1进行比较
						return compare(str1, str2.substring(i));
					}
					else{
						//同上理
						return compare(str1.substring(i), str2);
					}
				}
			}
		});
		
		//构造结果字符串
		StringBuilder sb=new StringBuilder();
		for(String str:list){
			sb.append(str);
		}
		String res=sb.toString();
		int i=0;
		/*	如果输入为[0],输出需要为"0";如果输入为[0,0,0,0,0],输出也应该为"0";
		  	如果输入为[0,0,0,1,2,3],输出应为"123"。
		 	下面的循环对此进行处理;
			i<res.length()-1 的控制目的就是为了应对输入为[0]的情况,此时不需要增长i
		*/
		while(res.charAt(i)=='0'&&i<res.length()-1){
			i++;
		}
		return res.substring(i);
    }
}

标记为Easy,难度确实不大。但是一般很难考虑周全,最后剔除前首 '0' 的步骤,如果不是提交失败收到提醒,则很难有人直接就考虑明白。

posted on 2016-08-22 12:18  HorseShoe2016  阅读(679)  评论(0编辑  收藏  举报