1706.球会落何处:模拟 - 很有意思的一道题

【LetMeFly】1706.球会落何处:模拟 - 很有意思的一道题

力扣题目链接:https://leetcode.cn/problems/where-will-the-ball-fall/

用一个大小为 m x n 的二维网格 grid 表示一个箱子。你有 n 颗球。箱子的顶部和底部都是开着的。

箱子中的每个单元格都有一个对角线挡板,跨过单元格的两个角,可以将球导向左侧或者右侧。

  • 将球导向右侧的挡板跨过左上角和右下角,在网格中用 1 表示。
  • 将球导向左侧的挡板跨过右上角和左下角,在网格中用 -1 表示。

在箱子每一列的顶端各放一颗球。每颗球都可能卡在箱子里或从底部掉出来。如果球恰好卡在两块挡板之间的 "V" 形图案,或者被一块挡导向到箱子的任意一侧边上,就会卡住。

返回一个大小为 n 的数组 answer ,其中 answer[i] 是球放在顶部的第 i 列后从底部掉出来的那一列对应的下标,如果球卡在盒子里,则返回 -1

 

示例 1:

输入:grid = [[1,1,1,-1,-1],[1,1,1,-1,-1],[-1,-1,-1,1,1],[1,1,1,1,-1],[-1,-1,-1,-1,-1]]
输出:[1,-1,-1,-1,-1]
解释:示例如图:
b0 球开始放在第 0 列上,最终从箱子底部第 1 列掉出。
b1 球开始放在第 1 列上,会卡在第 2、3 列和第 1 行之间的 "V" 形里。
b2 球开始放在第 2 列上,会卡在第 2、3 列和第 0 行之间的 "V" 形里。
b3 球开始放在第 3 列上,会卡在第 2、3 列和第 0 行之间的 "V" 形里。
b4 球开始放在第 4 列上,会卡在第 2、3 列和第 1 行之间的 "V" 形里。

示例 2:

输入:grid = [[-1]]
输出:[-1]
解释:球被卡在箱子左侧边上。

示例 3:

输入:grid = [[1,1,1,1,1,1],[-1,-1,-1,-1,-1,-1],[1,1,1,1,1,1],[-1,-1,-1,-1,-1,-1]]
输出:[0,1,2,3,4,-1]

 

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 100
  • grid[i][j]1-1

解题方法:模拟

球斜着落对于某些人的人脑来说可能有点复杂,因此可以把球斜着落拆成“先水平移动后数值下降”两个部分。

对于一个小球(x, y),它水平移动的下一个坐标是(x, y + grid[x][y])

如果下一个坐标没越界隔板方向和当前相同,则说明可以完成一次“水平移动并下坠”。

对于一个小球,模拟最多m次,就会从底部掉出或被中途卡住。

  • 时间复杂度$O(mn)$
  • 空间复杂度$O(1)$,答案不计入力扣算法空间复杂度

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
* @Author: LetMeFly // 中间中断了
* @Date: 2025-02-15 11:04:20
* @LastEditors: LetMeFly.xyz
* @LastEditTime: 2025-02-15 11:19:25
*/
class Solution {
private:
void drop(vector<vector<int>>& grid, vector<int>& ans, int j) {
int x = 0, y = j;
while (x < grid.size()) {
int nextY = y + grid[x][y];
if (nextY < 0 || nextY >= grid[0].size() || grid[x][y] != grid[x][nextY]) {
return;
}
x++, y = nextY;
}
ans[j] = y;
}
public:
vector<int> findBall(vector<vector<int>>& grid) {
vector<int> ans(grid[0].size(), -1);
for (int j = 0; j < grid[0].size(); j++) {
drop(grid, ans, j);
}
return ans;
}
};

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
'''
Author: LetMeFly
Date: 2025-02-15 11:20:53
LastEditors: LetMeFly.xyz
LastEditTime: 2025-02-15 11:24:22
Description: AC,67.31%,26.92%
'''
from typing import List

class Solution:
def drop(self, j: int) -> None:
y = j
for x in range(len(self.grid)):
nextY = self.grid[x][y] + y
if nextY < 0 or nextY >= len(self.grid[0]) or self.grid[x][y] != self.grid[x][nextY]:
return
y = nextY
self.ans[j] = y

def findBall(self, grid: List[List[int]]) -> List[int]:
self.grid = grid
self.ans = [-1] * len(grid[0])
for j in range(len(grid[0])):
self.drop(j)
return self.ans

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
* @Author: LetMeFly
* @Date: 2025-02-15 11:20:57
* @LastEditors: LetMeFly.xyz
* @LastEditTime: 2025-02-15 11:30:31
*/
class Solution {
private int[][] grid;

private int drop(int y) {
for (int x = 0; x < grid.length; x++) {
int nextY = grid[x][y] + y;
if (nextY < 0 || nextY >= grid[0].length || grid[x][y] != grid[x][nextY]) {
return -1;
}
y = nextY;
}
return y;
}

public int[] findBall(int[][] grid) {
this.grid = grid;
int[] ans = new int[grid[0].length];
for (int j = 0; j < grid[0].length; j++) {
ans[j] = drop(j);
}
return ans;
}
}

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
* @Author: LetMeFly
* @Date: 2025-02-15 11:21:06
* @LastEditors: LetMeFly.xyz
* @LastEditTime: 2025-02-15 11:27:19
*/
package main

func drop_WWTBF(grid [][]int, y int) int {
for x := range grid {
nextY := y + grid[x][y]
if nextY < 0 || nextY >= len(grid[0]) || grid[x][y] != grid[x][nextY] {
return -1
}
y = nextY
}
return y
}

func findBall(grid [][]int) []int {
ans := make([]int, len(grid[0]))
for j := range grid[0] {
ans[j] = drop_WWTBF(grid, j)
}
return ans
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

Tisfy:https://blog.letmefly.xyz/2025/02/15/LeetCode 1706.球会落何处/


1706.球会落何处:模拟 - 很有意思的一道题
https://blog.letmefly.xyz/2025/02/15/LeetCode 1706.球会落何处/
作者
Tisfy
发布于
2025年2月15日
许可协议