leetcode 11.20(77、组合&&78、子集)

这两道题目比较具有相似性,都是考察深搜,因此写在一起,希望有所广益。
由于最近主要在使用python编写程序,所以今天第一次使用python编写,一次成功,很棒,由于python里面的各种函数实在是太好用了,为了全面提升,也应该使用c++再编写一下

77. 组合(通过—python版本)

思路:

使用递归公式:

f[n][k]=f[n-1][k]+f[n-1][k-1]

效率:91.5%(在python的所有答案中的效率)

时间:160 ms

程序代码:

class Solution:
    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        if k==1:
            return [[i] for i in range(1,n+1)]
        if n==k:
            return [list(range(1,n+1))]###这是一个一维的列表
        vec1=self.combine(n-1,k)
        pre_vec2=self.combine(n-1,k-1)
        vec2=[]##二维的列表
        for ls in pre_vec2:
            ls.append(n)
            vec2.append(ls)
        vec1.extend(vec2)
        #print(vec1)
        return vec1  
        
if __name__=="__main__":
    b=Solution()
    a=b.combine(4,2)
    for i in a:
        print(i)

77. 组合(通过—c++版本)

思路:和上面的一样,使用递归

效率:67.51%

时间:68ms

class Solution {
public:
	vector<vector<int>> combine(int n, int k) {
		vector<vector<int>> vec1,pre_vec2,vec2;
		vector<int> tmp;
		if (k == 1) {
			for (int i = 1; i <= n; i++) {
				tmp.push_back(i);
				vec1.push_back(tmp);
				tmp.clear();
			}
			return vec1;
		}
		if (n == k) {
			for (int i = 1; i <= n; i++) {
				tmp.push_back(i);
			}
			vec1.push_back(tmp);
			return vec1;
		}
		vec1 = combine(n-1,k);
		pre_vec2 = combine(n-1,k-1);
		for (int i = 0; i < pre_vec2.size(); i++) {
			pre_vec2[i].push_back(n);
			vec2.push_back(pre_vec2[i]);
		}
		vec1.insert(vec1.end(), vec2.begin(), vec2.end());//将另一个向量压入第一个向量中
		return vec1;
	}

};

同样的思路,一毛一样的过程。c++的速度比python快了两倍以上

77. 组合(c++,更换其他的思路)

思路:

这一次使用深搜的思路,一次成功,牛掰得不要不要的

效率:81.23%

时间:64ms

程序代码:

class Solution {
public:
	vector<int> tmp;
	vector<vector<int>> combine(int n, int k) {
		vector<vector<int>> result;
		vector<int> visited(n+1, 0);
		int index = 1;
		Haha(index,result,visited, n, k);//卧槽,今日的脑子有点智障
		return result;
	}
	void Haha(int index, vector<vector<int>> &result, vector<int> &visited, int n, int k) {
		if (tmp.size() == k) {
			result.push_back(tmp);
			return;
		}
		for (int i = index; i <= n; i++) {
			if (visited[i] == 0) {
				tmp.push_back(i);
				visited[i] = 1;
				Haha(i + 1, result, visited,n, k);
				tmp.pop_back();
				visited[i] = 0;//再次恢复原状
			}
		}
	}
};


int main() {
	int n, k;
	cin >> n >> k;
	Solution bb;
	vector<vector<int>> result = bb.combine(n,k);
	for (int i = 0; i < result.size(); i++) {
		for (int j = 0; j < result[0].size(); j++) {
			cout << result[i][j] << "**";
		}
		cout << endl;
	}
	return 0;
}

78. 子集

这一道题目是很久之前写的,但是考虑到和今天得题目有比较大的相似性,因此再重新写一次,并且考虑使用新的方法来提高一下效率。

思路:和77题可以使用相同的思路

效率:100%,卧槽,一不小心,效率居然是100%

程序代码:

class Solution {
public:
	vector<int> tmp;
	vector<vector<int>> subsets(vector<int>& nums) {
		vector<vector<int>> result;
		int index = 0;
		Haha(index,result,nums);//卧槽,今日的脑子有点智障
		return result;
	}
	void Haha(int index, vector<vector<int>> &result,vector<int> &nums) {
		if (index > nums.size()) return;
		result.push_back(tmp);
		for (int i = index; i <nums.size(); i++) {		
				tmp.push_back(nums[i]);
				Haha(i + 1, result,nums);
				tmp.pop_back();
		}
	}
};

需要注意的一点是,貌似压根不需要使用visited数组,因为在访问的时候有顺序。

把77题的最后一种解法去掉visited数组之后发现效率降低到了30%。

90. 子集 II

思路:

和78道题目的思路差不多,只是在之前对所有的元素进行了排序。

效率:99+%

时间:8ms

程序代码:

class Solution {
public:
	vector<int> tmp;
	vector<vector<int>> subsetsWithDup(vector<int>& nums) {
		vector<vector<int>> result;
		sort(nums.begin(),nums.end());
		int index = 0;
		Haha(index,result,nums);//卧槽,今日的脑子有点智障
		return result;
	}
	void Haha(int index, vector<vector<int>> &result,vector<int> &nums) {
		if (index > nums.size()) return;
		result.push_back(tmp);
		for (int i = index; i <nums.size(); i++) {	
			if (i!= index&&nums[i] == nums[i - 1])
				continue;//表示如果相同就不再考虑
			tmp.push_back(nums[i]);
			Haha(i + 1, result,nums);
			tmp.pop_back();
		}
	}
};

猜你喜欢

转载自blog.csdn.net/the_little_fairy___/article/details/84258993