Android Unlock Pattern

这个题一直以为是DP结果被吓住了,实际上这就是个跟数独和N皇后一样的穷举问题,通过枚举和检查来减少无效搜索,但是这道题的检查因为这个规则的复杂变成了最难的地方,而回溯的过程倒是无比简单,这里设置了一个-1初始位置来方便判断

class Solution(object):
    def numberOfPatterns(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        result = 0
        for i in xrange(m, n + 1):
            used = [False] * 9
            result += self.calPattern(-1, i, used)
        return result

    def calPattern(self, last, time, used):
        if time == 0:
            return 1

        result = 0
        for i in xrange(9):
            if self.check(last, i, used):
                used[i] = True
                result += self.calPattern(i, time - 1, used)
                used[i] = False

        return result

    def check(self, last, i, used):
        if used[i]:               # 已经被占用了则不行
            return False    
        if last == -1:            # 第一个位置自然没问题
            return True

        if (last + i) % 2:        # 前一个位置和当前选择位置如果构成马跳位或者相邻位合法
            return True
        mid = (last + i) / 2      # 找对角线末端的点
        if mid == 4:              # 如果前一个位置和当前位置跨过正中间的点,返回中间点的占用状态
            return used[mid]
        if i % 3 != last % 3 and i / 3 != last / 3:      # 同对角线上相邻的点
            return True
        return used[mid]

上面是完全穷举的方法,calPattern函数的时间复杂度是O(n!),此题的1,3,7,9和2,4,6,8四个位置的结果实际上是均等的,我们可以只计算其中一个乘以4就可以优化计算

results matching ""

    No results matching ""