ترکیبها و جایگشتها
تولید همه جایگشتها، ترکیبها و ترکیبهای تکراری با Backtracking — سه مسئله خواهر و تفاوتهای ظریفشان
سه مسئله خواهر
| مسئله | تعریف | تعداد | مثال [1,2,3] |
|---|---|---|---|
| جایگشت (Permutation) | همه چیدمانها | n! | [1,2,3], [2,1,3]... |
| ترکیب (Combination) | انتخاب kتایی بدون ترتیب | C(n,k) | [1,2], [1,3], [2,3] |
| زیرمجموعه (Subset) | همه ترکیبها (هر اندازه) | 2ⁿ | [], [1], [1,2]... |
جایگشتها — هر عنصر یکبار
در هر سطح، هر عنصر استفادهنشده را انتخاب کن:
def permute(nums):
result = []
def backtrack(path, remaining):
if not remaining:
result.append(path[:])
return
for i in range(len(remaining)):
backtrack(path + [remaining[i]],
remaining[:i] + remaining[i+1:])
backtrack([], nums)
return result
ترکیبها — ترتیب مهم نیست
ترفند طلایی: فقط به جلو! هر انتخاب از «بعد از آخرین انتخاب» شروع شود — تکرار [1,2] و [2,1] حذف میشود:
def combine(n, k):
result = []
def backtrack(start, path):
if len(path) == k:
result.append(path[:])
return
for i in range(start, n + 1): # از start به بعد!
path.append(i)
backtrack(i + 1, path) # بعدی: بعد از i
path.pop()
backtrack(1, [])
return result
ترکیب با تکرار (عناصر تکراری)
سه تفاوت ظریف:
- ورودی مرتب شود
- در حلقه:
i > start و nums[i] == nums[i-1]← رد کن (تکرار در همین سطح) - backtrack با i (نه i+1) — عنصر قابل استفاده مجدد (اگر مجاز باشد)
پیچیدگیها
- جایگشت: n! جواب × کار هر کدام O(n) ← O(n × n!)
- ترکیب: C(n,k) × O(k)
- زیرمجموعه: 2ⁿ × O(n)
همه نماییاند — طبیعت «همه حالتها»!
نکته: در پایتون، itertools (permutations، combinations) اینها را آماده دارد — اما پیادهسازی Backtracking برای مصاحبه و درک الگو ضروری است!
جمعبندی
- جایگشت: انتخاب از استفادهنشدهها
- ترکیب: «فقط به جلو» — حذف تکرار ترتیبی
- تکراری: مرتب + رد تکرار همسطح
- همه نمایی — تعداد جوابها همینقدرند
این مبحث بخشی از دوره آموزش کامل الگوریتمها است.