package com.freetymekiyan.algorithms.level.medium;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Given a digit string, return all possible letter combinations that the number could represent.
* <p>
* A mapping of digit to letters (just like on the telephone buttons) is given below.
* <p>
* http://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Telephone-keypad2.svg/200px-Telephone-keypad2.svg.png
* <p>
* Input:Digit string "23"
* Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
* <p>
* Note:
* Although the above answer is in lexicographical order, your answer could be in any order you want.
* <p>
* Company Tags: Amazon, Dropbox, Google, Uber, Facebook
* Tags: Backtracking, String
* Similar Problems: (M) Generate Parentheses, (M) Combination Sum, (E) Binary Watch
*/
public class LetterCombinationsOfPhoneNum {
private static final String[] LETTERS = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz" // 9
};
private LetterCombinationsOfPhoneNum l;
/**
* Backtracking. DFS.
* The backtrack is like a DFS function that generates all possible combinations by:
* 1) Assign one letter at current level
* 2) Call the backtrack recursively to generate the rest
* Stop when we reach the end of the digits string, and add the combination to result.
*/
public List<String> letterCombinations(String digits) {
if (digits == null || digits.isEmpty()) { // When digits is "", should return empty.
return Collections.emptyList();
}
List<String> res = new ArrayList<>();
backtrack(res, digits, 0, "");
return res;
}
/**
* Backtracking.
* Generate combination position by position.
* Get current position's possible letters.
* Append to the combination so far.
* Pass the subset and generated combination to the next call.
* When all digits are used, add combination to the result collection.
*/
private void backtrack(List<String> res, String digits, int start, String comb) {
if (start == digits.length()) {
res.add(comb);
return;
}
String cur = LETTERS[digits.charAt(start) - '0'];
for (char c : cur.toCharArray()) {
backtrack(res, digits, start + 1, comb + c);
}
}
/**
* BFS.
* Build combination level by level.
* The length of the combination is the same as the level.
* Add all possible letters to each of the result in previous level.
*/
public List<String> letterCombinationsBFS(String digits) {
LinkedList<String> queue = new LinkedList<>();
if (digits == null || digits.length() == 0) {
return queue;
}
queue.add("");
for (int i = 0; i < digits.length(); i++) {
char[] letters = LETTERS[digits.charAt(i) - '0'].toCharArray();
while (queue.peek().length() == i) { // Get all at this level
String s = queue.poll();
for (char l : letters) {
queue.offer(s + l);
}
}
}
return queue;
}
@Before
public void setUp() {
l = new LetterCombinationsOfPhoneNum();
}
@Test
public void testExamples() {
l.letterCombinations("22");
}
@After
public void tearDown() {
l = null;
}
}