3628. Maximum Number of Subsequences After One Inserting
Problem Description
You are given a string s
consisting of uppercase English letters.
You are allowed to insert at most one uppercase English letter at any position (including the beginning or end) of the string.
Return the maximum number of "LCT"
subsequences that can be formed in the resulting string after at most one insertion.
A subsequence is a sequence that can be derived from the string by deleting some or no letters without changing the order of the remaining letters.
For example, if s = "LCT"
and you insert a 'T'
at the end to get "LCTT"
, subsequences like "LCT"
and "LCT"
(using the second 'T'
) are both counted.
Intuition
To maximize the number of "LCT"
subsequences after at most one insertion, first think about how such subsequences form: for every 'C'
in the string, you can pair any 'L'
before it with any 'T'
after it. So, for each 'C'
, the number of new subsequences is the product of the count of 'L'
before and 'T'
after. The total is the sum over all 'C'
.
Now, with the option of one insertion, the best way to increase the count is to insert 'L'
, 'C'
, or 'T'
to create more combinations:
- Inserting
'L'
increases the number of possible"LCT"
by boosting all"CT"
subsequences. - Inserting
'C'
increases the count by helping form"LCT"
from every combination of'L'
before and'T'
after where the new letter is the center'C'
. - Inserting
'T'
connects all"LC"
pairs into new"LCT"
subsequences.
The task then is to try these three insert options separately and, in each case, count how many new "LCT"
subsequences are created, then pick the maximum result overall. This way, we consider all possible single insertions to ensure the answer is maximized.
Solution Approach
To solve this problem efficiently, we need to count the number of "LCT"
subsequences before and after one possible insertion.
The key is to recognize that for each 'C'
in the string, the number of "LCT"
subsequences that use that 'C'
is the product of the number of 'L'
characters to its left and the number of 'T'
characters to its right. So, for each character, we keep two running totals:
l
: the number of'L'
s encountered so far (to the left)r
: the number of'T'
s remaining to the right
The main algorithm is:
- Count the total number of
'T'
s in the string and store it inr
. - Traverse the string from left to right:
- For every character, if it's a
'C'
, calculate how many'L'
s have appeared before (l
) and how many'T'
s remain after (r
), then addl * r
to the answer. - If the character is
'L'
, increasel
by 1. - If the character is
'T'
, decreaser
by 1 since one'T'
is now to the left. - Keep track of the maximum possible
l * r
, which represents the result after inserting a'C'
at the best spot.
- For every character, if it's a
Next, consider all three possible types of insertions:
- Insert an
'L'
: This helps create new"LCT"
from each"CT"
pair. So, compute the total number of"CT"
subsequences. We can do this by scanning the string for every'T'
and counting the number of'C'
s before it, accumulating that count. - Insert a
'C'
: For this, maximize the productl * r
where we pick some potential place to insert'C'
. - Insert a
'T'
: We compute the total number of"LC"
subsequences. This requires traversing the string and, for each'C'
found, adding the current count of'L'
.
The code calculates the result of each of these choices and returns the initial number of "LCT"
plus the largest possible increase achievable by one insertion.
All calculations are done in linear time, making the approach efficient even for longer strings, since each step is an O(n) traversal or operation.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's use the string s = "LCTC"
as an example.
Step 1: Calculate Initial "LCT" Subsequences
We want to count all the "LCT"
subsequences in s
.
For each 'C'
, count all 'L'
to its left and all 'T'
to its right.
-
First
'C'
at index 1:'L'
to the left: 1 (s[0]
)'T'
to the right: 1 (s[2]
) Total for this'C'
: (1 \times 1 = 1) -
Second
'C'
at index 3:'L'
to the left: 1 (s[0]
)'T'
to the right: 0 Total for this'C'
: (1 \times 0 = 0)
So, initially there is 1 "LCT"
subsequence.
Step 2: Evaluate Inserting Each Possible Character
A) Insert 'L'
After inserting an extra 'L'
, count the number of "CT"
pairs.
- Scan from left to right:
- For each
'T'
, count how many'C'
s were before it.
- For each
'C'
before'T'
(s[2]
): 1 (s[1]
) So, one"CT"
pair exists. Adding an'L'
creates an extra"LCT"
for each"CT"
pair: +1
B) Insert 'C'
Find the maximum value of (number of L's before
(\times) number of T's after
) at any position (including beginning/end or between).
Track cumulative 'L'
s from left and 'T'
s from right.
Record at each position:
- Before index 0: L=0, T=2 → (0 \times 2 = 0)
- Between 0-1: L=1, T=2 → (1 \times 2 = 2)
- Between 1-2: L=1, T=1 → (1 \times 1 = 1)
- Between 2-3: L=1, T=1 → (1 \times 1 = 1)
- After index 3: L=1, T=0 → (1 \times 0 = 0)
The max is 2, so by inserting 'C'
between the first 'L'
and the first 'C'
, we gain +2 new "LCT"
subsequences.
C) Insert 'T'
Count the number of "LC"
pairs.
- Scan from left to right: For each
'C'
, add the current count of'L'
s before it. - First
'C'
(s[1]
): L=1 → +1 - Second
'C'
(s[3]
): L=1 → +1
Total "LC"
pairs: 2.
Adding a 'T'
gives an extra "LCT"
for each "LC"
pair: +2
Step 3: Get the Maximum
- Original
"LCT"
subsequences: 1 - Insert
'L'
: 1 + 1 = 2 - Insert
'C'
: 1 + 2 = 3 - Insert
'T'
: 1 + 2 = 3
Maximum achievable subsequences: 3
Summary
For s = "LCTC"
, after at most one optimal character insertion, the maximum number of "LCT"
subsequences is 3.
Solution Implementation
1class Solution:
2 def numOfSubsequences(self, s: str) -> int:
3 # Helper function to count subsequences of the form t[0]...t[1] (e.g. 'LC' or 'CT')
4 def calc(t: str) -> int:
5 subseq_count = 0 # Number of valid subsequences
6 count_first = 0 # Count of t[0] seen so far
7 for char in s:
8 if char == t[1]:
9 subseq_count += count_first
10 if char == t[0]:
11 count_first += 1
12 return subseq_count
13
14 left_L = 0 # Number of 'L' seen so far
15 right_T = s.count("T") # Number of 'T' remaining to the right
16 answer = 0 # Final answer (sum of all wanted subsequences)
17 max_value = 0 # Maximum value for special cases
18
19 # Iterate through the string once to count 'L...C...T' type subsequences
20 for char in s:
21 right_T -= int(char == "T") # Decrease T count as we move past
22 if char == "C":
23 answer += left_L * right_T # For each 'C', add possible (L on left) * (T on right)
24 if char == "L":
25 left_L += 1
26 max_value = max(max_value, left_L * right_T) # Track max possible product
27
28 # Consider the best two-letter subsequences and single max_value
29 max_value = max(max_value, calc("LC"), calc("CT"))
30 answer += max_value
31
32 return answer
33
1class Solution {
2 private char[] s; // Character array to store the string
3
4 // Main method to count the number of specific subsequences
5 public long numOfSubsequences(String S) {
6 s = S.toCharArray();
7
8 int countL = 0; // Counts number of 'L's seen so far (to the left)
9 int countT = 0; // Counts number of 'T's remaining (to the right, including current)
10 for (char c : s) {
11 if (c == 'T') {
12 ++countT;
13 }
14 }
15
16 long total = 0; // Final answer
17 long maxVal = 0; // Maximum l * r seen for 'C' position
18
19 // Traverse the string to calculate the number of valid subsequences
20 for (char c : s) {
21 if (c == 'T') {
22 countT--;
23 }
24 if (c == 'C') {
25 // For each 'C', add number of valid subsequences "L...C...T"
26 total += 1L * countL * countT;
27 }
28 if (c == 'L') {
29 countL++;
30 }
31 // Keep track of the maximum l * r for use later
32 maxVal = Math.max(maxVal, 1L * countL * countT);
33 }
34
35 // Also consider the maximum values for "LC" and "CT" subsequences
36 maxVal = Math.max(maxVal, Math.max(calc("LC"), calc("CT")));
37 total += maxVal;
38
39 return total;
40 }
41
42 // Helper method to count subsequences of type "ab" in the string
43 // For each 'b', add the current count of 'a' before it
44 private long calc(String pattern) {
45 long count = 0;
46 int countA = 0;
47 for (char c : s) {
48 if (c == pattern.charAt(1)) {
49 count += countA;
50 }
51 if (c == pattern.charAt(0)) {
52 countA++;
53 }
54 }
55 return count;
56 }
57}
58
1class Solution {
2public:
3 long long numOfSubsequences(string s) {
4 // Helper lambda to count subsequences "ab" in string s
5 auto countSubseq = [&](string ab) {
6 long long count = 0;
7 long long count_a = 0;
8 for (char c : s) {
9 if (c == ab[1]) {
10 // For each 'b', add number of previous 'a's
11 count += count_a;
12 }
13 if (c == ab[0]) {
14 ++count_a;
15 }
16 }
17 return count;
18 };
19
20 long long count_L = 0; // Number of 'L's seen so far
21 long long count_T_remain = count(s.begin(), s.end(), 'T'); // Number of 'T's to the right
22 long long total = 0; // Accumulated answer
23 long long max_any_pattern = 0; // Track the max of possible patterns
24
25 // Pass through the string to count the "L C T" triplet patterns
26 for (char c : s) {
27 if (c == 'T') {
28 --count_T_remain;
29 }
30 if (c == 'C') {
31 total += count_L * count_T_remain; // Count "L C T" for every 'C'
32 }
33 if (c == 'L') {
34 ++count_L;
35 }
36 // Track the max product of current counts for any update
37 max_any_pattern = max(max_any_pattern, count_L * count_T_remain);
38 }
39
40 // Consider the max of the pure pairs "LC" and "CT"
41 max_any_pattern = max(max_any_pattern, countSubseq("LC"));
42 max_any_pattern = max(max_any_pattern, countSubseq("CT"));
43
44 // Add the best possible extra pair to the overall answer
45 total += max_any_pattern;
46 return total;
47 }
48};
49
1/**
2 * Calculates the number of specific subsequences in a string.
3 * @param s Input string consisting of 'L', 'C', 'T'
4 * @returns Number of subsequences as per the logic
5 */
6function numOfSubsequences(s: string): number {
7 /**
8 * Helper function to count the number of subsequences
9 * for a given two-character pattern (first, second) in s.
10 * @param pattern String of length 2 (e.g., 'LC', 'CT')
11 * @returns Count of such subsequences in s
12 */
13 const calc = (pattern: string): number => {
14 let count = 0; // Count of subsequences found
15 let firstCharCount = 0; // Number of times pattern[0] has appeared so far
16
17 for (const c of s) {
18 if (c === pattern[1]) count += firstCharCount; // Every previous pattern[0] forms a subsequence
19 if (c === pattern[0]) firstCharCount++; // Increment count of pattern[0] found
20 }
21 return count;
22 };
23
24 // Initial pass: count number of 'T' for use in next loop
25 let leftL = 0; // Number of 'L's to the left (encountered so far)
26 let rightT = 0; // Number of 'T's to the right (remaining)
27 for (const c of s) {
28 if (c === 'T') rightT++;
29 }
30
31 let answer = 0; // The answer to be returned
32 let maxCombo = 0; // Maximum number of valid subsequences involving 'L'...'C'...'T'
33
34 for (const c of s) {
35 if (c === 'T') rightT--; // Decrement count when passing over 'T'
36 if (c === 'C') answer += leftL * rightT; // For every 'C', all previous 'L's and remaining 'T's form sequences
37 if (c === 'L') leftL++; // Count encountered 'L's for later subsequences
38 maxCombo = Math.max(maxCombo, leftL * rightT); // Track largest L-T pairing after current index
39 }
40
41 // Calculate max subsequences from ('L','C') and ('C','T') pairs for optimal combination
42 maxCombo = Math.max(maxCombo, calc('LC'));
43 maxCombo = Math.max(maxCombo, calc('CT'));
44
45 answer += maxCombo; // Add maximum possible combinations from any single best pattern
46 return answer;
47}
48
49// Example usage (remove/comment when testing in actual LeetCode):
50// console.log(numOfSubsequences("LCTLTTC")); // Example test
51
Time and Space Complexity
The time complexity of the code is O(n)
, where n
is the length of the string s
. This is because the code performs several single-pass traversals over the string: once in the calc
function (called at most twice), and once in the main loop. Each traversal takes linear time.
The space complexity is O(1)
, as only a constant number of integer variables are used to store counts and results, regardless of the input size.
Which of the following uses divide and conquer strategy?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!