leetcode-面试题45.把数组排成最小的数

看题第一感觉:

  • IPO(input、process、output)分别为:I:非负 整数的数组; P:拼接数组元素; O:拼接成的最小的数。
  • 分析一些例子感觉应该是按照数的最高位排序,再按次高位排序,但对于没有次高位的数来说,那又如何比较呢。例如3和30比较次高位时,3并没有次高位,如果用补0操作的话就无法判断是个位数3补的0,还是原本30就存在的0。所以这个方法弃用。
  • 那是不是和整除有关,或者对数进行归一化?——想不通了,看题解思路吧。

题解思路:
  对于两个数x和y,如果x+y,那么可以看作x(这里的+代表字符串连接)。

代码思路:
  有了以上题解思路,所以如果将数组中元素按照这个比较方式进行从小到大排序,那么数组元素顺序连接即为所求。代码采用快速排序进行数组元素的比较排序。

public String minNumber(int[] nums) {
        int left=0, right=nums.length-1;
        QuickSort(nums, left, right);
        StringBuilder res = new StringBuilder();
        for(int num:nums){
        	//res.append(String.valueOf(num));
        	res.append(num);
        }
        return res.toString();
    }
    public void QuickSort(int[] nums, int left, int right){
    	if(left >= right) return;
        int key = nums[left];
        int i=left, j=right;
        while(i<j){
            while(i<j && Compare(key,nums[j])) j--;
            nums[i]=nums[j];
            while(i<j && Compare(nums[i],key)) i++;
            nums[j]=nums[i];
        }
        nums[i]=key;
        QuickSort(nums,left,j-1);
        QuickSort(nums,j+1,right);
    }
	
	// 比较的规则
	private boolean Compare(int target, int key) {
		String x = String.valueOf(target);
		String y = String.valueOf(key);
		//return Integer.parseInt(x+y)>=Integer.parseInt(y+x);	
		if((x+y).compareTo(y+x)>=0) {
			return true;
		}
		else return false;		
	}
}

执行结果:
leetcode-面试题45.把数组排成最小的数_第1张图片
自己编代码出现的问题&知识点补充

  1. 强制类型转换 string<——>int
  2. 快速排序:递归;低位和高位比较之处的区别
  3. 陷入了无限循环的原因:将Compare(key,nums[i]))写成了Compare(nums[i],key)),这样会导致只考虑了>而不是考虑>=
  4. 比较两个数字连接成的数字的大小:其实完全可以看作是字符串比较,不必转换成int比较,再说长度太长已经超出int范围了。
  5. 字符串比较:String类中方的compare()方法
  6. string初始化:String s="";
  7. 返回minNumber的字符串连接输出
  8. StringBuilder-官方文档;StringBuilder-拼接字符串
  9. java1.8新特性-Lambda表达式理解
  10. void java.util.Arrays.sort(T[] a, Comparator c) ;
  11. Comparator接口实现自定义排序(与Comparable比较)
  12. 递归地快速排序的思路:都是先从后往前找
    (1)挖坑法:找一个基准元素key,从后往前找比key小的数,找到则将该数换到low的位置上,同时换方向,从前往后找比key大的数,找到则将该数换到high的位置上,重复直到i>=j,最后将key的值赋给low的位置(其实此时low=high),递归地对数组两侧进行排序。
    (2)指针交换法:找一个基准元素key,从后往前找比key小的数,找到则换方向,从前往后找比key大的数,找到则交换二者的值,重复直到i>=j,最后将key的值赋给high位置,递归地对两侧进行排序

评论区解法1:

public String minNumber(int[] nums) {
		String[] strs = new String[nums.length];
		for(int i=0;i<nums.length;i++)
			strs[i] = String.valueOf(nums[i]);
		QuickSort2(strs,0,strs.length-1);
		StringBuilder res = new StringBuilder();
		for(String str:strs) 
			res.append(str);
		return res.toString();	
	}

	private void QuickSort2(String[] strs, int left, int right) {
		if(left>=right) return;
		int i = left, j = right;
		String key = strs[i];
		while(i<j) {		
			while(i<j && (strs[j]+key).compareTo(key+strs[j]) >= 0)
				j--;
			strs[i] = strs[j];
			while(i<j && (strs[i]+key).compareTo(key+strs[i]) <= 0)
				i++;
			strs[j] = strs[i];
		}
		strs[i] = key;
		QuickSort2(strs, left, i-1);
		QuickSort2(strs, i+1, right);
	}

leetcode-面试题45.把数组排成最小的数_第2张图片
解法2:

public String minNumber(int[] nums) {
		String[] strs = new String[nums.length];
		for(int i=0;i<nums.length;i++) {
			strs[i] = String.valueOf(nums[i]);
		}
		Arrays.sort(strs,(x,y)->(x+y).compareTo(y+x));
		StringBuilder res = new StringBuilder();
		for(String s:strs)
			res.append(s);
		return res.toString();		
	}	

leetcode-面试题45.把数组排成最小的数_第3张图片

你可能感兴趣的:(leetcode,leetcode)