- 下降路径最小和 II
给你一个 n x n 整数矩阵 grid ,请你返回 非零偏移下降路径 数字和的最小值。非零偏移下降路径 定义为:从 grid 数组中的每一行选择一个数字,且按顺序选出来的数字中,相邻数字不在原数组的同一列。
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;
}
};
- 二进制链表转整数
给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。请你返回该链表所表示数字的 十进制值 。
按位操作即可。
/**
* 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;
}
};
- 顺次数
我们定义「顺次数」为:每一位上的数字都比前一位上的数字大 1 的整数。请你返回由 [low, high] 范围内所有顺次数组成的 有序 列表(从小到大排序)。
外层循环定第一位数字,内层循环遍历所有可能性,枚举就完事。
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;
}
};
- 元素和小于等于阈值的正方形的最大边长
给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold。请你返回元素总和小于或等于阈值的正方形区域的最大边长;如果没有这样的正方形区域,则返回 0 。
要点主要有: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;
}
};
- 网格中的最短路径
给你一个 m * n 的网格,其中每个单元格不是 0(空)就是 1(障碍物)。每一步,您都可以在空白单元格中上、下、左、右移动。如果您 最多 可以消除 k 个障碍物,请找出从左上角 (0, 0) 到右下角 (m-1, n-1) 的最短路径,并返回通过该路径所需的步数。如果找不到这样的路径,则返回 -1 。
广度优先搜索 + 队列
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;
}
};
- 统计位数为偶数的数字
给你一个整数数组 nums,请你返回其中位数为 偶数 的数字的个数。
转化成string取长度,或者直接对数看奇偶。文章来源:https://www.toymoban.com/news/detail-705850.html
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;
}
};
- 划分数组为连续数字的集合
给你一个整数数组 nums 和一个正整数 k,请你判断是否可以把这个数组划分成一些由 k 个连续数字组成的集合。
如果可以,请返回 true;否则,返回 false。
贪心算法:排序后依次遍历。用一个哈希表存储元素及其次数,每次用到了就–。文章来源地址https://www.toymoban.com/news/detail-705850.html
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;
}
};
到了这里,关于leetcode解题思路分析(一百四十八)1289 - 1296 题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!