[GeeksForGeeks] Friends Pairing Problem

Given n friends, each one can remain single or can be paired up with some other friend. Each friend can be paired only once. Find out the total number of ways in which friends can remain single or can be paired up.

Examples:

Input  : n = 3
Output : 4
Explanation
{1}, {2}, {3} : all single
{1}, {2,3} : 2 and 3 paired but 1 is single.
{1,2}, {3} : 1 and 2 are paired but 3 is single.
{1,3}, {2} : 1 and 3 are paired but 2 is single.
Note that {1,2} and {2,1} are considered same.

The problem itself is pretty straightforward with the following optimal substructure:

f(n) = f(n - 1) + (n - 1) * f(n - 2);

To make it more challenging, write a method that generates all possible pairing ways and save them in a list.

This is a dfs + backtracking question.

Provided the optimal substructure, we know that for a given person, either he is single or he pairs with one other person.

If he is single, we simply reduce the problem to be one fewer person smaller;

If he is paired with another person, we pick one from all the available persons pool.

To avoid duplicated answers, we only pick person with a bigger number as the pair of the current person.

We also need a global flag for each person to indicate if a person has been picked or not. This is needed because when picking

a pair, there will be persons left in between these 2 picked persons and these left persons have not been picked yet. The remaining

subproblem should include these unpicked persons. By only advancing the current index does not address this issue.

 1 import java.util.List;
 2 import java.util.ArrayList;
 3
 4 public class FriendsPairing {
 5     //f(n) = f(n - 1) + (n - 1) * f(n - 2);
 6     //Recursive solution
 7     public static int pairingWaysRecursion(int n) {
 8         if(n <= 1) {
 9             return 1;
10         }
11         return pairingWaysRecursion(n - 1) + (n - 1) * pairingWaysRecursion(n - 2);
12     }
13     //Dynamic Programming
14     public static int pairingWaysDp(int n) {
15         int[] T = new int[n + 1];
16         T[0] = 1;
17         T[1] = 1;
18         for(int i = 2; i <= n; i++) {
19             T[i] = T[i - 1] + (i - 1) * T[i - 2];
20         }
21         return T[n];
22     }
23     //Dfs + backtracking to get all pairing ways
24     public static List<List<List<Integer>>> getAllPairingWays(int n) {
25         boolean[] available = new boolean[n + 1];
26         for(int i = 1; i <= n; i++) {
27             available[i] = true;
28         }
29         List<List<List<Integer>>> ways = new ArrayList<>();
30         getAllWaysDfs(ways, new ArrayList<>(), available, n, 1, 0);
31         return ways;
32     }
33     private static void getAllWaysDfs(List<List<List<Integer>>> ways,
34                                 List<List<Integer>> way,
35                                 boolean[] available, int n, int currIdx, int addedCount) {
36         if(addedCount == n) {
37             ways.add(new ArrayList<List<Integer>>(way));
38             return;
39         }
40         for(int i = currIdx; i <= n; i++) {
41             if(available[i]) {
42                 ArrayList<Integer> group1 = new ArrayList<Integer>();
43                 group1.add(i);
44                 way.add(group1);
45                 available[i] = false;
46                 getAllWaysDfs(ways, way, available, n, i + 1, addedCount + 1);
47                 way.remove(way.size() - 1);
48
49                 int j = i + 1;
50                 for(; j <= n; j++) {
51                     if(available[j]) {
52                         ArrayList<Integer> group2 = new ArrayList<Integer>();
53                         group2.add(i);
54                         group2.add(j);
55                         way.add(group2);
56                         available[j] = false;
57                         getAllWaysDfs(ways, way, available, n, i + 1, addedCount + 2);
58                         way.remove(way.size() - 1);
59                         available[j] = true;
60                     }
61                 }
62                 available[i] = true;
63             }
64         }
65     }
66     public static void main(String[] args) {
67         System.out.println(pairingWaysDp(3));
68         System.out.println(pairingWaysDp(6));
69         List<List<List<Integer>>> ways = getAllPairingWays(3);
70         for(int i = 0; i < ways.size(); i++) {
71             for(int j = 0; j < ways.get(i).size(); j++) {
72                 for(int k = 0; k < ways.get(i).get(j).size(); k++) {
73                     System.out.print(ways.get(i).get(j).get(k) + ",");
74                 }
75                 System.out.print("  ");
76             }
77             System.out.println();
78         }
79     }
80 }

Related Problems

Permutations

Permutations II

				
时间: 2024-08-02 10:29:21

[GeeksForGeeks] Friends Pairing Problem的相关文章

[LeetCode] The Skyline Problem

An interesting problem! But not very easy at first glance. You need to think very clear about how will a keypoint be generated. Since I only learn from others' solutions and am still unable to give my personal explanations, I would suggest you to the

Geeks Ford-Fulkerson Algorithm for Maximum Flow Problem 最大网络流问题

很久之前就想攻克一下网络流的问题了,一直拖着,一是觉得这部分的内容好像非常高级,二是还有很多其他算法也需要学习,三是觉得先补补相关算法会好点 不过其实这虽然是图论比较高级的内容,但是基础打好了,那么还是不会太难的,而且它的相关算法并不多,熟悉图论之后就可以学习了,就算法不会二分图也可以学习. 这里使用Ford-Fulkerson算法,其实现的方法叫做:Edmonds-Karp Algorithm 其实两者前者是基本算法思想,后者是具体实现方法. 两个图十分清楚: 图1:原图,求这个图的最大网络流

Nuts &amp; Bolts Problem

Given a set of n nuts of different sizes and n bolts of different sizes. There is a one-one mapping between nuts and bolts. Comparison of a nut to another nut or a bolt to another bolt is not allowed. It means nut can only be compared with bolt and b

[email&#160;protected] Sieve of Eratosthenes (素数筛选算法) &amp; Related Problem (Return two prime numbers )

Sieve of Eratosthenes (素数筛选算法) Given a number n, print all primes smaller than or equal to n. It is also given that n is a small number. For example, if n is 10, the output should be “2, 3, 5, 7″. If n is 20, the output should be “2, 3, 5, 7, 11, 13,

[geeksforgeeks] Convert a given Binary Tree to Doubly Linked List

http://www.geeksforgeeks.org/in-place-convert-a-given-binary-tree-to-doubly-linked-list/ Given a Binary Tree (Bt), convert it to a Doubly Linked List(DLL). The left and right pointers in nodes are to be used as previous and next pointers respectively

[geeksforgeeks] Lowest Common Ancestor in a Binary Search Tree.

http://www.geeksforgeeks.org/lowest-common-ancestor-in-a-binary-search-tree/ Lowest Common Ancestor in a Binary Search Tree. Given values of two nodes in a Binary Search Tree, write a c program to find the Lowest Common Ancestor (LCA). You may assume

[Daily Coding Problem 223] O(1) space in order traversal of a binary tree

Typically, an implementation of in-order traversal of a binary tree has O(h) space complexity, where h is the height of the tree. Write a program to compute the in-order traversal of a binary tree using O(1) space. In-order traversal without recursio

A Math Problem

A Math Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 237    Accepted Submission(s): 117 Problem Description You are given a positive integer n, please count how many positive integers

Water Problem

water problem 发布时间: 2015年10月10日 15:34   时间限制: 1000ms   内存限制: 256M 描述 题意很简单 给你N个数, Q个查询 每次查询给你一个区间[L, R] 你要找出 [L, R] 这个区间里面取模M后的最大值. 输入 第一行一个T,表示测试数据组数.第二行两个整数N, M (1<=N<=10^5, 1<=M<=10^9).第三行给你N个整数 整数范围在1到10^9之间.第四行给你一个整数Q. ( 1<=Q<=10^5)