You are given the strings key
and message
, which represent a cipher key and a secret message, respectively. The steps to decode message
are as follows:
key
as the order of the substitution table.message
is then substituted using the table.' '
are transformed to themselves.key = "happy boy"
(actual key would have at least one instance of each letter in the alphabet), we have the partial substitution table of ('h' -> 'a'
, 'a' -> 'b'
, 'p' -> 'c'
, 'y' -> 'd'
, 'b' -> 'e'
, 'o' -> 'f'
).Return the decoded message.
Example 1:
Input: key = "the quick brown fox jumps over the lazy dog", message = "vkbs bs t suepuv" Output: "this is a secret" Explanation: The diagram above shows the substitution table. It is obtained by taking the first appearance of each letter in "the quick brown fox jumps over the lazy dog".
Example 2:
Input: key = "eljuxhpwnyrdgtqkviszcfmabo", message = "zwx hnfx lqantp mnoeius ycgk vcnjrdb" Output: "the five boxing wizards jump quickly" Explanation: The diagram above shows the substitution table. It is obtained by taking the first appearance of each letter in "eljuxhpwnyrdgtqkviszcfmabo".
Constraints:
26 <= key.length <= 2000
key
consists of lowercase English letters and ' '
.key
contains every letter in the English alphabet ('a'
to 'z'
) at least once.1 <= message.length <= 2000
message
consists of lowercase English letters and ' '
.This problem involves decoding a message using a cipher key. The key determines a substitution table where the first occurrence of each letter in the key maps to the next available letter in the alphabet (a-z). The solution involves creating this mapping and then applying it to the message.
Approach:
Create the substitution table: We iterate through the key
string. For each character, if it's not already in our mapping and it's a lowercase alphabet character, we map it to the next unused alphabet character. We use a hash map (dictionary in Python) or an array to efficiently store this mapping. Spaces are handled specially, remaining as spaces.
Decode the message: We iterate through the message
string. For each character, we look it up in our substitution table. If found, we replace it with its corresponding decoded character. If not found (it should be a space), the character remains unchanged.
Return the decoded message: Finally, we concatenate the decoded characters to form the decoded message string.
The code examples below demonstrate the approach in multiple programming languages. The time complexity is dominated by the iterations through the key and message strings. The space complexity depends on the size of the substitution table, which is constant (O(1) because it's limited to 26 letters).
Time Complexity: O(M + K), where M is the length of the message and K is the length of the key. We iterate through the key once to create the mapping and the message once to decode.
Space Complexity: O(1). The space used by the substitution table is constant (26 letters), regardless of the input size.
Python:
class Solution:
def decodeMessage(self, key: str, message: str) -> str:
mapping = {} #Using a dictionary for efficient lookup.
alphabet_index = 0
for char in key:
if char != ' ' and char not in mapping:
mapping[char] = chr(ord('a') + alphabet_index) #chr converts ascii to character, ord does the opposite
alphabet_index += 1
mapping[' '] = ' ' #Handle spaces separately.
decoded_message = ""
for char in message:
decoded_message += mapping[char] #Efficient lookup in dictionary
return decoded_message
Java:
class Solution {
public String decodeMessage(String key, String message) {
char[] mapping = new char[26]; // Array for efficient lookup (index represents a-z)
Arrays.fill(mapping, ' '); //Initialize with spaces.
int index = 0;
for (char c : key.toCharArray()) {
if (c != ' ' && mapping[c - 'a'] == ' ') {
mapping[c - 'a'] = (char) ('a' + index++);
}
}
StringBuilder decodedMessage = new StringBuilder();
for (char c : message.toCharArray()) {
decodedMessage.append(c == ' ' ? ' ' : mapping[c - 'a']);
}
return decodedMessage.toString();
}
}
C++:
class Solution {
public:
string decodeMessage(string key, string message) {
vector<char> mapping(26, ' '); // Vector for efficient lookup.
int index = 0;
for (char c : key) {
if (c != ' ' && mapping[c - 'a'] == ' ') {
mapping[c - 'a'] = 'a' + index++;
}
}
string decodedMessage = "";
for (char c : message) {
decodedMessage += (c == ' ' ? ' ' : mapping[c - 'a']);
}
return decodedMessage;
}
};
The other languages (Go, TypeScript, Rust, C) follow a similar structure, adapting the data structures and syntax as needed while maintaining the same overall algorithmic approach and complexity. The core idea is always to create a fast lookup table (hash map or array) for character substitution and efficiently apply it to the message string.