- 分割平衡字符串
平衡字符串 中,‘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;
}
};
- 可以攻击国王的皇后
在一个 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 到 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];
}
};
- 最大相等频率
给你一个正整数数组 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;
}
};
- 哲学家进餐
给你 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;
};
- 飞机座位分配概率
有 n 位乘客即将登机,飞机正好有 n 个座位。第一位乘客的票丢了,他随便选了一个座位坐下。
剩下的乘客将会:
如果他们自己的座位还空着,就坐到自己的座位上,
当他们自己的座位被占用时,随机选择其他座位
第 n 位乘客坐在自己的座位上的概率是多少?
本题的是一个数学概率推导的题,难点主要在于推导f(n)的递推公式以及f(n)和f(n-1)的关系探索。不同于纯随机,本体的关键点在于如果一个人座位空着的,那一定会选择这个座位而不是随机做。
class Solution {
public:
double nthPersonGetsNthSeat(int n) {
return n == 1 ? 1.0 : 0.5;
}
};
- 缀点成线
给定一个数组 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;
}
};