90.子集II
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex, vector<bool>& used){
result.push_back(path);// 收集子集,要放在终止添加的上面,否则会漏掉自己
// if(startIndex >= nums.size()) return;
for(int i=startIndex; i<nums.size(); i++){
if(i>0 && nums[i]==nums[i-1] && used[i-1]==false) continue;
path.push_back(nums[i]);
used[i]=true;
backtracking(nums,i+1,used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
result.clear();
path.clear();
vector<bool> used(nums.size(),false);
sort(nums.begin(),nums.end());
backtracking(nums, 0, used);
return result;
}
};
491.递增子序列
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex){
if(path.size()>1)
result.push_back(path);// 收集子集,要放在终止添加的上面,否则会漏掉自己
unordered_set<int> uset;
for(int i=startIndex; i<nums.size(); i++){
if((!path.empty() && nums[i]<path.back()) || uset.find(nums[i]) != uset.end() )
continue;
uset.insert(nums[i]);
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
result.clear();
path.clear();
//vector<bool> used(nums.size(),false);
backtracking(nums, 0);
return result;
}
};
此种解答 有问题,
前面的几题,自己不强调顺序,因此可以对原数组排序后采用used数组,而递增子序列需要保证原数组顺序,不可对原数组进行排序,因此nums[i]==nums[i-1]这个条件不适用,像4 7 6 7,nums[i]==nums[i-1] 对 7 和 6 不适用。
遗失的美好:
nums[i] 需要 不等于 前面所有的num[0]~nums[i-1]
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex, vector<bool>& used){
if(path.size()>1)
result.push_back(path);
for(int i=startIndex; i<nums.size(); i++){
if((!path.empty() && nums[i]<path.back()) || (i>0 && nums[i]==nums[i-1] && used[i-1]==false))
continue;
path.push_back(nums[i]);
used[i]=true;
backtracking(nums,i+1,used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
result.clear();
path.clear();
vector<bool> used(nums.size(),false);
backtracking(nums, 0, used);
return result;
}
};
可以写一个 for循环 然后判断一下?不行,1个continue 不能连跳 两个循环
if((!path.empty() && nums[i]<path.back()) || (i>0 && nums[i]==nums[i-1] && used[i-1]==false))
continue;
改为:
if(!path.empty() && nums[i]<path.back()) continue;
for(int j=0;j<i;j++){
if(i>0 && nums[i]==nums[j] && used[j]==false)
continue;
}
还是不行,只能用set
46.全排列
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, vector<bool>& used) {
if (path.size() == nums.size()) {
result.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
if(used[i] == true) continue;
used[i]=true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
result.clear();
path.clear();
vector<bool> used(nums.size(),false);
backtracking(nums, used);
return result;
}
};
47.全排列 II
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, vector<bool>& used) {
if (path.size() == nums.size()) {
result.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
if(used[i] == true) continue;
if(i>0 && nums[i]==nums[i-1] && used[i-1]==false) continue;
used[i]=true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
result.clear();
path.clear();
vector<bool> used(nums.size(),false);
sort(nums.begin(),nums.end());
backtracking(nums, used);
return result;
}
};
332. 重新安排行程
还是有一点问题,没找到 问题在哪,超时了,有一个用例通过不了。
class Solution {
private:
vector<string> path={"JFK"};
vector<string> res;
void backtracking(vector<vector<string>>& tickets,string from,vector<int>& used){
if(used.back()==tickets.size()){
res=path;
return;
}
for(int i=0;i<tickets.size();i++){
if(tickets[i][0]==from&&used[i]==0){
used[i]=1;
used[tickets.size()]+=1;
path.push_back(tickets[i][1]);
backtracking(tickets,tickets[i][1],used);
path.pop_back();
used[i]=0;
used[tickets.size()]-=1;
}
if(res.size()){
return;
}
}
}
public:
static bool combine(const vector<string>& a,const vector<string>& b){
return a[1]<b[1];
}
vector<string> findItinerary(vector<vector<string>>& tickets) {
sort(tickets.begin(),tickets.end(),combine);
vector<int> used(tickets.size()+1,0);
backtracking(tickets,"JFK",used);
return res;
}
};
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
class Solution {
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
sort(tickets.begin(), tickets.end(), [](const vector<string>& a, const vector<string>& b) {
return a[1] < b[1];
});
path.emplace_back("JFK");
vector<bool> used(tickets.size(), false);
backTracking(tickets, used);
return result;
}
bool backTracking(vector<vector<string>>& tickets, vector<bool>& used) {
if (path.size() == tickets.size() + 1) {
result = path;
return true;
}
for (int i = 0; i < tickets.size(); i++) {
if (!used[i] && tickets[i].front() == path.back()) {
path.push_back(tickets[i][1]);
used[i] = true;
if (backTracking(tickets, used)) {
return true;
}
used[i] = false;
path.pop_back();
}
}
return false;
}
private:
vector<string> result;
vector<string> path;
};
// int main() {
// Solution solution;
// vector<vector<string>> tickets = {{"MUC", "LHR"}, {"JFK", "MUC"}, {"SFO", "SJC"}, {"LHR", "SFO"}};
// vector<string> itinerary = solution.findItinerary(tickets);
// for (const string& city : itinerary) {
// cout << city << " ";
// }
// cout << endl;
// return 0;
// }
51. N皇后
class Solution {
public:
/*验证棋盘是否合法
按照如下标准去重:
不能同行
不能同列
不能同斜线 (45度和135度角)*/
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;
}
}
// 检查 45度角是否有皇后
for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
// 检查 135度角是否有皇后
for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
return true;
}
vector<vector<string>> result;
// n 为输入的棋盘大小
// row 是当前递归到棋盘的第几行了
void backtracking(int n,int row,vector<string>& chessboard){
if(row==n){
result.push_back(chessboard);
return;
}
for(int i=0;i<n;i++){
if(isValid(row,i,chessboard,n)){
chessboard[row][i]='Q';
backtracking(n,row+1,chessboard);
chessboard[row][i]='.';
}
}
}
vector<vector<string>> solveNQueens(int n) {
result.clear();
std::vector<std::string> chessboard(n, std::string(n, '.'));
/*创建一个n*n的棋盘,vector表示一个动态数组,
string表示一个字符串,string初始化为一个由n个‘.’组成的字符串,
然后这个字符串复制n次,,得到了n行n列的棋盘。*/
backtracking(n, 0, chessboard);
return result;
}
};
37. 解数独
class Solution {
public:
bool isValid(int row, int col, char val, vector<vector<char>>& board) {
for (int i = 0; i < 9; i++) { // 判断行里是否重复
if (board[row][i] == val) {
return false;
}
}
for (int j = 0; j < 9; j++) { // 判断列里是否重复
if (board[j][col] == val) {
return false;
}
}
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for (int i = startRow; i < startRow + 3; i++) { // 判断9方格里是否重复
for (int j = startCol; j < startCol + 3; j++) {
if (board[i][j] == val ) {
return false;
}
}
}
return true;
}
bool backtracking(vector<vector<char>>& board){
for(int i = 0; i < board.size(); i++){// 遍历行
for (int j = 0; j < board[0].size(); j++) { // 遍历列
if(board[i][j] == '.'){
for(char k='1';k<='9';k++){// (i, j) 这个位置放k是否合适
if(isValid(i,j,k,board)){
board[i][j]=k; // 放置k
if(backtracking(board))
return true;// 如果找到合适一组立刻返回
board[i][j]='.'; // 回溯,撤销k
}
}
return false; // 9个数都试完了,都不行,那么就返回false
}
}
}
return true;// 遍历完没有返回false,说明找到了合适棋盘位置了
}
void solveSudoku(vector<vector<char>>& board) {
backtracking(board);
}
};