lcp63
遍历矩形边界的空位置,模拟小球按指定步数和方向规则移动
判断是否能到达目标点O,收集所有符合条件的起始位置
++'W'
d = (d + 3) % 4; // 逆时针转++抽象出检查函数复用
check(0, j, 1, num, plate))
ans.push_back({0, j});
#include <vector>
#include <string>
using namespace std;
class Solution {
private:
// 右下左上(顺时针)
const int DIRS[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int m, n;
bool check(int x, int y, int d, int num, const vector<string>& plate) {
int left = num;
while (plate[x][y] != 'O') {
if (left == 0) return false;
if (plate[x][y] == ++'W')
d = (d + 3) % 4; // 逆时针转++
else if (plate[x][y] == 'E')
d = (d + 1) % 4; // 顺时针转
x += DIRS[d][0];
y += DIRS[d][1];
if (x < 0 || x >= m || y < 0 || y >= n)
return false;
left--;
}
return true;
}
public:
vector<vector<int>> ballGame(int num, vector<string>& plate) {
m = plate.size();
n = plate[0].size();
vector<vector<int>> ans;
// 检查上边(除首尾)
for (int j = 1; j < n - 1; j++) {
if (plate[0][j] == '.' && ++check(0, j, 1, num, plate)) {
ans.push_back({0, j});++
}
}
// 检查下边
for (int j = 1; j < n - 1; j++) {
if (plate[m - 1][j] == '.' && check(m - 1, j, 3, num, plate)) {
ans.push_back({m - 1, j});
}
}
// 检查左边
for (int i = 1; i < m - 1; i++) {
if (plate[i][0] == '.' && check(i, 0, 0, num, plate)) {
ans.push_back({i, 0});
}
}
// 检查右边
for (int i = 1; i < m - 1; i++) {
if (plate[i][n - 1] == '.' && check(i, n - 1, 2, num, plate)) {
ans.push_back({i, n - 1});
}
}
return ans;
}
};
lc2835
给一个全是2的幂的非负整数数组和目标值,可将数组中大于1的元素拆成两个其1/2的数(算一次操作)
求让数组存在和为目标值的子序列的最少操作次数,无法实现则返回-1
统计数组元素的二进制幂次计数,
累加幂次和并与目标值二进制分段比对,++不足时拆分更大幂次元素补充++
统计拆分操作次数得到最小操作数
class Solution {
public:
int minOperations(vector<int>& nums, int target) {
if (accumulate(nums.begin(), nums.end(), 0LL) < target) {
return -1;
}
int cnt[31]{};
for (int x : nums) {
cnt[__builtin_ctz(x)]++;
}
int ans = 0, i = 0;
long long s = 0;
while ((1LL << i) <= target) {
s += (long long) cnt[i] << i;
int mask = (1LL << ++i) - 1;
if (s >= (target & mask)) {
continue;
}
ans++; // 一定要找更大的数操作
for (; cnt[i] == 0; i++) {
ans++; // 还没找到,继续找更大的数
}
}
return ans;
}
};