questions A (01-matrix - avoid-flood)
This commit is contained in:
151
backend/data/questions/a-number-after-a-double-reversal.yaml
Normal file
151
backend/data/questions/a-number-after-a-double-reversal.yaml
Normal file
@@ -0,0 +1,151 @@
|
||||
title: A Number After a Double Reversal
|
||||
slug: a-number-after-a-double-reversal
|
||||
difficulty: easy
|
||||
leetcode_id: 2119
|
||||
leetcode_url: https://leetcode.com/problems/a-number-after-a-double-reversal/
|
||||
categories:
|
||||
- math
|
||||
patterns:
|
||||
- greedy
|
||||
|
||||
description: |
|
||||
**Reversing** an integer means to reverse all its digits.
|
||||
|
||||
- For example, reversing `2021` gives `1202`. Reversing `12300` gives `321` as the **leading zeros are not retained**.
|
||||
|
||||
Given an integer `num`, **reverse** `num` to get `reversed1`, then **reverse** `reversed1` to get `reversed2`. Return `true` *if* `reversed2` *equals* `num`. Otherwise return `false`.
|
||||
|
||||
constraints: |
|
||||
- `0 <= num <= 10^6`
|
||||
|
||||
examples:
|
||||
- input: "num = 526"
|
||||
output: "true"
|
||||
explanation: "Reverse num to get 625, then reverse 625 to get 526, which equals num."
|
||||
- input: "num = 1800"
|
||||
output: "false"
|
||||
explanation: "Reverse num to get 81, then reverse 81 to get 18, which does not equal num."
|
||||
- input: "num = 0"
|
||||
output: "true"
|
||||
explanation: "Reverse num to get 0, then reverse 0 to get 0, which equals num."
|
||||
|
||||
explanation:
|
||||
intuition: |
|
||||
At first glance, this problem seems to require implementing a digit reversal function and applying it twice. But let's think deeper about what actually happens during reversal.
|
||||
|
||||
The key insight is understanding **when information is lost**. When you reverse a number, the only way you lose information is if the original number has **trailing zeros**. These trailing zeros become leading zeros after the first reversal, and leading zeros are dropped (since `0123` is just `123`).
|
||||
|
||||
Think of it like this: imagine writing a number on a piece of paper and flipping it horizontally. If the number ends in zeros, those zeros move to the front — and we don't write leading zeros! So `1800` becomes `0081` which we write as `81`. Flipping again gives `18`, not `1800`.
|
||||
|
||||
The only exception is zero itself (`0`), which remains `0` no matter how many times you reverse it.
|
||||
|
||||
So the question reduces to: **does `num` have trailing zeros?** If yes (and it's not zero), the double reversal won't recover the original. If no, it will.
|
||||
|
||||
approach: |
|
||||
We solve this with a **simple mathematical observation**:
|
||||
|
||||
**Step 1: Handle the special case**
|
||||
|
||||
- If `num` is `0`, return `true` immediately
|
||||
- Zero reversed is zero, so double reversal preserves it
|
||||
|
||||
|
||||
|
||||
**Step 2: Check for trailing zeros**
|
||||
|
||||
- A number has trailing zeros if and only if it is divisible by 10
|
||||
- Check: `num % 10 == 0`
|
||||
- If true, the number has trailing zeros and will lose them on reversal
|
||||
|
||||
|
||||
|
||||
**Step 3: Return the result**
|
||||
|
||||
- Return `true` if `num` has no trailing zeros (or is zero)
|
||||
- Return `false` if `num` has trailing zeros
|
||||
|
||||
|
||||
|
||||
This can be simplified to a single expression: `num == 0 or num % 10 != 0`.
|
||||
|
||||
common_pitfalls:
|
||||
- title: Actually Implementing Reversal
|
||||
description: |
|
||||
A common first instinct is to implement a digit-reversal function and apply it twice. While this works, it's unnecessarily complex:
|
||||
|
||||
```python
|
||||
def reverse(n):
|
||||
result = 0
|
||||
while n > 0:
|
||||
result = result * 10 + n % 10
|
||||
n //= 10
|
||||
return result
|
||||
```
|
||||
|
||||
This is O(log n) time and requires careful handling. The mathematical insight reduces this to O(1).
|
||||
wrong_approach: "Implement reverse function and call twice"
|
||||
correct_approach: "Check if number has trailing zeros"
|
||||
|
||||
- title: Forgetting Zero is a Special Case
|
||||
description: |
|
||||
Zero ends in zero (`0 % 10 == 0`), but zero reversed is still zero. If you only check for trailing zeros without handling this case, you'll incorrectly return `false` for `num = 0`.
|
||||
|
||||
The condition `num == 0 or num % 10 != 0` handles this elegantly.
|
||||
wrong_approach: "Only check num % 10 != 0"
|
||||
correct_approach: "Check num == 0 OR num % 10 != 0"
|
||||
|
||||
- title: Confusing Trailing vs Leading Zeros
|
||||
description: |
|
||||
Leading zeros don't affect a number's value (`007` is just `7`), so they're not the issue. **Trailing zeros** are what get lost because they become leading zeros after reversal.
|
||||
|
||||
For example: `120` → reverse → `021` = `21` → reverse → `12` ≠ `120`.
|
||||
|
||||
key_takeaways:
|
||||
- "**Look for the invariant**: Instead of simulating the operation, ask 'when does this operation lose information?'"
|
||||
- "**Trailing zeros are the only information loss**: Reversing a number only loses data when trailing zeros become leading zeros"
|
||||
- "**Mathematical insight beats simulation**: Recognising the pattern gives O(1) instead of O(log n)"
|
||||
- "**Edge cases matter**: Zero is a special case that satisfies `num % 10 == 0` but should return `true`"
|
||||
|
||||
time_complexity: "O(1). We perform a single modulo operation and comparison."
|
||||
space_complexity: "O(1). We use no additional space beyond the input."
|
||||
|
||||
solutions:
|
||||
- approach_name: Mathematical Insight
|
||||
is_optimal: true
|
||||
code: |
|
||||
def is_same_after_reversals(num: int) -> bool:
|
||||
# Zero is a special case - reversing 0 gives 0
|
||||
# Otherwise, check if number has trailing zeros
|
||||
# Trailing zeros become leading zeros after first reversal
|
||||
# and are lost, making double reversal different from original
|
||||
return num == 0 or num % 10 != 0
|
||||
explanation: |
|
||||
**Time Complexity:** O(1) — Single modulo operation.
|
||||
|
||||
**Space Complexity:** O(1) — No additional space used.
|
||||
|
||||
We recognise that the only way a double reversal changes a number is if it has trailing zeros (which become leading zeros and get dropped). Zero itself is the exception since `0` reversed is `0`.
|
||||
|
||||
- approach_name: Simulation
|
||||
is_optimal: false
|
||||
code: |
|
||||
def is_same_after_reversals(num: int) -> bool:
|
||||
def reverse(n: int) -> int:
|
||||
"""Reverse the digits of a non-negative integer."""
|
||||
result = 0
|
||||
while n > 0:
|
||||
# Extract last digit and append to result
|
||||
result = result * 10 + n % 10
|
||||
n //= 10
|
||||
return result
|
||||
|
||||
# Apply reversal twice and compare
|
||||
reversed1 = reverse(num)
|
||||
reversed2 = reverse(reversed1)
|
||||
return reversed2 == num
|
||||
explanation: |
|
||||
**Time Complexity:** O(log n) — Each reversal iterates through all digits.
|
||||
|
||||
**Space Complexity:** O(1) — Only integer variables used.
|
||||
|
||||
This approach directly simulates the problem statement. While correct, it's more complex than necessary. Understanding why the mathematical approach works is more valuable for interviews.
|
||||
Reference in New Issue
Block a user