JavaScript问题解决方案:访问所有点的最短时间

I seemed to have fallen into a web of nested arrays, matrices and pattern matching. Today’s problem isn’t as complex as last week’s Onion Swap hullabaloo, but technically still deals with matrices. Technically technically, we are dealing with a graph, but at the same time, we aren’t.

我似乎陷入了嵌套数组,矩阵和模式匹配的网络中。 今天的问题并不像上周的Onion Swap hullabaloo那样复杂,但从技术上讲,它仍然可以处理矩阵。 从技术上讲,我们正在处理图形,但与此同时,我们不是。

I have also been working on my skills with recursion. One of the ways I’ve been practicing is by going back to problems I have already solved and refactoring them using recursion. So, at the end of this blog, I will also be providing a solution using Tail Call Recursion.

我还一直在研究递归的技巧。 我一直在练习的方法之一是回到已经解决的问题,然后使用递归重构它们。 因此,在此博客的结尾,我还将提供使用尾部调用递归的解决方案。

Anyways, let’s get solving.

无论如何,让我们解决吧。

问题 (THE PROBLEM)

Here is a link to the problem on LeetCode

这是有关LeetCode问题的链接

On a plane there are n points with integer coordinates points[i] = [xi, yi]. Your task is to find the minimum time in seconds to visit all points.You can move according to the next rules:
- In one second always you can either move vertically, horizontally by one unit or diagonally (it means to move one unit vertically and one unit horizontally in one second).
- You have to visit the points in the same order as they appear in the array.
Image for post

约束 (THE CONSTRAINTS)

points.length == n

This isn’t really a necessary constraint, but provides a definition for the next constraint. n is only used in the problem’s explanation, and is not used anywhere else.

这实际上不是必需的约束,但是为下一个约束提供了定义。 n仅在问题的解释中使用,在其他任何地方均未使用。

1 <= n <= 100

Here we get a range for how many sets of points we should expect, with the lower limit of 1 and an upper limit of 100. This tells us we don’t have to worry about a given array being empty.

在这里,我们得到了一个预期的点集范围,下限为1,上限为100。这告诉我们,我们不必担心给定数组为空。

points[i].length == 2

We are given a static value for how many elements each set of points will have. Each set of points, or points[i], should have an x value and y value, or [x, y] or points[i][x, y]. We can use this information to avoid nesting iterations in our solution.

对于每个点集将具有多少元素,我们将获得一个静态值。 每组点或points[i]应当具有x值和y值,或者[x, y]points[i][x, y] 。 我们可以使用此信息来避免在解决方案中嵌套迭代。

-1000 <= points[i][0], points[i][1] <= 1000

This gives us the size of the coordinate plane, and a range for where we should expect to see any points. points[i][0] is the x value for each set of points, and points[i][1] is the y value, meaning we need to account for points appearing in the range of [-1000, -1000] to [1000, 1000]. In other words, the entire plane.

这给了我们坐标平面的大小,以及我们期望看到任何点的范围。 points[i][0]是每组点的x值, points[i][1]y值,这意味着我们需要考虑出现在[-1000, -1000][1000, 1000] 换句话说,整个飞机。

测试 (THE TESTS)

崩溃 (THE BREAK DOWN)

With our constraints dissected and test cases observed, let’s start breaking down the problem’s explanation and figuring out what we need to do:

剖析我们的约束并观察到测试用例之后,让我们开始分解问题的解释并弄清楚我们需要做什么:

On a plane there are n points with integer coordinates points[i] = [xi, yi].

Here is the context for the problem. n (or points.length) is a set of points on 2-D graph (coordinate plane), and points[i] represents each set of points. The elements of points[i] are the x and y position for each point, with points[i][0] being the x position, and points[i][1] being the y position. We can use static values for x and y thanks to the constraint points[i].length == 2.

这是问题的背景。 n (或points.length )是二维图形(坐标平面)上的一组点,而points[i]代表每组点。 points[i]的元素是每个点的xy位置, points[i][0]x位置, points[i][1]y位置。 由于约束points[i].length == 2我们可以为xy使用静态值。

Your task is to find the minimum time in seconds to visit all points.

This is our task, obviously. We simply have to find the shortest distance between each set of points, starting with points[0], and ending with points[points.length - 1]. I say distance because we can only move 1 unit on the coordinate plane per second. We get some more information about how time works relative to this problem in the rules below.

显然,这是我们的任务。 我们只需要找到每组点之间的最短距离,以points[0] ,以points[points.length - 1] 。 我说距离是因为我们每秒只能在坐标平面上移动1个单位。 在下面的规则中,我们将获得有关时间如何相对于此问题的更多信息。

In one second always you can either move vertically, horizontally by one unit or diagonally (it means to move one unit vertically and one unit horizontally in one second).

This is why time and distance is relatively interchangeable. Speed is a fixed value at 1. We can only traverse through the coordinate plane 1 point at a time.

这就是时间和距离相对可互换的原因。 速度是1的固定值。我们一次只能遍历1个坐标平面。

Moving diagonally between two points is the equivalent of incrementing or decrementing points[i][0] and points[i][1] at the same time. Moving horizontally is equal to incrementing/decrementing only points[i][0], while moving vertically is equal to incrementing/decrementing points[i][1].

在两个点之间对角移动等同于同时增加或减少points[i][0]points[i][1] 。 水平移动等于仅增加/减少points[i][0] ,而垂直移动等于incrementing/decrementing points[i][1]

You have to visit the points in the same order as they appear in the array.

This is more of a constraint than anything else. It tells us we must iterate through the elements in points as they are indexed. We must start at the beginning and move through to the end.

这比其他任何事情都更具约束性。 它告诉我们在索引points必须迭代points的元素。 我们必须从头开始,一直到结束。

Since we can only move 1 point at a time, we will need to compare points[i] and points[i + 1]. We are strictly dealing with adjacent pairs.

由于我们一次只能移动1个点,因此需要比较points[i]points[i + 1] 。 我们严格处理相邻对。

犯罪嫌疑人 (THE SUSPECT)

Based off the problem’s explanation and with the extra information we gained through breaking down each part, I came up with 6 things we need to do:

基于问题的解释,并通过分解各个部分获得了更多信息,我提出了我们需要做的6件事:

1.) Iterate from 0 until i < points.length — 1

This is the basic setup. We need to use a for loop and iterate through the entire set of points so we can access the next set of points relative to i. We need to set our upper limit to points.length - 1 since we are going to be accessing the next adjacent element of i.

这是基本设置。 我们需要使用for循环并遍历整个点集,以便可以访问相对于i的下一组点。 我们需要将上限设置为points.length - 1因为我们将要访问i的下一个相邻元素。

2.) Find the distance between points[i][0] and points[i + 1][0]

Since we can move diagonally, we need to find the greatest difference between two sets of adjacent points. For the x axis, that is the difference between points[i][0] and points[i + 1][0].

由于我们可以沿对角线移动,因此我们需要找到两组相邻点之间的最大差。 对于x轴,这是points[i][0]points[i + 1][0]

We might encounter a problem though. If the value of points[i + 1][0] is larger than points[i][0], we will get a negative difference. We don’t want that. But, we can fix this by finding the absolute value of the difference between points[i][0] and points[i + 1][0] instead.

我们可能会遇到问题。 如果points[i + 1][0]值大于points[i][0] ,我们将得到一个负差。 我们不想要那个。 但是,我们可以通过找到points[i][0]points[i + 1][0]之间的差的绝对值来解决此问题。

3.) Find the distance between points[i][1] and points[i + 1][1]

This is the same thing as step 2, but for the y values for each set of points. Everything we do in step 2 can be reapplied to step 3.

这与步骤2相同,但是对于每个点集的y值。 我们在步骤2中所做的所有操作都可以重新应用于步骤3。

4.) Find the maximum of each difference

We can set the absolute value of the difference between points[i][0] and points[i + 1][0] to an out scoped variable xDist. We can do the same for the absolute value of the difference between points[i][1] and points[i + 1][1], and set the result to another out scoped variable yDist.

我们可以将points[i][0]points[i + 1][0]之间的差的绝对值设置为范围外变量xDist 。 我们可以对points[i][1]points[i + 1][1]之间的差的绝对值执行相同的操作,并将结果设置为另一个超出范围的变量yDist

We can then compare the values of xDist and yDist to find which is greater.

然后,我们可以比较xDistyDist的值以发现更大的值。

Since we can move diagonally, the only thing that matters is how many steps we need to purely take horizontally or vertically. If points[i][0] === points[i][1], we can walk diagonally the entire time we are travelling between two points and the difference doesn’t matter. But as soon as points[i][0] !== points[i][1], we will need to travel horizontally or vertically at least once without moving diagonally. This is why the maximum difference between x and y values also represent the minimum distance between two points.

由于我们可以沿对角线移动,因此唯一重要的是我们仅需水平或垂直执行几步即可。 如果points[i][0] === points[i][1] ,我们可以在两点之间的整个旅行过程中沿对角线行走,而差异并不重要。 但是,一旦points[i][0] !== points[i][1] ,我们将至少需要水平或垂直移动一次而不对角移动。 这就是为什么xy值之间的最大差异也表示两点之间的最小距离的原因。

5.) Add the maximum difference of each pair to the total

Once we have compared xDist and yDist and found which is greater, we can add this to the total distance variable called totalDist.

比较xDistyDist并发现更大的值后,可以将其添加到名为totalDist的总距离变量中。

6.) Return the total amount of distance between each set of points.

Once we have iterated through the entire set of points, found the absolute value of the difference for each set of points, found the maximum difference and added the maximum difference to the total distance, totalDist should equal the minimum time to visit all points, and we can return totalDist.

遍历整个点集之后,找到每个点集的差的绝对值,找到最大差,并将最大差加到总距离中, totalDist应该等于访问所有点的最短时间,并且我们可以return totalDist

伪代码 (THE PSEUDO CODE)

Let’s take the 6 steps we’ve outlined and condense them down into to some easier to digest pseudo code:

让我们按照概述的6个步骤进行操作,然后将它们压缩为更易于理解的伪代码:

代码 (THE CODE)

With our pseudo code looking good, let’s start writing out a solution.

在伪代码看起来不错的情况下,让我们开始编写解决方案。

First, let’s define the 3 variables xDist, yDist, and totalDist. Then, set up the basics for the for loop:

首先,让我们定义3个变量xDistyDisttotalDist 。 然后,设置for循环的基础知识:

Next, we can add the logic to reassign xDist and yDist to the absolute difference of the x and y values for each set of points:

接下来,我们可以添加逻辑以将xDistyDist重新分配给每组点的xy值的绝对差:

Then, at the end of each iteration, we can add the maximum value of xDist and yDist to totalDist:

然后,在每次迭代结束时,我们可以将xDistyDist的最大值添加到totalDist

And finally, add our return value of totalDist:

最后,加上我们的totalDist return值:

If we run our solution against the 3 test cases we have, we should be passing all of them without any problems:

如果我们针对现有的3个测试用例运行解决方案,则应该顺利通过所有测试用例:

Image for post

Nice.

真好

回归 (THE RECURSION)

As promised here is the recursive version of our solution using Tail Call Optimization. I won’t go into too much detail here because recursion is a whole other can of worms, but I will outline some of the basic refactoring we would have to do.

如此处所承诺的,是使用尾调用优化的解决方案的递归版本。 由于递归是蠕虫的另一种形式,因此在这里我不做过多介绍,但是我将概述一些我们必须要做的基本重构。

We can set up our base case equal to the upper limit of our for loop. When we hit that base case, we want to return totalDist:

我们可以将基本情况设置为等于for循环的上限。 当我们遇到基本情况时,我们想return totalDist

Then, we want to take the 3 variables we are using to keep track of distances (xDist, yDist, totalDist), add them to the function’s arguments, and set their default values to 0. We also want to add i with a default value of 0 as well:

然后,我们要获取用于跟踪距离的3个变量( xDistyDisttotalDist ),将它们添加到函数的参数中,并将其默认值设置为0。我们还希望将i添加为默认值也为0:

Finally, we want to return our recursive function call. Since we want to use Tail Call Recursion, we need to make sure we are not creating a new local execution context on each recursive invocation. We can do so by updating each variable within the arguments of our recursive invocation:

最后,我们要return递归function调用。 由于我们要使用尾调用递归,因此需要确保不在每次递归调用上创建新的本地执行上下文。 我们可以通过在递归调用的参数中更新每个变量来做到这一点:

If we run our recursive solution against our 3 test cases, we should be passing them once more:

如果针对3个测试用例运行递归解决方案,则应再次传递它们:

Image for post

Nice.

真好

最终解决方案 (THE FINAL SOLUTIONS)

Let’s take a final look at our solutions without the comments, and clean up some of our syntax:

让我们最后看一下没有注释的解决方案,并清理一些语法:

Non-recursive:

非递归:

LeetCode Submission Detail

LeetCode提交详细信息

Recursive:

递归:

LeetCode Submission Detail

LeetCode提交详细信息

Seems like the recursive solution is a little bit faster. Interesting.

似乎递归解决方案要快一点。 有趣。

任务完成 (MISSION COMPLETE)

While minTimeToVisitAllPoints isn’t the most complicated problem out there, I felt like the solution we came up with was interesting enough to share, and refactoring it with Tail Call recursion was interesting enough as well.

尽管minTimeToVisitAllPoints并不是最复杂的问题,但我觉得我们想出的解决方案很有趣,可以分享,并且使用Tail Call递归进行重构也很有趣。

Recursion can be an overwhelming topic to tackle and remains somewhat of a mystery to me, so I think adding a little recursion to each blog (where applicable) would be a good way for me to practice and improve.

递归可能是一个难以解决的话题,对我来说仍然是一个谜,因此,我认为在每个博客(如果适用)上增加一点递归将是我练习和改进的好方法。

I definitely understand my solutions won’t be the best or most efficient, but either way I hope they help you or someone else figure out a way to solve a problem you encounter on this journey we call JavaScript.

我绝对知道我的解决方案不是最佳或最有效的,但是我希望它们能帮助您或其他人找到解决您在我们称为JavaScript的过程中遇到的问题的方法。

Either way, I hope you got some useful information, and may all your functions return true, and all your requests respond with 200.

无论哪种方式,我都希望您能获得一些有用的信息,并希望所有函数都返回true,并且所有请求均以200响应。

Stay safe…stay healthy…and keep fighting the good fight.

保持安全……保持健康……并继续打好仗。

翻译自: https://levelup.gitconnected.com/javascript-problem-solvers-minimum-time-visiting-all-points-bd9122929ce2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值