f[i][j] 表示从数组的前i行中的每一行选择一个数字,并且第 i 行选择的数字为 grid[i][j]时,可以得到的路径和最小值
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& grid) {
int n = grid.size();
vector<vector<int>> d(n, vector<int>(n, INT_MAX));
for (int i = 0; i < n; i++) {
d[0][i] = grid[0][i];
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
if (j == k) {
continue;
}
d[i][j] = min(d[i][j], d[i - 1][k] + grid[i][j]);
}
}
}
int res = INT_MAX;
for (int j = 0; j < n; j++) {
res = min(res, d[n - 1][j]);
}
return res;
}
};
按位操作即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
int getDecimalValue(ListNode* head) {
int n = 0;
while (head)
{
n = n << 1 | head->val;
head = head->next;
}
return n;
}
};
外层循环定第一位数字,内层循环遍历所有可能性,枚举就完事。
class Solution {
public:
vector<int> sequentialDigits(int low, int high) {
vector<int> ans;
for (int i = 1; i <= 9; ++i) {
int num = i;
for (int j = i + 1; j <= 9; ++j) {
num = num * 10 + j;
if (num >= low && num <= high) {
ans.push_back(num);
}
}
}
sort(ans.begin(), ans.end());
return ans;
}
};
要点主要有:1.二位前缀和;2.三种循环遍历查找;3. 三种循环的两个优化:找到了大小为n的,后面直接n+1找起/如果c都不行,后面就不用看了直接跳过当前循环。
class Solution {
public:
int getRect(const vector<vector<int>>& P, int x1, int y1, int x2, int y2) {
return P[x2][y2] - P[x1 - 1][y2] - P[x2][y1 - 1] + P[x1 - 1][y1 - 1];
}
int maxSideLength(vector<vector<int>>& mat, int threshold) {
int m = mat.size(), n = mat[0].size();
vector<vector<int>> P(m + 1, vector<int>(n + 1));
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
P[i][j] = P[i - 1][j] + P[i][j - 1] - P[i - 1][j - 1] + mat[i - 1][j - 1];
}
}
int r = min(m, n), ans = 0;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
for (int c = ans + 1; c <= r; ++c) {
if (i + c - 1 <= m && j + c - 1 <= n && getRect(P, i, j, i + c - 1, j + c - 1) <= threshold) {
++ans;
}
else {
break;
}
}
}
}
return ans;
}
};
广度优先搜索 + 队列
struct Nagato {
int x, y;
int rest;
Nagato(int _x, int _y, int _r): x(_x), y(_y), rest(_r) {}
};
class Solution {
private:
static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public:
int shortestPath(vector<vector<int>>& grid, int k) {
int m = grid.size(), n = grid[0].size();
if (m == 1 && n == 1) {
return 0;
}
k = min(k, m + n - 3);
bool visited[m][n][k + 1];
memset(visited, false, sizeof(visited));
queue<Nagato> q;
q.emplace(0, 0, k);
visited[0][0][k] = true;
for (int step = 1; q.size() > 0; ++step) {
int cnt = q.size();
for (int _ = 0; _ < cnt; ++_) {
Nagato cur = q.front();
q.pop();
for (int i = 0; i < 4; ++i) {
int nx = cur.x + dirs[i][0];
int ny = cur.y + dirs[i][1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
if (grid[nx][ny] == 0 && !visited[nx][ny][cur.rest]) {
if (nx == m - 1 && ny == n - 1) {
return step;
}
q.emplace(nx, ny, cur.rest);
visited[nx][ny][cur.rest] = true;
}
else if (grid[nx][ny] == 1 && cur.rest > 0 && !visited[nx][ny][cur.rest - 1]) {
q.emplace(nx, ny, cur.rest - 1);
visited[nx][ny][cur.rest - 1] = true;
}
}
}
}
}
return -1;
}
};
转化成string取长度,或者直接对数看奇偶。
class Solution {
public:
int findNumbers(vector<int>& nums) {
int ans = 0;
for (int num: nums) {
if ((int)(log10(num) + 1) % 2 == 0) {
++ans;
}
}
return ans;
}
};
贪心算法:排序后依次遍历。用一个哈希表存储元素及其次数,每次用到了就–。
class Solution {
public:
bool isPossibleDivide(vector<int>& nums, int k) {
int n = nums.size();
if (n % k != 0) {
return false;
}
sort(nums.begin(), nums.end());
unordered_map<int, int> cnt;
for (auto & num : nums) {
cnt[num]++;
}
for (auto & x : nums) {
if (!cnt.count(x)) {
continue;
}
for (int j = 0; j < k; j++) {
int num = x + j;
if (!cnt.count(num)) {
return false;
}
cnt[num]--;
if (cnt[num] == 0) {
cnt.erase(num);
}
}
}
return true;
}
};