京东2020校招笔试题-算法工程师

1、笔试题目说明:

30道选择(包括单选和多选),占60分;2道编程题,占40分;

2、编程题解:

第一道编程题没怎么理解题意,重点在做第2道,根据当时的草稿及事后调通的代码,记录如下:

2.1 题目描述:迷宫问题(仅提取核心部分,有所简化)

给一个N*M的迷宫单元,其中的元素仅包含3个字符:“#”、“P”和“S”。其中“#”代表墙壁,表示不能通过;“S”代表单元迷宫的起点;“P”代表的是路,表示可以通行的道路。

若干个N*M的迷宫单元可以任意组合,迷宫单元之间只能进行左右拼接和上下拼接操作。并且,当大迷宫中的某个“S”被确定为起始点后,其他的“S”可被看作能够行走的道路,相当于“P”。

对于拼接之后的大迷宫,从某个起点“S”开始,可以无限地走下去(不会被墙壁阻隔,行走的方式只能是上下左右,不能斜着走),则认为这个迷宫单元是合法的

输入:

第一行是两个正整数N和M,表示迷宫单元是N行M列(1≤N, M≤300)。之后N行,每一行是一个长度为M的字符串,如题所述,描述了一个迷宫单元。

输出:

如果这个迷宫单元是合法的,就输出“Yes”,否则输出“No”。

示例 1:

输入:

2 2

S#

#P

输出:

No

示例 2:

输入:

3 3

PPP

###

#S#

输出:

Yes

2.2 解题思路

(1)某个“S”被确定为起始位置之后,其他的“S”相当于“P”。因为起始位置是任意的,所以可以将问题简化为:迷宫单元仅包含两种情况的点:能通过的点(非墙)和不能通过的点(墙);这里分别用●和×来表示。

(2)合法的迷宫单元,组成的大迷宫可以无限地走下去,也就是始终有一条通路能够走出迷宫。对于无限地情况,不好用条件去限制,所以反过来判断有限的情况,也就是判断什么情况下是非法的迷宫单元。这里,根据示例绘制如下两种迷宫单元的组合,进行说明:

示例1:

如图,是4个2*2的迷宫单元组成的大迷宫,组合方式包括左右拼接和上下拼接,包含了所有的组合方式。

从示例结果来看,该迷宫单元非法;

从组合图来看,可以发现,每个 ● 周围(上下左右)都是墙壁,所有的通路都被堵死了

示例2:

如图,是4个3*3的迷宫单元组成的大迷宫,包含了所有的组合方式。

从示例结果来看,该迷宫单元合法;

从组合图来看,可以很明显地发现,●周围有通路

综合示例1和2的组合图及结果,可以发现:

(1)只要 ● 周围有通路,该迷宫单元组合出来的大迷宫就能够无限地走下去;

(2)从单个迷宫单元无法观测出●周围是否有通路,而4个迷宫单元上下左右拼接之后的大迷宫,则可以清楚地显示出●周围的通路情况;

(3)通过大迷宫判断出每个点的通路情况之后,只要迷宫单元中有一个点周围有通路,那么该迷宫单元即是合法的。

因此有如下解决方案:

(1)将4个迷宫单元进行上下左右拼接,组合成大迷宫;

(2)遍历大迷宫中的每个点(●和×),判断其周围是否有通路(此处要特别注意大迷宫4个角以及外围4个边行上的点的判断)。因此,还需要构造与大迷宫尺寸相等的数组,用来记录每个点的通路情况。

(3)对于迷宫中每个点的通路情况,若其周围都是墙(上下左右都是×),则说明通路被封死,可以用False表示;否则,只要周围有通路,则该点的即可走通,可以用True来表示。

2.3 代码实现如下:

# 判断是否能组合成合法迷宫
def check(ans, rows, cols):
    recds = [[True] * cols for _ in range(rows)]
    for i in range(rows):
        for j in range(cols):
            if ans[i][j] == '#':     # 表示该点的路径被封死
                recds[i][j] = False
                continue

            # 四个边角
            if i == 0 and j == 0:  # 左上角
                if ans[i][j + 1] == '#' and ans[i + 1][j] == '#':
                    recds[i][j] = False
                continue
            if i == 0 and j == cols - 1:  # 右上角
                if ans[i + 1][j] == '#' and ans[i - 1][j] == '#':
                    recds[i][j] = False
                continue
            if i == rows - 1 and j == 0:  # 左下角
                if ans[i][j + 1] == '#' and ans[i - 1][j] == '#':
                    recds[i][j] = False
                continue
            if i == rows - 1 and j == cols - 1:  # 右下角
                if ans[i - 1][j] == '#' and ans[i][j - 1] == '#':
                    recds[i][j] = False
                continue

            # 四个边行
            if i == 0:
                if ans[i + 1][j] == '#' and ans[i][j + 1] == '#' \
                        and ans[i][j - 1] == '#':
                    recds[i][j] = False
                continue
            if i == rows - 1:
                if ans[i - 1][j] == '#' and ans[i][j + 1] == '#' \
                        and ans[i][j - 1] == '#':
                    recds[i][j] = False
                continue
            if j == 0:
                if ans[i - 1][j] == '#' and ans[i + 1][j] == '#'\
                        and ans[i][j+1] == '#':
                    recds[i][j] = False
                continue
            if j == cols - 1:
                if ans[i-1][j] == '#' and ans[i + 1][j] == '#'\
                        and ans[i][j-1] == '#':
                    recds[i][j] = False
                continue

            # 其他有四个邻居的点
            if 0 < i < rows - 1 and 0 < j < cols - 1:
                if ans[i - 1][j] == '#' and ans[i + 1][j] == '#' and \
                        ans[i][j - 1] == '#' and ans[i][j + 1] == '#':
                    recds[i][j] = False

    # 判断迷宫单元是否合法
    flag = False
    for i in range(rows // 2):
        for j in range(cols // 2):
            if recds[i][j]:
                flag = True
                break
    return flag
    pass


if __name__ == '__main__':

    line = input().split(' ')
    n, m = int(line[0]), int(line[1])
    vals = []
    for idx in range(n):
        vals_temp = input()
        vals.append(vals_temp * 2)  # 左右拼接
    vals = vals * 2   # 上下拼接
    
    if check(vals, n * 2, m * 2):
        print('Yes')
    else:
        print('no')
    pass

以上,即是个人的解决思路。时间复杂度为O(NM)。

思路和代码比较暴力,还有需要改进和完善的地方。若有好的思路和方案,希望能够相互交流学习~

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值