二维网格迁移 | 在受污染的二叉树中查找元素 | 可被三整除的最大和 | 推箱子 | LeetCode 周赛第 163 场 JAVA 实现「163」

1260. 二维网格迁移

给你一个 nm 列的二维网格 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

[ 1 2 3 4 5 6 7 8 9 ] − > [ 9 1 2 3 4 5 6 7 8 ] \left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{matrix} \right]->\left[ \begin{matrix} 9 & 1 & 2 \\ 3 & 4 & 5 \\ 6 & 7 & 8 \end{matrix} \right] 147258369>936147258

输入:grid = [ [1,2,3],[4,5,6],[7,8,9] ], k = 1
输出:[ [9,1,2],[3,4,5],[6,7,8] ]

示例 2

[ 3 8 1 9   19 7 2 5   4 6 11 10   12 0 21 13 ] − > [ 13 3 8 1   9 19 7 2   5 4 6 11   10 12 0 21 ] − > [ 21 13 3 8   1 9 19 7   2 5 4 6   11 10 12 0 ] − > \left[ \begin{matrix} 3 & 8 & 1 &9 \\\ 19&7&2&5 \\\ 4&6&11&10 \\\ 12&0&21&13 \end{matrix} \right] -> \left[ \begin{matrix} 13&3&8&1 \\\ 9&19&7&2 \\\ 5&4&6&11 \\\ 10&12&0&21 \end{matrix} \right] -> \left[ \begin{matrix} 21&13&3&8 \\\ 1&9&19&7 \\\ 2&5&4&6 \\\ 11&10&12&0 \end{matrix} \right]-> 3 19 4 128760121121951013>13 9 5 103194128760121121>21 1 2 111395103194128760>

[ 0 21 13 3   8 1 9 19   7 2 5 4   6 11 10 12 ] − > [ 12 0 21 13   3 8 1 9   19 7 2 5   4 6 11 10 ] \left[ \begin{matrix} 0&21&13&3 \\\ 8&1&9&19 \\\ 7&2&5&4 \\\ 6&11&10&12 \end{matrix} \right] -> \left[ \begin{matrix} 12&0&21&13 \\\ 3&8&1&9 \\\ 19&7&2&5 \\\ 4&6&11&10 \end{matrix} \right] 0 8 7 6211211139510319412>12 3 19 40876211211139510

输入: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
解题思路

找出 gird[i,j] 与移动 k 次后的位置 newGird[x,y] 之间的位置关系

  1. 二维网格为 n 行 m 列
  2. 位置 [ i , j ] 移动 k 次后,对应新位置 y = ( j + k ) % m
  3. 位置 [ i , j ] 移动 k 次后,row = ( j + k ) / m 为向下移动的行数,则 x = ( i + row ) % n

即:grid[ i , j ] 移动后的位置为 newGird[( i + ( j + k ) / m ) % n,( j + k ) % m]

循环遍历二维数组给新数组赋值即可

题解 JAVA 实现

点击查看本期周赛题解源码

public List<List<Integer>> shiftGrid(int[][] grid, int k) {
    int rowLength = grid.length;
    int colLength = grid[0].length;
    List<List<Integer>> resultList = new ArrayList<>(rowLength);
    Integer[][] newGrid = new Integer[rowLength][colLength];
    for (int i = 0; i < grid.length; i++) {
        for (int j = 0; j < grid[0].length; j++) {
            newGrid[(i + (j + k) / colLength) % rowLength][(j + k) % colLength] = grid[i][j];
        }
    }
    for (Integer[] integers : newGrid) {
        resultList.add(Arrays.asList(integers));
    }
    return resultList;
}

1261. 在受污染的二叉树中查找元素

给出一个满足下述规则的二叉树:

  1. root.val == 0
  2. 如果 treeNode.val == xtreeNode.left != null,那么 treeNode.left.val == 2 * x + 1
  3. 如果 treeNode.val == xtreeNode.right != null,那么 treeNode.right.val == 2 * x + 2

现在这个二叉树受到「污染」,所有的 treeNode.val 都变成了 -1

请你先还原二叉树,然后实现 FindElements 类:

  • FindElements(TreeNode* root) 用受污染的二叉树初始化对象,你需要先把它还原。
  • bool find(int target) 判断目标值 target 是否存在于还原后的二叉树中并返回结果。
示例 1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-duLU6UZI-1574219292548)(/img/leetcode/img/163-2-1.jpg)]

输入
[“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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IJN88j8o-1574219292551)(/img/leetcode/img/163-2-2.jpg)]

输入
[“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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ntWyGLaB-1574219292551)(/img/leetcode/img/163-2-3.jpg)]

输入
[“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 填充,定义一个全局变量 Set 或 Map 集合,Find 方法从集合中查找是否存在

题解 JAVA 实现

点击查看本期周赛题解源码

HashSet<Integer> set;
public FindElements(TreeNode root) {
    set = new HashSet<>();
    dfs(root, 0);
}
public void dfs(TreeNode root, int val) {
    if (root==null) {
        return;
    }
    root.val = val;
    set.add(val);
    dfs(root.left, val * 2 + 1);
    dfs(root.right, val * 2 + 2);
}
public boolean find(int target) {
    return set.contains(target);
}

1262. 可被三整除的最大和

给你一个整数数组 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
解题思路

数组 nums 求总和 sum

求余数 x = sum % 3

根据 x(0,1,2) 的值,找出使 sum 能被三整除需要减去的最小值 min

  1. x = 0,min 为 0
  2. x = 1,min 为 (最小 num % 3 == 1 的数)和(最小 2 个 sum % 3 == 2 的数的和)中的最小值
  3. x = 2,min 为 (最小 num % 3 == 2 的数)和(最小 2 个 sum % 3 == 1 的数的和)中的最小值

最终结果即:sum = sum - min

题解 JAVA 实现

点击查看本期周赛题解源码

public int maxSumDivThree(int[] nums) {

    int result = 0;

    List<Integer> list1 = new ArrayList<>();
    List<Integer> list2 = new ArrayList<>();

    for (int num : nums) {
        if (num % 3 == 1) {
            list1.add(num);
        } else if (num % 3 == 2) {
            list2.add(num);
        }
        result += num;
    }
    list1 = list1.stream().sorted().collect(Collectors.toList());
    list2 = list2.stream().sorted().collect(Collectors.toList());

    int num = result % 3;

    if (num == 0) {
        return result;
    }

    int min = Integer.MAX_VALUE;
    if (num == 1) {
        if (!list1.isEmpty()) {
            min = Math.min(list1.get(0), min);
        }
        if (list2.size() >= 2) {
            min = Math.min(min, list2.get(0) + list2.get(1));
        }
        if (!list1.isEmpty() && list2.size() >= 2) {
            min = Math.min(Math.min(list1.get(0), list2.get(0) + list2.get(1)), min);
        }
    } else {
        if (list1.size() >= 2) {
            min = Math.min(list1.get(0) + list1.get(1), min);
        }
        if (!list2.isEmpty()) {
            min = Math.min(list2.get(0), min);
        }
        if (list1.size() >= 2 && !list2.isEmpty()) {
            min = Math.min(Math.min(list1.get(0) + list1.get(1), list2.get(0)), min);
        }
    }

    if (min == Integer.MAX_VALUE) {
        return result;
    }

    return result - min;
}

1263. 推箱子难度困难

「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置。

游戏地图用大小为 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' 各只能出现一个。
解题思路

博主没解出来!!!(~ ̄▽ ̄)~

后续有时间研究的话再来补解题思路,没时间就不补了!!!

: LeetCode 用户 Yi Chen解题源码

有需要的自行研究吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值