|
| 1 | +# [Problem 1550: Three Consecutive Odds](https://leetcode.com/problems/three-consecutive-odds/description/) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | + |
| 5 | +- seems like a pretty easy one |
| 6 | +- need to track the number of consecutive odds |
| 7 | + - if counter ever reaches 3, return True |
| 8 | + - if we encounter an even number, reset counter to 0 |
| 9 | + |
| 10 | +## Refining the problem |
| 11 | + |
| 12 | +- I bet this will ultimately be slower, but I can think of a kinda fun, roundabout way solve this: |
| 13 | + - convert `arr` to a string |
| 14 | + - use regular expression to search for 3 consecutive occurrences of values that end in 1, 3, 5, 7, or 9, separated by a command and space |
| 15 | + - we know that all values are <= 1000, and 1000 is an even number, so all odd numbers will have 1, 2, or 3 digits -- so for each number we need to match 0, 1, or 2 digits of any value, followed by an odd digit: `[0-9]{0,2}[13579]` |
| 16 | + - base pattern would be `(?:[0-9]{0,2}[13579], ){3}` but: |
| 17 | + - this would fail for the last 3 values in the list because there's no trailing comma. So instead use `(?:[0-9]{0,2}[13579], ){2}[0-9]{0,2}[13579]` |
| 18 | + - Also for the first of the 3 odd numbers, we should only try to match the final digit rather than all digits, otherwise the search will be slower because the pattern will initially match all values in the list and waste a bunch of time backtracking. So instead use `[13579], [0-9]{0,2}[13579], [0-9]{0,2}[13579]` or `[13579](?:, [0-9]{0,2}[13579]){2}` |
| 19 | + |
| 20 | + - `re.search` returns a `Match` object as soon as it encounters the first match, and `None` if no match is found. So we should be able to just `bool()` the result and return it. |
| 21 | + - I wonder if compiling the pattern upfront would be faster than using using the module-level functions... depends on how leetcode runs the test cases, I guess. If I compile the expression in the class body outside the method definition, and all test case runs reuse the same instance of the class, then it should save time. Otherwise, it probably wouldn't. Maybe I'll just compile it in the global namespace and see. |
| 22 | + |
| 23 | +## Attempted solution(s) |
| 24 | + |
| 25 | +```python |
| 26 | +class Solution: |
| 27 | + def threeConsecutiveOdds(self, arr: List[int]) -> bool: |
| 28 | + if len(arr) < 3: |
| 29 | + return False |
| 30 | + |
| 31 | + consec_odds = 0 |
| 32 | + for val in arr: |
| 33 | + if val % 2: |
| 34 | + if consec_odds == 2: |
| 35 | + return True |
| 36 | + consec_odds += 1 |
| 37 | + else: |
| 38 | + consec_odds = 0 |
| 39 | + return False |
| 40 | +``` |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | +```python |
| 45 | +from re import compile |
| 46 | + |
| 47 | +pattern = compile(r"[13579](?:, [0-9]{0,2}[13579]){2}") |
| 48 | + |
| 49 | +class Solution: |
| 50 | + def threeConsecutiveOdds(self, arr: List[int]) -> bool: |
| 51 | + return bool(pattern.search(str(arr))) |
| 52 | +``` |
| 53 | + |
| 54 | + |
0 commit comments