Luận bàn về Subsets
Đến phần ta cần sử dụng nhiều đệ quy rồi đây @@. Ở post này ta sẽ nói tới pattern Subsets, đây là pattern giúp ta giải quyết các bài toán yêu cầu tìm permutations và combinations ko lặp của các elements trong 1 data structure.
Ví dụ, 1 array [1,2,3]. Ta có các subsets như sau
{1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}
Ý tưởng là ta sẽ xây dựng nên các subsets từ từng elements trong array. Cụ thể trong ví dụ trên:
Ta bắt đầu với 1 tập rỗng {}. Từ tập rỗng này ta generate ra 2 array mới từ 2 option: bỏ qua element 1 và thêm element 1 vào trong array. Như vậy ta đc:
{}, {1}
Ta lưu tập hợp 2 array trên, rồi với mỗi array ta kết hợp với element
2
bằng 2 cách như ở bước 1. Ta có;{}, {2}, {1}, {1,2}
Áp dụng tương tự với tập hợp các array có đc ở bước 2. Ta sẽ đc:
{}, {3}, {2}, {2,3}, {1}, {1,3}, {1,2}, {1,2,3}
Như vậy bỏ qua tập rỗng ở đầu đi thì ta có được kết quả rồi.

Áp dụng vào đệ quy, ta sẽ có pseudocode như sau;
function(saveArrays, inputIndex):
If inputIndex >= inputArray.size:
Return saveArrays
Initialize size = saveArrays.size
Repeat
For i from 0 to size-1:
Initialize newArray = saveArrays[i]
Append inputArray[inputIndex] to newArray
Append newArray to saveArrays
End repeat
Return function(saveArrays, inputindex+1)
Snippet
vector<vector<int>> subsets(vector<vector<int>>& saveArrays, int inputIndex) {
if (inputIndex >= inputArray.size()) {
return saveArrays;
}
int size = saveArrays.size();
// Add new arrays with the new element to the newArrays
for (int i = 0; i < size; i++) {
vector<int> newArray (saveArrays[i]);
newArray.push_back(inputArray[inputIndex]);
saveArrays.push_back(newArray);
}
return subsets(saveArrays, inputIndex+1);
}
Follow up
Ta có thể áp dụng cách tiếp cận BFS thay vì đệ quy như trên. Gợi ý là trong phần ý tưởng ta đã bàn tới phía trên, mỗi bước ta cần lưu từng set arrays một và dùng set đó để thêm element tiếp theo. Đặc điểm này ta thấy giống hệt với cách ta sử dụng queue trong BFS rồi.
Cách tiếp cận này sẽ tốn của ta tới O(n*2^n) time complexity. Nhìn chung các dạng bài về subsets vs combinations đều có độ phức tạp thời gian rất lớn. Ae tiếp cận tới pattern subsets trước tiên cũng tạo dựng bước tiền đề để sau này học pattern dynamic programming (quy hoạch động) được dễ dàng hơn.