有趣的算法题 (一)

今天在刷题的过程中看到了一道有趣的算法题.

这是一道典型的追逐问题.

只是这道题求的是 时间, 另外一些题目或许会求 距离.

原题地址 : https://www.codewars.com/kata/55e2adece53b4cdcb900006c/solutions/java

Description:

Two tortoises named A and B must run a race. A starts with an average speed of 720 feet per hour. Young B knows she runs faster than A, and furthermore has not finished her cabbage.

When she starts, at last, she can see that A has a 70 feet lead but B's speed is 850 feet per hour. How long will it take B to catch A?

More generally: given two speeds v1 (A's speed, integer > 0) and v2 (B's speed, integer > 0) and a lead g (integer > 0) how long will it take B to catch A?

The result will be an array [hour, min, sec] which is the time needed in hours, minutes and seconds (round down to the nearest second).

If v1 >= v2 then return nilnothingnullNone or {-1, -1, -1} for C++, C, Go, Nim, [] for Kotlin.

 

Examples

race(720, 850, 70) => [0, 32, 18]
race(80, 91, 37)   => [3, 21, 49]

---

简单翻译一下.

有A 和 B 两只小动物 ([勤奋A], 和[机智B]), [勤奋A] 的速度比较慢, 720英尺每小时, 所以让他先跑一段.

当 [勤奋A] 跑出了 70 英尺时, [机智B] 开始跑. [机智B] 的速度为每小时 850 英尺. [机智B] 要用多久能追上 [勤奋A].

---

这个问题非常有意思. 

首先 A 跑了 70 英尺.  这时B要追上这段距离.

T1 = S1 / v2 = 70 / 850 = 0.0823 (h)

B 跑这段距离的同时, A 也在跑.

S2 = T1 * v1 = 0.0823 * 720 = 59.256 (feet per)

......

......

如果这么算下去, 会被拆分为 很多很多段追逐路径 ( 如果最短追逐单位不尽兴限定的话, 例如 时->分->秒-> 毫秒 -> 微秒 -> 纳秒 -> 皮秒 -> 飞秒, 则追逐段数可能会变得非常之长. )

很显然, 我们用线代确实可以解决这个问题, 但确非常复杂.

其实这个题有更加简单的解法.

两个移动的物体速度有差异的时候, 例如甲开车, 乙跑步. 

从速度上来说,

对于甲来说, 乙是静止的.

对于乙来说, 甲是高速移动的.

甲的速度 - 乙的速度, 是他们的速度差.

分析到这里, 问题化简了.

假如我们用这个概念带入到刚才的题目中 :

速度差表示 [机制B] 的速度, 而 [勤奋A] 则会变得静止不动.  

那么, 追上一个静止不动的目标的时间就变成了 :

S1 / DS (diff speed)  = 70 / (850 - 720) = 70 / 130 = 0.538..

恩, 相当于半小时.

那么我们如何计算精确的时间单位呢 : (这里使用秒)

S1 * 60 * 60 / DS (diff speed)  = 70 * 60 * 60 / (850 - 720) = 70 * 3600 / 130 = 1938

那么 现在我们总共使用了 1938秒.

1938 / 60 = 32 分

1938 / 60 / 60 = 0 小时

 

假设要用分组统计的方式显示.

时 = 1938 / 3600

分 = 1938 % 3600 / 60

秒 = 1938 % 60

代码书写 :

public static int[] race(int v1, int v2, int g) {
    if (v1>=v2) return null;
    int result = g * 3600 / (v2 - v1);
    return new int[] {result / 3600, result % 3600 / 60, result % 60};
}

 

这个题目有两个陷阱 :

1. 需要计算的是超过所用的时间, 而不是最终超过的距离.

2. 很容易陷入线代思考的方式.

---

 

补充 :

假设题目需要计算的是, 最终 B 超过 A 需要跑多少米, 那么我们也可以简单的对此次结果的时间乘以B的速度. 即可解出题目.

 

转载于:https://my.oschina.net/u/273647/blog/1808408

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值