74. Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
- Integers in each row are sorted from left to right.
- The first integer of each row is greater than the last integer of the previous row.
For example,
Consider the following matrix:
[ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ]
Given target = 3
, return true
.
Solution: 二分查找,通过下标转换将一维下标转换成二维下标。
Code:
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size()==0 || matrix[0].size()==0) return false;
int first = 0;
int m = matrix[0].size(); //注意这里不要写错
int x,y,mid;
int last = matrix.size() * matrix[0].size();
while(first<last){
mid = first + (last-first)/2;
x = mid/m;
y = mid%m;
if(target <= matrix[x][y])
last = mid;
else
first = mid+1;
}
x = first/m;
y = first%m;
if(first==(matrix.size() * matrix[0].size()) || matrix[x][y]!=target)
return false;
else
return true;
}
};
78. Subsets
Given a set of distinct integers, nums, return all possible subsets.
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3]
, a solution is:
[ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
Code:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ans;
ans.push_back(vector<int>());
for(int i=0; i<nums.size(); i++){
int size = ans.size();
for(int t=0; t<size; t++){
ans.push_back(ans[t]);
ans[t+size].push_back(nums[i]);
}
}
return ans;
}
};
Solution(2): 增量构造法,递归实现。
Code:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> path;
vector<vector<int>> ans;
subsets(nums, 0, path, ans);
return ans;
}
private:
void subsets(vector<int>& nums, int cur, vector<int>& path, vector<vector<int>>& ans){
if(cur==nums.size()){
ans.push_back(path);
return;
}
subsets(nums, cur+1, path, ans);
path.push_back(nums[cur]);
subsets(nums, cur+1, path, ans);
path.pop_back();
}
};
Solution(3): 位向量法,构造一个位向量path,而不是直接。
Code(1):
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<bool> path(nums.size(), false);
vector<vector<int>> ans;
subsets(nums, 0, path, ans);
return ans;
}
private:
void subsets(vector<int>& nums, int cur, vector<bool>& path, vector<vector<int>>& ans){
if(cur==nums.size()){
vector<int> subset;
for(int i=0; i<nums.size(); i++)
if(path[i]) subset.push_back(nums[i]);
ans.push_back(subset);
return;
}
subsets(nums, cur+1, path, ans);
path[cur] = true;
subsets(nums, cur+1, path, ans);
path[cur] = false;
}
};
Code(2): 二进制法,使用一个整型来替代位向量法中的path数组,用整型二进制的每一位表示数组中的一位bool值,但是这种做法有个前提就是nums的大小不能超过整型的位数。这种方法最巧妙,因为不仅能够生成子集,还能方便的表示集合的交并差运算。设两个集合的位向量分别为B1 和B2,则B1|B2;B1&B2;B1^B2 分别对应集合的并、交、对称差。(注:对称差即所有在B1中或B2中,但不同时在B1和B2中的元素)。
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
int path = 0;
vector<vector<int>> ans;
subsets(nums, 0, path, ans);
return ans;
}
private:
void subsets(vector<int>& nums, int cur, int path, vector<vector<int>>& ans){
if(cur==nums.size()){
vector<int> subset;
for(int i=0; i<nums.size(); i++){
if(path%2) subset.push_back(nums[i]);
path = path>>1;
}
ans.push_back(subset);
return;
}
subsets(nums, cur+1, path, ans);
path = path | (1<<cur);
subsets(nums, cur+1, path, ans);
}
};
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], [] ]
Code(1): 这种写法在几种方法中在leetcode上的运行时间最短(6ms)。
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> path;
vector<vector<int>>(ans);
subsetsWithDup(nums, 0, path, ans);
return ans;
}
private:
void subsetsWithDup(vector<int>& nums, int cur, vector<int>& path, vector<vector<int>>& ans){
if(cur==nums.size()){
ans.push_back(path);
return;
}
int next = cur+1;
while(next!=nums.size() && nums[next]==nums[cur]) next++;
subsetsWithDup(nums, next, path, ans);
path.push_back(nums[cur]);
subsetsWithDup(nums, cur+1, path, ans);
path.pop_back();
}
};
Code(2):
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> path;
vector<vector<int>>(ans);
subsetsWithDup(nums, 0, path, ans);
return ans;
}
private:
void subsetsWithDup(vector<int>& nums, int start, vector<int>& path, vector<vector<int>>& ans){
ans.push_back(path);
for(int i=start; i<nums.size(); i++){
if(i!=start && nums[i]==nums[i-1]) continue;
path.push_back(nums[i]);
subsetsWithDup(nums, i+1, path, ans);
path.pop_back();
}
}
};
Solution(2): 迭代。
Code:
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
ans.push_back(vector<int>());
int prev_size = ans.size();
for(int i=0; i<nums.size(); i++){
int size = ans.size();
int start = 0;
if(i!=0 && nums[i]==nums[i-1]) start = prev_size; //为了避免重复,重复的元素只能加入到前一个相同元素存在的子集中
for(int t=start; t<size; t++){
ans.push_back(ans[t]);
ans.back().push_back(nums[i]);
}
prev_size = size;
}
return ans;
}
};