这两道题目比较具有相似性,都是考察深搜,因此写在一起,希望有所广益。
由于最近主要在使用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();
}
}
};