Skip to content

Commit 513b6c6

Browse files
Merge branch 'master' into feature/search-insert-position
2 parents 04c43fa + 5dd7da3 commit 513b6c6

File tree

11 files changed

+661
-0
lines changed

11 files changed

+661
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# 169. Majority Element
2+
3+
**Difficulty:** *Easy*
4+
**Category:** *Arrays, Hash Table, Divide and Conquer*
5+
**Leetcode Link:** [Problem Link](https://leetcode.com/problems/majority-element/)
6+
7+
---
8+
9+
## 📝 Introduction
10+
11+
*Given an array nums of size n, return the majority element — the element that appears more than ⌊n / 2⌋ times.*
12+
13+
*Constraints typically include:<br>
14+
- It is guaranteed that the majority element always exists in the array.*
15+
16+
---
17+
18+
## 💡 Approach & Key Insights
19+
20+
*The problem centers on identifying an element that occurs more than n/2 times. Three approaches are commonly used:<br>
21+
- Brute-force with nested loops.<br>
22+
- Better approach using hash map frequency counting.<br>
23+
- Optimal approach using Moore’s Voting Algorithm for O(n) time and O(1) space.*
24+
25+
---
26+
27+
## 🛠️ Breakdown of Approaches
28+
29+
### 1️⃣ Brute Force / Naive Approach
30+
31+
- **Explanation:** *For each element, count its frequency using a nested loop. If any element occurs more than ⌊n/2⌋ times, return it.*
32+
- **Time Complexity:** O(n²) – due to nested iterations.
33+
- **Space Complexity:** O(1)
34+
- **Example/Dry Run:**
35+
36+
```plaintext
37+
Input: [3, 2, 3]
38+
Step 1: Check 3 → appears 2 times → not > 1.5
39+
Step 2: Check 2 → appears 1 time → not > 1.5
40+
Return 3
41+
```
42+
43+
---
44+
45+
### 2️⃣ Better Approach
46+
47+
- **Explanation:** *Use a hash map to store frequencies of each number. As you update counts, if any value exceeds ⌊n/2⌋, return it.*
48+
- **Time Complexity:** O(n) – single pass to count.
49+
- **Space Complexity:** O(n) – for storing frequencies.
50+
- **Example/Dry Run:**
51+
52+
```plaintext
53+
Input: [2, 2, 1, 1, 1, 2, 2]
54+
Count Map:
55+
{2: 1}
56+
{2: 2}
57+
{2: 2, 1: 1}
58+
...
59+
{2: 4, 1: 3}
60+
Check: 4 > floor(7/2) = 3 → return 2
61+
```
62+
63+
---
64+
65+
### 3️⃣ Optimal Approach
66+
67+
- **Explanation:** *Use Moore’s Voting Algorithm. Keep a count and a candidate. If count is zero, pick a new candidate. If current number equals candidate, increment count. Else decrement. At the end, the candidate is the majority element.*
68+
- **Time Complexity:** O(n) – single pass.
69+
- **Space Complexity:** O(1) – constant space.
70+
- **Example/Dry Run:**
71+
72+
```plaintext
73+
Input: [2, 2, 1, 1, 1, 2, 2]
74+
Step-by-step:
75+
candidate = 2, count = 1
76+
2 == 2 → count = 2
77+
1 != 2 → count = 1
78+
1 != 2 → count = 0 → candidate = 1, count = 1
79+
1 == 1 → count = 2
80+
2 != 1 → count = 1
81+
2 != 1 → count = 0 → candidate = 2, count = 1
82+
Final candidate = 2 → return 2
83+
```
84+
85+
---
86+
87+
## 📊 Complexity Analysis
88+
89+
| Approach | Time Complexity | Space Complexity |
90+
| -------------------- | --------------- | ---------------- |
91+
| Brute Force | O(n²) | O(1) |
92+
| Hash Map Counting | O(n) | O(n) |
93+
| Moore’s Voting Algo | O(n) | O(1) |
94+
95+
---
96+
97+
## 📉 Optimization Ideas
98+
99+
*The Moore’s Voting Algorithm is already optimal, with a single pass and constant space. If the array does not guarantee a majority element, a second pass is needed to verify the candidate.*
100+
101+
---
102+
103+
## 📌 Example Walkthroughs & Dry Runs
104+
105+
```plaintext
106+
Example: [3, 3, 4, 2, 4, 4, 2, 4, 4]
107+
Step-by-step:
108+
candidate = 3, count = 1
109+
3 == 3 → count = 2
110+
4 != 3 → count = 1
111+
2 != 3 → count = 0 → candidate = 2
112+
...
113+
Final candidate = 4 → verify by count = 5
114+
n = 9 → ⌊9/2⌋ = 4 → 5 > 4 → return 4
115+
```
116+
117+
---
118+
119+
## 🔗 Additional Resources
120+
121+
- [Moore's Voting Algorithm - GeeksforGeeks](https://www.geeksforgeeks.org/theory-of-computation/boyer-moore-majority-voting-algorithm/)
122+
123+
---
124+
125+
Author: Neha Amin <br>
126+
Date: 19/07/2025
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class Solution {
2+
public:
3+
int majorityElement(vector<int>& nums) {
4+
int n = nums.size();
5+
int cnt = 0;
6+
int el;
7+
8+
// Boyer-Moore Voting Algorithm
9+
for (int i = 0; i < n; i++) {
10+
if (cnt == 0) {
11+
cnt = 1;
12+
el = nums[i];
13+
} else if (nums[i] == el) {
14+
cnt++;
15+
} else {
16+
cnt--;
17+
}
18+
}
19+
20+
// Optional: Verify if the candidate is actually the majority
21+
int cnt1 = 0;
22+
for (int i = 0; i < n; i++) {
23+
if (nums[i] == el)
24+
cnt1++;
25+
}
26+
if (cnt1 > n / 2)
27+
return el;
28+
return -1;
29+
}
30+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class Solution:
2+
def majorityElement(self, nums: List[int]) -> int:
3+
n = len(nums)
4+
cnt = 0
5+
el = None
6+
7+
# Boyer-Moore Voting Algorithm
8+
for i in range(n):
9+
if cnt == 0:
10+
cnt = 1
11+
el = nums[i]
12+
elif nums[i] == el:
13+
cnt += 1
14+
else:
15+
cnt -= 1
16+
17+
# Optional: Verify if el is actually the majority element.
18+
cnt1 = 0
19+
for i in range(n):
20+
if nums[i] == el:
21+
cnt1 += 1
22+
if cnt1 > n // 2:
23+
return el
24+
return -1
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# 31. Next Permutation
2+
3+
**Difficulty:** *Medium*
4+
**Category:** *Arrays, Permutations, Greedy*
5+
**Leetcode Link:** [Problem Link](https://leetcode.com/problems/next-permutation/)
6+
7+
---
8+
9+
## 📝 Introduction
10+
11+
*Given an array Arr[] of integers, rearrange the numbers into the lexicographically next greater permutation of numbers.
12+
If such an arrangement is not possible, rearrange it to the lowest possible order (i.e., sorted in ascending order).*
13+
14+
*Constraints typically include:<br>
15+
- All integers may be distinct or contain duplicates.<br>
16+
- The transformation must be done in-place with only constant extra memory.*
17+
18+
---
19+
20+
## 💡 Approach & Key Insights
21+
22+
*There are three main approaches to solve this problem:<br>
23+
- Brute Force: Generate all permutations and pick the next.<br>
24+
- In-Built Function: Use next_permutation() if language provides it.<br>
25+
- Optimal: Use the standard algorithm to compute the next permutation by identifying a break point, swapping, and reversing.*
26+
27+
---
28+
29+
## 🛠️ Breakdown of Approaches
30+
31+
### 1️⃣ Brute Force / Naive Approach
32+
33+
- **Explanation:** *Generate all permutations of the array, sort them, and locate the input permutation. Return the next one in sequence. If not found or if it's the last permutation, return the first (sorted array).*
34+
- **Time Complexity:** *O(N! × N) – N! permutations each of length N.*
35+
- **Space Complexity:** *O(1) – ignoring recursion stack used for generating permutations.*
36+
- **Example/Dry Run:**
37+
38+
```plaintext
39+
Input: [1, 2, 3]
40+
All permutations: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
41+
Current permutation: [1,2,3]
42+
Next permutation: [1,3,2]
43+
```
44+
45+
### 2️⃣ Language Built-in (C++ std::next_permutation)
46+
47+
- **Explanation:** *C++ provides next_permutation() which directly modifies the array to the next permutation.*
48+
- **Time Complexity:** *O(N) – internally optimized.*
49+
- **Space Complexity:** *O(1).*
50+
- **Example:**
51+
52+
```cpp
53+
std::vector<int> nums = {1, 2, 3};
54+
std::next_permutation(nums.begin(), nums.end());
55+
// nums is now [1, 3, 2]
56+
```
57+
58+
### 3️⃣ Optimal Approach
59+
60+
- **Explanation:**
61+
1. Find the break-point: The first index i from the back where arr[i] < arr[i+1].
62+
2. If no such index exists, reverse the whole array (it was the last permutation).
63+
3. Else, find the smallest number greater than arr[i] from the right half, swap it with arr[i].
64+
4. Reverse the subarray from i+1 to end.
65+
66+
- **Time Complexity:** *O(3N) = O(N) – each of the three steps (finding break-point, finding next greater, reversing) takes O(N).*
67+
- **Space Complexity:** *O(1) – all operations are done in-place.*
68+
- **Example/Dry Run:**
69+
70+
```plaintext
71+
Input: [1, 2, 3]
72+
73+
Step 1: Find break-point: 2 < 3 at index 1 → i = 1
74+
Step 2: Find element just greater than arr[i]: 3 at index 2
75+
Step 3: Swap 2 and 3 → [1, 3, 2]
76+
Step 4: Reverse from i+1 = 2 to end → Already sorted
77+
78+
Output: [1, 3, 2]
79+
```
80+
81+
---
82+
83+
## 📊 Complexity Analysis
84+
85+
| Approach | Time Complexity | Space Complexity |
86+
| -------------- | ----------------- | ---------------- |
87+
| Brute Force | O(N! × N) | O(1) |
88+
| In-Built | O(N) | O(1) |
89+
| Optimal | O(N) | O(1) |
90+
91+
---
92+
93+
## 📉 Optimization Ideas
94+
95+
*The optimal solution is already efficient for all constraints.
96+
You may consider early exits in case the array is already in decreasing order to avoid redundant operations.*
97+
98+
---
99+
100+
## 📌 Example Walkthroughs & Dry Runs
101+
102+
```plaintext
103+
Example 1:
104+
Input: [1, 3, 2]
105+
Break-point: index 0 (1 < 3)
106+
Swap with next greater: swap 1 and 2 → [2, 3, 1]
107+
Reverse after index 0 → [2, 1, 3]
108+
Output: [2, 1, 3]
109+
110+
Example 2:
111+
Input: [3, 2, 1]
112+
Break-point: None (fully decreasing)
113+
Reverse entire array → [1, 2, 3]
114+
Output: [1, 2, 3]
115+
```
116+
117+
---
118+
119+
## 🔗 Additional Resources
120+
121+
- [C++ next_permutation documentation](https://en.cppreference.com/w/cpp/algorithm/next_permutation)
122+
123+
---
124+
125+
Author: Neha Amin <br>
126+
Date: 19/07/2025
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
class Solution {
2+
public:
3+
void nextPermutation(vector<int>& nums) {
4+
int n = nums.size();
5+
int ind = -1;
6+
// Step 1: Find the break point
7+
for (int i = n - 2; i >= 0; i--) {
8+
if (nums[i] < nums[i + 1]) {
9+
ind = i;
10+
break;
11+
}
12+
}
13+
// If break point does not exist, reverse the whole array
14+
if (ind == -1) {
15+
reverse(nums.begin(), nums.end());
16+
return;
17+
}
18+
// Step 2: Find element just greater than nums[ind] and swap
19+
for (int i = n - 1; i > ind; i--) {
20+
if (nums[i] > nums[ind]) {
21+
swap(nums[i], nums[ind]);
22+
break;
23+
}
24+
}
25+
// Step 3: Reverse the right half
26+
reverse(nums.begin() + ind + 1, nums.end());
27+
}
28+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution:
2+
def nextPermutation(self, nums: List[int]) -> None:
3+
"""
4+
Do not return anything, modify nums in-place instead.
5+
"""
6+
n = len(nums)
7+
ind = -1
8+
# Step 1: Find the break point
9+
for i in range(n-2, -1, -1):
10+
if nums[i] < nums[i + 1]:
11+
ind = i
12+
break
13+
# If break point does not exist, reverse the whole array
14+
if ind == -1:
15+
nums.reverse()
16+
return
17+
# Step 2: Find the next greater element and swap
18+
for i in range(n - 1, ind, -1):
19+
if nums[i] > nums[ind]:
20+
nums[i], nums[ind] = nums[ind], nums[i]
21+
break
22+
# Step 3: Reverse the right half
23+
nums[ind+1:] = reversed(nums[ind+1:])

0 commit comments

Comments
 (0)