diff --git a/01-task-scheduler.cpp b/01-task-scheduler.cpp new file mode 100644 index 0000000..ecc394c --- /dev/null +++ b/01-task-scheduler.cpp @@ -0,0 +1,42 @@ +/* +TC - O(N) - performed linear scans only +SC - O(26) i.e. O(1) - used extra space to hold constant freq counts for lowercase alphaeb +Issues Faced - that idle slots logic does make sense, but I often forget to account for more than one character having max frequency .. need to be more careful +Solved on LeetCode - Yes + + +*/ + + + + +class Solution { + public: + int leastInterval(vector& tasks, int n) { + int freq_table[26] = {0}; + + int totalTasks = tasks.size(); + + int maxFreq = INT_MIN; + + for (char c: tasks) { + freq_table[c - 'A'] += 1; + maxFreq = max(maxFreq, freq_table[c - 'A']); + } + + int maxFreqCount = 0; + for (int i = 0; i < 26; i++) { + if (freq_table[i] == maxFreq) { + maxFreqCount++; + } + } + + int idle_slots = (maxFreq - 1) * (n - (maxFreqCount - 1)); + + idle_slots = idle_slots - (totalTasks - (maxFreq*maxFreqCount)); + if (idle_slots < 0) idle_slots = 0; + + return totalTasks + idle_slots; + + } + }; diff --git a/02-queue-reconstruction-by-height.cpp b/02-queue-reconstruction-by-height.cpp new file mode 100644 index 0000000..d4c201f --- /dev/null +++ b/02-queue-reconstruction-by-height.cpp @@ -0,0 +1,44 @@ +/* +TC - O(N^2) - performed sorting operation O(NlogN), but insertion can be quadratic worst case. +SC - O(n) - used extra space to hold sorted person objects +Issues Faced - need to be clear about why we sort like this - it is because without the greedy approach, we would overwrite entries for previously placed people +Solved on LeetCode - Yes + + +*/ + + +class Solution { + public: + vector> reconstructQueue(vector>& source) { + + std::vector> target; + target.reserve(source.size()); + + for (const auto &vec : source) { + if (vec.size() == 2) { + target.emplace_back(vec[0], vec[1]); + } + } + + // 2. Sort: Descending by 2nd element, Ascending by 1st element on ties + std::sort(target.begin(), target.end(), [](const auto& a, const auto& b) { + if (a.first != b.first) { + return a.first > b.first; // Primary sort: Descending heights + } + return a.second < b.second; // Tie-breaker: Ascending number of people ahead of you (to really put the tallest first) + }); + + vector> result; + for (const auto& person : target) { + int height = person.first; + int count = person.second; + + // Greedily insert directly at the position dictated by 'count' + result.insert(result.begin() + count, {height, count}); + } + return result; + + + } + }; diff --git a/03-partition-labels.cpp b/03-partition-labels.cpp new file mode 100644 index 0000000..b7b840b --- /dev/null +++ b/03-partition-labels.cpp @@ -0,0 +1,53 @@ +/* +TC - O(n) - two linear passes only +SC - O(n) - used extra space to hold rightmost positions +Issues Faced - fairly intuitive, but need to remember two-pass is just one of several greedy string approaches +Solved on LeetCode - Yes + + +*/ + + + +class Solution { + public: + + vector partitionLabels(string s) { + + + + int posFromRight[26]; + std::fill(std::begin(posFromRight), std::end(posFromRight), -1); + + + for (int i = s.size() - 1 ; i >= 0 ; i--) { + int currVal = s[i] - 'a'; + if (posFromRight[currVal] == -1) { + posFromRight[currVal] = i; + // cout<<"rightmost pos of "< res; + + for (int i = 0 ; i < s.size() ; i++) { + int currVal = s[i] - 'a'; + // cout<<"s[i] = "<