考虑一个将字母转换为整数的编码系统,其中“ a”表示为1,“ b”表示为2,..“ z”表示为26。给定一个数字数组(1到9)作为输入,编写一个输出所有数字的函数输入数组的有效解释。
例子
Input: {1, 1}
Output: ("aa", 'k")
[2 interpretations: aa(1, 1), k(11)]
Input: {1, 2, 1}
Output: ("aba", "au", "la")
[3 interpretations: aba(1,2,1), au(1,21), la(12,1)]
Input: {9, 1, 8}
Output: {"iah", "ir"}
[2 interpretations: iah(9,1,8), ir(9,18)]
请注意,我们无法更改数组的顺序。这意味着{1,2,1}不能成为{2,1,1}
乍一看,它看起来像是排列/组合的问题。但是仔细观察,您会发现这是一个有趣的树问题。
这里的想法是字符串最多可以采用两条路径:
1.处理一位数
2.处理两位数
这意味着我们可以在这里使用二叉树。用一位数字处理将是左子代,而两位数字将是右子代。如果两位数的值大于26,则我们的右子元素将为null,因为我们没有大于26的字母。
我们来看一个示例.Array a = {1,2,1}。下图显示了我们的树如何生长。
“” {1,2,1} Codes used in tree
/ \ "a" --> 1
/ \ "b" --> 2
"a"{2,1} "l"{1} "l" --> 12
/ \ / \
/ \ / \
"ab"{1} "au" "la" null
/ \
/ \
"aba" null
大括号{}包含仍在等待处理的数组。请注意,对于每个级别,我们的数组大小都会减小。如果您仔细观察,不难发现树高始终为n(数组大小)
如何打印所有字符串(解释)?输出字符串是树的叶子节点。例如,对于{1,2,1},输出为{aba au la}。
我们可以得出结论,主要有两个步骤可以打印给定整数数组的所有解释。
步骤1:使用叶节点中的所有可能解释创建一个二叉树。
步骤2:从步骤1中创建的二叉树中打印所有叶节点。
以下是上述算法的Java实现。
// A Java program to print all interpretations of an integer array
import java.util.Arrays;
// A Binary Tree node
class Node {
String dataString;
Node left;
Node right;
Node(String dataString) {
this.dataString = dataString;
//Be default left and right child are null.
}
public String getDataString() {
return dataString;
}
}
public class arrayToAllInterpretations {
// Method to create a binary tree which stores all interpretations
// of arr[] in lead nodes
public static Node createTree(int data, String pString, int[] arr) {
// Invalid input as alphabets maps from 1 to 26
if (data > 26)
return null;
// Parent String + String for this node
String dataToStr = pString + alphabet[data];
Node root = new Node(dataToStr);
// if arr.length is 0 means we are done
if (arr.length != 0) {
data = arr[0];
// new array will be from index 1 to end as we are consuming
// first index with this node
int newArr[] = Arrays.copyOfRange(arr, 1, arr.length);
// left child
root.left = createTree(data, dataToStr, newArr);
// right child will be null if size of array is 0 or 1
if (arr.length > 1) {
data = arr[0] * 10 + arr[1];
// new array will be from index 2 to end as we
// are consuming first two index with this node
newArr = Arrays.copyOfRange(arr, 2, arr.length);
root.right = createTree(data, dataToStr, newArr);
}
}
return root;
}
// To print out leaf nodes
public static void printleaf(Node root) {
if (root == null)
return;
if (root.left == null && root.right == null)
System.out.print(root.getDataString() + " ");
printleaf(root.left);
printleaf(root.right);
}
// The main function that prints all interpretations of array
static void printAllInterpretations(int[] arr) {
// Step 1: Create Tree
Node root = createTree(0, "", arr);
// Step 2: Print Leaf nodes
printleaf(root);
System.out.println(); // Print new line
}
// For simplicity I am taking it as string array. Char Array will save space
private static final String[] alphabet = {"", "a", "b", "c", "d", "e",
"f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
"s", "t", "u", "v", "w", "x", "v", "z"};
// Driver method to test above methods
public static void main(String args[]) {
// aacd(1,1,3,4) amd(1,13,4) kcd(11,3,4)
// Note : 1,1,34 is not valid as we don't have values corresponding
// to 34 in alphabet
int[] arr = {1, 1, 3, 4};
printAllInterpretations(arr);
// aaa(1,1,1) ak(1,11) ka(11,1)
int[] arr2 = {1, 1, 1};
printAllInterpretations(arr2);
// bf(2,6) z(26)
int[] arr3 = {2, 6};
printAllInterpretations(arr3);
// ab(1,2), l(12)
int[] arr4 = {1, 2};
printAllInterpretations(arr4);
// a(1,0} j(10)
int[] arr5 = {1, 0};
printAllInterpretations(arr5);
// "" empty string output as array is empty
int[] arr6 = {};
printAllInterpretations(arr6);
// abba abu ava lba lu
int[] arr7 = {1, 2, 2, 1};
printAllInterpretations(arr7);
}
}
输出:
aacd amd kcd
aaa ak ka
bf z
ab l
a j
abba abu ava lba lu
锻炼:
1.该解决方案的时间复杂度是多少? [提示:树的大小+查找叶节点]
2.我们可以在创建树时存储叶节点,这样就不需要再次运行循环来获取叶节点了吗?
3.我们如何减少多余的空间?