LeetCode 1259 - Handshakes That Don't Cross


https://algorithm-notes-allinone.blogspot.com/2019/11/leetcode-1259-handshakes-that-dont-cross.html
https://leetcode.com/problems/handshakes-that-dont-cross/description/

You are given an even number of people num_people that stand around a circle and each person shakes hands with someone else, so that there are num_people / 2 handshakes total.
Return the number of ways these handshakes could occur such that none of the handshakes cross.
Since this number could be very big, return the answer mod 10^9 + 7

Example 1:
Input: num_people = 2
Output: 1
Example 2:
Input: num_people = 4
Output: 2
Explanation: There are two ways to do it, the first way is [(1,2),(3,4)] and the second one is [(2,3),(4,1)].
Example 3:
Input: num_people = 6
Output: 5
Example 4:
Input: num_people = 8
Output: 14

Constraints:
  • 2 <= num_people <= 1000
  • num_people % 2 == 0

This problem can be solved by dp.

Why? because, as shown in the above figures, it can be easily converted to similar questions but with smaller sizes.

Let us use dp[n] to represent the total ways for n people.

The first person can shake hands with the second one, but cannot shake hands with the second one. Why?

Because if the first person connects with the third one, then the second one have to cross the "line" to shake hands with other people.

Thus, if the first person shake hands with the jth person, this essentially divide the original circle into two parts:

one is from i+1 to the j-1 people, and the other is from j+1 to the nth people.

So we need to leave even number of people in both sides.

Thus, dp[n] = dp[0]* dp[n-2] + dp[2]*dp[n-2-2] + ... + dp[j]*dp[n-j-2].

In addition, due to symmetry, we can just calculate half of the circle.

  1.     int numberOfWays(int num_people) {
  2.         int n = num_people, mod = 1e9+7;
  3.         vector<long> dp(n+1, 0);
  4.         dp[0] = 1;
  5.         for(int i=2; i<=n; i += 2) {
  6.             for(int j=0; j<=i-j-2; j += 2) {//calculate half circle
  7.                 if(j==i-j-2) dp[i] += dp[j]*dp[i-j-2]%mod;
  8.                 else dp[i] += 2*((dp[j]%mod)*(dp[i-j-2]%mod)%mod);
  9.                 dp[i] %=mod;
  10. }
  11.         }
  12.         return dp[n];
  13.     }

https://www.acwing.com/file_system/file/content/whole/index/content/150818/
(动态规划) O(n2)
  1. f(i) 表示 i 个时的方案数,其中 i 为偶数。
  2. 初始时 f(0)=1,其余为 0。
  3. 转移时,枚举第 i 个人和编号为 j 的人握手,其中 j 为奇数,则 f(i)=f(i)+f(j1)f(ij1)。这个公式的含义是,如果第 i 个人与第 j 个人握手,则前 j1 个人的握手问题为子问题,共有 f(j1) 种方案;[j + 1, i - 1] 为 ij1 个人握手的问题,共有 f(ij1) 种方案,根据乘法原理和加法原理,对于每个 j,我们需要累加答案 f(j1)f(ij1)
  4. 最终答案为 f(n)

时间复杂度

  • 共有 O(n) 个状态,每个状态需要 O(n) 的时间转移,故总时间复杂度为 O(n2)

空间复杂度

  • 需要额外 O(n) 的空间存储状态。
    
    int numberOfWays(int num_people) {
        const int mod = 1000000007;
        vector<int> f(num_people + 1, 0);
        f[0] = 1;

        for (int i = 2; i <= num_people; i += 2)
            for (int j = 1; j < i; j += 2)
                f[i] = (f[i] + (LL)(f[j - 1]) * f[i - j - 1] % mod) % mod;

        return f[num_people];
    }

https://www.cnblogs.com/wowpH/p/11880952.html
先分析一下示例 3,
第 6 个人和第 5 个人握手,圆被分成两部分,一部分是 4 个人,另一部分是 0 个人。0 个人的方案数为 1,4 个人的方案数可以递归计算为 2,所以这种情况有 2 种方案。
第 6 个人和第 3 个人握手,圆被分成两部分,每部分都是 2 个人,2 个人的方案数是 1,所以这种情况有 1 种方案。
第 6 个人和第 1 个人握手,圆被分成两部分,一部分是 0 个人,另一部分是 4 个人,所以这种情况有 2 中方案。
因此 6 个人的时候有 5 种方案数。@wowpH
有 n 个人(n为偶数),如果第 n 个人和第 i (i = n - 1, n - 3, ……,1)个人握手,那么分成的两部分中,一部分有 i - 1 人,另一部分有 n - i - 1 人。这两部分又是一个新的子问题。
所以题目可以采用 动态规划(DP) 来解决。
用大小为 num_people + 1 的 long型一维数组 arr 来保存每种人数时的方案数。公式为:



arr[n]={1 n=0n=2i=1n1(arr[i1]arr[ni1]) n>2ni.
private static final int mod = 1000000007; private long[] arr; public int numberOfWays(int num_people) { arr = new long[num_people + 1]; return (int) dp(num_people); } private long dp(int n) { if (n == 0 || n == 2) { return 1; } long ret = 0; for (int i = n - 1; i >= 1; i -= 2) { if (arr[i - 1] == 0) { arr[i - 1] = dp(i - 1); } if (arr[n - i - 1] == 0) { arr[n - i - 1] = dp(n - i - 1); } ret += arr[i - 1] * arr[n - i - 1]; ret %= mod; } return ret; }


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts