刚参加工作的小伙伴可能觉得算法没什么用处,会工程开发就行,会写业务就行。但是当你达到一定的水平以后,你会发现系统的瓶颈可能在于算法,一个好的算法和一个差的算法在系统性能上的表现有云泥之别。不止于此,学习和练习算法也能锻炼人的思维能力,不管你做什么事都会有潜移默化的影响。所以,总之一句话,让我们现在就开始学习算法吧!
今年实习生招聘差不多也接近尾声了,各大厂的笔试题目在网上都能找到。今天我们看一道美团的笔试题,比较容易。
题目如下图所示:
image.png
这种题目切忌一上来就暴力求解。首先要分析一下题目的规律。我们假设小王从正方形的左上角(记为原点)开始走起。
首先分析一下小王会在哪里停下来。小王从起点走n+1步后打了第一个标记,我们记为A点,再走n+1步又打一个标记,记为B点,以此类推。假设小王打了若干次标记后不是在A点停下来,比如是在B点停下来,那么往回退n+1步,小王上一次一定是在A点重复打了一个标记,这就有矛盾了,所以,小王一定是在A点停下来的。
这个结论一旦成立,说明小王在A点重复打标记之前的一次就是在原点打标记。我们记小王一共标记了m次,那么在原点打标记就是第m-1次打标记,而每打一次标记要走n+1步,所以到第m-1次打标记为止一共走了(n+1)(m-1)步,这(n+1)(m-1)步刚好等于周长的若干倍,即
(n+1)(m-1)=4n*k
从这个式子中可以看出,(n+1)(m-1)既是n+1的倍数,也是4n的倍数,又因为我们要找的m是让上式第一次成立的m,所以我们只要找出n+1和4n的最小公倍数,然后除以n+1即可得到答案。
所以m=[n+1, 4n] / (n+1) + 1
而最小公倍数[n+1, 4n] = (n+1)*4n / (n+1, 4n)
所以m = 4n / (n+1, 4n) + 1
到这里我们发现这道题的本质变成了求最大公约数问题(gcd)。最大公约数问题的代码网上到处都是。
最后附上golang版的代码:
package main
import (
"fmt"
"strconv"
"bufio"
"os"
"strings"
)
func main() {
var ts string
var ns string
fmt.Scanln(&ts)
t, _ := strconv.Atoi(ts)
inputReader := bufio.NewReader(os.Stdin)
ns, _ = inputReader.ReadString('\n')
ns = strings.Trim(ns, "\r\n")
n_slice := strings.Split(ns, " ")
for i := 0; i < t; i++ {
n, _ := strconv.Atoi(n_slice[i])
fmt.Println(4*n/gcd(n+1, 4*n)+1)
}
}
func gcd(a, b int) int {
if b == 0 {
return a
} else {
return gcd(b, a%b)
}
}
大家想看更详细的视频解答的话,可以上b站或者斗鱼等网站上搜“大雪菜”(这个up主是北大的大神级人物),能找到相关的视频。
欢迎关注博主个人微信公众号~~~