1812. 判断国际象棋棋盘中一个格子的颜色
题目
给你一个坐标 coordinates ,它是一个字符串,表示国际象棋棋盘中一个格子的坐标。下图是国际象棋棋盘示意图。

如果所给格子的颜色是白色,请你返回 true,如果是黑色,请返回 false 。
给定坐标一定代表国际象棋棋盘上一个存在的格子。坐标第一个字符是字母,第二个字符是数字。
示例 1:
输入:coordinates = "a1"
输出:false
解释:如上图棋盘所示,"a1" 坐标的格子是黑色的,所以返回 false 。
示例 2:
输入:coordinates = "h3"
输出:true
解释:如上图棋盘所示,"h3" 坐标的格子是白色的,所以返回 true 。
示例 3:
输入:coordinates = "c7"
输出:false
提示:
coordinates.length == 2'a' <= coordinates[0] <= 'h''1' <= coordinates[1] <= '8'
代码
class Solution {
public:
bool squareIsWhite(string c) {
return ((c[0] - 'a') + (c[1] - '0')) % 2 == 0;
}
};
1813. 句子相似性 III
题目
一个句子是由一些单词与它们之间的单个空格组成,且句子的开头和结尾没有多余空格。比方说,"Hello World" ,"HELLO" ,"hello world hello world" 都是句子。每个单词都 只 包含大写和小写英文字母。
如果两个句子 sentence1 和 sentence2 ,可以通过往其中一个句子插入一个任意的句子(可以是空句子)而得到另一个句子,那么我们称这两个句子是 相似的 。比方说,sentence1 = "Hello my name is Jane" 且 sentence2 = "Hello Jane" ,我们可以往 sentence2 中 "Hello" 和 "Jane" 之间插入 "my name is" 得到 sentence1 。
给你两个句子 sentence1 和 sentence2 ,如果 sentence1 和 sentence2 是相似的,请你返回 true ,否则返回 false 。
示例 1:
输入:sentence1 = "My name is Haley", sentence2 = "My Haley"
输出:true
解释:可以往 sentence2 中 "My" 和 "Haley" 之间插入 "name is" ,得到 sentence1 。
示例 2:
输入:sentence1 = "of", sentence2 = "A lot of words"
输出:false
解释:没法往这两个句子中的一个句子只插入一个句子就得到另一个句子。
示例 3:
输入:sentence1 = "Eating right now", sentence2 = "Eating"
输出:true
解释:可以往 sentence2 的结尾插入 "right now" 得到 sentence1 。
示例 4:
输入:sentence1 = "Luky", sentence2 = "Lucccky"
输出:false
提示:
1 <= sentence1.length, sentence2.length <= 100sentence1和sentence2都只包含大小写英文字母和空格。sentence1和sentence2中的单词都只由单个空格隔开。
思路
c++没有string相应的函数,所以用stringstream读入string内容,这里相似性就是等价于某一句话中间插入了一些单词,匹配到s2
因此,前后匹配即可
代码
class Solution {
public:
bool areSentencesSimilar(string s1, string s2) {
if (s1.size() > s2.size()) return areSentencesSimilar(s2, s1);
stringstream s1in(s1), s2in(s2);
vector<string> a, b;
string s;
while (s1in >> s) a.push_back(s);
while (s2in >> s) b.push_back(s);
int i = 0, j = a.size() - 1;
for (int k = 0; k < b.size() && i < a.size(); k++) {
if (a[i] == b[k]) i++;
else break;
}
for (int k = b.size() - 1; k >= 0 && j >= 0; k--) {
if (a[j] == b[k]) j--;
else break;
}
return i > j;
}
};
1814. 统计一个数组中好对子的数目
题目
给你一个数组 nums ,数组中只包含非负整数。定义 rev(x) 的值为将整数 x 各个数字位反转得到的结果。比方说 rev(123) = 321 , rev(120) = 21 。我们称满足下面条件的下标对 (i, j) 是 好的 :
0 <= i < j < nums.lengthnums[i] + rev(nums[j]) == nums[j] + rev(nums[i])
请你返回好下标对的数目。由于结果可能会很大,请将结果对 109 + 7 取余 后返回。
示例 1:
输入:nums = [42,11,1,97]
输出:2
解释:两个坐标对为:
- (0,3):42 + rev(97) = 42 + 79 = 121, 97 + rev(42) = 97 + 24 = 121 。
- (1,2):11 + rev(1) = 11 + 1 = 12, 1 + rev(11) = 1 + 11 = 12 。
示例 2:
输入:nums = [13,10,35,24,76]
输出:4
提示:
1 <= nums.length <= 1050 <= nums[i] <= 109
思路
nums[i] + rev(nums[j]) == nums[j] + rev(nums[i]) 等价于 nums[i] - rev(nums[i]) == nums[j] - rev(nums[j]) 然后存值到map中,算C n 2的排列组合即可
代码
int mod = 1e9 + 7;
typedef long long ll;
class Solution {
public:
int rev(int num) {
int ret = 0;
while (num) {
ret = ret * 10 + num % 10;
num /= 10;
}
return ret;
}
int countNicePairs(vector<int>& nums) {
ll ret = 0;
unordered_map<ll, ll> mp;
for (auto& n : nums) {
mp[n - rev(n)]++;
}
for (auto& [k, v] : mp) {
ret = (ret + v * (v - 1) / 2) % mod;
}
return (int)ret;
}
};
1815. 得到新鲜甜甜圈的最多组数
题目
有一个甜甜圈商店,每批次都烤 batchSize 个甜甜圈。这个店铺有个规则,就是在烤一批新的甜甜圈时,之前 所有 甜甜圈都必须已经全部销售完毕。给你一个整数 batchSize 和一个整数数组 groups ,数组中的每个整数都代表一批前来购买甜甜圈的顾客,其中 groups[i] 表示这一批顾客的人数。每一位顾客都恰好只要一个甜甜圈。
当有一批顾客来到商店时,他们所有人都必须在下一批顾客来之前购买完甜甜圈。如果一批顾客中第一位顾客得到的甜甜圈不是上一组剩下的,那么这一组人都会很开心。
你可以随意安排每批顾客到来的顺序。请你返回在此前提下,最多 有多少组人会感到开心。
示例 1:
输入:batchSize = 3, groups = [1,2,3,4,5,6]
输出:4
解释:你可以将这些批次的顾客顺序安排为 [6,2,4,5,1,3] 。那么第 1,2,4,6 组都会感到开心。
示例 2:
输入:batchSize = 4, groups = [1,3,2,5,2,2,1,6]
输出:4
提示:
1 <= batchSize <= 91 <= groups.length <= 301 <= groups[i] <= 109
思路
模拟退火 算法 :
一个可以尽量达到全局最优的算法
每次随机交换序列中的两个位置 来判断当前的序列是否可以比原始序列更优
- 若比原始序列更优,则保留交换
- 否则按一定概率保留交换 (这样才有机会达到全局最优)
还有一种思路就是状态压缩+记忆化搜索
具体可以参考leetcode-cn.com/problems/ma…
代码
模拟退火代码
class Solution {
public:
int n, m;
vector<int> w;
int ans;
int calc() {
int res = 1;
for (int i = 0, s = 0; i < n; i ++ ) {
s = (s + w[i]) % m;
if (!s && i < n - 1) res ++ ;
}
ans = max(ans, res);
return res;
}
void simulate_anneal() {
random_shuffle(w.begin(), w.end());
for (double t = 1e6; t > 1e-5; t *= 0.97) {
int a = rand() % n, b = rand() % n;
int x = calc();
swap(w[a], w[b]);
int y = calc();
int delta = x - y;
if (!(exp(-delta / t) > (double)rand() / RAND_MAX))
swap(w[a], w[b]);
}
}
int maxHappyGroups(int batchSize, vector<int>& groups) {
w = groups;
n = w.size();
m = batchSize;
ans = 0;
for (int i = 0; i < 80; i ++ ) simulate_anneal();
return ans;
}
};
状态压缩
class Solution {
public:
int dp[1111111];
int maxHappyGroups(int batchSize, vector<int>& groups) {
int cnt[batchSize];
memset(cnt, 0, sizeof(cnt));
for (int group: groups) {
cnt[group % batchSize]++;
}
int sz = 1;
int w[11];
w[0] = 1;
for (int i = 0; i < batchSize; i++) {
w[i + 1] = w[i] * (cnt[i] + 1);
sz *= (cnt[i] + 1);
}
dp[0] = 0;
for (int mask = 1; mask < sz; mask++) {
dp[mask] = 0;
int tmp = mask, sum = 0;
int v[10];
memset(v, 0, sizeof(v));
for (int b = 0; b < batchSize; b++) {
if (!cnt[b]) continue;
int x = tmp % (cnt[b] + 1);
v[b] = x;
sum = (sum + x * b) % batchSize;
tmp /= (cnt[b] + 1);
}
for (int b = 0; b < batchSize; b++) {
if (v[b]) {
int last = (sum - b + batchSize) % batchSize;
dp[mask] = max(dp[mask], dp[mask - w[b]] + (last == 0));
}
}
}
return dp[sz - 1];
}
};