解题博客:LeetCode 1706. 球会落何处

解题博客:LeetCode 1706. 球会落何处

问题描述

我们有一个大小为 m x n 的二维网格 grid,它表示一个箱子。每一列的顶部都放有一颗球。每个格子中有一个斜向的挡板,可以将球导向左侧或右侧。球的移动规则如下:

  • 1 表示将球导向右侧。
  • -1 表示将球导向左侧。

在箱子的顶部每一列放置一颗球,球会向下移动,并可能被卡在箱子里。球可能在底部掉出,也可能被卡住。球卡住的情况:

  1. 当球在两个挡板之间形成 "V" 形状时会被卡住;
  2. 球可能会被导向箱子的左右边界而卡住。

我们的任务是模拟每颗球的移动,判断每颗球最终会从哪个列的底部掉出,或者是否会被卡住。结果应该是一个大小为 n 的数组 answer,其中每个元素表示球从对应列顶部开始的最终落点。如果球被卡住,则返回 -1

示例

示例 1

输入:

python 复制代码
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]
]

输出:

python 复制代码
[1, -1, -1, -1, -1]

解释:

  • 球 b0 从第 0 列掉出,从第 1 列出来;
  • 球 b1 被卡在第 1 行、第 2 列和第 3 列之间的 "V" 形里,无法掉出,结果是 -1
  • 其他球也因为类似的原因无法掉出。

示例 2

输入:

python 复制代码
grid = [[-1]]

输出:

python 复制代码
[-1]

解释:球从顶部掉落后被卡在了箱子的左边界。

示例 3

输入:

python 复制代码
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]
]

输出:

python 复制代码
[0, 1, 2, 3, 4, -1]

解释:

  • 球从每一列开始依次掉落,最终除了第 5 列外,其他球都成功掉出。

解题思路

为了模拟每颗球的移动,我们可以逐列模拟球的下落过程。每颗球从顶部的某一列开始,并根据当前格子的值判断球的移动方向。如果球被导向左侧或右侧,我们继续向下遍历并检查下一个格子,直到球最终被卡住或者成功掉落。

步骤

  1. 初始化: 我们维护一个大小为 n 的数组 ans,每个位置初始化为 -1,表示所有球都尚未掉落。
  2. 逐列模拟: 对于每列,我们模拟球的下落过程。球从每列顶部出发,根据当前格子的值(1-1)决定球向左或向右移动。
  3. 判断卡住: 如果球在某一格后超出边界(即小于 0 或大于等于 n),或者球被卡在 "V" 形结构中(即当前格子的值与下一格的值方向相反),我们就认为球卡住,直接跳出循环。
  4. 记录结果: 如果球成功通过所有行并最终落在某个列上,我们记录下该列的下标。

代码实现

python 复制代码
class Solution:
    def findBall(self, grid: List[List[int]]) -> List[int]:
        n = len(grid[0])  # 获取列数
        ans = [-1] * n  # 初始化答案数组,-1 表示球被卡住

        for j in range(n):  # 对每列进行模拟
            cur = j  # 当前球的列
            for row in grid:  # 遍历每一行
                d = row[cur]  # 获取当前格子的值,-1 或 1
                cur += d  # 根据值决定球的方向
                # 如果球出界,或者球卡在 V 形结构中,则提前结束
                if cur < 0 or cur >= n or row[cur] != d:
                    break
            else:
                # 如果没有提前结束,说明球成功掉出
                ans[j] = cur
        
        return ans

代码解释

  1. 初始化:

    • n = len(grid[0]):获取网格的列数 n
    • ans = [-1] * n:初始化答案数组,所有球都假设会卡住。
  2. 模拟每列球的移动:

    • for j in range(n)::对于每列,从顶部开始模拟球的下落。
    • cur = j:当前球位于第 j 列。
  3. 遍历每一行:

    • d = row[cur]:获取当前格子的值,1-1,决定球的移动方向。
    • cur += d:球根据当前格子的值移动到下一列。
    • if cur < 0 or cur >= n or row[cur] != d::判断球是否出界或卡住。
  4. 记录结果:

    • 如果球没有被卡住,最终会通过所有行,我们将其最终落点记录在 ans[j] 中。
  5. 返回结果:

    • 返回 ans 数组,表示每颗球最终的位置或是否卡住。
      先列后行,如果同一行内的两次行动不是相同的,即不是都在左或者都在右边,就是V形状,否则是互通的。如果没有V形状,或者到达边界那么,可以记录这里的else是相对于for而言,如果for循环没有break就会记录

复杂度分析

  • 时间复杂度: O(mn),其中 m 是网格的行数,n 是网格的列数。我们需要模拟每个球的下落过程,最多遍历 m 行,对于每个球最多遍历一次 n 列。
  • 空间复杂度: O(n),我们需要一个大小为 n 的数组 ans 来存储每颗球的最终位置。

总结

这道题目主要考察模拟和判断的能力,通过逐列模拟每颗球的下落过程,判断球是否会卡住,并记录球最终的落点。通过使用简单的循环和条件判断,我们能够高效地解决这个问题。

相关推荐
Dizzy.5174 小时前
数据结构(查找)
数据结构·学习·算法
hello_simon5 小时前
【Word转PDF】在线Doc/Docx转换为PDF格式 免费在线转换 功能强大好用
职场和发展·pdf·word·学习方法·word转pdf·石墨文档·word转换
分别努力读书6 小时前
acm培训 part 7
算法·图论
武乐乐~6 小时前
欢乐力扣:赎金信
算法·leetcode·职场和发展
'Debug7 小时前
算法从0到100之【专题一】- 双指针第一练(数组划分、数组分块)
算法
Fansv5877 小时前
深度学习-2.机械学习基础
人工智能·经验分享·python·深度学习·算法·机器学习
测试19988 小时前
接口测试工具:Postman
自动化测试·软件测试·python·测试工具·职场和发展·接口测试·postman
yatingliu20198 小时前
代码随想录算法训练营第六天| 242.有效的字母异位词 、349. 两个数组的交集、202. 快乐数 、1. 两数之和
c++·算法
uhakadotcom9 小时前
Google DeepMind最近发布了SigLIP 2
人工智能·算法·架构
sjsjs119 小时前
【数据结构-并查集】力扣1202. 交换字符串中的元素
数据结构·leetcode·并查集