0
点赞
收藏
分享

微信扫一扫

Linux定时任务--crontab

蚁族的乐土 2023-06-25 阅读 89
  1. 分割平衡字符串
    平衡字符串 中,‘L’ 和 ‘R’ 字符的数量是相同的。
    给你一个平衡字符串 s,请你将它分割成尽可能多的子字符串,并满足:
    每个子字符串都是平衡字符串。
    返回可以通过分割得到的平衡字符串的 最大数量 。

遍历一遍即可,贪心算法解题。

class Solution {
public:
    int balancedStringSplit(string s) 
    {
        int pair = 0;
        int cnt  = 0;
        for (auto c : s)
        {
            if (c == 'L') 
                pair++;
            else
                pair--;
            if (pair == 0)
                cnt++;
        }

        return cnt;
    }
};
  1. 可以攻击国王的皇后
    在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」。
    给定一个由整数坐标组成的数组 queens ,表示黑皇后的位置;以及一对坐标 king ,表示白国王的位置,返回所有可以攻击国王的皇后的坐标(任意顺序)

让国王朝着各方向遍历,遇到的第一个Q都是可行的。

class Solution {
public:
    vector<vector<int>> queensAttacktheKing(vector<vector<int>>& queens, vector<int>& k) {
        vector<vector<int>> rcs {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {-1, -1}, {1, -1}, {-1, 1}};
        int n = 8;
        set<vector<int>> s(queens.begin(), queens.end());
        vector<vector<int>> ans;
        for (auto& rc : rcs) {
            int r = k[0], c = k[1];
            while (r + rc[0] < n && r + rc[0] >= 0 && c + rc[1] < n && c + rc[1] >= 0) {
                if (s.count(vector<int>{r+rc[0], c+rc[1]})) {
                    ans.push_back(vector<int>{r+rc[0], c+rc[1]});
                    break;
                }
                r += rc[0];
                c += rc[1];
            }
        }
        return ans;
    }
};


  1. 掷骰子模拟
    有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数。不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号)。现在,给你一个整数数组 rollMax 和一个整数 n,请你来计算掷 n 次骰子可得到的不同点数序列的数量。假如两个序列中至少存在一个元素不同,就认为这两个序列是不同的。由于答案可能很大,所以请返回 模 10^9 + 7 之后的结果。

动态规划解题。

class Solution {
public:
    static constexpr int mod = 1E9 + 7;
    int dieSimulator(int n, vector<int>& rollMax) {
        vector d(n + 1, vector<int>(6, 0));
        vector<int> sum(n + 1, 0);
        sum[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < 6; j++) {
                int pos = max(i - rollMax[j] - 1, 0);
                int sub = ((sum[pos] - d[pos][j]) % mod + mod) % mod;
                d[i][j] = ((sum[i - 1] - sub) % mod + mod) % mod;
                if (i <= rollMax[j]) {
                    d[i][j] = (d[i][j] + 1) % mod;
                }
                sum[i] = (sum[i] + d[i][j]) % mod;
            }
        }
        return sum[n];
    }
};


  1. 最大相等频率
    给你一个正整数数组 nums,请你帮忙从该数组中找出能满足下面要求的 最长 前缀,并返回该前缀的长度:从前缀中 恰好删除一个 元素后,剩下每个数字的出现次数都相同。如果删除这个元素后没有剩余元素存在,仍可认为每个数字都具有相同的出现次数(也就是 0 次)。

充要条件为满足以下三个条件之一:
1.maxFreq=1:那么所有数的出现次数都是一次,随意删除一个数既可符合要求。
2.所有数的出现次数都是 maxFreq 或 maxFreq−1,并且最大出现次数的数只有一个:删除一个最大出现次数的数,那么所有数的出现次数都是 maxFreq
3.除开一个数,其他所有数的出现次数都是 maxFreq,并且该数的出现次数为 1. 直接删除出现次数为 1 的数,那么所有数的出现次数都是 maxFreq

class Solution {
public:
    int maxEqualFreq(vector<int>& nums) {
        unordered_map<int, int> freq, count;
        int res = 0, maxFreq = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (count[nums[i]] > 0) {
                freq[count[nums[i]]]--;
            }
            count[nums[i]]++;
            maxFreq = max(maxFreq, count[nums[i]]);
            freq[count[nums[i]]]++;
            bool ok = maxFreq == 1 ||
                    freq[maxFreq] * maxFreq + freq[maxFreq - 1] * (maxFreq - 1) == i + 1 && freq[maxFreq] == 1 ||
                    freq[maxFreq] * maxFreq + 1 == i + 1 && freq[1] == 1;
            if (ok) {
                res = max(res, i + 1);
            }
        }
        return res;
    }
};


  1. 哲学家进餐
    给你 5 个线程,每个都代表一个哲学家,请你使用类的同一个对象来模拟这个过程。在最后一次调用结束之前,可能会为同一个哲学家多次调用该函数。

本体主要是解决死锁问题。有几种方案可选:只允许四个/三个人拿左边筷子;分奇偶数选左边或右边的筷子;即当一个线程要执行时一次性将所需的资源全部给他,否则不分给他资源

#include<semaphore.h>
class DiningPhilosophers {
public:
    DiningPhilosophers() {
        fork = vector<sem_t>(5);
        sem_init(&room,0,4);
        for(int i = 0;i < 5;i++){
            sem_init(&(fork[i]),0,1);
        }
    }

    void wantsToEat(int philosopher,
                    function<void()> pickLeftFork,
                    function<void()> pickRightFork,
                    function<void()> eat,
                    function<void()> putLeftFork,
                    function<void()> putRightFork) {
        sem_wait(&room);
        sem_wait(&(fork[philosopher]));
        sem_wait(&(fork[(philosopher+1)%5]));
        pickLeftFork();
        pickRightFork();
        eat();
        putRightFork();
        putLeftFork();
        sem_post(&(fork[(philosopher+1)%5]));
        sem_post(&(fork[philosopher]));
        sem_post(&room);
    }
    vector<sem_t> fork;
    sem_t room;
};

  1. 飞机座位分配概率
    有 n 位乘客即将登机,飞机正好有 n 个座位。第一位乘客的票丢了,他随便选了一个座位坐下。
    剩下的乘客将会:
    如果他们自己的座位还空着,就坐到自己的座位上,
    当他们自己的座位被占用时,随机选择其他座位
    第 n 位乘客坐在自己的座位上的概率是多少?

本题的是一个数学概率推导的题,难点主要在于推导f(n)的递推公式以及f(n)和f(n-1)的关系探索。不同于纯随机,本体的关键点在于如果一个人座位空着的,那一定会选择这个座位而不是随机做。

class Solution {
public:
    double nthPersonGetsNthSeat(int n) {
        return n == 1 ? 1.0 : 0.5;
    }
};


  1. 缀点成线
    给定一个数组 coordinates ,其中 coordinates[i] = [x, y] , [x, y] 表示横坐标为 x、纵坐标为 y 的点。请你来判断,这些点是否在该坐标系中属于同一条直线上。

求斜率的做法无疑是很蠢的,比较优秀且节省空间的做法是以第一、二个点为基点,后续每个点求向量并比较是否平行。因为均过A且平行一定在一条线上。

class Solution {
public:
    bool checkStraightLine(vector<vector<int>>& coordinates) {
        int n = coordinates.size();
        int x0 = coordinates[0][0], y0 = coordinates[0][1];
        int x = coordinates[1][0] - x0;
        int y = coordinates[1][1] - y0;
        for (int i = 2; i < n; ++i) {
            int xi = coordinates[i][0] - x0;
            int yi = coordinates[i][1] - y0;
            if (x * yi - y * xi) { 
                return false;
            }
        }
        return true;
    }
};


举报

相关推荐

0 条评论