一、Gray Code

 class Solution
{
public:
vector<int> grayCode(int n)
{
vector<int> result={};
if(n==) return result;
return dfs(n);
}
vector<int> dfs(int n)
{
if(n==)
{
vector<int> v={,};
return v;
}
vector<int> tmp=dfs(n-);
int len=tmp.size();
for(int i=len-;i>=;i--)
{
tmp.push_back(tmp[i]+len);
}
return tmp;
}
};

这个方法主要是利用对称性。但是性能上并不是太好。最优解法应该是利用位运算。参考此代码中的第一个评论

需要注意,在n=0时返回的不是空vector,而是{0}.

二、Generate Parentheses

update 8.13

 class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string tmp;
string brackets("()");
dfs(res, tmp, n, , , brackets);
return res;
} void dfs(vector<string>& res, string tmp, int n, int left, int right, string brackets) {
if (left == n && right == n) {
res.push_back(tmp);
return;
}
for (int i = ; i < brackets.size(); i++) {
if ((i == && left <= right) || (left == n && i == )) {
continue;
}
tmp += brackets[i];
if (i == ) {
dfs(res, tmp, n, left + , right, brackets);
} else {
dfs(res, tmp, n, left, right + , brackets);
}
tmp.pop_back();
}
}
};

按照之前的套路来写的。就是对于dfs的for循环而言,应当是对于同一个位置的所有可能情况来循环的。

写的有点繁琐。

 class Solution
{
public:
vector<string> generateParenthesis(int n)
{
if(n==) return result;
finalPos=*n;
left=n;
right=n;
dfs();
return result;
}
void dfs(int n)
{
if(n==finalPos)
{
result.push_back(tmp);
return;
}
if(dif> && right>)
{
right--;
dif--;
tmp+=')';
dfs(n+);
tmp.resize(tmp.size()-);
right++;
dif++;
}
if(left>)
{
left--;
dif++;
tmp+='(';
dfs(n+);
tmp.resize(tmp.size()-);
left++;
dif--;
}
}
int finalPos;
int dif=;
string tmp;
int left;
int right;
vector<string> result;
};

下面的代码参考于此。非常巧妙,简洁。

 class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
addingpar(res, "", n, );
return res;
}
void addingpar(vector<string> &v, string str, int n, int m){
if(n== && m==) {
v.push_back(str);
return;
}
if(m > ){ addingpar(v, str+")", n, m-); }
if(n > ){ addingpar(v, str+"(", n-, m+); }
}
};

三、Permutation

1. Permutations

 class Solution
{
public:
vector<vector<int>> permute(vector<int> &num)
{
dfs(num);
return result;
}
private:
vector<vector<int>> result;
vector<int> path;
void dfs(vector<int> &num)
{
if(path.size()==num.size())
{
result.push_back(path);
return;
}
for(int i=;i<num.size();i++)
{
if(find(path.begin(),path.end(),num[i])==path.end())
{
path.push_back(num[i]);
dfs(num);
path.pop_back();
}
}
}
};

refer to soulMach.中规中矩,可以一用。

 class Solution
{
public:
vector<vector<int>> permute(vector<int> &nums)
{
len=nums.size();
vector<vector<int>> result;
for(int i=;i<nums.size();i++)
umap[nums[i]]=;
helper(result,umap,);
return result;
}
void helper(vector<vector<int>> &result,unordered_map<int,int> &umap,int n)
{
if(n==len)
{
result.push_back(tmp);
return;
}
for(auto it=umap.begin();it!=umap.end();it++)
{
if(it->second==)
{
tmp.push_back(it->first);
umap[it->first]=;
helper(result,umap,n+);
umap[it->first]=;
tmp.resize(tmp.size()-);
}
}
}
int len;
unordered_map<int,int> umap;
vector<int> tmp;
};

中规中矩的做法。不过多分配了一个umap.

较简洁的做法

 class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > result;
permuteRecursive(num, , result);
return result;
}
void permuteRecursive(vector<int> &num, int begin, vector<vector<int> > &result) {
if (begin >= num.size()) {
result.push_back(num);
return;
}
for (int i = begin; i < num.size(); i++) {
swap(num[begin], num[i]);
permuteRecursive(num, begin + , result);
swap(num[begin], num[i]);
}
}
};

2. Permutations II

 class Solution
{
public:
vector<vector<int>> permuteUnique(vector<int> &nums)
{
for(auto n:nums)
umap[n]++;
dfs(nums);
return result;
}
private:
vector<vector<int>> result;
vector<int> path;
unordered_map<int,int> umap;
void dfs(vector<int> &nums)
{
if(path.size()==nums.size())
{
result.push_back(path);
return;
}
for(auto p:umap)
{
if(p.second>)
{
path.push_back(p.first);
umap[p.first]--;//不能用p.second--.因为p是临时变量,影响不到umap。
dfs(nums);
umap[p.first]++;
path.pop_back();
}
}
}
};

注意:老是会忘刚开始时初始化umap!

比较奇怪的是,在dfs函数里,如果把对umap遍历改为对vector num遍历,就会TLE。

这里还遇到一个问题,就是我一开始遍历umap时用的是for(auto p:umap),然后对p.second做修改后是影响不到umap[p.first]的。因为这里的p相当于一个临时变量,无法影响umap的映射关系。如果换成指针的话就可以了。

对比两个permute。

对于不含重复元素的permute,如果以前没用过该元素,就可以用。即需要判定下path中是否含有该元素。若没有,即可用之。

对于含有重复元素的permute,借助于umap存储每个元素的个数。dfs时遍历umap,只要umap中该元素个数大于0,就可以用之。

四、Combination & Subset

1. Combinations

 class Solution
{
public:
vector<vector<int>> combine(int n, int k)
{
dfs(n, k, );
return result;
}
private:
vector<vector<int>> result;
vector<int> path;
void dfs(int n, int k, int start)
{
if (path.size() == k)
{
result.push_back(path);
return;
}
for (int i = start; i <= n; i++)
{
// if (find(path.begin(), path.end(), i) == path.end())
path.push_back(i);
dfs(n, k, i+ );//dfs(n, k, start + 1);
path.pop_back();
}
}
};

在combination里,和permutation不同的地方在于,为了保证不会出现重复,遍历的时候按照升序来,即后一个数一定要大于前一个数。

同时,由于保证了后一个数必定比前一个数大,那么其实就保证了唯一性,也就不用find去判断是否在path里出现过了。

另外注意for循环的i是从start开始,而next dfs里的start是取的i+1而不是start+1.

2. Subsets

递归版

[Templated]

 class Solution
{
public:
vector<vector<int>> subsets(vector<int> &nums)
{
sort(nums.begin(),nums.end());
dfs(nums,);
return result;
}
vector<vector<int>> result;
vector<int> path;
void dfs(vector<int> &nums,int start)
{
result.push_back(path);
for(int i=start;i<nums.size();i++)
{
path.push_back(nums[i]);
dfs(nums,i+);
path.pop_back();
}
}
};

该模板化版本和combination与subsets II都很类似。它和combination的区别在于,dfs函数一开始不需要判断长度就压入result,因为它不需要在乎长度。

和subsets II的区别在于,不用判重。

版本2:

 class Solution
{
public:
vector<vector<int>> subsets(vector<int> &nums)
{
sort(nums.begin(),nums.end());
dfs(nums,);
return result;
}
vector<vector<int>> result;
vector<int> path;
void dfs(vector<int> &nums, int step)
{
if(step==nums.size())
{
result.push_back(path);
return;
}
path.push_back(nums[step]);
dfs(nums,step+);
path.pop_back();
dfs(nums,step+);
}
};

一开始打算利用combinations,即依次指定combination的长度。但是那样很繁琐。

需要注意的是Elements in a subset must be in non-descending order。所以在操作之前需要先sort一下;

迭代版

 class Solution
{
public:
vector<vector<int>> subsets(vector<int> &nums)
{
vector<vector<int>> result(,vector<int>());
sort(nums.begin(),nums.end());
for(int i=;i<nums.size();i++)
{
int n=result.size();
for(int j=;j<n;j++)
{
result.push_back(result[j]);
result.back().push_back(nums[i]);
}
}
return result;
}
};

基本思路就是每次循环都把当前vector已有的子集合拷贝一份并在末尾添加一个新元素。再加入到vector里。比如对于{1,2,3},就先加入空,然后复制一下空并末尾添加1(当前子集合即为{空,{1}}),然后把空和{1}再各拷贝一份并在末尾添上2(即{2},{1,2}),并加入原vector。子集合变成了{空,{1},{2},{1,2}},再拷贝一份当前vector所有内容并在各自末尾添上3({3},{1,2},{2,3},{1,2,3}),并加入到vector里,变成(空,{1},{2},{1,2}, {3},{1,2},{2,3},{1,2,3})。

用二进制法也可以让空间复杂度降为O(1),参考soulMach。

3. Subsets II

 class Solution
{
public:
vector<vector<int>> subsetsWithDup(vector<int> &nums)
{
sort(nums.begin(),nums.end());
dfs(nums,);
return result;
}
vector<vector<int>> result;
vector<int> path;
void dfs(vector<int> &nums, int start)
{
result.push_back(path);
for(int i=start;i<nums.size();i++)
{
if(i!=start && nums[i]==nums[i-]) continue;
path.push_back(nums[i]);
dfs(nums,i+);
path.pop_back();
}
}
};

在产生path时,path的任何一个确定的位置(如第3个位置,第5个位置),都不选相同值的元素,这样就能防止结果中有重复。

那怎么叫确定的位置呢?在代码Line15的for循环里,遍历的每个元素都处于同一层,它们都是将要放置在或不放置在某一个相同的位置。(这里的位置值得是结果path中的位置,比如{1,2,3}这个path,第2个位置是2,第3个位置是3.) for 循环里的每个元素都是面临对同一个位置做取舍决定。

每嵌套调用一个dfs,就走的更深一层,体现在path的位数增加1. 类似于:

 dfs
{//现在path长度为1
dfs
{//现在path长度为2
dfs
{//现在path长度为3
......
}
//现在path长度又恢复为2.继续遍历for循环的下一元素来填充path
......
}
//现在path长度又恢复为1.继续遍历for循环的下一元素来填充path
......
}

回头去看,该算法就是保证了相同深度的path的末尾元素不选取选过的元素。所以可以通过在dfs里加个for循环(并且循环内部加个判断去重)来实现。

refer to this blog.

4. Combination Sum

 class Solution
{
public:
vector<vector<int>> combinationSum(vector<int> &candidates,int target)
{
sort(candidates.begin(),candidates.end());
dfs(candidates,,,target);
return result;
}
vector<vector<int>> result;
vector<int> path;
void dfs(vector<int> &nums, int start,int sum,int target)
{
if(sum>target) return;
if(sum==target)
{
result.push_back(path);
return;
}
for(int i=start;i<nums.size();i++)
{
path.push_back(nums[i]);
dfs(nums,i,sum+nums[i],target);
path.pop_back();
}
}
};

5. Combination Sum II

 class Solution
{
public:
vector<vector<int>> combinationSum2(vector<int> &candidates,int target)
{
sort(candidates.begin(),candidates.end());
dfs(candidates,,,target);
return result;
}
vector<vector<int>> result;
vector<int> path;
void dfs(vector<int> &nums, int start,int sum,int target)
{
if(sum>target) return;
if(sum==target)
{
result.push_back(path);
return;
}
for(int i=start;i<nums.size();i++)
{
if(i!=start && nums[i]==nums[i-]) continue;
path.push_back(nums[i]);
dfs(nums,i+,sum+nums[i],target);
path.pop_back();
}
}
};

Combination sum II 比 I 就多在加一个判重。和之前subsets II 比 I 多一句判重是一样的。

6. Combination Sum III

 class Solution
{
public:
vector<vector<int>> combinationSum3(int k,int n)
{
vector<int> nums={,,,,,,,,};
dfs(nums,k,n,,);
return result;
}
vector<vector<int>> result;
vector<int> path;
void dfs(vector<int> &nums,int k,int n,int start,int sum)
{
if(sum==n && path.size()==k)
{
result.push_back(path);
return;
}
if(sum>n||path.size()>=k) return;
for(int i=start;i<nums.size();i++)
{
path.push_back(nums[i]);
dfs(nums,k,n,i+,sum+nums[i]);
path.pop_back();
}
}
};

判断的时候多了个限制条件,需要既让sum相等同时也要让path.size()等于k。

小结:对于combination,subset这种题,元素顺序不同不能作为区分点(不像permutation那样)。因此为了防止dfs时会出现{1,2}和{2,1}这种,需要借助start这个机制来确保下一个将要遍历的元素在位置上必须在上一个遍历的元素之后。

五、Palindrome Partitioning

 class Solution
{
public:
vector<vector<string>> partition(string s)
{
dfs(,s);
return result;
}
vector<vector<string>> result;
vector<string> path;
void dfs(int start,string &s)
{
if(start==s.length())
{
result.push_back(path);
return;
}
for(int i=start;i<s.length();i++)
{
if(isPalindrome(s.substr(start,i-start+)))
{
path.push_back(s.substr(start,i-start+));
dfs(i+,s);
path.pop_back();
}
}
}
bool isPalindrome(string s)
{
if(s.empty()) return true;
int len=s.length();
for(int i=;i<len/;i++)
{
if(s[i]!=s[len-i-])
return false;
}
return true;
}
};

注意Line34,是s[len-1-i],不是s[len-i].

Palindrome Partitioning有DP解法。后序补充上。

六、Letter Combinations of a Phone Number

 class Solution
{
public:
vector<string> letterCombinations(string digits)
{
if(digits.empty()) return result;
initialization();
dfs(digits,);
return result;
}
private:
vector<string> result;
string path;
unordered_map<int,string> umap;
void dfs(string s,int step)
{
if(path.size()==s.size())
{
result.push_back(path);
return;
}
string tmp=umap[int(s[step]-'')];
for(int i=;i<tmp.size();i++)
{
path.push_back(tmp[i]);
dfs(s,step+);
path.pop_back();
}
}
void initialization()
{
umap[]="abc";
umap[]="def";
umap[]="ghi";
umap[]="jkl";
umap[]="mno";
umap[]="pqrs";
umap[]="tuv";
umap[]="wxyz";
umap[]=" ";
}
};

 注意:Line6!这种corner case要格外小心!

七、 Permutation Sequence

 class Solution
{
public:
string getPermutation(int n,int k)
{
string result(n,' ');
string s("");
string str=s.substr(,n);
k--;
for(int i=;i<n;i++)
{
int tmp=factorial(str.size()-);
int q=k/tmp;
result[i]=str[q];
str.erase(q,);
k-=tmp*q;
}
return result;
}
int factorial(int n)
{
if(n==) return ;
int result=;
for(int i=;i<=n;i++)
result*=i;
return result;
}
};

主要利用康托展开。康托展开详细内容参见此文

八、Sudoku

1. Sudoku Solver

 class Solution
{
public:
void solveSudoku(vector<vector<char>> &board)
{
dfs(board,);
}
bool dfs(vector<vector<char>> &board, int pos)
{
if(pos>=) return true;
int row=pos/;
int col=pos%;
if(board[row][col]!='.')
return dfs(board,pos+);
else
{
for(char c='';c<='';c++)
{
if(check(board,row,col,c))
{
board[row][col]=c;
if(dfs(board,pos+)) return true;
else board[row][col]='.';
}
}
return false;
}
}
bool check(vector<vector<char>> &board, int row,int col,char value)
{
for(int i=;i<;i++)
if(board[row][i]==value) return false;
for(int i=;i<;i++)
if(board[i][col]==value) return false;
for(int i=;i<;i++)
{
int r=row/*+i/;
int c=col/*+i%;
if(board[r][c]==value) return false;
}
return true;
}
};

注意一些技巧。Line11,12通过对board.size取余和取商,将二维的遍历转化为一维的遍历,每次只需pos++即可。

Line37,38也类似,对每个方块遍历时,(row/3*3,col/3*3)能得到坐标为(row,col)的点所在的方块的左上角的点对应的坐标。

2. Valid Sudoku

 class Solution {
public:
bool isValidSudoku(vector<vector<char>> &board)
{
vector<bool> mark(,false);
for(int i=;i<;i++)
{
fill(mark.begin(),mark.end(),false);
for(int j=;j<;j++)
{
if(board[i][j]=='.') continue;
if(mark[board[i][j]-'']==true) return false;
mark[board[i][j]-'']=true;
}
}
for(int j=;j<;j++)
{
fill(mark.begin(),mark.end(),false);
for(int i=;i<;i++)
{
if(board[i][j]=='.') continue;
if(mark[board[i][j]-'']==true) return false;
mark[board[i][j]-'']=true;
}
}
for(int i=;i<;i+=)
{
for(int j=;j<;j+=)
{
fill(mark.begin(),mark.end(),false);
for(int k=;k<;k++)
{
int row=i+k/;
int col=j+k%;
if(board[row][col]=='.') continue;
if(mark[board[row][col]-'']==true) return false;
mark[board[row][col]-'']=true;
}
}
}
return true;
}
};

分别从行,列,块的角度来check是否符合valid。(不是DFS类的,只是因为同属于Sudoku问题所以放进来。)

九、Restore IP Addresses

 class Solution
{
public:
vector<string> restoreIpAddresses(string s)
{
dfs(s,,);
return result;
}
vector<string> result;
string path;
void dfs(string s,int start,int step)
{
if (step == )
{
if (start == s.size())
result.push_back(path);
return;
}
for (int i = start; i < start + && i<s.size(); i++)
{
string tmp = s.substr(start, i - start + );
if (isValid(tmp))
{
path += tmp;
if (step < ) path += '.';
dfs(s,i+,step+);
path.resize(path.size()-tmp.size());
if (step < ) path.resize(path.size()-);
}
}
}
bool isValid(string s)
{
if (s.size() > && s[] == '') return false;
return (stoi(s) >= && stoi(s) <= );
}
};

第一遍做错了。除了标记start之外,还要记录当前partition几次了。超过4次就得return了。

十、Trie

1. Implement Trie (Prefix Tree)

 class TrieNode
{
public:
char content;
bool isend;
int shared;
vector<TrieNode*> children;
TrieNode():content(' '),isend(false),shared(){}
TrieNode(char ch):content(ch),isend(false),shared(){}
TrieNode* subNode(char ch)
{
for(auto child:children)
{
if(child->content==ch)
return child;
}
return NULL;
}
~TrieNode()
{
for(auto child:children)
delete child;
}
}; class Trie
{
private:
TrieNode* root;
public:
Trie()
{
root=new TrieNode();
}
void insert(string s)
{
if(search(s)) return;
TrieNode* curr=root;
for(auto ch:s)
{
TrieNode* child=curr->subNode(ch);
if(child!=NULL)
curr=child;
else
{
TrieNode* newNode=new TrieNode(ch);
curr->children.push_back(newNode);
curr=newNode;
}
++curr->shared;
}
curr->isend=true;
}
bool search(string key)
{
TrieNode* curr=root;
for(auto ch:key)
{
curr=curr->subNode(ch);
if(curr==NULL) return false;
}
return curr->isend==true;
}
bool startsWith(string prefix)
{
TrieNode* curr=root;
for(auto ch:prefix)
{
curr=curr->subNode(ch);
if(curr==NULL) return false;
}
return true;
}
~Trie()
{
delete root;
}
};

reference here.

2. Add and Search Word - Data structure design

 class TrieNode
{
public:
char content;
vector<TrieNode*> children;
bool isend;
int shared;
TrieNode* subNode(char ch)
{
for(auto child:children)
if(child->content==ch) return child;
return NULL;
}
TrieNode():content(' '),isend(),shared(){}
TrieNode(char ch):content(ch),isend(),shared(){}
~TrieNode()
{
for(auto child:children)
delete child;
}
}; class WordDictionary
{
public:
void addWord(string word)
{
TrieNode* curr=root;
for(auto ch:word)
{
TrieNode* child=curr->subNode(ch);
if(child!=NULL)
curr=child;
else
{
TrieNode* newNode=new TrieNode(ch);
curr->children.push_back(newNode);
curr=newNode;
}
}
curr->isend=true;
}
bool search(string word)
{
return dfs(word,root);
}
bool dfs(string word,TrieNode* root)
{
if(word.empty()) return root->isend;
if(word[]=='.')
{
for(auto child:root->children)
if(dfs(word.substr(,word.size()-),child)==true)
return true;
return false;
}
else
{
TrieNode* curr=root->subNode(word[]);
if(curr==NULL) return false;
else return dfs(word.substr(,word.size()-),curr);
}
}
WordDictionary()
{
root=new TrieNode();
}
~WordDictionary()
{
delete root;
}
private:
TrieNode* root;
};

主要是需要处理有通配符'.'的情况,search函数修改了一下。其他跟Implement Trie一样。

十一、字符串匹配

1. Regular Expression Matching

     class Solution
{
public:
bool isMatch(string s,string p)
{
return dfs(s,p,,);
}
bool dfs(string s,string p,int sStart,int pStart)
{
if(pStart==p.size()) return (sStart==s.size());
if(sStart>s.size()) return false;
if(p[pStart+]!='*')
{
if(p[pStart]==s[sStart]||(p[pStart]=='.'))
return dfs(s,p,sStart+,pStart+);
return false;
}
else
{
while(s[sStart]==p[pStart]||(p[pStart]=='.'&& sStart<s.size()))
{//相当于将x*替代为0~n个x
if(dfs(s,p,sStart,pStart+)==true)
return true;
sStart++;
}
return dfs(s,p,sStart,pStart+);//相当于将x*替代为0个x
}
}
};

主要是题意别理解错。正则表达式(Regex)和通配符(Wildcard)并不一样。通配符里的*是可以代表任意数量任意字符,而正则表达式里的*是指的*前面的字符可以连续重复使用任意次。正则表达式里的“.*”才等价于通配符里的“*”。

注意Line20最后,需要判断sStart<s.size()。

还有DP解法。在DP部分重做一遍。

2. Wildcard Matching

 class Solution
{
public:
bool isMatch(string s,string p)
{
return dfs(s,p,,);
}
bool dfs(string s,string p,int sStart,int pStart)
{
if(pStart==p.size()) return (sStart==s.size());
if(sStart>s.size()) return false;
if(p[pStart]!='*')
{
if(p[pStart]==s[sStart]||p[pStart]=='?')
return dfs(s,p,sStart+,pStart+);
return false;
}
else
{
while(sStart<s.size())
{
if(dfs(s,p,sStart,pStart+)==true) return true;
sStart++;
}
return dfs(s,p,sStart,pStart+);
}
}
};

参照上题模式来做。用dfs会TLE。但是对于面试应该可以用。

关于Line25存在的意义(不存在肯定不行,会返回一个乱七八糟的整数。因为运行到这里时没有合适的return语句,就会返回一个随便什么数。)思考一下这里的Line25以及上一道题里的。

我认为Line20 & 25可以替换为:

             while (sStart <= s.size())
{
if (dfs(s, p, sStart, pStart + ) == true) return true;
sStart++;
}
return false;

因为Line25之所以执行是因为前面的while语句一直到循环结束都没有符合要求的情况出现。原来的代码中,while循环是while (sStart < s.size()),因此当sStart等于s.size()时,就会执行Line25的内容。由于sStart==s.size()时仍是可能符合条件的(如果此时pStart也等于p.size()的话),因此直接return dfs(s,p,sStart,pStart+1)去判断是否符合条件即可。如果把while循环改为while (sStart <= s.size()),退出循环时是sStart==s.size()+1时,此时必然不可能符合要求了。因此Line25就直接return false。

以上属猜测。目测是对的。有机会找别的oj检验一下。

关于非递归做法,参考此答案。回头做一下。

十二、

1. Word Search

 class Solution
{
public:
bool exist(vector<vector<char>> &board,string word)
{
int m=board.size(),n=board[].size();
vector<vector<bool>> visited(m,vector<bool>(n,false));
for(int i=;i<m;i++)
{
for(int j=;j<n;j++)
{
if(dfs(board,word,i,j,visited,))
return true;
}
}
return false;
}
bool dfs(vector<vector<char>> &board,string word,int x,int y,vector<vector<bool>> &visited,int index)
{
if(index==word.size()) return true;
if(x<||y<||x>=board.size()||y>=board[].size()) return false;
if(visited[x][y]) return false;
if(board[x][y]!=word[index]) return false;
visited[x][y]=true;
bool result=dfs(board,word,x-,y,visited,index+)||dfs(board,word,x+,y,visited,index+)||
dfs(board,word,x,y-,visited,index+)||dfs(board,word,x,y+,visited,index+);
visited[x][y]=false;
return result;
}
};

refer to soulMach.

TO BE CONTINUED

2. Word Search II

3. Word Break II

4. Word Ladder II

leetcode Ch3-DFS & Backtracking II的更多相关文章

  1. LeetCode:路径总和II【113】

    LeetCode:路径总和II[113] 题目描述 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例:给定如下二叉树, ...

  2. LeetCode Single Number I / II / III

    [1]LeetCode 136 Single Number 题意:奇数个数,其中除了一个数只出现一次外,其他数都是成对出现,比如1,2,2,3,3...,求出该单个数. 解法:容易想到异或的性质,两个 ...

  3. [array] leetcode - 40. Combination Sum II - Medium

    leetcode - 40. Combination Sum II - Medium descrition Given a collection of candidate numbers (C) an ...

  4. LeetCode 137. Single Number II(只出现一次的数字 II)

    LeetCode 137. Single Number II(只出现一次的数字 II)

  5. LeetCode:组合总数II【40】

    LeetCode:组合总数II[40] 题目描述 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candi ...

  6. leetcode@ [126] Word Ladder II (BFS + 层次遍历 + DFS)

    https://leetcode.com/problems/word-ladder-ii/ Given two words (beginWord and endWord), and a diction ...

  7. Leetcode总结之Backtracking

    本文我们就Leetcode中的一个类型的题目backtracking进行一系列的总结和归纳.backtracking这个方法本质是建立在递归的基础上,不断尝试新的路径,这里关键是每次尝试完以后需要退回 ...

  8. LeetCode:Word Ladder I II

    其他LeetCode题目欢迎访问:LeetCode结题报告索引 LeetCode:Word Ladder Given two words (start and end), and a dictiona ...

  9. LeetCode: Word Break I && II

    I title: https://leetcode.com/problems/word-break/ Given a string s and a dictionary of words dict, ...

随机推荐

  1. JavaScript数据结构-16.二叉树计数

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 错误:‘lock_guard’ 在此作用域中尚未声明

    解决:修改报错文件,加入#include <boost/thread/lock_guard.hpp>

  3. 关于cmder 目录右键打开当前目录的方法

    在 Cmder 目录直接运行 cmder /register user或者cmder /register all

  4. 【TCP协议】MTU和MSS详解

    需要注意的是,区别两种帧封装格式:802标准帧和以太网帧 1,在802标准定义的帧格式中,长度字段是指它后续数据的字节长度,但不包括C R C检验码.RFC 1042(IEEE 802) 2,RFC ...

  5. RestTemplate的一个请求过程,mark一下

    来看下RestTemplate中默认的的ResponseErrorHandler: package org.springframework.web.client; import java.io.IOE ...

  6. [转]Redis 数据类型

    本文转自:http://www.runoob.com/redis/redis-data-types.html Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),s ...

  7. forms身份认证仍然能访问html页面解决办法

    asp.net的forms身份认证保护是一个非常棒的东西,用VS2010创建一个Web应用程序即可看到范例 在web.config中配置 <authentication mode="F ...

  8. Bundle传递数据,Handler更新UI

    Bundle主要用于传递数据:它保存的数据,是以key-value(键值对)的形式存在的. Bundle经常使用在Activity之间或者线程间传递数据,传递的数据可以是boolean.byte.in ...

  9. android FrameLayout

    FrameLayout:帧布局,可以显示图片的动画效果 前景图像: 永远处于帧布局最顶的,直接面对用户的图像,,就是不会被覆盖的图片 常用属性: android:foreground:设置该帧布局容器 ...

  10. [模板]选择排序&&冒泡排序&&插入排序

    #include<iostream> #include<cstdio> #include<bits/stdc++.h> using namespace std; v ...