Subsets II [leetcode] 从获取子集的递归和循环方法说起,解决重复子集的问题

这一题和Permutation II很像,一个是排列一个是组合。

我们理清思路,从最基本的获取子集的方法开始分析:

获取子集总的来说可以用循环或者递归做,同时还可以根据数字对应的binary code得到。

例如s = {x,y,z}可以生成的组合有:x,y,z,xy,yz,xz,xyz,0

第一种思路:

1. 维护一个集合Set(i),包含s[0...i]可生成的所有组合

s[0...i+1]可以生成的所有组合为:Set(i) + (Set(i)+s[i+1])

void permutation(vector<int> &s, vector<vector<int>> & res, int index)
{
	permutation(s, res,  index + 1);
	for (int i = res.size(); i >= 0; i—)
	{
		res.push_back(res[i] + s[index]);
	}
}

以上是一个递归的伪代码,我们可以将其改为循环的:

vector<vector<int>> permutation(vector<int> &s)
{
	vector<vector<int>> res;
	for (int index = 0; index < s.size(); index++)
	{
		for (int i = res.size(); i >= 0; i—)
		{
			res.push_back(res[i] + s[index]);
		}
	}
	return res;
}

2.下面考虑如何去除相同的子集:

当输入为{x,y,y}时,对index = 0,res={0, x}; index = 1时res={0,x,y,xy}

当index=2时,问题来了。如果对0和x都加上y,会生成重复的子集y和xy。此时res={0,x,y,xy,y,xy,yy,xyy}

重复的原因是我们将index=1时处理过的集合{0,x}又处理了一遍。

所以我们加上preEnd标记上一个index处理过的集合的结尾位置(如{0,x})。

如果s[index]和s[index-1]一样,preEnd为处理s[index-1]之前res的大小;否则preEnd=0

代码如下:

vector<vector<int> > subsetsWithDup(vector<int> &s) {
        sort(s.begin(), s.end());
        vector<vector<int>> res;
        res.push_back(vector<int>());
        int preEnd = 0;
        for (int i = 0; i < s.size(); i++)
        {
            int resSize = res.size();
            for (int j = preEnd; j < resSize; j++)
            {
                vector<int> curSet = res[j];
                curSet.push_back(s[i]);
                res.push_back(curSet);
            }
            if (i + 1 < s.size() && s[i] == s[i + 1]) preEnd = resSize;
            else preEnd = 0;
        }
        return res;
    }

第二种思路:

1.再回看所有的子集{x,y,z,xy,yz,xz,xyz,0}。我们发现x没有出现在第二位,y没有出现在第三位...

1.1设{x,y,z}为Set1,则对Set1中的每个元素,向其添加可行的其他元素,如x可以添加y和z;y可以添加z;z已经到末尾了,不能添加其他元素了。所以我们得到Set2{xy,xz,yz}。

1.2 接着向Set2添加元素,得到Set3{xyz}。Set3不可能再扩展出其他子集了,所以循环结束。

{0, Set1, Set2, Set3}是最终结果。

递归的伪代码如下:

void permutation(vector<int> &s, int inPos, int outPos, vector<int> & out, vector<vector<int>> & res)
{
	for (int index = inPos; index < s.size(); index++)
	{
		out[outPos] = s[index];
		res.push_back(out);
		permutation(s, index + 1, outPos + 1, out, s);
	}
}

循环的时候,依次生成Set1,Set2,Set3。代码如下:

vector<vector<int> > subsets(vector<int> &s) {
        vector<vector<int>> res;
        vector<int> inPos;
        res.push_back(vector<int>());
        inPos.push_back(-1);
        sort(s.begin(), s.end());

        for (int i = 0; i < res.size(); i++)
        {
            for (int index = inPos[i] + 1; index < s.size(); index++)
            {
                vector<int> temp = res[i];
                temp.push_back(s[index]);
                res.push_back(temp);
                inPos.push_back(index);
            }
        }
        return res;
    }

下面考虑有重复元素的情况:

在生成每个Seti的时候,均有可能遇见重复元素,从而生成重复子集,所以在里层的for循环里要跳过相同元素。

这里只需要加上简单的一句话即可 while(index + 1 < s.size() && s[index] == s[index + 1]) index++;

代码如下:

 vector<vector<int> > subsetsWithDup(vector<int> &s) {
        vector<vector<int>> res;
        vector<int> inPos;
        res.push_back(vector<int>());
        inPos.push_back(-1);
        sort(s.begin(), s.end());

        for (int i = 0; i < res.size(); i++)
        {
            for (int index = inPos[i] + 1; index < s.size(); index++)
            {
                vector<int> temp = res[i];
                temp.push_back(s[index]);
                res.push_back(temp);
                inPos.push_back(index);
                while(index + 1 < s.size() && s[index] == s[index + 1]) index++;
            }
        }
        return res;
    }

第三种思路:

当前子集包含/不包含 index

用递归来做的时候很简单,伪代码如下:

void permutation(vector<int> &s, int inPos, vector<int> & out, vector<vector<int>> & res)
{
	if (inPos == s.size())
	{
		res.push_back(out);
		return;
	}
	permutation(s, inPos + 1, out, res);
	permutation(s, inPos + 1, out + s[inPos], res);
}

非递归实现和第一种思路类似

第四种思路:

含有K个元素的集合有2^K个子集,每个数字的第i位代表是否含有第s[i]个元素

时间: 2024-10-25 03:14:46

Subsets II [leetcode] 从获取子集的递归和循环方法说起,解决重复子集的问题的相关文章

Subsets II -- LeetCode

Given a collection of integers that might contain duplicates, nums, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example,If nums = [1,2,2], a solutio

Subsets II ——LeetCode

Given a collection of integers that might contain duplicates, nums, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example,If nums = [1,2,2], a solutio

Ajax异步获取html数据中包含js方法无效的解决方法

页面上使用js写了一个获取后台数据的方法 function data() { var tab = $("#dic") $.ajax({ url: '../demo.ashx?method=GetList', data: {}, dataType: 'json', type: 'post', async: true, success: function (data) { //console.log(data); var parentStr = ''; $.each(data, funct

LeetCode: Subsets II [091]

[题目] Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,2], a solutio

LeetCode --- 90. Subsets II

题目链接:Subsets II Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,2]

【leetcode】Subsets II

Subsets II Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example,If S = [1,2,2], a so

[leetcode]Subsets II @ Python

原题地址:https://oj.leetcode.com/problems/subsets-ii/ 题意: Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicat

leetcode: Subsets &amp; Subsets II

SubsetsGiven a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example,If S = [1,2,3], a solution is: [ [3], [1], [2], [1,2

lintcode 中等题:subsets II 带重复元素的子集

题目 带重复元素的子集 给定一个可能具有重复数字的列表,返回其所有可能的子集 样例 如果 S = [1,2,2],一个可能的答案为: [ [2], [1], [1,2,2], [2,2], [1,2], [] ] 注意 子集中的每个元素都是非降序的 两个子集间的顺序是无关紧要的 解集中不能包含重复子集 挑战 你可以同时用递归与非递归的方式解决么? 解题 一个很简单的想法就是在上一题目中增加判断是否已经存在某个子集 class Solution: """ @param S: A