সমস্যা বিবরণ
একটি INTEGER অ্যারে arr দেওয়া আছে। আমরা একটি INTEGER SET বেছে নিতে পারি এবং সেই সেটের সব INTEGER-গুলোর সব OCURRENCE অ্যারে থেকে মুছে ফেলতে পারি। লক্ষ্য হলো ন্যূনতম আকারের সেট বের করা যাতে অ্যারে এর অন্তত অর্ধেক INTEGER মুছে যায়।
উদাহরণ
Input: arr = [3,3,3,3,5,5,5,2,2,7]
Output: 2
ব্যাখ্যা: অ্যারের আকার = 10। অর্ধেক = 5।
যদি সেট {3, 7} বেছে নিই: 3 (৪ বার) এবং 7 (১ বার) = ৫টি এলিমেন্ট মুছে যায়। বাকি থাকে [5,5,5,2,2] (আকার ৫)।
অন্য বৈধ সেট: {3,5}, {3,2}, {5,2}।
{2,7} অবৈধ কারণ তখন ৩টি মात्र মুছে যায়, বাকি থাকে ৭টি (>5)।
সমাধানের অ্যালগরিদম (Greedy Approach)
- ফ্রিকোয়েন্সি গণনা: প্রতিটি অনন্য INTEGER-র ফ্রিকোয়েন্সি (কতবার এসেছে) একটি HASH MAP-এ সংরক্ষণ করুন।
- ফ্রিকোয়েন্সি সাজান: সমস্ত ফ্রিকোয়েন্সি মানগুলো একটি VECTOR-এ নিয়ে DESCENDING ORDER-এ সাজান (সর্বোচ্চ ফ্রিকোয়েন্সি আগে)।
- লালচী বেছে নেওয়া (Greedy Selection): সর্বোচ্চ ফ্রিকোয়েন্সি वालা INTEGER-গুলো এক এক করে সেটে যোগ করুন যতক্ষণ না মুছে যাওয়া INTEGER-র সংখ্যা অ্যারে আকারের অর্ধেক বা তার বেশি হয়।
- ফলাফল: সেটে কতটি INTEGER যোগ করা লাগলো, সেটিই উত্তর।
সময় ও জটিলতা বিশ্লেষণ
| মেট্রিক | জটিলতা | ব্যাখ্যা |
|---|---|---|
| Time Complexity | O(n log n) | n = অ্যারে আকার। ফ্রিকোয়েন্সি গণনা O(n), সর্টিং O(k log k) যেখানে k = অনন্য INTEGER সংখ্যা (k ≤ n) |
| Space Complexity | O(n) | Hash map + frequency vector |
C++ বাস্তবায়ন (Solution Class)
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int minSetSize(vector<int>& arr) {
// 1. ফ্রিকোয়েন্সি গণনা
unordered_map<int, int> freq;
for (int num : arr) {
freq[num]++;
}
// 2. ফ্রিকোয়েন্সি ভেক্টরে সংগ্রহ ও ডিসেন্ডিং সর্ট
vector<int> frequencies;
frequencies.reserve(freq.size());
for (auto& [num, count] : freq) {
frequencies.push_back(count);
}
sort(frequencies.rbegin(), frequencies.rend()); // descending
// 3. Greedy selection
int n = arr.size();
int removed = 0;
int setSize = 0;
for (int count : frequencies) {
if (removed >= n / 2) break;
removed += count;
setSize++;
}
return setSize;
}
};
// টেস্ট ড্রাইভার
int main() {
Solution sol;
vector<int> arr = {3,3,3,3,5,5,5,2,2,7};
cout << "Minimum set size: " << sol.minSetSize(arr) << endl; // Output: 2
return 0;
}
কোড ব্যাখ্যা
unordered_map— O(1) গড় সময়ে ফ্রিকোয়েন্সি গণনায় ব্যবহৃত।sort(frequencies.rbegin(), frequencies.rend())— রিভার্স ইটারেটর ব্যবহার করে ডিসেন্ডিং অর্ডারে সাজানো।removed >= n / 2— শর্ত পূরণ হলে লুপ ব্রেক করে দিচ্ছে।frequencies.reserve(freq.size())— মেমরি রি-অ্যালোকেশন এড়াতে রিজার্ভ করা হয়েছে।
LeetCode সমস্যা রেফারেন্স
এটি LeetCode 1338. Reduce Array Size to The Half সমস্যার সমাধান। অনুশীলনের জন্য LeetCode-এ জমা দিন।
অতিরিক্ত টেস্ট কেস
| Input | Output | ব্যাখ্যা |
|---|---|---|
| [7,7,7,7,7,7] | 1 | শুধু {7} বেছে নিলে ৬টি মুছে যায় (অর্ধেক ৩) |
| [1,2,3,4,5,6,7,8,9,10] | 5 | সব ফ্রিকোয়েন্সি ১। ৫টি বেছে নিলে ৫টি মুছে যায় |
| [1,1,1,1,2,2,2,3,3] | 2 | {1,2} বেছে নিলে ৪+৩=৭টি মুছে যায় (অর্ধেক ৪.৫ → ৫) |