[Leetcode] 74, 78, 90

来源:互联网 发布:银泰证券股票交易软件 编辑:程序博客网 时间:2024/05/31 11:03

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],  []]

Solution(1): 对于每个数,有两种可能:加入数组或者不加入数组。使用迭代构造数组。

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],  []]

Solution(1): 基本思路和上一题相同。但是对于重复的元素,如果其中一个舍弃了,那它之后的相同元素都被舍弃,以此避免子集重复。注意:此题必须提前排序。增量构造法。

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;    }};
原创粉丝点击