zoukankan      html  css  js  c++  java
  • 边工作边刷题:70天一遍leetcode: day 94-3

    Android Unlock Patterns

    要点:

    • 本质:递归选下一个位置,返回count(规律:count的就返回count,True/False就返回True/False)
      • 递归类似permutation,所以用used记录
      • =m and <=n:

        • 类似strobogramatic III,作为recursion的结束条件。
        • 为了省事,不pass in当前len,可以减m/n:
        • 这里有技巧:如果m<=0,表示至少有一个解(如果之前的,就表示之前的,本位置不选,如果初始,就是空,符合>=0的条件),只有n<=0(不选,但是也要返回累积的),提前结束返回1
    • valid条件:used没有用并且:具体来说,
      • 一个used变量用bit可以表示9个位置的True/False,used用来记录当前dfs递归的stacktrace
      • 技巧:对于下一个位置的测试点i,j:得到used2,如果used2>used:表示i,j没有用
      • 无间隔条件:当前点和下一个测试点之间的中点有没有?因为是3X3,2个点之间差0或者1,所以可以用这个条件%2。
        • 错误理解:不是横纵都为%2==1,而是any(想想一个方向可以坐标相同)。注意跨越6格斜角是符合的。
        • 符合的是%21,不是0
    • 初始:注意recursion内loop,开始点选(1,1)是因为所有其他点都符合%2==1条件,而(1,1)这个点第三个条件满足。所以recursion内任意点都可以初始。

    https://repl.it/Cmup/1 (backtracking: beat 22.73%)
    https://repl.it/Cmup/2 (dp, beat 100%)

    • dp: dp[used][j]: all possible used of 9: 1<<9, end with j的个数。递推:
      • loop: 最外层是used,所以从less used到more used构建
      • 当前目标找到所有used里以某个i结尾,loop on last end with j, 这样可以扩展到下一个,dp[used][j]已经count过。
      • dp有很多hole是invalid的。比如used里没有i或者j
      • init: 如果只有1个键,那是1个
    # Given an Android 3x3 key lock screen and two integers m and n, where 1 ≤ m ≤ n ≤ 9, count the total number of unlock patterns of the Android lock screen, which consist of minimum of m keys and maximum n keys.
    
    # Rules for a valid pattern:
    # Each pattern must connect at least m keys and at most n keys.
    # All the keys must be distinct.
    # If the line connecting two consecutive keys in the pattern passes through any other keys, the other keys must have previously selected in the pattern. No jumps through non selected key is allowed.
    # The order of keys used matters.
    
    # Explanation:
    # | 1 | 2 | 3 |
    # | 4 | 5 | 6 |
    # | 7 | 8 | 9 |
    # Invalid move: 4 - 1 - 3 - 6 
    # Line 1 - 3 passes through key 2 which had not been selected in the pattern.
    
    # Invalid move: 4 - 1 - 9 - 2
    # Line 1 - 9 passes through key 5 which had not been selected in the pattern.
    
    # Valid move: 2 - 4 - 1 - 3 - 6
    # Line 1 - 3 is valid because it passes through key 2, which had been selected in the pattern
    
    # Valid move: 6 - 5 - 4 - 1 - 9 - 2
    # Line 1 - 9 is valid because it passes through key 5, which had been selected in the pattern.
    
    # Example:
    # Given m = 1, n = 1, return 9.
    
    # Hide Company Tags Google
    # Hide Tags Dynamic Programming Backtracking
    
    class Solution(object):
        def numberOfPatterns(self, m, n):
            """
            :type m: int
            :type n: int
            :rtype: int
            """
            def dfs(m, n, used, x, y):
                res = m<=0
                if n<=0:
                    return 1
                
                for i in xrange(3):
                    for j in xrange(3):
                        I,J,used2 = x+i,y+j,used | (1<<(i*3+j))
                        # print I,J,bin(used2)
                        if used2>used and (I%2 or J%2 or used2 & 1<<(I/2*3+J/2)):
                            res+=dfs(m-1,n-1, used2, i,j)
                return res
    
            return dfs(m, n, 0, 1, 1)
            
    sol = Solution()
    assert sol.numberOfPatterns(1,1)==9, "must be 9"                
    
    
    class Solution(object):
        def numberOfPatterns(self, m, n):
            """
            :type m: int
            :type n: int
            :rtype: int
            """
            def setused(used, i):
                return used | (1<<i) # error: not &: & is used to get bit 1, not set bit 1
            
            def unsetused(used, i):
                return used & ~(1<<i) # error: not | : set to 0
            
            def contains(used, i):
                return used & (1<<i) # error: not | : get, not set
            
            def keynumber(used):
                count = 0
                for i in xrange(9):
                    count+= (used & 1)
                    used >>= 1
                return count
            
            dp = [[0]*9 for i in xrange(1<<9)]
    
            for i in xrange(9):
                dp[setused(0, i)][i] = 1
        
            res = 0
            for used in xrange(len(dp)): # error: this is actually number
                nk = keynumber(used)
                # print bin(used), nk
                if nk>n: # error: not >= as currently testing used
                    continue
    
                for i in xrange(9):
                    if not contains(used, i):
                        continue
                    
                    for j in xrange(9):
                        if i==j or not contains(used, j): # error: not (contains) as testing used
                            continue
                        
                        x0, y0 = i/3, i%3
                        x1, y1 = j/3, j%3
                    
                        I,J = x0+x1, y0+y1
                        if I%2 or J%2 or contains(used, I/2*3+J/2):
                            # print bin(used), j
                            dp[used][i]+=dp[unsetused(used, i)][j]
                        
                    if m<=nk<=n: # error: 
                        # print bin(used), nk, i, dp[used][i]
                        res+=dp[used][i]
            return res
                    
    
  • 相关阅读:
    Spring 中出现Element : property Bean definitions can have zero or more properties. Property elements correspond to JavaBean setter methods exposed by the bean classes. Spring supports primitives, refer
    java定时器schedule和scheduleAtFixedRate区别
    hql语句中的select字句和from 字句
    使用maven搭建hibernate的pom文件配置
    Failure to transfer org.apache.maven:maven-archiver:pom:2.5 from http://repo.maven.apache.org/ maven2 was cached in the local repository, resolution will not be reattempted until the update interv
    对于文件File类型中的目录分隔符
    hibernate的事务管理和session对象的详解
    解决mac 中的myeclipse控制台中文乱码问题
    ibatis selectKey用法问题
    Java中getResourceAsStream的用法
  • 原文地址:https://www.cnblogs.com/absolute/p/5815860.html
Copyright © 2011-2022 走看看