5263. 二维网格迁移
给你一个 n 行 m 列的二维网格 grid 和一个整数 k。你需要将 grid 迁移 k 次。
每次「迁移」操作将会引发下述活动:
位于 grid[i][j] 的元素将会移动到 grid[i][j + 1]。
位于 grid[i][m - 1] 的元素将会移动到 grid[i + 1][0]。
位于 grid[n - 1][m - 1] 的元素将会移动到 grid[0][0]。
请你返回 k 次迁移操作后最终得到的 二维网格。
示例 1:
输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出:[[9,1,2],[3,4,5],[6,7,8]]
示例 2:
输入:grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
输出:[[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]
示例 3:
输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
输出:[[1,2,3],[4,5,6],[7,8,9]]
提示:
1 <= grid.length <= 50
1 <= grid[i].length <= 50
-1000 <= grid[i][j] <= 1000
0 <= k <= 100
思路
首先把k
对n * m
求模作为新的k
,然后计算k
与n * m
的最小公约数g
。之后,将n * m
个元素分成g
组,每组n * m / g
个元素,分别内部循环。时间复杂度O(n * m).
代码
class Solution {
public:
int gcd(int a, int b) {
while (b != 0) {
int tmp = b;
b = a % b;
a = tmp;
}
return a;
}
vector<vector<int>> shiftGrid(vector<vector<int>>& grid, int k) {
int n = grid.size();
if (n == 0) {
return grid;
}
int m = grid[0].size(), total = n * m;
k %= total;
if (k == 0) {
return grid;
}
int i = 0, j = 0, pre = 0, cur = 0, pos = 0, g = gcd(total, k), t = total / g;
for (i = 0; i < g; ++i) {
pos = i;
pre = grid[i / m][i % m];
for (j=0; j<t; ++j) {
pos += k;
pos %= total;
cur = grid[pos / m][pos % m];
grid[pos / m][pos % m] = pre;
pre = cur;
}
}
return grid;
}
};
5264. 在受污染的二叉树中查找元素
给出一个满足下述规则的二叉树:
root.val == 0
如果 treeNode.val == x
且 treeNode.left != null
,那么 treeNode.left.val == 2 * x + 1
如果 treeNode.val == x
且 treeNode.right != null
,那么 treeNode.right.val == 2 * x + 2
现在这个二叉树受到「污染」,所有的 treeNode.val 都变成了 -1。
请你先还原二叉树,然后实现 FindElements 类:
FindElements(TreeNode* root) 用受污染的二叉树初始化对象,你需要先把它还原。
bool find(int target) 判断目标值 target 是否存在于还原后的二叉树中并返回结果。
示例 1:
输入:
[“FindElements”,“find”,“find”]
[[[-1,null,-1]],[1],[2]]
输出:
[null,false,true]
解释:
FindElements findElements = new FindElements([-1,null,-1]);
findElements.find(1); // return False
findElements.find(2); // return True
示例 2:
输入:
[“FindElements”,“find”,“find”,“find”]
[[[-1,-1,-1,-1,-1]],[1],[3],[5]]
输出:
[null,true,true,false]
解释:
FindElements findElements = new FindElements([-1,-1,-1,-1,-1]);
findElements.find(1); // return True
findElements.find(3); // return True
findElements.find(5); // return False
示例 3:
输入:
[“FindElements”,“find”,“find”,“find”,“find”]
[[[-1,null,-1,-1,null,-1]],[2],[3],[4],[5]]
输出:
[null,true,false,false,true]
解释:
FindElements findElements = new FindElements([-1,null,-1,-1,null,-1]);
findElements.find(2); // return True
findElements.find(3); // return False
findElements.find(4); // return False
findElements.find(5); // return True
提示:
TreeNode.val == -1
二叉树的高度不超过 20
节点的总数在 [1, 10^4] 之间
调用 find() 的总次数在 [1, 10^4] 之间
0 <= target <= 10^6
思路
简单的dfs. find(n)
的时间复杂度为O(logn).
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class FindElements {
private:
TreeNode * _root;
void recover(TreeNode* root, int value) {
root->val = value;
if (root->left) {
recover(root->left, 2 * value + 1);
}
if (root->right) {
recover(root->right, 2 * value + 2);
}
}
bool recuFind(TreeNode* root, int target) {
if (!root) {
return false;
}
if (root->val == target) {
return true;
}
if (target > root->val && target <= 2 * (root->val)) {
return false;
}
return recuFind(root->left, target) || recuFind(root->right, target);
}
public:
FindElements(TreeNode* root) {
recover(root, 0);
_root = root;
}
bool find(int target) {
return recuFind(_root, target);
}
};
/**
* Your FindElements object will be instantiated and called as such:
* FindElements* obj = new FindElements(root);
* bool param_1 = obj->find(target);
*/
5265. 可被三整除的最大和
给你一个整数数组 nums,请你找出并返回能被三整除的元素最大和。
示例 1:
输入:nums = [3,6,5,1,8]
输出:18
解释:选出数字 3, 6, 1 和 8,它们的和是 18(可被 3 整除的最大和)。
示例 2:
输入:nums = [4]
输出:0
解释:4 不能被 3 整除,所以无法选出数字,返回 0。
示例 3:
输入:nums = [1,2,3,4,4]
输出:12
解释:选出数字 1, 3, 4 以及 4,它们的和是 12(可被 3 整除的最大和)。
提示:
1 <= nums.length <= 4 * 10^4
1 <= nums[i] <= 10^4
思路
贪心。求所有数字的和total
,如果total
模3余1,则去掉最小的一个模3余1的数或者最小的两个模3余2的数,如果total
模3余2,则去掉最小的一个模3余2的数或者最小的两个模3余1的数
代码
class Solution {
public:
int maxSumDivThree(vector<int>& nums) {
const int MAX = 0x3f3f3f3f;
int total = 0, mod1min = MAX, mod1min2 = MAX, mod2min = MAX, mod2min2 = MAX, idx1 = -1, idx2 = -1, i = 0;
i = 0;
for (auto num: nums) {
total += num;
if (num % 3 == 1) {
if (num < mod1min) {
mod1min = num;
idx1 = i;
}
} else if (num % 3 == 2) {
if (num < mod2min) {
mod2min = num;
idx2 = i;
}
}
++i;
}
i = 0;
for (auto num: nums) {
if (num % 3 == 1) {
if (i != idx1 && num >= mod1min && num < mod1min2) {
mod1min2 = num;
}
} else if (num % 3 == 2) {
if (i != idx2 && num >= mod2min && num < mod2min2) {
mod2min2 = num;
}
}
++i;
}
if (total % 3 == 0) {
return total;
} else if (total % 3 == 1) {
return max(total - mod1min, total - mod2min - mod2min2);
} else {
return max(total - mod1min - mod1min2, total - mod2min);
}
}
};
5266. 推箱子
「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置。
游戏地图用大小为 n * m 的网格 grid 表示,其中每个元素可以是墙、地板或者是箱子。
现在你将作为玩家参与游戏,按规则将箱子 ‘B’ 移动到目标位置 ‘T’ :
玩家用字符 ‘S’ 表示,只要他在地板上,就可以在网格中向上、下、左、右四个方向移动。
地板用字符 ‘.’ 表示,意味着可以自由行走。
墙用字符 ‘#’ 表示,意味着障碍物,不能通行。
箱子仅有一个,用字符 ‘B’ 表示。相应地,网格上有一个目标位置 ‘T’。
玩家需要站在箱子旁边,然后沿着箱子的方向进行移动,此时箱子会被移动到相邻的地板单元格。记作一次「推动」。
玩家无法越过箱子。
返回将箱子推到目标位置的最小 推动 次数,如果无法做到,请返回 -1。
示例 1:
输入:grid = [["#","#","#","#","#","#"],
["#",“T”,"#","#","#","#"],
["#",".",".",“B”,".","#"],
["#",".","#","#",".","#"],
["#",".",".",".",“S”,"#"],
["#","#","#","#","#","#"]]
输出:3
解释:我们只需要返回推箱子的次数。
示例 2:
输入:grid = [["#","#","#","#","#","#"],
["#",“T”,"#","#","#","#"],
["#",".",".",“B”,".","#"],
["#","#","#","#",".","#"],
["#",".",".",".",“S”,"#"],
["#","#","#","#","#","#"]]
输出:-1
示例 3:
输入:grid = [["#","#","#","#","#","#"],
["#",“T”,".",".","#","#"],
["#",".","#",“B”,".","#"],
["#",".",".",".",".","#"],
["#",".",".",".",“S”,"#"],
["#","#","#","#","#","#"]]
输出:5
解释:向下、向左、向左、向上再向上。
示例 4:
输入:grid = [["#","#","#","#","#","#","#"],
["#",“S”,"#",".",“B”,“T”,"#"],
["#","#","#","#","#","#","#"]]
输出:-1
提示:
1 <= grid.length <= 20
1 <= grid[i].length <= 20
grid 仅包含字符 ‘.’, ‘#’, ‘S’ , ‘T’, 以及 ‘B’。
grid 中 ‘S’, ‘B’ 和 ‘T’ 各只能出现一个。
思路
如果只考虑箱子的移动,则就是简单的bfs求最短路。由于还要考虑人推箱子的行为,所以在箱子每次移动的时候判断人能不能走到推箱子需要的位置
代码
class Solution {
private:
struct Node {
int bx, by, sx, sy, cnt;
Node(): bx(0), by(0), sx(0), sy(0), cnt(0) {}
Node(int _bx, int _by, int _sx, int _sy, int _cnt): bx(_bx), by(_by), sx(_sx), sy(_sy), cnt(_cnt) {}
};
const int MOV[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
inline bool isValid(int bx, int by, int sx, int sy, int n, int m, const vector<vector<char>>& grid) {
return bx >= 0 && bx < n && by >= 0 && by < m && sx >=0 && sx < n && sy >= 0 && sy < m && grid[bx][by] != '#' && grid[sx][sy] != '#';
}
// inner dfs
bool dfs(int px, int py, int nx, int ny, int bx, int by, int n, int m, bool (*svis)[22], const vector<vector<char>>& grid) {
if (px == nx && py == ny) {
return true;
}
int rx = 0, ry = 0;
for (int i = 0; i < 4; ++i) {
rx = px + MOV[i][0];
ry = py + MOV[i][1];
if (rx >= 0 && rx < n && ry >= 0 && ry < m && (rx != bx || ry != by) && grid[rx][ry] != '#' && !svis[rx][ry]) {
svis[rx][ry] = 1;
if (dfs(rx, ry, nx, ny, bx, by, n, m, svis, grid)) {
return true;
}
}
}
return false;
}
public:
int minPushBox(vector<vector<char>>& grid) {
bool vis[22][22][22][22] = {0}, svis[22][22] = {0};
int n = grid.size(), m = grid[0].size(), i = 0, j = 0, bx = 0, by = 0, tx = 0, ty = 0, sx = 0, sy = 0;
for (i=0; i<n; ++i) {
for (j=0; j<m; ++j) {
switch(grid[i][j]) {
case 'S':
sx = i;
sy = j;
break;
case 'B':
bx = i;
by = j;
break;
case 'T':
tx = i;
ty = j;
break;
}
}
}
// outer bfs
queue<Node> q;
Node head;
int nbx = 0, nby = 0, nsx = 0, nsy = 0;
vis[bx][by][sx][sy] = 1;
q.emplace(bx, by, sx, sy, 0);
while (!q.empty()){
head = q.front();
q.pop();
if (head.bx == tx && head.by == ty) {
return head.cnt;
}
for (i=0; i<4; ++i) {
nbx = head.bx + MOV[i][0];
nby = head.by + MOV[i][1];
nsx = head.bx - MOV[i][0];
nsy = head.by - MOV[i][1];
memset(svis, 0, sizeof(svis));
svis[head.sx][head.sy] = 1;
if (isValid(nbx, nby, nsx, nsy, n, m, grid) && !vis[nbx][nby][nsx][nsy] && dfs(head.sx, head.sy, nsx, nsy, head.bx, head.by, n, m, svis, grid)) {
q.emplace(nbx, nby, nsx, nsy, head.cnt + 1);
vis[nbx][nby][nsx][nsy] = 1;
}
}
}
return -1;
}
};