Count Asterisks
EasyPrompt
You are given a string s, where every two consecutive vertical bars '|' are grouped into a pair. In other words, the 1st and 2nd '|' make a pair, the 3rd and 4th '|' make a pair, and so forth.
Return the number of '*' in s, excluding the '*' between each pair of '|'.
Note that each '|' will belong to exactly one pair.
Example 1:
Input: s = "l|*e*et|c**o|*de|"
Output: 2
Explanation: The considered characters are underlined: "l|*e*et|c**o|*de|".
The characters between the first and second '|' are excluded from the answer.
Also, the characters between the third and fourth '|' are excluded from the answer.
There are 2 asterisks considered. Therefore, we return 2.Example 2:
Input: s = "iamprogrammer"
Output: 0
Explanation: In this example, there are no asterisks in s. Therefore, we return 0.Example 3:
Input: s = "yo|uar|e**|b|e***au|tifu|l"
Output: 5
Explanation: The considered characters are underlined: "yo|uar|e**|b|e***au|tifu|l". There are 5 asterisks considered. Therefore, we return 5.
Constraints:
1 <= s.length <= 1000sconsists of lowercase English letters, vertical bars'|', and asterisks'*'.scontains an even number of vertical bars'|'.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach involves splitting the input string s using the vertical bar | as a delimiter. This operation creates an array of substrings. The problem states that asterisks between pairs of | should be excluded. When we split the string by |, the substrings at even indices (0, 2, 4, ...) correspond to the parts of the original string that are outside the pairs of vertical bars. The substrings at odd indices (1, 3, 5, ...) are the parts inside the pairs.
Algorithm
- Split the input string
sby the delimiter|into an array of strings,parts.\n* Initialize a counterasteriskCountto 0.\n* Loop through thepartsarray, considering only the elements at even indices (0, 2, 4, ...).\n* For each element at an even index, count the number of asterisks it contains and add it toasteriskCount.\n* Return the finalasteriskCount.
Walkthrough
This approach works by first segmenting the string by the | character. This naturally separates the sections inside pairs from those outside. We then only need to process the segments that were originally outside the pairs. The process is as follows:\n\n1. The input string s is split by the delimiter | into an array of strings, let's call it parts.\n2. A counter asteriskCount is initialized to 0.\n3. We loop through the parts array, but only visit the elements at even indices (0, 2, 4, ...), as these correspond to the sections outside the | pairs.\n4. For each of these even-indexed parts, we iterate through its characters.\n5. If a character is an asterisk (*), we increment asteriskCount.\n6. Finally, asteriskCount holds the total count and is returned.\n\nFor example, s = \"l|*e*et|c**o|*de|\" becomes [\"l\", \"*e*et\", \"c**o\", \"*de\", \"\"]. We count asterisks in parts[0] ("l"), parts[2] ("c**o"), and parts[4] (""), yielding a total of 2.\n\njava\nclass Solution {\n public int countAsterisks(String s) {\n String[] parts = s.split("\\|");\n int count = 0;\n // Iterate over the parts that are outside the vertical bars\n for (int i = 0; i < parts.length; i += 2) {\n for (char c : parts[i].toCharArray()) {\n if (c == '*') {\n count++;\n }\n }\n }\n return count;\n }\n}\n
Complexity
Time
O(N), where N is the length of the string. The `split` operation takes O(N) time. The subsequent loops iterate through the characters of the even-indexed parts, which in total is at most N characters. Thus, the total time complexity is O(N).
Space
O(N). The `split` method creates a new array of strings. The total space required to store these substrings is proportional to the original string's length N.
Trade-offs
Pros
Conceptually simple and easy to understand.
Leverages built-in string manipulation functions, leading to concise code.
Cons
Higher space complexity (O(N)) compared to a single-pass approach.
Can be less performant due to the overhead of creating an array and multiple string objects.
This is the most efficient approach, solving the problem in a single pass through the string. It avoids creating any intermediate data structures by simply keeping track of whether the current character being processed is inside or outside a pair of vertical bars. A state variable, such as a counter for | characters or a boolean flag, is used for this purpose.
Algorithm
- Initialize two integer variables:
asteriskCount = 0andpipeCount = 0.\n* Iterate through each charactercof the strings.\n* Ifcis'|', incrementpipeCount.\n* Ifcis'*', check ifpipeCountis even. If it is, incrementasteriskCount.\n* After the loop finishes, returnasteriskCount.
Walkthrough
This optimal solution involves a single traversal of the string. We maintain a state to determine if we are currently inside or outside a pair of vertical bars. This state can be tracked using a simple counter for the | characters encountered.\n\nThe algorithm proceeds as follows:\n\n1. Initialize an asteriskCount to 0 and a pipeCount to 0.\n2. Iterate through each character c of the string from left to right.\n3. If the character c is a |, we've crossed a boundary, so we increment pipeCount.\n4. If the character c is an *, we must decide whether to count it. We check the parity of pipeCount. If pipeCount is even (0, 2, 4, ...), it means we are currently outside a pair, so we increment asteriskCount.\n5. If pipeCount is odd, we are inside a pair, and we do nothing.\n6. After the loop completes, asteriskCount will contain the desired total.\n\nThis method is efficient because it processes each character once without needing to store parts of the string.\n\njava\nclass Solution {\n public int countAsterisks(String s) {\n int asteriskCount = 0;\n int pipeCount = 0;\n for (int i = 0; i < s.length(); i++) {\n char c = s.charAt(i);\n if (c == '|') {\n pipeCount++;\n } else if (c == '*') {\n // If pipeCount is even, we are outside a pair.\n if (pipeCount % 2 == 0) {\n asteriskCount++;\n }\n }\n }\n return asteriskCount;\n }\n}\n
Complexity
Time
O(N), where N is the length of the string. We perform a single pass over the string.
Space
O(1). We only use a constant amount of extra space for a few counter variables, regardless of the input size.
Trade-offs
Pros
Optimal time complexity of O(N).
Optimal space complexity of O(1).
Highly efficient as it avoids the overhead of creating new data structures.
Cons
While simple for this problem, state management can become complex in more intricate problems.
Solutions
Solution
public class Solution { public int CountAsterisks(string s) { int ans = 0, ok = 1; foreach(char c in s) { if (c == '*') { ans += ok; } else if (c == '|') { ok ^= 1; } } return ans; }}class Solution {public int countAsterisks(String s) { int ans = 0; for (int i = 0, ok = 1; i < s.length(); ++i) { char c = s.charAt(i); if (c == '*') { ans += ok; } else if (c == '|') { ok ^= 1; } } return ans; }}class Solution {public: int countAsterisks(string s) { int ans = 0, ok = 1; for (char &c : s) { if (c == '*') { ans += ok; } else if (c == '|') { ok ^= 1; } } return ans; }};class Solution: def countAsterisks(self, s: str) -> int: ans, ok = 0, 1 for c in s: if c == "*": ans += ok elif c == "|": ok ^= 1 return ansVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.