X

LEETCODE 1259. Handshakes That Don’t Cross 解题思路分析

题目大意:

不相交的握手

偶数 个人站成一个圆,总人数为 num_people。每个人与除自己外的一个人握手,所以总共会有 num_people / 2 次握手。

将握手的人之间连线,请你返回连线不会相交的握手方案数。

由于结果可能会很大,请你返回答案 模 10^9+7 后的结果。

示例1:

输入:num_people = 2
输出:1

示例2:

输入:num_people = 4
输出:2
解释:总共有两种方案,第一种方案是 [(1,2),(3,4)] ,第二种方案是 [(2,3),(4,1)] 。

示例3:

输入:num_people = 6
输出:5

示例4:

输入:num_people = 8
输出:14

提示:

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

如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1259

解题思路分析:

开始看到本题时本没有太多的思路,不过仔细一想,其实并没有那么复杂,要想满足不相交握手,其实就是将人分割成 (num_people / 2) 这么多组,很像切蛋糕,每一组都只有2个人,他们2个人之间握手一定不会影响到其他组。再反过来想,当前人可以与谁进行握手?最简单的想法应该是和相邻的人握手,这肯定是可以的。如果隔着一个人跟下一个人握手是绝对不行的,因为中间那个被隔开的人不论再与谁握手都会发生交叉。接下来,如果隔着2个人与下一个人握手,那么是可行的,因为中间被隔开的2个人可以进行握手并且不会与当前握手交叉。因此我们可以得到一个结论,只要当前人与握手对象之间存在偶数个人,那么即可以握手。

比如一共有8个人(编号0-7),0应该可以与1,3,5,7四人握手是成立的。我们设定握手的对象为i,当0和i进行握手后,其实是将所有人分成了2个部分,分别是0和i中间的部分,以及i之后的部分,即分为了i-1个人和num_people-i-1个人,假如当前i为3,即第0个人与第3个人握手之后,可以将人群分为2人和4人,这时我们可以将2人和4人分别扔给递归子问题去求解,求解方式与当前解法是相同的。两者的乘积是当前的结果。递归的结束条件是当前总人数只有2人时,可以直接返回1。

因此,循环所有握手的可能(1,3,5,7),分别递归求出每种可能的解,求和即是答案。设f(n)代表:总共n个人能产生的不交叉握手方案数。

f(8)=
 f(0) * f(6) // 0与1握手后,剩下的人被分为0人和6人2组
+ f(2) * f(4) // 0与3握手,剩下的人被分为2人和4人2组
+ f(4) * f(2) // 0与5握手,剩下的人被分为4人和2人2组
+ f(6) * f(0) // 0与7握手,剩下的人被分为6人和0人2组

实现代码:

int[] memo; // 记忆数组
public int numberOfWays(int num_people) {
    memo=new int[1+num_people]; // 初始化记忆数组
    return (int)help(num_people); // 递归求解
}
long help(int num_people){
    // 如果记忆数组存在值,直接发挥
    if(memo[num_people]>0){
        return memo[num_people];
    }
    // 如果总人数小于等于2,返回1
    if(num_people<=2) return 1;
    // 返回结果
    long res=0;
    // 从相邻人开始循环可能握手的人(相隔人数为偶数)
    for(int i=1;i<num_people;i+=2){
       // 握手后将人分为两部分,两部分递归求解的乘积加入返回结果
        res+=(help(i-1)*help(num_people-i-1))%1000000007;
    }
    // 将结果存入记忆数组
    memo[num_people]=(int)(res%1000000007);
    return memo[num_people];
}

本题解法执行时间为8ms。

Runtime: 8 ms, faster than 94.50% of Java online submissions for Handshakes That Don’t Cross.

Memory Usage: 33.1 MB, less than 100.00% of Java online submissions for Handshakes That Don’t Cross.

本网站文章均为原创内容,并可随意转载,但请标明本文链接
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: http://leetcode.jp/leetcode-1259-handshakes-that-dont-cross-解题思路分析/
Categories: leetcode
kwantong: