Divide Two Integers without div operator

This Question is about how to divide two integers without using multiplication, division and mod operator. If it is overflow, return MAX_INT.

I think the essential of the division is about how many divisor are contained in a dividend. First, we can keep the negative sign “-“, then count how many times we have subtracted the divisor from the dividend, at last, put the negative sign back to the result. The edge cases are critical, I enlarge the int to long in div() and abs() methods to avoid the eventual conversion errors.

My approach is to use recursion to repeat the subtraction and at the same time count the result. I tried to program a tail recursion to optimized the computation. But it seems not working, I will explain it later.

public int divide(int dividend, int divisor) {
	int res = Integer.MAX_VALUE;
	if (divisor != 0) {
		res = (int) div(abs(dividend), abs(divisor), 0);
		if (dividend > 0 ^ divisor > 0) {
			res = 0 - res;
		}
	}
	return res;
}

private long abs(final long x) {
	return x < 0 ? 0 - x : x;
}

private long div(final long x, final long y, final long res) {
	return x < y ? res : div(x - y, y, res + 1);
}

This solution passes almost all the unit tests except when dividend is quite big and divisor is very small, for example dividend = 2147483647 (MAX_INT), divisor = 1. In this case we will only get stack overflow exception, it seems that java does not support or optimize the tail recursion very well (correct me if I am wrong). The recursion method still attempts to call itself 2147483647 times on the stack!

Fortunately we know any recursion can be replaced by a while/for loop, so to fix this problem is not difficult.

public int divide(int dividend, int divisor) {
	int res = Integer.MAX_VALUE;
	if (divisor != 0) {
		res = (int) div(abs(dividend), abs(divisor), 0);
		if (dividend > 0 ^ divisor > 0) {
			res = 0 - res;
		}
	}
	return res;
}

private long abs(final long x) {
	return x < 0 ? 0 - x : x;
}

private long div(long x, final long y) {
	long res = 0;
	while(x >= y ){
		x -= y;
		res++;
	}
	return res;
}

The second solution can pass all the predefined unit tests, it will however take too long for the worse cases, on my PC it’s nearly 1.45 sec. So the problem is that the div() method above is not efficient enough, next we want to improve the div() method to make the algorithm faster. I considered to use bit operator to realize the double function:

public int divide(int dividend, int divisor) {
	int res = Integer.MAX_VALUE;
	if (divisor != 0) {
		res = (int) div(abs(dividend), abs(divisor), 0);
		// if dividend and divisor are not positive at the same time
		if (dividend > 0 ^ divisor > 0) {
			res = 0 - res;
		}
	}
	return res;
}

private long abs(final long x) {
	return x < 0 ? 0 - x : x;
}

private long div(long x, long y, int sum) {
	long oy = y, res = sum; // keep the origial y and the old sum
	sum = 1; // reinitialize sum
	while (x >= y) {
		if (x < y << 1) { // if x smaller than double y
			return res + div(x - y, oy, sum);
		} else {
			y <<= 1; // double y
			sum <<= 1; // double sum
		}
	}
	return res;
}

this solution has passed all the unit tests, and the performance is very good. However it will not pass the OJ System without the condition below because of the overflow condition at the beginning. in java, -2147483648/-1 returns exactly -2147483648, but in the online judge system, it expects 2147483647 (MAX_INT). Thus I will not say this solution is wrong. If you just want to pass the LeetCode OJ System, then replace the 3. line “if (divisor != 0)” with the following code:

// just to satisfy the leetcode online judge system
if (divisor != 0 && (dividend != Integer.MIN_VALUE || divisor != -1))

Find letter combinations of a phone number using backtracking approach

It seems to be a real problem: (we like solving real problems :p) Given a digit string, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below:
telephone keypad
For example if the input is a digit string “23”, the outputs should be in a string array: [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]. Note: Although the example above is in lexicographical order, the answer could however be in any order.

This time we will try using Backtracking approach to solve this problem. Backtracking is a refinement of brute force approach and is in most cases a form of recursion, which systematically searches for a solution to a problem among all available options. If the program run into a certain state/step that obviously can not get any correct solution, it will go back to the last step and choose another possible way such like what DFS (deep first search) appoach do in a tree. If you need some further reading, you can read here.

If the input ist “23”, the tree will look like:
Backtracking
say we go down the tree child-nodes, if there is no way down, the nodes that the we passed by with the green path will compose a target we are looking for. Next step we go follow the orange path back to the parent-node and select the next child-node and so on and so forth until we passed by all the nodes of the tree. Here is the common solution in recursion:

private final static String[] LETTERS = { "", "", "abc", "def", "ghi",
 "jkl", "mno", "pqrs", "tuv", "wxyz" };

public List<String> letterCombinations1(String digits) {
	List<String> res = new ArrayList<>();
	combination("", digits, 0, res);
	return res;
}

private void combination(String prefix, String digits, int idx, List<String> res) {
	if (idx < digits.length()) {
		for (char letter : LETTERS[digits.charAt(idx) - '0'].toCharArray()) {
			combination(prefix + letter, digits, idx+1, res);
		}
	} else {
		res.add(prefix);
	}
}

It’s to me at the beginning hard to imagine that the input can be seen as a “tree”, and I have spent a lot of time to adapt the mode of my thinking. But yet there is maybe a good news for those who also needs time to get with it — this problem can also be solved without using recursion, here is another solution:

private final static String[] LETTERS = { "", "", "abc", "def",
 "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };

public List<String> letterCombinations(String digits) {
	List<String> res = Arrays.asList("");
	for (char dig : digits.toCharArray()) {
		List<String> track = new ArrayList<>();
		for (char letter : LETTERS[dig - '0'].toCharArray()) {
			for (String prefix : res) {
				track.add(prefix + letter);
			}
		}
		res = track;
	}
	return res;
}

Some might ask what did the dig-‘0’ do here? It’s actually a trick, will convert a digit char to int which will be used as the index of the LETTERS string array. By the way, we can also use HashMap for mapping the letter buttons, let’s see the concrete code:

private static final Map<Character, String> map = new HashMap<>();
static {
	map.put('2', "abc");
	map.put('3', "def");
	map.put('4', "ghi");
	map.put('5', "jkl");
	map.put('6', "mno");
	map.put('7', "pqrs");
	map.put('8', "tuv");
	map.put('9', "wxyz");
}

public List<String> letterCombinations2(String digits) {
	List<String> res = Arrays.asList("");
	for (char dig : digits.toCharArray()) {
		List<String> track = new ArrayList<>();
		for (char letter : map.get(dig).toCharArray()) {
			for (String prefix : res) {
				track.add(prefix + letter);
			}
		}
		res = track;
	}
	return res;
}

It’s basically the same as the former solution, the only benefit is that we don’t need to use the trick to convert the char to int for indexing, the digit chars indexed the letters already.