204 lines
7.8 KiB
YAML
204 lines
7.8 KiB
YAML
title: Base 7
|
|
slug: base-7
|
|
difficulty: easy
|
|
leetcode_id: 504
|
|
leetcode_url: https://leetcode.com/problems/base-7/
|
|
categories:
|
|
- strings
|
|
- math
|
|
patterns:
|
|
- greedy
|
|
|
|
function_signature: "def convert_to_base7(num: int) -> str:"
|
|
|
|
test_cases:
|
|
visible:
|
|
- input: { num: 100 }
|
|
expected: "202"
|
|
- input: { num: -7 }
|
|
expected: "-10"
|
|
hidden:
|
|
- input: { num: 0 }
|
|
expected: "0"
|
|
- input: { num: 7 }
|
|
expected: "10"
|
|
- input: { num: 1 }
|
|
expected: "1"
|
|
- input: { num: -1 }
|
|
expected: "-1"
|
|
- input: { num: 49 }
|
|
expected: "100"
|
|
- input: { num: -100 }
|
|
expected: "-202"
|
|
|
|
description: |
|
|
Given an integer `num`, return *a string of its **base 7** representation*.
|
|
|
|
constraints: |
|
|
- `-10^7 <= num <= 10^7`
|
|
|
|
examples:
|
|
- input: "num = 100"
|
|
output: "202"
|
|
explanation: "100 in base 10 equals 2*49 + 0*7 + 2*1 = 202 in base 7."
|
|
- input: "num = -7"
|
|
output: "-10"
|
|
explanation: "-7 in base 10 equals -1*7 + 0*1 = -10 in base 7."
|
|
|
|
explanation:
|
|
intuition: |
|
|
Think of how we normally write numbers in base 10. The number 345 means 3 hundreds + 4 tens + 5 ones, or `3*10^2 + 4*10^1 + 5*10^0`. Each digit represents how many of that power of 10 we have.
|
|
|
|
Converting to base 7 works the same way, but with powers of 7 instead. We need to figure out how many 49s (7^2), how many 7s (7^1), and how many 1s (7^0) make up our number.
|
|
|
|
The key insight is that **repeatedly dividing by 7 and collecting remainders** gives us the digits from right to left. When you divide a number by 7:
|
|
- The **remainder** tells you the rightmost digit (the "ones" place in base 7)
|
|
- The **quotient** represents what's left to convert for the higher digits
|
|
|
|
For example, with `num = 100`:
|
|
- `100 % 7 = 2` (rightmost digit), `100 // 7 = 14` (continue with this)
|
|
- `14 % 7 = 0` (middle digit), `14 // 7 = 2` (continue with this)
|
|
- `2 % 7 = 2` (leftmost digit), `2 // 7 = 0` (done!)
|
|
- Reading remainders in reverse: **202**
|
|
|
|
approach: |
|
|
We solve this using **Repeated Division**:
|
|
|
|
**Step 1: Handle the special case**
|
|
|
|
- If `num` is `0`, return `"0"` immediately
|
|
- This avoids an empty result from the main loop
|
|
|
|
|
|
|
|
**Step 2: Handle the sign**
|
|
|
|
- If `num` is negative, remember this fact and work with the absolute value
|
|
- We'll prepend the minus sign at the end
|
|
|
|
|
|
|
|
**Step 3: Repeatedly divide by 7**
|
|
|
|
- While `num > 0`:
|
|
- Calculate `num % 7` to get the current digit
|
|
- Prepend this digit to your result (or append and reverse later)
|
|
- Update `num = num // 7` to move to the next higher digit
|
|
|
|
|
|
|
|
**Step 4: Add the sign and return**
|
|
|
|
- If the original number was negative, prepend `"-"` to the result
|
|
- Return the final string
|
|
|
|
common_pitfalls:
|
|
- title: Forgetting the Zero Case
|
|
description: |
|
|
If `num = 0`, the while loop `while num > 0` never executes, leaving you with an empty string.
|
|
|
|
You must handle `num = 0` as a special case and return `"0"` directly.
|
|
wrong_approach: "Relying on the loop to handle zero"
|
|
correct_approach: "Check for zero before entering the loop"
|
|
|
|
- title: Incorrect Sign Handling
|
|
description: |
|
|
In Python, the modulo operator with negative numbers can give unexpected results. For example, `-7 % 7 = 0` in Python, but the division `-7 // 7 = -1` (floor division).
|
|
|
|
To avoid confusion, convert to absolute value first, then add the minus sign at the end.
|
|
wrong_approach: "Performing modulo on negative numbers directly"
|
|
correct_approach: "Use abs(num) and track the sign separately"
|
|
|
|
- title: Building the String in Wrong Order
|
|
description: |
|
|
The digits come out in reverse order (least significant first). If you append each digit, you'll need to reverse at the end.
|
|
|
|
Alternatively, prepend each digit to build the string in the correct order from the start.
|
|
wrong_approach: "Appending digits without reversing"
|
|
correct_approach: "Either prepend digits or reverse at the end"
|
|
|
|
key_takeaways:
|
|
- "**Base conversion pattern**: Repeated division by the target base, collecting remainders, gives digits from least to most significant"
|
|
- "**Sign handling**: Work with absolute values and track sign separately to avoid edge cases with negative modulo operations"
|
|
- "**Generalises to any base**: This same algorithm works for converting to binary, octal, hex, or any base — just change the divisor"
|
|
- "**Foundation for encoding problems**: Understanding base conversion helps with problems involving bit manipulation, encoding schemes, and number representations"
|
|
|
|
time_complexity: "O(log_7(n)). Each division reduces the number by a factor of 7, so we perform approximately log base 7 of n iterations."
|
|
space_complexity: "O(log_7(n)). The output string has one character per digit, which is proportional to log base 7 of n."
|
|
|
|
solutions:
|
|
- approach_name: Repeated Division
|
|
is_optimal: true
|
|
code: |
|
|
def convert_to_base7(num: int) -> str:
|
|
# Special case: zero is just "0"
|
|
if num == 0:
|
|
return "0"
|
|
|
|
# Track if negative, then work with absolute value
|
|
negative = num < 0
|
|
num = abs(num)
|
|
|
|
digits = []
|
|
while num > 0:
|
|
# Get the rightmost digit in base 7
|
|
digits.append(str(num % 7))
|
|
# Move to the next higher digit
|
|
num //= 7
|
|
|
|
# Digits are collected in reverse order, so reverse them
|
|
result = ''.join(reversed(digits))
|
|
|
|
# Add minus sign if original was negative
|
|
return '-' + result if negative else result
|
|
explanation: |
|
|
**Time Complexity:** O(log_7(n)) — We divide by 7 until the number becomes 0.
|
|
|
|
**Space Complexity:** O(log_7(n)) — The result string contains one digit per division.
|
|
|
|
We repeatedly extract the least significant digit using modulo 7, then shift right by dividing by 7. The digits come out in reverse order, so we reverse at the end.
|
|
|
|
- approach_name: Recursion
|
|
is_optimal: false
|
|
code: |
|
|
def convert_to_base7(num: int) -> str:
|
|
# Base case: single digit
|
|
if num >= 0 and num < 7:
|
|
return str(num)
|
|
# Handle negatives
|
|
if num < 0:
|
|
return '-' + convert_to_base7(-num)
|
|
|
|
# Recursive case: higher digits + current digit
|
|
return convert_to_base7(num // 7) + str(num % 7)
|
|
explanation: |
|
|
**Time Complexity:** O(log_7(n)) — Same number of operations as iterative.
|
|
|
|
**Space Complexity:** O(log_7(n)) — Call stack depth plus string concatenation.
|
|
|
|
The recursive approach naturally builds digits from most significant to least significant. The base case handles single digits (0-6), and the recursive case processes the quotient first before appending the current remainder. While elegant, this uses additional stack space.
|
|
|
|
- approach_name: Built-in (Python-specific)
|
|
is_optimal: false
|
|
code: |
|
|
def convert_to_base7(num: int) -> str:
|
|
# Handle negative numbers
|
|
if num < 0:
|
|
return '-' + convert_to_base7(-num)
|
|
# Handle zero
|
|
if num == 0:
|
|
return "0"
|
|
|
|
# Use divmod for cleaner extraction
|
|
result = []
|
|
while num:
|
|
num, remainder = divmod(num, 7)
|
|
result.append(str(remainder))
|
|
return ''.join(reversed(result))
|
|
explanation: |
|
|
**Time Complexity:** O(log_7(n)) — Same as other approaches.
|
|
|
|
**Space Complexity:** O(log_7(n)) — Same as other approaches.
|
|
|
|
This version uses Python's `divmod()` function which returns both quotient and remainder in one operation. While not fundamentally different, it's a cleaner idiom that some interviewers appreciate. Note that Python has no built-in for arbitrary base conversion, so the algorithm remains the same.
|