90. Subsets II(中等,编写代码有难度)

Given a collection of integers that might contain duplicates, nums, return all possible subsets.

Note: The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,2], a solution is:

[
 [2],
 [1],
 [1,2,2],
 [2,2],
 [1,2],
 []
]

有重复值的序列的所有子集.
核心想法是:
把 [2,2] 看成1个特殊的元素,它不想其他元素只有两种状态(存在,不存在).
This element([2, 2]) has more than two choices: you can either NOT put it into the subset, or put ONE 2 into the subset, or put TWO 2s into the subset.
上面是老外的解释,很精彩且到位.

这题,对我来说,即使知道想法,编这个东西难度也挺大.
仔细考察人家的代码后,发现下面的事实:

下面程序生成序列的顺序如下:

[[]]->[[],[1]]->[[],[1],[2],[2,2],[1,2],[1,2,2]]
                         |<- []->| |<-  [1]  ->|

|<- []->| 这个地方代表 [2],[2,2] 是由 [] 生成的;
|<-[1]->| 这个地方代表 [1,2],[1,2,2] 是由 [1] 生成的.

了解了上述生成顺序,下面的代码就好理解了.

人家想法,复写人家代码(那想法好难实现).
有三个亮点:

  1. i += count; // smart~!
  2. 以 i 为 base,对 count 计数: while (count + i < A.size() && A[count + i] == A[i]) count++;
  3. preN 保存了 res 未改变前的长度;
  4. 用一个 vector 保存 res[k]: vector<int> inst = res[k]; // [].
    • 这个太重要了,因为可以实现 [1] -> [1,2](store this in res) -> [1,2,2](store this value in res again base on [1, 2])

(O(n^2)) time, (O(1)) extra space.

// sample: A = [1, 2, 2]
// 即使知道想法,编这个东西难度也挺大
// 把 2,2 看成一个特殊的元素.
// 可以出现1个2, 也可以出现两个2
// 下面程序生成序列的顺序如下:
// [[]]->[[],[1]]->[[],[1],[2],[2,2],[1,2],[1,2,2]]
//                         |<- []->| |<-  [1]  ->|
vector<vector<int>> subsetsWithDup(vector<int>& A) {
	sort(A.begin(), A.end());
	vector<vector<int> > res = { {}}; //[[],]

	for (int i = 0; i < A.size();) {

		// 以 indx = i 为base
		// 在A中向后查和A[i]相同的元素个数 -> count
		int count = 0;
		while (count + i < A.size() && A[count + i] == A[i]) count++;

		// res 未改之前的长度 -- 初始时,这个熊样--> res = [[]]
		int preN = res.size();
		for (int k = 0; k < preN; k++) {
			vector<int> inst = res[k]; // []

			for (int j = 0; j < count; j++) {
				// e.g. 若 inst = []
				// when j = 0, inst = [2]
				//      j = 1, inst = [2, 2]
				// inst 所代表的 array 都将送入 res
				inst.push_back(A[i]);
				res.push_back(inst);
			}
		}
		i += count; // smart~!
	}
	return res;
}
原文地址:https://www.cnblogs.com/ZhongliangXiang/p/7485994.html