Count Number of Texts
Problem
Alice is texting Bob using her phone. The mapping of digits to letters is shown in the figure below.

In order to add a letter, Alice has to press the key of the corresponding digit i times, where i is the position of the letter in the key.
- For example, to add the letter
's', Alice has to press'7'four times. Similarly, to add the letter'k', Alice has to press'5'twice. - Note that the digits
'0'and'1'do not map to any letters, so Alice does not use them.
However, due to an error in transmission, Bob did not receive Alice's text message but received a string of pressed keys instead.
- For example, when Alice sent the message
"bob", Bob received the string"2266622".
Given a string pressedKeys representing the string received by Bob, return thetotal number of possible text messages Alice could have sent.
Since the answer may be very large, return it modulo 10^9 + 7.
Examples
Example 1
Input: pressedKeys = "22233"
Output: 8
Explanation:
The possible text messages Alice could have sent are:
"aaadd", "abdd", "badd", "cdd", "aaae", "abe", "bae", and "ce".
Since there are 8 possible messages, we return 8.
Example 2
Input: pressedKeys = "222222222222222222222222222222222222"
Output: 82876089
Explanation:
There are 2082876103 possible text messages Alice could have sent.
Since we need to return the answer modulo 10^9 + 7, we return 2082876103 % (10^9 + 7) = 82876089.
Constraints
1 <= pressedKeys.length <= 10^5pressedKeysonly consists of digits from'2'-'9'.
Solution
Method 1 – Dynamic Programming with Grouped Key Presses
Intuition
We can use dynamic programming to count the number of ways to decode the pressed keys. For each position, we look back up to 3 or 4 previous positions (depending on the digit) to see if a valid group can be formed, and sum the ways to reach those positions.
Approach
- Let
dp[i]be the number of ways to decode the firsticharacters. - Initialize
dp[0] = 1(empty string has one way). - For each position
ifrom 1 to n:- For each possible group size (up to 3 for digits 2-6,8, and up to 4 for 7,9), if the last
kdigits are the same, adddp[i-k]todp[i].
- For each possible group size (up to 3 for digits 2-6,8, and up to 4 for 7,9), if the last
- Return
dp[n]modulo10^9+7.
Code
C++
class Solution {
public:
int countTexts(string pressedKeys) {
const int MOD = 1e9+7;
int n = pressedKeys.size();
vector<int> dp(n+1, 0);
dp[0] = 1;
for (int i = 1; i <= n; ++i) {
dp[i] = dp[i-1];
for (int k = 2; k <= (pressedKeys[i-1] == '7' || pressedKeys[i-1] == '9' ? 4 : 3); ++k) {
if (i-k < 0) break;
bool ok = true;
for (int j = 1; j < k; ++j) if (pressedKeys[i-j-1] != pressedKeys[i-1]) ok = false;
if (ok) dp[i] = (dp[i] + dp[i-k]) % MOD;
else break;
}
}
return dp[n];
}
};
Go
func CountTexts(pressedKeys string) int {
MOD := 1_000_000_007
n := len(pressedKeys)
dp := make([]int, n+1)
dp[0] = 1
for i := 1; i <= n; i++ {
dp[i] = dp[i-1]
maxK := 3
if pressedKeys[i-1] == '7' || pressedKeys[i-1] == '9' {
maxK = 4
}
for k := 2; k <= maxK; k++ {
if i-k < 0 {
break
}
ok := true
for j := 1; j < k; j++ {
if pressedKeys[i-j-1] != pressedKeys[i-1] {
ok = false
break
}
}
if ok {
dp[i] = (dp[i] + dp[i-k]) % MOD
} else {
break
}
}
}
return dp[n]
}
Java
class Solution {
public int countTexts(String pressedKeys) {
int MOD = 1_000_000_007, n = pressedKeys.length();
int[] dp = new int[n+1];
dp[0] = 1;
for (int i = 1; i <= n; i++) {
dp[i] = dp[i-1];
int maxK = (pressedKeys.charAt(i-1) == '7' || pressedKeys.charAt(i-1) == '9') ? 4 : 3;
for (int k = 2; k <= maxK; k++) {
if (i-k < 0) break;
boolean ok = true;
for (int j = 1; j < k; j++) if (pressedKeys.charAt(i-j-1) != pressedKeys.charAt(i-1)) ok = false;
if (ok) dp[i] = (dp[i] + dp[i-k]) % MOD;
else break;
}
}
return dp[n];
}
}
Kotlin
class Solution {
fun countTexts(pressedKeys: String): Int {
val MOD = 1_000_000_007
val n = pressedKeys.length
val dp = IntArray(n+1)
dp[0] = 1
for (i in 1..n) {
dp[i] = dp[i-1]
val maxK = if (pressedKeys[i-1] == '7' || pressedKeys[i-1] == '9') 4 else 3
for (k in 2..maxK) {
if (i-k < 0) break
var ok = true
for (j in 1 until k) if (pressedKeys[i-j-1] != pressedKeys[i-1]) ok = false
if (ok) dp[i] = (dp[i] + dp[i-k]) % MOD else break
}
}
return dp[n]
}
}
Python
class Solution:
def countTexts(self, pressedKeys: str) -> int:
MOD = 10**9 + 7
n = len(pressedKeys)
dp = [0] * (n+1)
dp[0] = 1
for i in range(1, n+1):
dp[i] = dp[i-1]
maxk = 4 if pressedKeys[i-1] in '79' else 3
for k in range(2, maxk+1):
if i-k < 0: break
if all(pressedKeys[i-j-1] == pressedKeys[i-1] for j in range(1, k)):
dp[i] = (dp[i] + dp[i-k]) % MOD
else:
break
return dp[n]
Rust
impl Solution {
pub fn count_texts(pressed_keys: String) -> i32 {
let m = 1_000_000_007;
let n = pressed_keys.len();
let s = pressed_keys.as_bytes();
let mut dp = vec![0; n+1];
dp[0] = 1;
for i in 1..=n {
dp[i] = dp[i-1];
let maxk = if s[i-1] == b'7' || s[i-1] == b'9' { 4 } else { 3 };
for k in 2..=maxk {
if i < k { break; }
if (1..k).all(|j| s[i-j-1] == s[i-1]) {
dp[i] = (dp[i] + dp[i-k]) % m;
} else {
break;
}
}
}
dp[n]
}
}
TypeScript
class Solution {
countTexts(pressedKeys: string): number {
const MOD = 1_000_000_007;
const n = pressedKeys.length;
const dp = new Array(n+1).fill(0);
dp[0] = 1;
for (let i = 1; i <= n; i++) {
dp[i] = dp[i-1];
const maxK = (pressedKeys[i-1] === '7' || pressedKeys[i-1] === '9') ? 4 : 3;
for (let k = 2; k <= maxK; k++) {
if (i-k < 0) break;
let ok = true;
for (let j = 1; j < k; j++) if (pressedKeys[i-j-1] !== pressedKeys[i-1]) ok = false;
if (ok) dp[i] = (dp[i] + dp[i-k]) % MOD;
else break;
}
}
return dp[n];
}
}
Complexity
- ⏰ Time complexity:
O(n), where n is the length of the pressedKeys string. For each position, we check up to 4 previous positions (constant time per position). - 🧺 Space complexity:
O(n), for the dp array of size n+1.