Skip to content

Commit 2dae331

Browse files
authored
Merge pull request #87 from mmhossain/csharp-solutions-heaps
Added C# solutions for Chapter 8: Heaps
2 parents 7e935b3 + b533f5a commit 2dae331

File tree

5 files changed

+240
-0
lines changed

5 files changed

+240
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using ds.ListNode;
2+
3+
/*
4+
Definition of ListNode:
5+
class ListNode : IComparable<ListNode>
6+
{
7+
public ListNode(int val, ListNode next = null)
8+
{
9+
Val = val;
10+
Next = next;
11+
}
12+
13+
public int Val { get; set; }
14+
15+
public ListNode Next { get; set; }
16+
17+
// Define a custom comparator for 'ListNode', enabling the min-heap
18+
// to prioritize nodes with smaller values.
19+
public int CompareTo(ListNode other)
20+
{
21+
return this.Val - other.Val;
22+
}
23+
}
24+
*/
25+
26+
public class Solution
27+
{
28+
public ListNode CombineSortedLinkedLists(ListNode[] lists)
29+
{
30+
PriorityQueue<ListNode, ListNode> heap = new();
31+
32+
// Push the head of each linked list into the heap.
33+
foreach (ListNode head in lists)
34+
if (head != null)
35+
heap.Enqueue(head, head);
36+
37+
// Set a dummy node to point to the head of the output linked list.
38+
ListNode dummy = new ListNode(-1);
39+
40+
// Create a pointer to iterate through the combined linked list as
41+
// we add nodes to it.
42+
ListNode curr = dummy;
43+
44+
while (heap.Count > 0)
45+
{
46+
// Pop the node with the smallest value from the heap and add it
47+
// to the output linked list
48+
ListNode smallestNode = heap.Dequeue();
49+
curr.Next = smallestNode;
50+
curr = curr.Next;
51+
52+
// Push the popped node's subsequent node to the heap.
53+
if (smallestNode.Next != null)
54+
heap.Enqueue(smallestNode.Next, smallestNode.Next);
55+
}
56+
57+
return dummy.Next;
58+
}
59+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
class Pair : IComparable<Pair>
2+
{
3+
public string Str { get; }
4+
public int Freq { get; }
5+
6+
public Pair(string str, int freq)
7+
{
8+
Str = str;
9+
Freq = freq;
10+
}
11+
12+
public int CompareTo(Pair other)
13+
{
14+
// Prioritize lexicographical order for strings with equal frequencies.
15+
if (this.Freq == other.Freq)
16+
return string.Compare(this.Str, other.Str, StringComparison.Ordinal);
17+
18+
// Otherwise, prioritize strings with higher frequencies.
19+
return other.Freq - this.Freq;
20+
}
21+
}
22+
23+
public class Solution
24+
{
25+
public string[] KMostFrequentStringsMaxHeap(string[] strs, int k)
26+
{
27+
Dictionary<string, int> freqs = [];
28+
foreach (string str in strs)
29+
freqs[str] = freqs.GetValueOrDefault(str) + 1;
30+
31+
// Create the max heap by adding all Pair objects.
32+
PriorityQueue<Pair, Pair> maxHeap = new();
33+
foreach ((string str, int freq) in freqs)
34+
{
35+
Pair pair = new Pair(str, freq);
36+
maxHeap.Enqueue(pair, pair);
37+
}
38+
39+
// Pop the most frequent string off the heap 'k' times and return
40+
// these 'k' most frequent strings.
41+
List<string> result = [];
42+
for (int i = 0; i < k && maxHeap.Count > 0; i++)
43+
result.Add(maxHeap.Dequeue().Str);
44+
45+
return result.ToArray();
46+
}
47+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
class Pair : IComparable<Pair>
2+
{
3+
public string Str { get; }
4+
public int Freq { get; }
5+
6+
public Pair(string str, int freq)
7+
{
8+
Str = str;
9+
Freq = freq;
10+
}
11+
12+
// Since this is a min-heap comparator, we can use the same
13+
// comparator as the one used in the max-heap, but reversing the
14+
// inequality signs to invert the priority.
15+
public int CompareTo(Pair other)
16+
{
17+
if (this.Freq == other.Freq)
18+
return string.Compare(other.Str, this.Str, StringComparison.Ordinal);
19+
20+
return this.Freq - other.Freq;
21+
}
22+
}
23+
24+
public class Solution
25+
{
26+
public string[] KMostFrequentStringsMinHeap(string[] strs, int k)
27+
{
28+
Dictionary<string, int> freqs = [];
29+
foreach (string str in strs)
30+
freqs[str] = freqs.GetValueOrDefault(str) + 1;
31+
32+
PriorityQueue<Pair, Pair> minHeap = new();
33+
34+
foreach ((string str, int freq) in freqs)
35+
{
36+
Pair pair = new Pair(str, freq);
37+
minHeap.Enqueue(pair, pair);
38+
39+
// If heap size exceeds 'k', pop the lowest frequency string to
40+
// ensure the heap only contains the 'k' most frequent words so far.
41+
if (minHeap.Count > k)
42+
minHeap.Dequeue();
43+
}
44+
45+
// Return the 'k' most frequent strings by popping the remaining 'k'
46+
// strings from the heap. Since we're using a min-heap, we need to
47+
// reverse the result after popping the elements to ensure the most
48+
// frequent strings are listed first.
49+
List<string> result = [];
50+
while (minHeap.Count > 0)
51+
result.Add(minHeap.Dequeue().Str);
52+
53+
result.Reverse();
54+
return result.ToArray();
55+
}
56+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
public class MedianOfAnIntegerStream
2+
{
3+
PriorityQueue<int, int> leftHalf; // max-heap
4+
PriorityQueue<int, int> rightHalf; // min-heap
5+
6+
public MedianOfAnIntegerStream()
7+
{
8+
leftHalf = new(Comparer<int>.Create((x, y) => y - x));
9+
rightHalf = new(Comparer<int>.Create((x, y) => x - y));
10+
}
11+
12+
public void Add(int num)
13+
{
14+
// If 'num' is less than or equal to the max of 'leftHalf', it
15+
// belongs to the left half.
16+
if (leftHalf.Count == 0 || num <= leftHalf.Peek())
17+
{
18+
leftHalf.Enqueue(num, num);
19+
20+
// Rebalance the heaps if the size of the 'leftHalf'
21+
// exceeds the size of the 'rightHalf' by more than one.
22+
if (leftHalf.Count > rightHalf.Count + 1)
23+
{
24+
int leftTop = leftHalf.Dequeue();
25+
rightHalf.Enqueue(leftTop, leftTop);
26+
}
27+
}
28+
// Otherwise, it belongs to the right half.
29+
else
30+
{
31+
rightHalf.Enqueue(num, num);
32+
33+
// Rebalance the heaps if 'rightHalf' is larger than 'leftHalf'.
34+
if (leftHalf.Count < rightHalf.Count)
35+
{
36+
int rightTop = rightHalf.Dequeue();
37+
leftHalf.Enqueue(rightTop, rightTop);
38+
}
39+
}
40+
}
41+
42+
public double GetMedian()
43+
{
44+
if (leftHalf.Count == rightHalf.Count)
45+
return (leftHalf.Peek() + rightHalf.Peek()) / 2.0;
46+
47+
return leftHalf.Peek();
48+
}
49+
}

csharp/Heaps/SortAKSortedArray.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
public class Solution
2+
{
3+
public int[] SortAKSortedArray(int[] nums, int k)
4+
{
5+
PriorityQueue<int, int> minHeap = new(Comparer<int>.Create((x, y) => x - y));
6+
7+
// Populate a min-heap with the first k + 1 values in 'nums'.
8+
for (int i = 0; i < k + 1; i++)
9+
minHeap.Enqueue(nums[i], nums[i]);
10+
11+
// Replace elements in the array with the minimum from the heap at each iteration.
12+
int insertIndx = 0;
13+
for (int i = k + 1; i < nums.Length; i++)
14+
{
15+
nums[insertIndx] = minHeap.Dequeue();
16+
insertIndx++;
17+
minHeap.Enqueue(nums[i], nums[i]);
18+
}
19+
20+
// Pop the remaining elements from the heap to finish sorting the array.
21+
while (minHeap.Count > 0)
22+
{
23+
nums[insertIndx] = minHeap.Dequeue();
24+
insertIndx++;
25+
}
26+
27+
return nums;
28+
}
29+
}

0 commit comments

Comments
 (0)