Skip to content

Commit c061165

Browse files
authored
Merge pull request #153 from BrianLusina/feat/algorithms-dynamic-programming
feat(algorithms, dynamic-programming): counting bits
2 parents e6eb579 + 26343df commit c061165

28 files changed

+470
-2
lines changed

DIRECTORY.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
* [Test Max Profit Three](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/buy_sell_stock/test_max_profit_three.py)
5656
* [Test Max Profit Two](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/buy_sell_stock/test_max_profit_two.py)
5757
* [Test Max Profit With Fee](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/buy_sell_stock/test_max_profit_with_fee.py)
58+
* Climb Stairs
59+
* [Test Climb Stairs](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/climb_stairs/test_climb_stairs.py)
60+
* Countingbits
61+
* [Test Counting Bits](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/countingbits/test_counting_bits.py)
5862
* Domino Tromino Tiling
5963
* [Test Domino Tromino Tiling](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/domino_tromino_tiling/test_domino_tromino_tiling.py)
6064
* Duffle Bug Value
@@ -69,6 +73,8 @@
6973
* [Test Min Distance](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/min_distance/test_min_distance.py)
7074
* Min Path Sum
7175
* [Test Min Path Sum](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/min_path_sum/test_min_path_sum.py)
76+
* Painthouse
77+
* [Test Min Cost To Paint Houses](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/painthouse/test_min_cost_to_paint_houses.py)
7278
* Palindromic Substring
7379
* [Longest Palindromic Substring](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/palindromic_substring/longest_palindromic_substring.py)
7480
* [Test Longest Palindromic Substring](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/palindromic_substring/test_longest_palindromic_substring.py)
@@ -138,12 +144,16 @@
138144
* Spread Stones
139145
* [Test Minimum Moves To Spread Stones](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/spread_stones/test_minimum_moves_to_spread_stones.py)
140146
* Heap
147+
* Kclosestelements
148+
* [Test Find K Closest Elements](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/heap/kclosestelements/test_find_k_closest_elements.py)
141149
* Longest Happy String
142150
* [Test Longest Happy String](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/heap/longest_happy_string/test_longest_happy_string.py)
143151
* Maximal Score After K Operations
144152
* [Test Maximal Score](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/heap/maximal_score_after_k_operations/test_maximal_score.py)
145153
* Maximum Subsequence Score
146154
* [Test Max Subsequence Score](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/heap/maximum_subsequence_score/test_max_subsequence_score.py)
155+
* Mergeksortedlists
156+
* [Test Merge K Sorted Lists](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/heap/mergeksortedlists/test_merge_k_sorted_lists.py)
147157
* Min Cost Hire K Workers
148158
* [Test Min Cost To Hire Workers](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/heap/min_cost_hire_k_workers/test_min_cost_to_hire_workers.py)
149159
* Min Cost To Connect Sticks
@@ -676,8 +686,6 @@
676686
* [Battleship](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/battleship/battleship.py)
677687
* Beeramid
678688
* [Test Bearamid](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/beeramid/test_bearamid.py)
679-
* Climb Stairs
680-
* [Test Climb Stairs](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/climb_stairs/test_climb_stairs.py)
681689
* Find Missing Elem
682690
* [Test Find Missing Elem](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/find_missing_elem/test_find_missing_elem.py)
683691
* Hashmap

puzzles/climb_stairs/README.md renamed to algorithms/dynamic_programming/climb_stairs/README.md

File renamed without changes.

puzzles/climb_stairs/__init__.py renamed to algorithms/dynamic_programming/climb_stairs/__init__.py

File renamed without changes.

puzzles/climb_stairs/test_climb_stairs.py renamed to algorithms/dynamic_programming/climb_stairs/test_climb_stairs.py

File renamed without changes.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Counting Bits
2+
3+
Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1's
4+
in the binary representation of i.
5+
6+
## Examples
7+
8+
```text
9+
Example 1:
10+
11+
Input: n = 2
12+
Output: [0,1,1]
13+
Explanation:
14+
0 --> 0
15+
1 --> 1
16+
2 --> 10
17+
```
18+
19+
```
20+
Example 2:
21+
22+
Input: n = 5
23+
Output: [0,1,1,2,1,2]
24+
Explanation:
25+
0 --> 0
26+
1 --> 1
27+
2 --> 10
28+
3 --> 11
29+
4 --> 100
30+
5 --> 101
31+
```
32+
33+
## Constraints
34+
35+
- 0 <= `n` <= 10^5
36+
37+
## Solution
38+
39+
This solution uses a bottom-up dynamic programming approach to solve the problem.
40+
The key to this problem lies in the fact that any binary number can be broken down into two parts: the least-significant
41+
(rightmost bit), and the rest of the bits. The rest of the bits can be expressed as the binary number divided by 2
42+
(rounded down), or `i >> 1`.
43+
44+
For example:
45+
- 4 in binary = 100
46+
- rightmost bit = 0
47+
- rest of bits = 10, which is also (4 // 2) = 2 in binary.
48+
49+
When the number is odd,
50+
- 5 in binary = 101
51+
- rightmost bit = 1
52+
- rest of bits = 10, which is also (5 // 2) = 2 in binary.
53+
54+
in the binary representation of i is that number plus 1 if the rightmost bit is 1. We can tell if the last significant
55+
bit is 1 by checking if it is odd.
56+
57+
As an example, we know that the number of 1's in 2 is 1. This information can be used to calculate the number of 1's in 4.
58+
The number of 1's in 4 is the number of 1's in 2 plus 0, because 4 is even.
59+
60+
This establishes a recurrence relationship between the number of 1's in the binary representation of i and the number of
61+
1's in the binary representation of i // 2: if count[i] is the number of 1's in the binary representation of i, then
62+
count[i] = count[i // 2] + (i % 2).
63+
64+
With the recurrence relationship established, we can now solve the problem using a bottom-up dynamic programming approach.
65+
We start with the base case dp[0] = 0, and then build up the solution for dp[i] for i from 1 to n.
66+
67+
![Solution 1](./images/solutions/counting_bits_solution_1.png)
68+
![Solution 2](./images/solutions/counting_bits_solution_2.png)
69+
![Solution 3](./images/solutions/counting_bits_solution_3.png)
70+
![Solution 4](./images/solutions/counting_bits_solution_4.png)
71+
![Solution 5](./images/solutions/counting_bits_solution_5.png)
72+
![Solution 6](./images/solutions/counting_bits_solution_6.png)
73+
![Solution 7](./images/solutions/counting_bits_solution_7.png)
74+
![Solution 8](./images/solutions/counting_bits_solution_8.png)
75+
![Solution 9](./images/solutions/counting_bits_solution_9.png)
76+
![Solution 10](./images/solutions/counting_bits_solution_10.png)
77+
![Solution 11](./images/solutions/counting_bits_solution_11.png)
78+
![Solution 12](./images/solutions/counting_bits_solution_12.png)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from typing import List
2+
3+
4+
def count_bits(n: int) -> List[int]:
5+
"""
6+
Counts the number of 1 bits in the given integer provided returning a list where count[i] stores the count of '1'
7+
bits in the binary form of i.
8+
Args:
9+
n(int): integer
10+
Returns:
11+
list: count of 1 bits where each index contains the count of 1 bits
12+
"""
13+
dp = [0] * (n + 1)
14+
15+
for i in range(1, n + 1):
16+
# this can also be solved as which is faster in Python
17+
# dp[i] = dp[i >> 1] + (i & 1)
18+
dp[i] = dp[i // 2] + (i % 2)
19+
20+
return dp
36.1 KB
Loading
40 KB
Loading
52.2 KB
Loading
33.1 KB
Loading

0 commit comments

Comments
 (0)