Combination and Permutation 4 - Real Problem
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 as the above image.
Input:Digit string "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
Note:
Although the above answer is in lexicographical order, your answer could be in any order you want.
利用通用模板:
vector < string > letterCombinations ( string digits ) {
// DFS,深搜解法!!
if ( digits . empty ()) return vector < string > ();
const string hash [ 10 ] = { " " , "'" , "abc" , "def" , "ghi" ,
"jkl" , "mno" , "pqrs" , "tuv" , "wxyz" };
vector < string > res ;
letterCombinationsCore ( digits , res , "" , hash , 0 );
return res ;
}
void letterCombinationsCore ( string digits , vector < string > & res , string path ,
const string * hash , int start ) {
if ( start == digits . size ()) { //收敛条件,处理完了
res . push_back ( path );
return ;
}
//处理start,这里和模板有些许区别。循环处理start中代表的各个字母
for ( int i = 0 ; i < hash [ digits [ start ] - '0' ]. size (); i ++ ) {
letterCombinationsCore ( digits , res , path + hash [ digits [ start ] - '0' ][ i ],
hash , start + 1 );
}
}
增量构造法,简洁代码:时间复杂度O(n^3),空间复杂度O(1),BFS广搜解法
vector < string > letterCombinations ( string digits ) {
if ( digits . empty ()) return vector < string > ();
const string hash [ 10 ] = { " " , "'" , "abc" , "def" , "ghi" ,
"jkl" , "mno" , "pqrs" , "tuv" , "wxyz" };
//迭代法就OK 但是res里,必须是有至少1个值的,不能从0开始
vector < string > res ( 1 , "" ); //若times=0, 应该返回[""]!!
for ( int i = 0 ; i < digits . size (); i ++ ) { //还剩几个数字没处理
vector < string > copyRes ( res );
res . clear (); //每次都,只存入最新的!!
for ( int k = 0 ; k < copyRes . size (); k ++ ) //循环之前的每一个
//每一个新的数字,代表的每个字母加进去
for ( int j = 0 ; j < hash [ digits [ i ] - '0' ]. size (); j ++ )
res . push_back ( copyRes [ k ] + hash [ digits [ i ] - '0' ][ j ]);
}
return res ;
}
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s. 注意区别,不是DP ==> 是DFS
For example, given s = "aab",
Return
[
["aa","b"],
["a","a","b"]
]
通用模板:
//一个长度为 n 的字符串,有n-1个地方可以砍断,每个地方可断可不断,因此复杂度为O(2^n)
vector < vector < string >> partition ( string s ) {
vector < vector < string >> res ;
vector < string > path ;
partitionCore ( res , path , s , 0 );
return res ;
}
void partitionCore ( vector < vector < string >> & res , vector < string > & path , string s ,
int start ) {
if ( start == s . size ()) {
res . push_back ( path );
return ;
}
for ( int i = start ; i < s . size (); i ++ ) { //从start开始往后切
if ( isPalindrome ( s . substr ( start , i - start + 1 ))) {
path . push_back ( s . substr ( start , i - start + 1 ));
partitionCore ( res , path , s , i + 1 );
path . pop_back ();
}
}
}
// 可以优化加速:借鉴DP思想,用二维数组存i到j是否为回文
bool isPalindrome ( string s ) {
if ( s . size () <= 1 ) return true ;
int i = 0 , j = s . size () - 1 ;
while ( i <= j ) {
if ( s [ i ] != s [ j ]) return false ;
i ++ ; j -- ;
}
return true ;
}
Placing n queens on an n×n chessboard, and the queens can't be in the same row, column, diagonal line.Given an integer n, return all distinct solutions.
Each solution contains a distinct board configuration of the N-queens' placement, where 'Q' and '.' each indicate a queen and an empty space respectively.
return all distinct solutions -> DFS:
void printQ ( vector < vector < string >> & results , vector < vector < int >> & positions ) {
for ( auto pos : positions ) {
vector < string > res ;
for ( int i = 0 ; i < pos . size (); i ++ ) {
// string line {};
// for(int j = 0; j < pos.size(); j++) {
// if(j == pos[i]) line += "Q";
// else line += ".";
// }
string line ( pos . size (), '.' ); // 注意string的这种初始化方式,类似vector!
line [ pos [ i ]] = 'Q' ;
res . push_back ( line );
}
results . push_back ( res );
}
}
bool canput ( vector < int > & path , int pos ) {
for ( int i = 0 ; i < path . size (); i ++ ) {
if ( pos == path [ i ] || abs ( pos - path [ i ]) == path . size () - i ) {
return false ;
}
}
return true ;
}
void dfs ( vector < vector < int >> & positions , vector < int > & path , int row , int N ) {
if ( row == N ) {
positions . push_back ( path );
return ;
}
// 第row行,从0位置开始放
for ( int i = 0 ; i < N ; i ++ ) {
if ( ! canput ( path , i )) continue ; // 这种continue方式代码缩进更少
path . push_back ( i );
dfs ( positions , path , row + 1 , N );
path . pop_back ();
}
}
vector < vector < string >> solveNQueens ( int n ) {
// DFS
vector < vector < int >> positions ;
vector < int > path ;
dfs ( positions , path , 0 , n ); // 从第0行开始
vector < vector < string >> result ;
printQ ( result , positions );
return result ;
}
find the shortest transformation sequence from start to end, output the length of the sequence
find the shortest path -> BFS:
int ladderLength ( string & start , string & end , unordered_set < string > & dict ) {
// 最短长度,那就是BFS啦
unordered_set < string > visited ;
queue < string > q ;
q . push ( start );
visited . insert ( start );
int shortest = 2 ;
while ( ! q . empty ()) {
// 把上一轮的都pop出来
for ( int i = q . size (); i > 0 ; i -- ) {
string cur = q . front ();
q . pop ();
for ( char c = 'a' ; c <= 'z' ; c ++ ) {
for ( int l = 0 ; l < cur . size (); l ++ ) {
string nextcur = cur ;
nextcur [ l ] = c ;
// 先判断,如果对了,就退出了。因为end不在dict里
if ( nextcur == end ) return shortest ;
// 是它自己,或者dict里没有,就continue
if ( nextcur == cur || dict . find ( nextcur ) == dict . end ()) continue ;
if ( visited . find ( nextcur ) != visited . end ()) continue ; // !!别忘了,如果放过了,否则死循环
q . push ( nextcur );
visited . insert ( nextcur );
}
}
}
shortest ++ ;
}
return 0 ;
}
// 拓展:找出所有从start到end的最短转换序列
// 那么需要在BFS过程中,记录图的边map<string, vector<string>> next_word_dict;然后用DFS找distance为最短的path
// 剪枝:用距离,比如存unordered_map<string, int> distance(代替之前的visited),保证distance是一个越来越近的状态