Skip to content

Commit 0b0c41e

Browse files
authored
Merge pull request #156 from BrianLusina/feat/algorithms-greedy-largest-palindromic-number
feat(algorithms, greedy): largest palindromic number
2 parents 51f4e7c + 4ea8684 commit 0b0c41e

17 files changed

+167
-8
lines changed

DIRECTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@
141141
* [Test Gas Stations](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/gas_stations/test_gas_stations.py)
142142
* Jump Game
143143
* [Test Jump Game](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/jump_game/test_jump_game.py)
144+
* Largest Palindromic Number
145+
* [Test Largest Palindromic Number](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/largest_palindromic_number/test_largest_palindromic_number.py)
144146
* Majority Element
145147
* [Test Majority Element](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/majority_element/test_majority_element.py)
146148
* Min Arrows

algorithms/dynamic_programming/buy_sell_stock/__init__.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@ def max_profit(prices: List[int]) -> int:
2626
return current_max_profit
2727

2828

29-
def max_profit_two_pointers(prices: List[int]) -> int:
30-
"""
31-
Variation of max_profit using 2 pointers
32-
Complexity Analysis:
33-
Space: O(1), no extra memory is used
34-
Time: O(n), where n is the size of the input list & we iterate through the list only once
35-
"""
3629
def max_profit_two_pointers(prices: List[int]) -> int:
3730
"""
3831
Variation of max_profit using 2 pointers
@@ -46,7 +39,6 @@ def max_profit_two_pointers(prices: List[int]) -> int:
4639
number_of_prices = len(prices)
4740

4841
left, right = 0, 1
49-
return 0
5042

5143
left, right = 0, 1
5244
current_max_profit = 0
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Largest Palindromic Number
2+
3+
You are given a string num consisting of digits from 0 to 9. Your task is to return the largest possible palindromic
4+
number as a string by using some or all of the digits in num.
5+
6+
The resulting palindromic number must not have leading zeros.
7+
8+
> Note: You may reorder the digits freely, and you must use at least one digit from the num string.
9+
10+
## Constraints
11+
12+
- 1 <= `num.length` <= 1000
13+
- `num` consists of digits
14+
15+
## Examples
16+
17+
![Example 1](./images/examples/largest_palindromic_number_example_1.png)
18+
![Example 2](./images/examples/largest_palindromic_number_example_2.png)
19+
![Example 3](./images/examples/largest_palindromic_number_example_3.png)
20+
21+
## Solution
22+
23+
We will use the greedy pattern to solve this problem. The goal is to maximize the size of the palindrome by making
24+
locally optimal choices at each step. Specifically, we aim to form the largest possible palindrome by first prioritizing
25+
using the highest digits.
26+
27+
The process begins by counting the frequency of each digit in the input string and storing it in a hash table. This
28+
allows us to determine how many times each digit appears. Starting with the highest digit, i.e., 9, and working down to
29+
the lowest, i.e., 0, we try to use the possible pairs of each digit to form the first half of the palindrome. This
30+
ensures that the most significant positions in the palindrome are filled with the largest digits. Out of the leftover
31+
single digits, the highest possible digit can be used as the middle digit to further enhance the size of the palindrome.
32+
33+
Finally, the palindrome is completed by appending the reverse of the first half to itself, with the middle digit in
34+
between, if applicable. This greedy strategy works effectively because it ensures that each decision made is the best
35+
possible choice at that moment, leading to an overall optimal solution.
36+
37+
Let’s review the algorithm to reach the solution:
38+
39+
- Initialize the frequency counter occurrences to count the frequency of each digit in the input string num.
40+
- We also initialize the first_half array to note down the first part of the palindrome and the middle string to track
41+
the middle element of the palindrome.
42+
- Traverse digits from 9 to 0 and for each digit do the following:
43+
- Check if its pairs can be made by looking at its frequency. If yes, then add it to the first_half array.
44+
- If applicable, check for the leading zeros and avoid them by explicitly setting their occurrence to 1.
45+
- Otherwise, check if it can be the middle element of the palindrome. Following the greedy approach, ensures that a
46+
larger number is selected to be the middle element among the elements occurring once.
47+
48+
- Once we have processed all the elements of the num array, we join the first_half, middle, and reverse of the first_half.
49+
- Finally, we return this palindromic number, the largest that can be generated using the given number.
50+
51+
![Solution 1](./images/solutions/largest_palindromic_number_solution_1.png)
52+
![Solution 2](./images/solutions/largest_palindromic_number_solution_2.png)
53+
![Solution 3](./images/solutions/largest_palindromic_number_solution_3.png)
54+
![Solution 4](./images/solutions/largest_palindromic_number_solution_4.png)
55+
![Solution 5](./images/solutions/largest_palindromic_number_solution_5.png)
56+
![Solution 6](./images/solutions/largest_palindromic_number_solution_6.png)
57+
![Solution 7](./images/solutions/largest_palindromic_number_solution_7.png)
58+
![Solution 8](./images/solutions/largest_palindromic_number_solution_8.png)
59+
![Solution 9](./images/solutions/largest_palindromic_number_solution_9.png)
60+
61+
### Time Complexity
62+
63+
The time complexity of the solution is O(n), where n is the length of the num string.
64+
65+
### Space Complexity
66+
67+
The space complexity of the solution is O(n). In the worst case, first_half could store up to n/2 digits if all digits
68+
are the same. Therefore, the space for first_half is O(n).
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from collections import Counter
2+
3+
4+
def largest_palindromic_number(num: str) -> str:
5+
# Count the frequency of each digit in the input string
6+
occureneces = Counter(num)
7+
8+
# first half and the middle of the palindrome
9+
first_half = []
10+
middle = ""
11+
12+
for digit in range(9, -1, -1):
13+
digit_char = str(digit)
14+
15+
if digit_char in occureneces:
16+
digit_count = occureneces[digit_char]
17+
18+
# num of pairs of this digit that can be used
19+
num_pairs = digit_count // 2
20+
21+
# If pairs available, add them to the first half
22+
if num_pairs:
23+
# Avoiding leading zeros
24+
if not first_half and not digit:
25+
occureneces["0"] = 1
26+
else:
27+
first_half.append(digit_char * num_pairs)
28+
29+
# Checking for a middle element
30+
if digit_count % 2 and not middle:
31+
middle = digit_char
32+
33+
# If all elements are '0'
34+
if not middle and not first_half:
35+
return "0"
36+
37+
# Returning the full palindrome
38+
return "".join(first_half + [middle] + first_half[::-1])
39+
40+
41+
def largest_palindromic_number_v2(num: str) -> str:
42+
# Count how many times each digit appears
43+
digit_counter = Counter(num)
44+
45+
result = ""
46+
# Find the middle digit by counting down from 9 to 0 while decrementing the count of a digit that appears an odd
47+
# number of times
48+
for digit in range(9, 0, -1):
49+
digit_str = str(digit)
50+
if digit_counter[digit_str] % 2 == 1:
51+
result = digit_str
52+
# decrement the count of this digit
53+
digit_counter[digit_str] -= 1
54+
break
55+
56+
# Build symmetric pairs by iterating from 0 to 9 for each digit with remaining count
57+
for number in range(10):
58+
number_str = str(number)
59+
if digit_counter[number_str] > 0:
60+
# Divide by two to get number of pairs
61+
digit_counter[number_str] //= 2
62+
temp = digit_counter[number_str] * number_str
63+
result = f"{temp}{result}{temp}"
64+
65+
return result.strip("0") or "0"
77.3 KB
Loading
77.4 KB
Loading
89.1 KB
Loading
85.1 KB
Loading
71.2 KB
Loading
86.3 KB
Loading

0 commit comments

Comments
 (0)