# 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 = "aab",
Return

  [
["aa","b"],
["a","a","b"]
]
/**
* author ： Jianxin Zhou
* email：zhoujx0219@163.com
*
* 该题dfs函数原型如下：
* void partitionHelper(const string &s, vector<vector<string>> &result, vector<string> &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<vector<string>> partition(string s) {
vector<vector<string>> result;
vector<string> path;
partitionHelper(s, result, path, 0);
return result;
}

private:
void partitionHelper(const string &s, vector<vector<string>> &result, vector<string> &path, int pos) {
// base case
if (pos == s.size()) {
result.push_back(path);
return;
}

for (int i = pos; i < 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 &s, int start, int end) {
while (start < end) {
if (s[start] == s[end]) {
start++;
end--;
} else {
break;
}
}

return start >= 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].

/**
* 思路：dfs。
*
* 以123举例，
*
*
*/

class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
vector<int> path;

bool visited[nums.size()];
for(int i = 0; i < nums.size(); i++) {
visited[i] = false;
}

sort(nums.begin(), nums.end());
dfs(nums, result, path, visited);
return result;
}

private:
void dfs(const vector<int> &nums, vector<vector<int>> &result, vector<int> &path, bool visited[]) {
// base case
if (path.size() == nums.size()) {
result.push_back(path);
return;
}

for (int i = 0; i < 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].

class Solution {
public:
/**
* @param nums: A list of integers.
* @return: A list of unique permutations.
*/
vector<vector<int> > permuteUnique(vector<int> &nums) {
vector<vector<int>> paths;
if (nums.empty()) {
return paths;
}

sort(nums.begin(), nums.end());
bool *visited = new bool[nums.size()]();
vector<int> path;
permuteUniqueHelper(nums, visited, path, paths);
return paths;
}

private:
void permuteUniqueHelper(const vector<int> &nums,
bool visited[],
vector<int> &path,
vector<vector<int>> &paths) {
if (path.size() == nums.size()) {
paths.push_back(path);
return;
}

for (int ix = 0; ix < nums.size(); ix++) {
if (visited[ix] == true || ix > 0 && nums[ix - 1] == nums[ix] && 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)
*
*
*/

class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
// ensure that elements in a subset must be in non-descending order.
sort(nums.begin(), nums.end());

vector<vector<int>> res;
vector<int> path;
dfs(nums, res, path, 0);
return res;
}

private:
void dfs(const vector<int> &nums, vector<vector<int>> &res, vector<int> &path, int pos) {
res.push_back(path);

for (int i = pos; i < 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],
[]
]

class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int> &nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> res;
vector<int> path;
dfs(nums, res, path, 0);
return res;
}

private:
void dfs(const vector<int> &nums, vector<vector<int>> &res, vector<int> &path, int pos) {
res.push_back(path);

for (int i = pos; i < nums.size(); i++) {
if (i != pos && nums[i] == nums[i - 1]) {
continue;
}

path.push_back(nums[i]);
dfs(nums, res, path, i + 1);
path.pop_back();
}
}
};

Given a string containing only digits, restore it by returning all possible valid IP address combinations.

For example:
Given "25525511135",

return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)

/**
* 该题思路与求回文划分相似
*/

class Solution {
public:
vector<string> res;

size_t len = s.size();
if (len < 4 || len > 12) {
return res;
}

vector<string> path;
dfs(s, res, path, 0);
return res;
}

private:
void dfs(const string &s, vector<string> &res, vector<string> &path, int pos) {
// base case
if (path.size() == 4) {
if (pos != s.size()) {
return;
}

string returnElem;
for (const auto &elem : path) {
returnElem += elem;
returnElem += ".";
}
returnElem.erase(returnElem.end() - 1);

res.push_back(returnElem);
return;
}

for (int i = pos; i < s.size() && i < pos + 3; i++) {
string tmp = s.substr(pos, i - pos + 1);
if (isValid(tmp)) {
path.push_back(tmp);
dfs(s, res, path, i + 1);
path.pop_back();
}
}
}

bool isValid(const string &s) {
// 排除 055 之类的数字
if (s[0] == '0' && s.size() > 1) {
return false;
}

int digit = atoi(s.c_str());
return 0 <= digit && digit <= 255;
}
};

# 7 N-Queens

http://www.lintcode.com/en/problem/n-queens/#

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

For example,
There exist two distinct solutions to the 4-queens puzzle:

[
[".Q..",  // Solution 1
"...Q",
"Q...",
"..Q."],

["..Q.",  // Solution 2
"Q...",
"...Q",
".Q.."]
]
/**
* 思路：一行一行的取数，例如第一行的皇后放在第1个位置，第二行的皇后放在第3个位置，
* 以此类推，直到最后一行的皇后放在正确的位置，如此视为一个方案，push到result中
*
* 显然，本题使用dfs，每一行可取的位置从0-N-1，
* 需要注意的是，每一行在取位置的时候，需要判断有效性（是否可以相互攻击）。
*/

class Solution {
public:
/**
* Get all distinct N-Queen solutions
* @param n: The number of queens
* @return: All distinct solutions
* For example, A string '...Q' shows a queen on forth position
*/
vector<vector<string> > solveNQueens(int n) {
vector<vector<string>> res;
vector<int> visitedCol;

if (n <= 0) {
return res;
}

dfs(n, res, visitedCol);
return res;
}

private:
void dfs(const int n, vector<vector<string>> &res, vector<int> &visitedCol) {
// base case
if (visitedCol.size() == n) {
res.push_back(draw(visitedCol));
return;
}

for (int i = 0; i < n; i++) {
if (!isValid(visitedCol, i)) {
continue;
}

visitedCol.push_back(i);
dfs(n, res, visitedCol);
visitedCol.pop_back();
}

}

bool isValid(const vector<int> &visitedCol, const int currentCol) {
size_t currentRow = visitedCol.size();

for (int rowIndex = 0; rowIndex < visitedCol.size(); rowIndex++) {
if (currentCol == visitedCol[rowIndex]) {
return false;
}

if (currentRow + currentCol == rowIndex + visitedCol[rowIndex]) {
return false;
}

if (currentRow - currentCol == rowIndex - visitedCol[rowIndex]) {
return false;
}
}

return true;
}

vector<string> draw(const vector<int> &visitedCol) {

vector<string> ret;
string row;
for (const auto &elem : visitedCol) {
row.clear();

for (int i = 0; i < visitedCol.size(); i++) {
if (i == elem) {
row += "Q";
} else {
row += ".";
}
}

ret.push_back(row);
}

return ret;
}
};

# 8 Sudoku Solver

https://leetcode.com/problems/sudoku-solver/

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.

A sudoku puzzle...

...and its solution numbers marked in red.

class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
dfs (board, 0, 0);
}

private:
/**
* 该题需要对sudoku中每一个以‘.’标记的方格进行dfs，
* 1. 如果对当前方格的以1-9这9个数字进行遍历，都不合法，那么不会再往下一个方格进行dfs，直接回溯到上一个方格取下一个数。
* 2. 如果当前方格所取的数合法，那么继续对下一个方格进行dfs，依次下去如果一直合法，那么直到走到sudoku中的最后一个需要放数字的方格，
*    尝试完它的所有选择，再往上回溯。
* 然后，在这边我们只需要一个可行解即可，因此只要当前方格合法，往下的dfs返回true，那么即为一个解，直接返回。
*
*
*
*/
bool dfs(vector<vector<char>> &board, int x, int y) {

for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
//dfs
if (board[i][j] == '.') {
// k从0-9走完才算走完,但是此处我们只要有一个解，就可以返回了，因此在以下循环中设置了return语句
for (int k = 0; k < 9; k++) {
bool flag;

if (!isValid(board, i ,j, k)) {
continue;
}

board[i][j] = '1' + k;

if (j != 8) {
flag = dfs(board, i, j + 1);
} else {
flag = dfs(board, i + 1, 0);
}

// 当前合法&&下一轮dfs合法，说明找到解
if (flag) {
return true;
}

board[i][j] = '.';
}

// 遍历完9个数，仍然找不到合适的解，则返回false
return false;
}
}
}

// 当所有各自都走完，自然返回true（注意只有当前合法，才会继续往下走，继续往下走的最终结果是越了sudoku的界限）
return true;

}

bool isValid(const vector<vector<char>> &board, int x, int y, int k) {
int i, j;
for (i = 0; i < 9; i++) // 检查 y 列
if (i != x && board[i][y] == '1' + k)
return false;

for (j = 0; j < 9; j++) // 检查 x 行
if (j != y && board[x][j] == '1' + k)
return false;

for (i = 3 * (x / 3); i < 3 * (x / 3 + 1); i++)
for (j = 3 * (y / 3); j < 3 * (y / 3 + 1); j++)
if ((i != x || j != y) && board[i][j] == '1' + k)
return false;

return true;
}
};


# 小结2

posted @ 2015-08-07 21:59  Acjx  阅读(3492)  评论(2编辑  收藏  举报