Subset Generation कैसे करें
def subsets(index, current):
if index == len(nums):
result.append(current[:])
return
subsets(index + 1, current) # exclude
current.append(nums[index])
subsets(index + 1, current) # include
current.pop()
Subset Idea
एक set के सभी subsets generate करने का मतलब है इसके elements का हर possible combination produce करना, empty set और पूरा set खुद सहित। यह एक foundational technique है जो तब दिखता है जब कोई problem आपसे items की 'हर possible selection' विचार करने को कहती है।
उदाहरण: Subset Idea
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> set = {1, 2};
cout << "{}, {1}, {2}, {1,2} - 4 subsets total for a 2-element set";
return 0;
}
public class Main {
public static void main(String[] args) {
System.out.println("{}, {1}, {2}, {1,2} - 4 subsets total for a 2-element set");
}
}
print("{}, {1}, {2}, {1,2} - 4 subsets total for a 2-element set")
#include <stdio.h>
int main() {
printf("{}, {1}, {2}, {1,2} - 4 subsets total for a 2-element set");
return 0;
}
Login to try C/C++/Java code in the editor
Include or Exclude
Core recursive idea हर element पर एक binary choice है: इसे बनाए जा रहे current subset में include करें, या इसे skip करें, और दोनों तरह से बाकी elements में recurse करें। Include/skip decisions का हर complete path एक distinct subset produce करता है।
उदाहरण: Include or Exclude
#include <iostream>
#include <vector>
using namespace std;
void subsets(vector<int>& nums, int i, vector<int>& cur) {
if (i == nums.size()) {
cout << "{ "; for (int x : cur) cout << x << " "; cout << "}" << endl;
return;
}
subsets(nums, i + 1, cur);
cur.push_back(nums[i]);
subsets(nums, i + 1, cur);
cur.pop_back();
}
int main() {
vector<int> nums = {1, 2};
vector<int> cur;
subsets(nums, 0, cur);
return 0;
}
import java.util.*;
public class Main {
static void subsets(int[] nums, int i, List<Integer> cur) {
if (i == nums.length) { System.out.println(cur); return; }
subsets(nums, i + 1, cur);
cur.add(nums[i]);
subsets(nums, i + 1, cur);
cur.remove(cur.size() - 1);
}
public static void main(String[] args) {
subsets(new int[]{1, 2}, 0, new ArrayList<>());
}
}
def subsets(nums, i, cur):
if i == len(nums):
print(cur)
return
subsets(nums, i + 1, cur)
cur.append(nums[i])
subsets(nums, i + 1, cur)
cur.pop()
subsets([1, 2], 0, [])
#include <stdio.h>
int cur[10], top = 0;
void subsets(int nums[], int i, int n) {
if (i == n) {
printf("{ "); for (int j = 0; j < top; j++) printf("%d ", cur[j]); printf("}\n");
return;
}
subsets(nums, i + 1, n);
cur[top++] = nums[i];
subsets(nums, i + 1, n);
top--;
}
int main() {
int nums[] = {1, 2};
subsets(nums, 0, 2);
return 0;
}
Login to try C/C++/Java code in the editor
Recursive Generation
Recursion naturally इसे प्रति call एक element process करके और चाहे जो भी choice हो अगले element पर move करके model करता है, जब तक हर element decided न हो और एक complete subset record न हो जाए।
उदाहरण: Recursive Generation
#include <iostream>
#include <vector>
using namespace std;
int count = 0;
void subsets(vector<int>& nums, int i, vector<int>& cur) {
if (i == nums.size()) { count++; return; }
subsets(nums, i + 1, cur);
cur.push_back(nums[i]);
subsets(nums, i + 1, cur);
cur.pop_back();
}
int main() {
vector<int> nums = {1, 2, 3};
vector<int> cur;
subsets(nums, 0, cur);
cout << "Total subsets generated: " << count;
return 0;
}
import java.util.*;
public class Main {
static int count = 0;
static void subsets(int[] nums, int i, List<Integer> cur) {
if (i == nums.length) { count++; return; }
subsets(nums, i + 1, cur);
cur.add(nums[i]);
subsets(nums, i + 1, cur);
cur.remove(cur.size() - 1);
}
public static void main(String[] args) {
subsets(new int[]{1, 2, 3}, 0, new ArrayList<>());
System.out.println("Total subsets generated: " + count);
}
}
count = 0
def subsets(nums, i, cur):
global count
if i == len(nums):
count += 1
return
subsets(nums, i + 1, cur)
cur.append(nums[i])
subsets(nums, i + 1, cur)
cur.pop()
subsets([1, 2, 3], 0, [])
print("Total subsets generated:", count)
#include <stdio.h>
int cur[10], top = 0, count = 0;
void subsets(int nums[], int i, int n) {
if (i == n) { count++; return; }
subsets(nums, i + 1, n);
cur[top++] = nums[i];
subsets(nums, i + 1, n);
top--;
}
int main() {
int nums[] = {1, 2, 3};
subsets(nums, 0, 3);
printf("Total subsets generated: %d", count);
return 0;
}
Login to try C/C++/Java code in the editor
Subset Properties
चूंकि n elements में से हर एक independently include या exclude हो सकता है, बिल्कुल 2^n possible subsets हैं — यह exponential count ही कारण है कि subset generation सिर्फ relatively छोटे input sizes के लिए practical है।
उदाहरण: Subset Properties
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int n = 5;
cout << n << " elements produce " << (int)pow(2, n) << " subsets";
return 0;
}
public class Main {
public static void main(String[] args) {
int n = 5;
System.out.println(n + " elements produce " + (int) Math.pow(2, n) + " subsets");
}
}
n = 5
print(n, "elements produce", 2 ** n, "subsets")
#include <stdio.h>
#include <math.h>
int main() {
int n = 5;
printf("%d elements produce %d subsets", n, (int)pow(2, n));
return 0;
}
Login to try C/C++/Java code in the editor
Practice
यही include-or-exclude recursive pattern 0/1 knapsack और combination-sum जैसी harder problems का direct ancestor है, जो उसी basic subset-generation structure के ऊपर constraints (जैसे एक weight limit या target sum) जोड़ती हैं।
उदाहरण: Practice
#include <iostream>
using namespace std;
int main() {
cout << "Include-or-exclude recursion is the direct ancestor of 0/1 knapsack and combination-sum";
return 0;
}
public class Main {
public static void main(String[] args) {
System.out.println("Include-or-exclude recursion is the direct ancestor of 0/1 knapsack and combination-sum");
}
}
print("Include-or-exclude recursion is the direct ancestor of 0/1 knapsack and combination-sum")
#include <stdio.h>
int main() {
printf("Include-or-exclude recursion is the direct ancestor of 0/1 knapsack and combination-sum");
return 0;
}
Login to try C/C++/Java code in the editor
curको result में बिना copy किए जोड़ना और फिर इसे बदलते रहना।- Include branch के बाद element हटाना भूल जाना (backtracking), इसलिए बाद वाली subsets में extra items होती हैं।
- Empty subset missing या
2^nसे कम subsets की उम्मीद करना।
- Recursion problems को उनकी खुद की छोटी versions में तोड़कर solve करता है, जैसे Fibonacci, factorial, और Tower of Hanoi में।
- Backtracking choices try करता है और जब वे fail हों तो उन्हें undo करता है।
- N-Queens, Sudoku Solver, और subset generation classic backtracking problems हैं।
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: