[算法专题] 深度优先搜索&回溯剪枝

来源:互联网 发布:linux能运行在arm上吗 编辑:程序博客网 时间:2024/05/17 23:38

1. Palindrome Partitioning

https://leetcode.com/problems/palindrome-partitioning/

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

For example, given s = %26quot;aab%26quot;,
Return

  [    [%26quot;aa%26quot;,%26quot;b%26quot;],    [%26quot;a%26quot;,%26quot;a%26quot;,%26quot;b%26quot;]  ]
/** * author : Jianxin Zhou * email:zhoujx0219@163.com *  * 该题dfs函数原型如下: * void partitionHelper(const string %26amp;s, vector%26lt;vector%26lt;string%26gt;%26gt; %26amp;result, vector%26lt;string%26gt; %26amp;path, int pos) *  * 以aaba举例。 * 1. 首先a为回文,然后对aba进行dfs * 2. 之后回溯到a时,以aa为回文,然后对ba做dfs * 3. 回溯到aa,试图以aab为回文,失败;试图以aaba为回文失败;结束。 *  * 注意:如果能顺利的找到一组回文,那么pos最终会等于s.size(),此时可以push到result。 *       如果找不到,例如之前的aaba不是回文,那么就会直接退出循环,没有机会执行下一步递归,也就没有pos等于s.size了。 *  * 实际上,此类题与真正的dfs的差别在于,dfs在回溯时,不会进行剪枝操作。而此类题,由于需要求出所有方案,所以需要剪枝。 * */class Solution {public:    vector%26lt;vector%26lt;string%26gt;%26gt; partition(string s) {        vector%26lt;vector%26lt;string%26gt;%26gt; result;        vector%26lt;string%26gt; path;        partitionHelper(s, result, path, 0);        return result;    }    private:    void partitionHelper(const string %26amp;s, vector%26lt;vector%26lt;string%26gt;%26gt; %26amp;result, vector%26lt;string%26gt; %26amp;path, int pos) {        // base case        if (pos == s.size()) {            result.push_back(path);            return;        }                for (int i = pos; i %26lt; s.size(); i++) {            if (isPalindrome(s, pos, i)) {                path.push_back(s.substr(pos, i - pos + 1));                partitionHelper(s, result, path, i + 1);                path.pop_back();            }        }    }        bool isPalindrome(const string %26amp;s, int start, int end) {        while (start %26lt; end) {            if (s[start] == s[end]) {                start++;                end--;            } else {                break;            }        }                return start %26gt;= end;    }};

2. Permutations

https://leetcode.com/problems/permutations/

Given a collection of numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1],[3,1,2], and [3,2,1].

具体可参加我之前写的文章:[LintCode] Permutations

/** * 思路:dfs。 *  * 以123举例, * 1. 首先以1作为head,然后对23做dfs * 2. 回溯到1, 以2作为head,对13做dfs * 3. 最后回溯到2,以3作为head,对12做dfs *  * 注意:例如以2为head,对其余元素做dfs时,那么2不能再取,因此在进行下一轮dfs时,需要标记2为以访问过 *  */class Solution {public:    vector%26lt;vector%26lt;int%26gt;%26gt; permute(vector%26lt;int%26gt;%26amp; nums) {        vector%26lt;vector%26lt;int%26gt;%26gt; result;        vector%26lt;int%26gt; path;                bool visited[nums.size()];        for(int i = 0; i %26lt; nums.size(); i++) {            visited[i] = false;        }                sort(nums.begin(), nums.end());        dfs(nums, result, path, visited);        return result;    }    private:    void dfs(const vector%26lt;int%26gt; %26amp;nums, vector%26lt;vector%26lt;int%26gt;%26gt; %26amp;result, vector%26lt;int%26gt; %26amp;path, bool visited[]) {        // base case        if (path.size() == nums.size()) {            result.push_back(path);            return;        }        for (int i = 0; i %26lt; nums.size(); i++) {            if (visited[i] == false) {                path.push_back(nums[i]);                visited[i] = true;                dfs(nums, result, path, visited);                path.pop_back();                visited[i] = false;            }                    }    }};

3. Permutations II

https://leetcode.com/problems/permutations-ii/

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].

要点在于保证相同的数不在同一位置出现两次以上,可以参见我写的这篇文章:[LintCode] Permutations II

class Solution {public:    /**     * @param nums: A list of integers.     * @return: A list of unique permutations.     */    vector%26lt;vector%26lt;int%26gt; %26gt; permuteUnique(vector%26lt;int%26gt; %26amp;nums) {        // write your code here        vector%26lt;vector%26lt;int%26gt;%26gt; paths;        if (nums.empty()) {            return paths;        }                 sort(nums.begin(), nums.end());        bool *visited = new bool[nums.size()]();        vector%26lt;int%26gt; path;        permuteUniqueHelper(nums, visited, path, paths);        return paths;    }     private:    void permuteUniqueHelper(const vector%26lt;int%26gt; %26amp;nums,                             bool visited[],                             vector%26lt;int%26gt; %26amp;path,                             vector%26lt;vector%26lt;int%26gt;%26gt; %26amp;paths) {        if (path.size() == nums.size()) {            paths.push_back(path);            return;        }                  for (int ix = 0; ix %26lt; nums.size(); ix++) {            if (visited[ix] == true || ix %26gt; 0 %26amp;%26amp; nums[ix - 1] == nums[ix] %26amp;%26amp; visited[ix - 1] == false) {                continue;                }                         visited[ix] = true;            path.push_back(nums[ix]);            permuteUniqueHelper(nums, visited, path, paths);            visited[ix] = false;            path.pop_back();        }    }};

4 Subsets

https://leetcode.com/problems/subsets/

Given a set of distinct integers, 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,3], a solution is:

[  [3],  [1],  [2],  [1,2,3],  [1,3],  [2,3],  [1,2],  []]
/** * 思路:找方案,一般都是使用搜索。 *  * 以123为例,在递归还没有开始前,先把空集push到result中,之后: * 1. 以1位head,对23做dfs,所以pos需要加1,用于分支限界(1 12 13 123) * 2. 回溯到1,以2为head,对3做dfs (2 23) * 3. 回溯到3,以3为head,之后循环结束。 (3) *  *  */class Solution {public:    vector%26lt;vector%26lt;int%26gt;%26gt; subsets(vector%26lt;int%26gt;%26amp; nums) {        // ensure that elements in a subset must be in non-descending order.        sort(nums.begin(), nums.end());                vector%26lt;vector%26lt;int%26gt;%26gt; res;        vector%26lt;int%26gt; path;        dfs(nums, res, path, 0);        return res;    }    private:    void dfs(const vector%26lt;int%26gt; %26amp;nums, vector%26lt;vector%26lt;int%26gt;%26gt; %26amp;res, vector%26lt;int%26gt; %26amp;path, int pos) {        res.push_back(path);                for (int i = pos; i %26lt; nums.size(); i++) {            path.push_back(nums[i]);            dfs(nums, res, path, i + 1);            path.pop_back();        }    }};

5. Subsets II

https://leetcode.com/problems/subsets-ii/

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 solution is:

[  [2],  [1],  [1,2,2],  [2,2],  [1,2],  []]

同一位置上,前面取过的数,后面就不要再重复取了,当然当i = pos时,这个数必然是第一次取。

class Solution {public:    vector%26lt;vector%26lt;int%26gt;%26gt; subsetsWithDup(vector%26lt;int%26gt; %26amp;nums) {        sort(nums.begin(), nums.end());        vector%26lt;vector%26lt;int%26gt;%26gt; res;        vector%26lt;int%26gt; path;        dfs(nums, res, path, 0);        return res;    }    private:    void dfs(const vector%26lt;int%26gt; %26amp;nums, vector%26lt;vector%26lt;int%26gt;%26gt; %26amp;res, vector%26lt;int%26gt; %26amp;path, int pos) {        res.push_back(path);                for (int i = pos; i %26lt; nums.size(); i++) {            if (i != pos %26amp;%26amp; nums[i] == nums[i - 1]) {                continue;            }                        path.push_back(nums[i]);            dfs(nums, res, path, i + 1);            path.pop_back();        }    }};

(未完待续)







0 0
原创粉丝点击