Leetcode 526. Beautiful Arrangement
Suppose you have N integers from 1 to N. We define a beautiful arrangement as an array that is constructed by these N numbers successfully if one of the following is true for the ithposition (1 <= i <= N) in this array:
- The number at the ith position is divisible by i.
- i is divisible by the number at the ith position.
Now given N, how many beautiful arrangements can you construct?
Example 1:
Input: 2 Output: 2 Explanation: The first beautiful arrangement is [1, 2]: Number at the 1st position (i=1) is 1, and 1 is divisible by i (i=1). Number at the 2nd position (i=2) is 2, and 2 is divisible by i (i=2). The second beautiful arrangement is [2, 1]: Number at the 1st position (i=1) is 2, and 2 is divisible by i (i=1). Number at the 2nd position (i=2) is 1, and i (i=2) is divisible by 1.
Note:
- N is a positive integer and will not exceed 15.
1 class Solution: 2 def DFS(self, N, glist, start, chosen): 3 if start == N+1: 4 self.count += 1 5 return 6 llist = glist[start-1] 7 for i,ele in enumerate(llist): 8 if ele in chosen: 9 continue 10 chosen.add(ele) 11 self.DFS(N, glist, start+1, chosen) 12 chosen.discard(ele) 13 return 14 15 def countArrangement(self, N): 16 """ 17 :type N: int 18 :rtype: int 19 """ 20 glist = [] 21 for i in range(1,N+1): 22 llist = [] 23 for j in range(1,i+1): 24 if i%j == 0: 25 llist.append(j) 26 for j in range(i+1,N+1): 27 if j%i == 0: 28 llist.append(j) 29 glist.append(llist[:]) 30 self.count = 0 31 chosen = set() 32 self.DFS(N, glist, 1, chosen) 33 return self.count
Above is my solution. First build the candidate list. Then loop thru it using DFS. Each time pick one and solve the rest.
Good: Clear
Bad: This DFS approach can NOT be changed to use memo approach to optimization. In fact, this code can only beat 40% python submissioin on LC
1 cache = {} 2 class Solution(object): 3 def countArrangement(self, N): 4 def helper(i, X): 5 if i == 1: 6 return 1 7 key = (i, X) 8 if key in cache: 9 return cache[key] 10 total = 0 11 for j in xrange(len(X)): 12 if X[j] % i == 0 or i % X[j] == 0: 13 total += helper(i - 1, X[:j] + X[j + 1:]) 14 cache[key] = total 15 return total 16 return helper(N, tuple(range(1, N + 1)))
The above approach presented by zhongyuan9817 here: https://leetcode.com/problems/beautiful-arrangement/discuss/99717/Python-recursion-%2B-DP-66ms
is better in that: 1) it's cacheable/Memorizable; 2) It select the eligible list on the fly!
How he achieved this? First, reduce the problem size N -> N-1; Second, in the reduced the size of problem, pick ONE out that's valid for this ith position, and then
recurse to the smaller problem.
虽然同样是DFS,但是答案的构造方向是不一样的!我所使用的是从上到下,必须全程走一遍才能得到答案,不利于Memorization!zhongyuan9817 提供的DFS的答案是从下而上
构造出来的,可以用记忆化方法加速!这个区别应该理解和注意!