[LeetCode] Count All Valid Pickup and Delivery Options

Description

Count All Valid Pickup and Delivery Options: Given n orders, each order consist in pickup and delivery services.

Count all valid pickup/delivery possible sequences such that delivery(i) is always after of pickup(i).

Since the answer may be too large, return it modulo 10^9 + 7.

Example:

Input: n = 2
Output: 6
Explanation: All possible orders: 
(P1,P2,D1,D2), (P1,P2,D2,D1), (P1,D1,P2,D2), (P2,P1,D1,D2), (P2,P1,D2,D1) and (P2,D2,P1,D1).
This is an invalid order (P1,D2,P2,D1) because Pickup 2 is after of Delivery 2.

Solution

This idea is based on DP and slot thinking.

If we have (i-1)th valid orders, how to make ith valid orders. Clearly, for a (i-1)th valid order, it contains 2 * i - 1 slots from top to end.

So, we set Pi to one of the slot, and set Di after it. Because the (i-1)th order is valid, the ith order is definitely valid after adding Pi and Di. In this way, there are totally (slot + slot - 1 + ... + 1) = (slot * (slot + 1)) / 2 valid ith orders.

Finally, for k (i-1)th valid orders, we totally have k * (slot * (slot + 1)) / 2 ith orders.

Take n = 3 as an example:

n = 2, we have 6 possible orders. Just pick an n = 2 order, like P1D1P2D2, which has 5 slots ( _P1_D1_P2_D2_, _ represents a slot).

We pick one of these slots to set P3, then we can set D3 to all of slots after the slot we picked:

P3_P1_D1_P2_D2_
P1P3_D1_P2_D2_
P1D1P3_P2_D2_
P1D1P2P3_D2_
P1D1P2D2P3_

As shown above, we can insert D3 into all of _ slot. There are 15 (5 + 4 + 3 + 2 + 1 = 5 *6 / 2 = 15) possible orders.

So the total order = 6 * 15 = 90.

Code

class Solution {
public:
    int countOrders(int n) {
        long ans = 1, mod = 1e9 + 7;
        for(int i = 1, slot = 3; i < n; i++, slot += 2)
            ans = (ans * (slot * (slot + 1)) / 2)%mod;
        return ans;
    }
};

Complexity

Time complexity: One loop, O(n)

Space complexity: O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值