[leetcode/lintcode 题解] 阿里巴巴面试题:金字塔

简介: [leetcode/lintcode 题解] 阿里巴巴面试题:金字塔

描述
给你一个金字型塔的数列,第一行一个0,第二行两个1……第六行六个5,现在金字塔数字打乱了,你只能移动0这个数字,并且只能左上、右上、左下、右下走,问在20步内能否回到原来状态。

保证输入合法
如果20步内不能回到原状态,就返回-1

在线评测地址:领扣题库官网

样例1
给定 `a=[[1],[2,0],[2,1,2],[3,3,3,3],[4,4,4,4,4],[5,5,5,5,5,5]]` 返回 `3`
输入:
[[1],[2,0],[2,1,2],[3,3,3,3],[4,4,4,4,4],[5,5,5,5,5,5]]
输出:
3

解释:
一开始,移动到(2,1)
然后,移动到(1,0)
最后,移动到(0,0)

样例2
给定 `a=[[1],[0,1],[2,2,2],[3,3,3,3],[4,4,4,4,4],[5,5,5,5,5,5]]` 返回 `1`
输入:
[[1],[0,1],[2,2,2],[3,3,3,3],[4,4,4,4,4],[5,5,5,5,5,5]]
输出:
1

解释:
直接移动到(0,0)

解题思路:双向BFS

  • 分别从起点和终点开始BFS,记录各自状态下的最少步数。两个状态中途相遇时,两个状态的最少步数之和就是答案。
  • 因为题目限定最多20步,所以从起点和终点开始只需要各走最多10步。
  • 金字塔数组进入哈希前,要先序列化成字符串。因为给定的金字塔数组不规则,不像华容道的正方形,所以我把字符串反序列化后再移动0的位置。这种办法比较易懂,也许存在更直接的数学办法。
  • state记录当前状态,rc记录0的座标,from_start记录当前状态从start开始还是从end开始。

import itertools
from collections import deque

class Solution:
    """
    @param a: the number admiral
    @return: the number of steps to return to the original state
    """
    def getSteps(self, a):
        start = self.serialize(a)
        end = self.serialize([[0], [1,1], [2,2,2], [3,3,3,3], [4,4,4,4,4], [5,5,5,5,5,5]])
        start_r, start_c = self.find_zero(a)
        
        queue = deque([(start, start_r, start_c, True), (end, 0, 0, False)])
        distances_from_start, distances_from_end = {start : 0}, {end : 0}
        
        while queue:
            state, r, c, from_start = queue.popleft()
            # Meet in the middle
            if (from_start and state in distances_from_end) or \
                (not from_start and state in distances_from_start):
                return distances_from_start[state] + distances_from_end[state]
            # Move to the next state from start / end
            for next_state, i, j in self.get_next(state, r, c, from_start, distances_from_start, distances_from_end):
                if from_start:
                    distances_from_start[next_state] = distances_from_start[state] + 1
                    # Maximum 10 steps from start
                    if distances_from_start[next_state] <= 10:
                        queue.append((next_state, i, j, from_start))
                else:
                    distances_from_end[next_state] = distances_from_end[state] + 1
                    # Maximum 10 steps from end
                    if distances_from_end[next_state] <= 10:
                        queue.append((next_state, i, j, from_start))
        
        return -1
    
    def get_next(self, state, r, c, from_start, distances_from_start, distances_from_end):
        a = self.deserialize(state)
        for i, j in [(r - 1, c), (r + 1, c), (r - 1, c - 1), (r + 1, c + 1)]:
            if 0 <= i < len(a) and 0 <= j < len(a[i]):
                next_state = self.swap(a, r, c, i, j)
                if (from_start and next_state not in distances_from_start) or \
                    (not from_start and next_state not in distances_from_end):
                    yield next_state, i, j
    
    def swap(self, a, r, c, i, j):
        a[r][c], a[i][j] = a[i][j], a[r][c]
        ret = self.serialize(a)
        a[r][c], a[i][j] = a[i][j], a[r][c]
        return ret

    def find_zero(self, a):
        for r in range(len(a)):
            for c in range(len(a[r])):
                if a[r][c] == 0:
                    return r, c
        return -1, -1

    def serialize(self, a):
        return "".join(map(str, itertools.chain(*a)))
    
    def deserialize(self, s):
        ret = []
        index = 0
        for i in range(1, 7):
            line = []
            for j in range(i):
                line.append(s[index + j])
            index += i
            ret.append(line)
        return ret

更多题解参考:九章官网solution

相关文章
|
1月前
|
算法
【数组相关面试题】LeetCode试题
【数组相关面试题】LeetCode试题
|
1月前
力扣面试经典题之哈希表
力扣面试经典题之哈希表
18 0
|
1月前
|
存储
力扣面试经典题之数组/字符串
力扣面试经典题之数组/字符串
21 0
|
3月前
|
存储 算法 程序员
【Leetcode 程序员面试金典 01.01】判定字符是否唯一 —— 位运算|哈希表
可以使用哈希表或位运算来解决此问题:由题可知s[i]仅包含小写字母,int[26]即能表示字符的出现次数;
|
3月前
|
算法 程序员 索引
【Leetcode 程序员面试金典 02.08】 —— 环路检测 |双指针
我们可以使用双指针解决本题,由数学推导可知:a 的距离为(环长度的倍数 - b),即 tmp 指针从头节点走到环开头节点等于 slow 指针走到环开头节点的距离
|
3月前
|
Java 程序员
【Leetcode 程序员面试金典 05.01】插入 —— 位运算
位运算问题,只需要把 N 的 i 到 j 位都置 0 后再和 M 左移 i 位的结果进行按位或即可
|
1月前
力扣面试经典题之二叉树
力扣面试经典题之二叉树
16 0
|
2月前
|
JavaScript 前端开发 C语言
leetcode每日一题 2021/4/2 面试题 17.21. 直方图的水量
leetcode每日一题 2021/4/2 面试题 17.21. 直方图的水量
23 0
|
1月前
|
机器学习/深度学习 人工智能 算法
LeetCode刷题--- 面试题 01.07. 旋转矩阵(原地旋转+翻转替旋转)
LeetCode刷题--- 面试题 01.07. 旋转矩阵(原地旋转+翻转替旋转)
|
1月前
|
存储 算法 Java
超全面!阿里巴巴最新发布23年秋招200道Java面试题(含答案)
马上过34岁生日了,和大家聊聊最近的情况 半年前还在迷茫该学什么,怎样才能走出现在的困境,半年后已经成功上岸阿里,感谢在这期间帮助我的每一个人。 面试中总结了200道经典的Java面试题,里面包含面试要回答的知识重点,并且我根据知识类型进行了分类,可以说非常全面了~ 因为篇幅原因,大部分的内容就不给大家一一展示了,需要获取的小伙伴可以直接点击此处取到! Java平台相关 1、JDK、JRE、JVM 分别是什么关系? 2、为什么 Java 被称作是“平台无关的编程语言”? 3、Java 和 C++ 的区别? 4、什么是字节码?采用字节码的最大好处是什么? 5、Java运行的过程? 6、
81 4