import java.math.*; import java.util.concurrent.atomic.*; public class Solution { public String largestNumber(int[] nums) { if (nums == null || nums.length == 0) { return "0"; } List sortedNums = new ArrayList(nums.length); for (int i = 0; i < nums.length; i++) sortedNums.add(nums[i]); Collections.sort(sortedNums); Collections.reverse(sortedNums); Function, List> idx2nums = indexes -> indexes.stream() .map(i -> sortedNums.get(i)) .collect(Collectors.toList()); Function, BigInteger> nums2bi = indexes -> new BigInteger(indexes.stream() .map(n -> Integer.toString(n)) .collect(Collectors.joining())); final AtomicReference refMax = new AtomicReference<>(); final AtomicReference> refMaxNums = new AtomicReference>(); permutateIndexes(nums.length, indexes -> { List thisNums = idx2nums.apply(indexes); BigInteger thisNum = nums2bi.apply(thisNums); if (refMax.get() == null || thisNum.compareTo(refMax.get()) > 0) { refMax.set(thisNum); refMaxNums.set(thisNums); } }, indexes -> { if (refMaxNums.get() == null) { return true; } List thisNums = idx2nums.apply(indexes); List maxNums = refMaxNums.get().subList(0, thisNums.size()); if (thisNums.equals(maxNums)) { return false; } String thisNum = nums2bi.apply(thisNums).toString(); String maxNum = nums2bi.apply(maxNums).toString(); if (thisNum.length() == maxNum.length()) { return thisNum.compareTo(maxNum) > 0; } int minLen = Math.min(thisNum.length(), maxNum.length()); return thisNum.substring(0, minLen).compareTo(maxNum.substring(0, minLen)) >= 0; }); return refMax.get().toString(); } public static void permutateIndexes(int length, Consumer> consumer, Predicate> continueCheck) { permutateIndexes(length, consumer, continueCheck, new LinkedList()); } private static void permutateIndexes(int length, Consumer> consumer, Predicate> continueCheck, LinkedList indexes) { if (indexes == null) { indexes = new LinkedList(); } else if (!indexes.isEmpty() && indexes.size() < length) { if (continueCheck != null && !continueCheck.test(indexes)) { return; } } else if (indexes.size() == length) { consumer.accept(indexes); return; } for (int i = 0; i < length; i++) { if (indexes.contains(i)) { continue; } indexes.add(i); permutateIndexes(length, consumer, continueCheck, indexes); indexes.removeLast(); } } }