10.Regular Expression Matching
Implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
The function prototype should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
class Solution {
public:
bool isMatch(string s, string p) {
if(s.length()==0){
if (p.length() & 1) return false;
else{
for(int i=1;i<p.length();i+=2){
if(p[i]!='*') return 0;
}
}
return 1;
}
if(p.length()==0) return 0;
if(p.length()>1&&p[1]=='*'){
if(s[0]==p[0]||p[0]=='.'){
return isMatch(s.substr(1),p)||isMatch(s,p.substr(2));
}
else return isMatch(s,p.substr(2));
}
else if(s[0]==p[0]||p[0]=='.'){
return isMatch(s.substr(1),p.substr(1));
}
else return 0;
}
};
17. Letter Combinations of a Phone Number
Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.
Input:Digit string "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
class Solution {//法一
public:
const vector<string> keybord={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
vector<string> result;
void backtrack(string remain){
string th=keybord[remain[0]-'0'];
if(result.empty()){
for(auto i:th){
string str="";
str+=i;//若令str=""+i则不可以,因为只有将""创建为string时才可以对string类型使用+运算符
result.push_back(str);
}
}
else{
vector<string> temp=result;
result.clear();
for (int i=0;i<th.length();i++){
for(int j=0;j<temp.size();j++){
string tt=temp[j]+th[i];
result.push_back(tt);
}
}
}
if(remain.length()>1)
backtrack(remain.substr(1));
else return;
}
vector<string> letterCombinations(string digits) {
backtrack(digits);
return result;
}
};
class Solution {//法二(深度优先搜索dfs)
public:
const vector<string> keybord={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
vector<string> letterCombinations(string digits) {
if(digits=="") return{};
vector<string> result;
dfs(digits,0,"",result);
return result;
}
void dfs(string &digits,int start,string path,vector<string> &result){
if(start==digits.length()){
result.push_back(path);
return;
}
for(auto c:keybord[digits[start]-'0']){
dfs(digits,start+1,path+c,result);
}
}
};
22. Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
class Solution {
public:
vector<string> result;
void dfs(int n,int leftnum,string cur,int mached){
if(leftnum<0) return;
if(leftnum+mached>n) return;
if(mached==n&&leftnum==0) {
result.push_back(cur);
return;
}
dfs(n,leftnum+1,cur+'(',mached);
dfs(n,leftnum-1,cur+')',mached+1);
}
vector<string> generateParenthesis(int n) {
dfs(n,0,"",0);
return result;
}
};
37. 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) {
sove(board);
}
bool sove(vector<vector<char>>& board){
for(int i=0;i<board.size();i++){
for(int j=0;j<board.size();j++){
if(board[i][j]!='.') continue;
if(board[i][j]=='.'){
for(int k=1;k<=9;k++){
board[i][j]='0'+k;
if(isValidSudoku(board)&&sove(board)){
return true;//这里若用void类型函数作为回溯函数则无法判断是否已找到
}
board[i][j]='.';
}
}
return false;//i,j位置上填任何数都不合法;
}
}
return true;
}
bool isValidSudoku(vector<vector<char>>& board) //略
39. Combination Sum
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7]
and target 7
,
A solution set is:
[
[7],
[2, 2, 3]
]
class Solution {
public:
void dfs(vector<vector<int>>& result,vector<int>& candidates, int target,int start,vector<int>& cur)
{
if(target==0){
result.push_back(cur);
return;
}
if(target<0) return;
for(int i=start;i<candidates.size();i++){
cur.push_back(candidates[i]);
dfs(result,candidates,target-candidates[i],i,cur);
cur.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> result;
vector<int> cur;
dfs(result,candidates,target,0,cur);
return result;
}
};
40. Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
For example, given candidate set [10, 1, 2, 7, 6, 1, 5]
and target 8
,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
class Solution {
public:
void dfs(vector<vector<int>>& result,vector<int>& candidates, int target,int start,vector<int>& cur)
{
if(target==0){
result.push_back(cur);
return;
}
if(target<0) return;
for(int i=start;i<candidates.size();i++){
if(i>start&&candidates[i]==candidates[i-1]) continue;//要使结果不重复只要使遍历的首元素不重复即可
cur.push_back(candidates[i]);
dfs(result,candidates,target-candidates[i],i+1,cur);
cur.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<vector<int>> result;
vector<int> cur;
sort(candidates.begin(),candidates.end());
dfs(result,candidates,target,0,cur);
return result;
}
};
131. 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.
Example:
Input: "aab" Output: [ ["aa","b"], ["a","a","b"] ]
class Solution {
public List<List<String>> partition(String s) {
List<List<String>> res = new ArrayList<>();
if(s==null ||s.length()==0){
return res;
}
List<String> partition = new ArrayList<String>();
helper(s,0,partition,res);
return res;
}
private void helper(String s,int start,List<String> partition,List<List<String>> res){//双指针遍历
if(start==s.length()){//检查边界情况
res.add(new ArrayList<String>(partition));
}
for (int i = start;i<s.length();i++){//展开所有情况
if(ifPalindorme(s.substring(start,i+1))){
partition.add(s.substring(start,i+1));
helper(s,i+1,partition,res);
partition.remove(partition.size()-1);
}
}
}
private boolean ifPalindorme(String s){
char[] str = s.toCharArray();
int i =0;
int len = str.length;
while(i<=len-i-1){
if (str[i]!=str[len-i-1]){
return false;
}
i++;
}
return true;
}
}
总结一下,回溯法的一般步骤为
1 判断当前是否为解(匹配,合法...)
2检查边界情况
3遍历当前点的所有可能并一一展开
第10题和第37题属于一类问题——零一问题,即判断是否匹配,或者只有唯一解时需要判断能否解出此解。此类问题的辅助函数一般为bool型。
其余题为另一类——找所有解问题。此类问题的返回值一般为一个容器类,辅助函数一般为void类型。
class Solution(object):
def restoreIpAddresses(self, s):
def findip(self,s,start,result,cur,num)
if num == 4:
result.append(cur) if cur not in result
return
if (len(s)-start)>(4-num)*3:
return
if int(s[start:start+3])<256 and start+3<len(s):
findip(s,start+3,result,cur+s[start:start+3]+'.',num+1)
elif int(s[start:len(s)])<256 and start+3>=len(s):
findip(s,start+3,result,cur+s[start:len(s)],num+1)
elif start+3>=len(s) and int(s[start:len(s)])>255: return
else:
findip(s,start+2,result,cur+s[start:start+2]+'.',num+1)
findip(s,start+1,result,cur+s[start:start+1]+'.',num+1)