Integers & Numbers
Roman to Integer
two things that need to consider
- how to initialize the map efficiently
- look at the Java 8 features, how to initialize map in a smart way
- how to deal with "IV" , "IX" ...
- will attempt to parse the two characters as a whole, and then parse the single character.
class Solution {
public int romanToInt(String s) {
Map<String, Integer> map = mapInit();
int sum = 0;
for (int i = 0; i < s.length(); ++i) {
if (i + 1 < s.length() && map.containsKey(s.substring(i, i + 2))) {
sum += map.get(s.substring(i, i + 2));
i++;
continue;
}
sum += map.get(String.valueOf(s.charAt(i)));
}
return sum;
}
private static Map<String, Integer> mapInit() {
return Collections.unmodifiableMap(new HashMap<String, Integer>(){
{
put("I", 1);
put("V", 5);
put("X", 10);
put("L", 50);
put("C", 100);
put("D", 500);
put("M", 1000);
put("IV", 4);
put("IX", 9);
put("XL", 40);
put("XC", 90);
put("CD", 400);
put("CM", 900);
}
});
}
}
String to Integer(atoi)
a lot of things that need to notice.
- it's better to use trim() to remove leading and trailing zeros.
- should deal with first char in advance.
- when we get a middle value, we should compare it with Integer.MAX_VALUE and Integer.MIN_VALUE.
class Solution {
public int myAtoi(String str) {
if (str == null || str.length() == 0) return 0;
str = str.trim();
char firstChar = str.toCharArray().length > 0 ? str.charAt(0) : ' ';
int sign = 1, start = 0, len = str.length();
long sum = 0;
if (firstChar == '+') {
sign = 1;
start++;
}else if (firstChar == '-') {
sign = -1;
start++;
}
for (int i = start; i < len; ++i) {
if (!Character.isDigit(str.charAt(i))) {
return (int)(sign * sum);
}
sum = sum * 10 + str.charAt(i) - '0';
if (sign == 1 && sum > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
} else if (sign == -1 && (-1) * sum < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
}
return (int)(sign * sum);
}
}
Reverse Integers
Note that, the modulo operator with negative numbers is a little bit tricky.
So for this problem, we don't need to care about the sign of the number.
class Solution {
public int reverse(int x) {
long answer = 0;
while (x != 0) {
answer = 10 * answer + x % 10;
x /= 10;
}
return (answer > Integer.MAX_VALUE || answer < Integer.MIN_VALUE) ? 0 : (int)answer;
}
}
Largest Integers
the key is how to sort the string value: here we can give a smart way: Assume that (without loss of generality), for some pair of integers a and b, our comparator dictates that a should precede b in sorted order. This means that a || b > b || a (where || represents concatenation). For the sort to produce an incorrect ordering, there must be some c for which b precedes c and c precedes a. This is a contradiction because a||b>b||a and b||c>c||b implies a||c>c||a. In other words, our custom comparator preserves transitivity, so the sort is correct.
Once the array is sorted, the most "signficant" number will be at the front. There is a minor edge case that comes up when the array consists of only zeroes, so if the most significant number is 0, we can simply return 0. Otherwise, we build a string out of the sorted array and return it.
class Solution {
public String largestNumber(int[] nums) {
// get input integers as Strings
String[] asStrs = new String[nums.length];
for (int i = 0; i < nums.length; ++i) {
asStrs[i] = String.valueOf(nums[i]);
}
// sort strings accordings to the custom comparactor
Arrays.sort(asStrs, new LargerNumberComparator());
if (asStrs[0].equals("0")) {
return "0";
}
// build largest number from sorted array
StringBuilder sb = new StringBuilder();
for (String numAsStr : asStrs) {
sb.append(numAsStr);
}
return sb.toString();
}
private class LargerNumberComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
String order1 = a + b;
String order2 = b + a;
return order2.compareTo(order1); // reverse order, b + a is larger than a + b...
}
}
}
PlusOne
most convenient way to solve the problem is to process the original array directly.
class Solution {
public int[] plusOne(int[] digits) {
if (digits == null || digits.length == 0){
return new int[0];
}
int leading = 1;
for (int i = digits.length - 1; i >= 0; i--){
int val = digits[i] + leading;
digits[i] = val % 10;
leading = val == 10 ? 1 : 0;
}
if (leading == 0){
return digits;
}
int[] res = new int[digits.length + 1];
res[0] = 1;
for (int i = 0; i < digits.length; i++){
res[i + 1] = digits[i];
}
return res;
}
}