51. N皇后
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例 1:
输入:n = 4 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] 解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1 输出:[["Q"]]
思路:也是做可以作为回溯算法的题型,把每一种情况枚举出来判断可不可行。不过在这一题中,判断是否可行好像需要花一点功夫,拿出来单独写一个函数好了。对整个棋盘,可以一行一行处理,每处理一行只需要判断前面添加过的行是否能满足要求。(初始化棋盘的时候需要注意,一个vector中要有n个有n个‘.’的字符串)。
代码实现:
class Solution {
private:
vector<vector<string>> result;
void backTrace(int row, int n, vector<string> &chessboard) {
if(row == n) { //添加到n行
result.push_back(chessboard);
return;
}
for(int col = 0; col < n; ++col) {
if(isValid(row, col, chessboard, n)) {
chessboard[row][col] = 'Q';
backTrace(row + 1, n, chessboard);
chessboard[row][col] = '.';
}
}
}
bool isValid(int row, int col, vector<string> &chessboard, int n) {
for(int i = 0; i < row; ++i) { //判断前面的每一行是否有皇后
if(chessboard[i][col] == 'Q') {
return false;
}
}
for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; --i, --j) {
if(chessboard[i][j] == 'Q') { //判断45度角
return false;
}
}
for(int i = row - 1, j = col + 1; i >= 0 && j < n; --i, ++j) {
if(chessboard[i][j] == 'Q') { //判断135度角
return false;
}
}
return true;
}
public:
vector<vector<string>> solveNQueens(int n) {
vector<string> chessboard(n, string(n, '.'));
backTrace(0, n, chessboard);
return result;
}
};
76. 最小覆盖子串
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
- 对于
t
中重复字符,我们寻找的子字符串中该字符数量必须不少于t
中该字符数量。 - 如果
s
中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC" 解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例 2:
输入:s = "a", t = "a" 输出:"a" 解释:整个字符串 s 是最小覆盖子串。
示例 3:
输入: s = "a", t = "aa" 输出: "" 解释: t 中两个字符 'a' 均应包含在 s 的子串中, 因此没有符合条件的子字符串,返回空字符串。
思路:运用滑动窗口的思想,遍历,对出现过的字符用哈希表计数,利用两个哈希表中特定字符数量大于或等于来延长子串(维护滑动窗口),最后用if判断哪个子串更短。其中,还需要一个valid值来记录有几个字符出现过了(valid == t.size( )就是终止条件)。
代码实现:
class Solution {
public:
string minWindow(string s, string t) {
string ret = s;
unordered_map<char,int> smap, tmap;
for(char c : t) {
tmap[c]++;
}
int i = 0;
int valid = 0;
bool flag = false;
for(int j = 0; j < s.size(); ++j) {
smap[s[j]]++; //维护right
if(tmap[s[j]] >= smap[s[j]]) { //计数
valid++;
}
while(smap[s[i]] > tmap[s[i]]) { //缩短窗口left
--smap[s[i]];
i++;
}
if(valid == t.size()) {
flag = true;
if(j - i + 1 < ret.size()) { //保留最小子串
ret = s.substr(i, j - i + 1);
}
}
}
if(flag == false) {
return "";
}
return ret;
}
};