Question:
You are given a list of positive int numbers, find out the max number that can be comprised of these input int numbers.
Example:
For input 1, 2, 3, the max number would be 321.
For 8, 87, 896, the max number would be 896887.
Answer:
For example, if the numbers are 24, 243, 2435? The max number should be [2435][243][24].
Is there a way we can sort this array, and get a new array: [2435, 243, 24]?
When we sort this array, we can define a comparator. When it compares two numbers (say a and b), if the two numbers has same digit numbers, we directly compare it, if they have different digit numbers (say a has less digit numbers than b), for the number (a in this case) has less digit numbers, we would get a new int number (get a new int a0 from b) by right padding it with the original digit numbers, and get a new number a0, then compare a0 and b.
So when compare 24 and 2435, we would think we are actually comparing 2[424] and 2435, so in the descending sorted array, 2535 would come before 24.
So the descending sorted array would be [2435, 243, 24], as 2435 > 243[2] > 24[24]; the generated max number would be [2435][243][24], this would be exactly what we expect.
Code:
The complete algorithm/test code and also many other algorithm problems and solutions are available from https://github.com/programmer-plus.
package org.codeexample.maxNumber;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.codeexample.common.OverflowException;
import org.codeexample.common.Utils;
class MyComparator implements Comparator<Integer> {
/**
* For input 87 and 8, it would return -1, for 89 and 8, return 1, for 88
* and 8, return 0.
*/
public int compare(Integer int1, Integer int2) {
if (int1 == null)
return -1;
if (int2 == null)
return 1;
// if eqauls, return directly to improve efficiency.
if (int1.equals(int2))
return 0;
int int1DigitNumber = Utils.getNumberOfDigits(int1), int2DigitNumber = Utils
.getNumberOfDigits(int2);
if (int1DigitNumber > int2DigitNumber) {
int2 = rightPadNumber(int2, int1DigitNumber);
} else if (int1DigitNumber < int2DigitNumber) {
int1 = rightPadNumber(int1, int2DigitNumber);
}
return int1.compareTo(int2);
}
/**
* @param ia
* @param newDigitalNumber
* @return pad the number by the original digital numbers in order. <br>
* For example, for input 98, 5, it would return 98989 - five
* numbers.
* @throws IllegalArgumentException,
* if the new digital number is less than the digital number of
* the old integer.
* @throws OverflowException,
* if the generated number would be larger than
* Integer.MAX_VALUE
*/
public static int rightPadNumber(int ia,
int newDigitalNumber)
throws IllegalArgumentException,
OverflowException {
int oldNumbers = Utils.getNumberOfDigits(ia);
if (oldNumbers > newDigitalNumber) {
throw new IllegalArgumentException(
"Invalid parameters: "
+ ia
+ " has "
+ oldNumbers
+ " digits, its larger than the specified new digit number: "
+ newDigitalNumber);
} else if (oldNumbers == newDigitalNumber) {
return ia; // Improve efficiency.
}
// example: to pad 98 to five numbers: 98988.
boolean negative = ia < 0;
if (negative) {
ia = -ia;
}
String orginalString = String.valueOf(ia);
StringBuffer resultString = new StringBuffer(
orginalString);
int diff = newDigitalNumber - oldNumbers;
while (diff >= oldNumbers) {
resultString.append(orginalString);
diff -= oldNumbers;
}
// now, result = 9898, diff = 1;
if (diff > 0) {
resultString.append(orginalString.substring(0,
diff));
}
if (negative) {
resultString.insert(0, "-");
}
try {
return Integer.valueOf(resultString.toString());
} catch (NumberFormatException e) {
throw new OverflowException(e);
}
}
}
public class MaxNumber {
/**
* @see org.codeexample.maxNumber#maxNumber(java.util.List)
*/
public static int maxNumber(int[] ia)
throws IllegalArgumentException,
OverflowException {
return maxNumber(Utils.toList(ia));
}
/**
* @param la,
* a list of positive Integer numbers
* @return the max value that is generated by concatting each Integer value<br>
* For example, for input 8, 87, 89, it would return 89887
* @throws IllegalArgumentException,
* if the parameters include negative number
* @throws OverflowException,
* if the generated number would be larger than
* Integer.MAX_VALUE
*/
public static int maxNumber(List<Integer> la)
throws IllegalArgumentException,
OverflowException {
Collections.sort(la, new MyComparator());
Collections.reverse(la);
Iterator<Integer> iterator = la.iterator();
int result = 0;
while (iterator.hasNext()) {
int tmpi = iterator.next();
if (tmpi < 0) {
throw new IllegalArgumentException(
"The list contains negative number: "
+ tmpi);
}
int digitNumber = Utils.getNumberOfDigits(tmpi);
// result = (10^digitNumber)*result + tmpi;
result = Utils.safeMultiply(new Double(Math
.pow(10, digitNumber)).intValue(),
result);
result = Utils.safeAdd(result, tmpi);
}
return result;
}
}