forked from aswinkumarrk/data-structures
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTotalWaysToDecodeAString.java
More file actions
128 lines (110 loc) · 4.7 KB
/
TotalWaysToDecodeAString.java
File metadata and controls
128 lines (110 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package com.geeksforgeeks.dynamicProgramming;
import com.util.LogUtil;
import java.util.*;
/**
* A message containing letters from A-Z is being encoded to numbers using the following mapping:
* <p>
* 'A' -> 1
* 'B' -> 2
* ...
* 'Z' -> 26
* Given a non-empty string containing only digits, determine the total number of ways to decode it.
* <p>
* Example 1:
* <p>
* Input: "12"
* Output: 2
* Explanation: It could be decoded as "AB" (1 2) or "L" (12).
* Example 2:
* <p>
* Input: "226"
* Output: 3
* Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
*
* @author neeraj on 2019-05-12
* Copyright (c) 2019, data-structures.
* All rights reserved.
*/
public class TotalWaysToDecodeAString {
private static List<String> decodedValues = new ArrayList<>();
public static void main(String[] args) {
getNumberOfWaysDigitCanBeDecoded("12");
getNumberOfWaysDigitCanBeDecoded("123");
getNumberOfWaysDigitCanBeDecoded("226");
getNumberOfWaysDigitCanBeDecoded("1234");
getNumberOfWaysDigitCanBeDecoded("01");
}
public static void getNumberOfWaysDigitCanBeDecoded(String digit) {
// Initialize the cache which will keep the count of ways for each decodePointer
// Decode Pointer (Moving from left to right)
// \/ \/
// 1 2 3 1 2 3
int[] cache = new int[digit.length()];
int decodePointer = 0;
Arrays.fill(cache, -1);
int noOfWays = getNumberOfWays(digit, decodePointer, cache, new StringBuffer());
LogUtil.logIt("Number of ways " + digit + " can be decoded " + noOfWays + " and the decoded values are ");
LogUtil.printList(decodedValues);
// Cleaning up the values
decodedValues = new ArrayList<>();
}
private static int getNumberOfWays(String digit, int decodePointer, int[] previousAnswer, StringBuffer currentDecodedItem) {
// Base Case 1
// If decode pointer reached at the end we have a valid decoding, hence return 1
if (decodePointer == digit.length()) {
// Adding that decoded string
decodedValues.add(String.valueOf(currentDecodedItem));
return 1;
}
// Base Case 2
// If we have previously stored value at the decodePointer in the previousAnswer lets just return it.
if (previousAnswer[decodePointer] != -1) {
decodedValues.add(String.valueOf(currentDecodedItem));
// currentDecodedItem.delete(0, currentDecodedItem.length());
return previousAnswer[decodePointer];
}
/*
We don't already know the answer to this sub-problem, calculate it
by taking the sum of the total ways for a single character decoding
or 2 character decoding.
*/
int totalWaysFromHere = 0;
// Now Since we know there are total 26 alphabets, so we can encode between 1<=char<=2
// Single character encoding
if (decodePointer + 1 <= digit.length()) {
String singleDigitChar = digit.substring(decodePointer, decodePointer + 1);
if (isValidDecoding(singleDigitChar)) {
currentDecodedItem.append((char) (Integer.parseInt(singleDigitChar) + 64));
totalWaysFromHere += getNumberOfWays(digit, decodePointer + 1, previousAnswer, currentDecodedItem);
if (currentDecodedItem.length() > 0)
currentDecodedItem.deleteCharAt(currentDecodedItem.length() - 1);
}
}
// Double Character
if (decodePointer + 2 <= digit.length()) {
String doubleDigitChar = digit.substring(decodePointer, decodePointer + 2);
if (isValidDecoding(doubleDigitChar)) {
currentDecodedItem.append((char) (Integer.parseInt(doubleDigitChar) + 64));
totalWaysFromHere += getNumberOfWays(digit, decodePointer + 2, previousAnswer, currentDecodedItem);
if (currentDecodedItem.length() > 1) {
currentDecodedItem.delete(currentDecodedItem.length() - 2, currentDecodedItem.length());
}
}
}
previousAnswer[decodePointer] = totalWaysFromHere;
return previousAnswer[decodePointer]; // Answer to the sub-problem
}
/**
* This method will tell, if the digit can be decoded into an alphabet
*/
private static boolean isValidDecoding(String singleDigitChar) {
if (singleDigitChar.length() == 0) {
return false;
}
if (singleDigitChar.charAt(0) == '0') {
return false;
}
Integer digit = Integer.parseInt(singleDigitChar);
return digit > 0 && digit <= 26;
}
}