题目描述:
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例1:
输入: [10,2] 输出: “102”
示例2:
输入: [3,30,34,5,9] 输出: “3033459”
解题思路:
这道题主要是要得出一个排序规则,数组根据这个规则排序之后进行拼接可以得到一个最小的数字。根据题目的要求,两个数字m和n能拼接成数字mn和nm。如果mn < nm,那么m应该排在n的前面(即m“小于”n)。mn和nm的大小可以使用String.compare(String)进行比较,因为mn和nm的长度是一样的,而compareTo方法在对比相同长度的字符串的大小时是逐个比较字符串中的字符的ASCII码的大小关系。因此,确定好数字之间的“大小关系”之后就可以对数组进行排序了,最后将排序好的数组拼接成一个字符串就是所有数字中的最小的一个。
排序的方法有三种实现方式,分别是快速排序法、使用现有的Arrays.sort()和小根堆PriorityQueue进行排序(后两种方式注意重写Comparator接口中的compare方法)
时间复杂度和空间复杂度: 时间复杂度为O(NlogN),空间复杂度为O(N)。
实现代码:
//解法1:使用快排对字符串进行排序 public String minNumber(int[] nums) { String[] str = new String[nums.length]; for(int i = 0; i < str.length; i++) str[i] = String.valueOf(nums[i]); quickSort(str, 0, str.length - 1); StringBuilder sb = new StringBuilder(); for(String s : str) sb.append(s); return sb.toString(); } public void quickSort(String[] str, int low, int high){ if(low >= high) return; int i, j; for (i = low, j = low; j < high; j++) //如果str[j]”小于“str[high]则交换str[i]和str[j](利用String.compareTo()方法进行对字符串比较) if((str[j] + str[high]).compareTo(str[high] + str[j]) < 0) swap(str, i++, j); swap(str, i, high); quickSort(str, low, i - 1); quickSort(str, i + 1, high); } public void swap(String[] str, int i, int j){ String temp = str[i]; str[i] = str[j]; str[j] = temp; } //解法2:使用Arrays.sort() public String minNumber1(int[] nums) { String[] str = new String[nums.length]; for(int i = 0; i < str.length; i++) str[i] = String.valueOf(nums[i]); Arrays.sort(str, (o1, o2) -> (o1 + o2).compareTo(o2 + o1));//注意重写compare方法 StringBuilder sb = new StringBuilder(); for(String s : str) sb.append(s); return sb.toString(); } //解法3:使用小根堆 public String minNumber2(int[] nums) { Queue<String> queue = new PriorityQueue<>((o1, o2) -> (o1 + o2).compareTo(o2 + o1));//注意重写compare方法 for (int num : nums) queue.add(num + ""); StringBuilder sb = new StringBuilder(); while(!queue.isEmpty()) sb.append(queue.poll()); return sb.toString(); }