• [LeetCode] 1866. Number of Ways to Rearrange Sticks With K Sticks Visible Review


    There are n uniquely-sized sticks whose lengths are integers from 1 to n. You want to arrange the sticks such that exactly k sticks are visible from the left. A stick is visible from the left if there are no longer sticks to the left of it.

    • For example, if the sticks are arranged [1,3,2,5,4], then the sticks with lengths 13, and 5 are visible from the left.

    Given n and k, return the number of such arrangements. Since the answer may be large, return it modulo 109 + 7.

     

    Example 1:

    Input: n = 3, k = 2
    Output: 3
    Explanation: [1,3,2], [2,3,1], and [2,1,3] are the only arrangements such that exactly 2 sticks are visible.
    The visible sticks are underlined.
    

    Example 2:

    Input: n = 5, k = 5
    Output: 1
    Explanation: [1,2,3,4,5] is the only arrangement such that all 5 sticks are visible.
    The visible sticks are underlined.
    

    Example 3:

    Input: n = 20, k = 11
    Output: 647427950
    Explanation: There are 647427950 (mod 109 + 7) ways to rearrange the sticks such that exactly 11 sticks are visible.
    

     

    Constraints:

    • 1 <= n <= 1000
    • 1 <= k <= n

    If using the commented out logic, the runtime will be O(N^3) instead of O(N^2). The key observation here is that if we try to arrange sticks from the right side, out of all the available sticks to choose from, the tallest one is always visible, it also always blocks all the shorter sticks to its right. So if we are given a subproblem of having n sticks to choose from and wanting to get k visible sticks, we either put the tallest on the right most position, which reduce to subproblem (n - 1, k - 1); Or we put any sticks that is not the tallest (there are n - 1 options), which reduce to subproblem (n - 1, k).

    class Solution {
        private long[][] dp;
        private int mod = (int)1e9 + 7;
        public int rearrangeSticks(int n, int k) {
            dp = new long[n + 1][k + 1];
            for(int i = 0; i <= n; i++) {
                Arrays.fill(dp[i], -1);
            }
            for(int i = 0; i <= k; i++) {
                dp[i][i] = 1;
            }
            for(int i = 1; i <= n; i++) {
                dp[i][0] = 0;
            }
            compute(n, k);
            return (int)(dp[n][k]);
        }
        
        private long compute(int n, int k) {
            if(dp[n][k] >= 0) {
                return dp[n][k];
            }
            dp[n][k] = 0;
            dp[n][k] = (dp[n][k] + compute(n - 1, k - 1)) % mod;
            dp[n][k] = (dp[n][k] + compute(n - 1, k) * (n - 1) % mod) % mod;
            // long p = n - 1;
            // for(int m = n - 2; m >= k - 1; m--) {
            //     dp[n][k] = (dp[n][k] + compute(m, k - 1) * p % mod) % mod;
            //     p = p * m % mod;
            // }
            return dp[n][k];
        }
    }
  • 相关阅读:
    AT2364 Colorful Balls
    SP5973 SELTEAM
    codeforces469B
    校内题目T2691 桶哥的问题——送桶
    关于一种6的倍数判定素数的方法
    P1903 奖学金题解
    说说关于洛谷P4779迪杰斯特拉的堆优化
    清北学堂北京大学文宏宇神仙讲课day7
    CF961F k-substrings
    CF985F Isomorphic Strings
  • 原文地址:https://www.cnblogs.com/lz87/p/16015244.html
Copyright © 2020-2023  润新知