算法Day30 | 332.重新安排行程,51. N皇后,37. 解数独,总结ing

332.重新安排行程

题目链接:332.重新安排行程
对于容器的选择,既然要将 tickets 转为其他容器,还不如一步到位。省的转为 vector 再排序什么的。

就像将之前的题目中 used 对应的值设置为 truefalse,而不用从数组中删除元素一样,同理可将容器也给出相应的信息用来标记。
因此容器选择 unordered_map<string, map<string, int>>,其中 unordered_map 的选择是将航班的 起点终点 构造映射关系。终点信息也包含航班次数,是和used同样的原理:避免删除数组中元素。题目要求是字典序,所以选择终点结构为map<string, int>
整体容器表示为 <起点, <终点,起点到终点的次数>>

unordered_map<string, map<string, int>> targets;
for (auto& ticket : tickets) {
	targets[ticket[0]][ticket[1]]++;
}

targets[ticket[0]][ticket[1]]++ :
targets[ticket[0]] 表示为 unordered_mapvalue,即 map<string, int>
targets[ticket[0]][ticket[1]] 表示为 map<string, int>value

class Solution {
    unordered_map<string, map<string, int>> targets;//<起点, <终点,起点到终点的次数>>
    bool backtracking(int ticketSum, vector<string>& res) {
        if (res.size()/*通过res大小来确定飞了几次*/ == ticketSum + 1) {
            return true;
        }
        for (auto& [k, v] : targets[res.back()]/*表示以res.back()为起点,对应的航班信息*/) {
            if (v > 0/*票不为零,还有票*/) {
                res.push_back(k);//起飞
                --v;//少一张票
                if (backtracking(ticketSum, res)) return true;
                res.pop_back();
                ++v;
            }
        }
        return false;
    }
public:
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        for (auto& ticket : tickets) {
            targets[ticket[0]][ticket[1]]++;//将targets赋值
        }
        vector<string> res;
        res.push_back("JFK");//起点
        backtracking(tickets.size(), res);
        return res;
    }
};
for (auto& [k, v] : targets[res.back()]);
auto& [k, v] = targets[res.back()];

auto i = targets[res.back()];
i.begin()->first;

第一行和第二行代码的区别:
首先,第一行代码是在 targets 中搜索出 keyres.back()value,是有遍历的。
其次,第二行代码是错误的,map 不能使用结构化绑定来提取元素,结构化绑定是从数组或者 tuple 中提取元素,map 是关联容器,想要提取元素可以通过迭代器 begin()->first 等。
第四行表示 i 的类型为 targets 所对应的 value 的类型,而 i 的取值 和 res.back() 具体为多少无关。看看下面的例子

auto i1 = (int)3;
cout << is_same_v<decltype(i1), int>;//输出为1

51. N皇后

题目链接:51. N皇后

class Solution {
    vector<vector<string>> res;
    void backtracking(vector<string>& chessBoard, int n, int row) {
        if (row == n) {
            res.push_back(chessBoard);
            return;
        }
        for (int i = 0; i < n; ++i) {
            if (isValid(chessBoard, n, row, i)) {
                chessBoard[row][i] = 'Q';
                backtracking(chessBoard, n, row + 1);
                chessBoard[row][i] = '.';
            }
        }
    }
    bool isValid(vector<string>& chessBoard, int n, int row, int col) {
        //列
        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;
    }
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<string> chessBoard(n, string(n, '.'));
        backtracking(chessBoard, n, 0);
        return res;
    }
};

37. 解数独

题目链接:37. 解数独
就是一个一个试出来,别想复杂了。计算机的优势就是算力强。
双层 for 循环定位坐标,递归寻找坐标所填的数字

class Solution {
    bool backtracking(vector<vector<char>>& board) {
        for (int i = 0; i < board.size(); ++i) {
            for (int j = 0; j < board.size(); ++j) {
                if (board[i][j] == '.') {
                    for (char ch = '1'; ch <= '9'; ++ch) {
                        if (isValid(board, i, j, ch)) {
                            board[i][j] = ch;
                            if (backtracking(board)) return true;
                            board[i][j] = '.';
                        }
                    }
                    return false;//1-9都试过了,还到了这一步,明显失败了
                }
            }
        }
        return true;//没有返回false,那就是对了,返回true
    }
    bool isValid(vector<vector<char>>& board, int row, int col, char ch) {
        //行
        for (int i = 0; i < 9; ++i) {
            if (board[i][col] == ch)
                return false;
        }
        //列
        for (int j = 0; j < 9; ++j) {
            if (board[row][j] == ch)
                return false;
        }
        //3X3的格子
        int startRow = (row / 3) * 3;
        int startCol = (col / 3) * 3;
        for (int i = startRow; i < startRow + 3; ++i) {
            for (int j = startCol; j < startCol + 3; ++j) {
                if (board[i][j] == ch)
                    return false;
            }
        }
        return true;
    }
public:
    void solveSudoku(vector<vector<char>>& board) {
        backtracking(board);
    }
};

总结

留给第二次吧。画思维导图。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值