“21 天好习惯”第一期-4

本文探讨了经典的N皇后问题的进阶版本,其中要求每个皇后都能看到其他的皇后。通过深度优先搜索(DFS)结合剪枝策略,实现了解决方案。同时,文章还介绍了离散数学中的集合运算,包括并、交、相对补和对称差,并简单提及了计算机组成原理中的计算机指令和运算。此外,还展示了如何使用单调栈解决LeetCode的每日一题,寻找数组中每个数右边的第一个更大数。
摘要由CSDN通过智能技术生成

目录

开心果:

离散数学:

计算机组成原理:

leetcode每日一题:


开心果:

一道 n 皇后 的进阶题 ( 多了点条件

首先再复习一下 n 皇后的 dfs + 剪枝 + 回溯 解法:

n 皇后 次元门

解题: 按行暴力枚举可能放置皇后的列 , 逐层判断每列是否能放下皇后 , 不能则回溯到上一行.

class Solution {
private:
    vector<string>Map;
    vector<vector<string>>re;

    bool cheak(int row , int col , int n){
        for(int i = 0;i < row;i ++) if(Map[i][col] == 'Q') return false;

        int r = row - 1 , c = col - 1;
        while(r >= 0 && c >= 0){
            if(Map[r][c] == 'Q') return false;
            r -- , c --;
        }

        r = row - 1 , c = col + 1;
        while(r >= 0 && c < n){
            if(Map[r][c] == 'Q') return false;
            r -- , c ++;
        }

        return true;
    }

    void dfs(int n , int row){
        if(row == n){ re.push_back(Map); return; }

        for(int col = 0;col < n;col ++){
            if(cheak(row , col , n)) Map[row][col] = 'Q' , dfs(n , row + 1) , Map[row][col] = '.';
        }

        return;
    }
 
public:
    vector<vector<string>> solveNQueens(int n) {
        string s(n , '.');
        for(int i = 0;i < n;i ++) Map.push_back(s);

        dfs(n , 0);

        return re;
    }
};

进阶版本:

ps: 比常规的 n皇后 多了 "每个皇后都能看到其她所有的皇后"; 即不存在在同一直线上的皇后.

解题: 就是cheak函数中再多加一个判断条件即可.

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
const int N = 1000;
vector<int>nums(N , 0);
int n , cnt = 0;

void Print(int n){
    for(int i = 1;i <= n;i ++){
        if(i != 1) cout << ' ';
        cout << nums[i];
    }cout << endl;
}

bool cheak(int row , int col , int n){
    for(int i = 1; i < row; i++) 
        if(nums[i] == col || abs(i - row) == abs(nums[i] - col)) 
            return false;
    
    for(int i = 1;i < row;i ++) 
        for(int j = row - 1;j > i;j --) 
            if((row - j) * (col - nums[i]) == (row - i) * (col - nums[j])) return false;

    return true;
}

bool dfs(int n , int row){
    if(cnt) return true;
    
    if(row == n + 1){ Print(n) , cnt = 1; return true; }

    for(int col = 1;col <= n;col ++){
        if(cnt) return true;

        if(cheak(row , col , n)) nums[row] = col , dfs(n , row + 1);
    }

    if(cnt) return true;

    return false;
}

signed main(void){ios;
    while(cin >> n && n){
        cnt = 0;
        nums.clear();
        if(!dfs(n , 1)) cout << "Impossible!!!" << endl;
    }
    return 0;
}

离散数学:

第六章: 集合代数

6.2 集合的运算 :

        集合的基本运算有并 , 交 , 相对补 和 对称差. 

                并: \cup

                交: \cap

                相对补: A - B 

                对称差: A\oplus B = (A - B) \cup (B - A)

        定义广义: 

                \cup A: A中所有的元素取并集.

                \cap A: A中所有的元素取交集.

        ps: 括号的优先级 > 广义\cap \cup > \cap \cup

6.3 有穷集的计数 :

        定义: 将集合进行计算 (有限个元素

        包含排斥原理: (有限个集合元素

                公式: \left | A_{_{1}} \cup A_{2} \cup A_{3} ... ...\cup A_{n} \right | = \sum_{n}^{}\left | A_{1} \cap \right... ...A_{n} | * (-1)_{}^{n+1}

                欧拉函数n(1 - \frac{1}{p_{1}})(1 - \frac{1}{p_{2}})... ...(1 - \frac{1}{p_{k}}) (计算 n 以内与 x 互质数 的个数. P为质因数.

                错排: n!\left [ 1 - \frac{1}{1!} + \frac{1}{2!} - \frac{1}{3!} ... ... +(-1)^{n} \frac{1}{n!} \right ]

计算机组成原理:

算机的指令和运算,主要包含:

  • 计算机指令:机器码(编译 -> 汇编 -> 机器码、指令格式和跳转、函数调用和程序栈)、程序的编译、链接、装载和执行;
  • 计算机运算:二进制编码(整数、反码、补码、浮点数、定点数)、数字电路(门电路、加法器、乘法器);

leetcode每日一题:

次元门

题意: 在 数组 nums2 中 找到 每个数 右边第一个比它大的数 , 如果不存在就是 -1 , 然后按 数组nums1 排序输出 ( 满足 nums1 是 nums2 的子集. 

数据不大 , 循环暴力

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int n1= nums1.size() , n2 = nums2.size();
        vector<int>re;

        for(int i = 0;i < n1;i ++){
            re.push_back(-1);
            int j = 0;

            while(j < n2 && nums2[j] != nums1[i]) j ++;
            while(j < n2 && nums2[j] <= nums1[i]) j ++;

            if(j < n2) re[i] = nums2[j];
        }

        return re;
    }
};

解题关键就在划线部分 , 这就是一个标准单调栈的问题 (找到 每个数 右边第一个比它大的数) , 所以在构造好单调栈后 , 只需要把单调栈按 nums1 重新排序即可 ( 更优的解法是在构造单调栈的同时 , 利用哈希索引.

class Solution {
private:
    unordered_map<int,int> u_map;
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int n1 = nums1.size() , n2 = nums2.size();
        vector<int>re;

        for(int i = 0;i < n1;i ++) u_map[nums1[i]] = i , re.push_back(-1);

        stack<int>sta;

        for(int i = 0;i < n2;i ++){
            while(!sta.empty() && nums2[i] > sta.top()){
                int cnt = sta.top();
                if(u_map.count(cnt)) re[u_map[cnt]] = nums2[i];
                sta.pop();
            }
            sta.push(nums2[i]);
        }

        return re;
    }
};

恰似草木对光阴.Day Four -- 酒醒花前坐.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值