LeetCode Entry

330. Patching Array

16.06.2024 hard 2024 kotlin rust

Insertions to make subsets sums fill 1..n

330. Patching Array hard blog post substack youtube 2024-06-16_06-59_1.webp

Join me on Telegram

https://t.me/leetcode_daily_unstoppable/641

Problem TLDR

Insertions to make subsets sums fill 1..n #hard

Intuition

The hard part for me was to understand range filling law: if range [1..x] is filled, then to fill range [1..x+x] we can add just one number x: it will add all the range of numbers: 1+x, 2+x, 3+x ... x+x

With this in mind, let’s explore example of how to fill the range:

    // 1 5 10      n=20
    // sums = 1, 5, 10, 1+5,1+10,5+10,1+5+10
    // 1 2 3 9
    // 1        [1..1]
    //   2      [..1+2] = [..3]
    //     3    [..3+3] = [..6]
    //       9  9>6+1, 7..9 -> 7 -> [..6+7]= [..13]
    //          [..13+9] = [..22]
    // 1 2 10 20    n=46
    // 1        ..1
    //   2      ..3
    //     10   10>4, ..3+4=..7
    //          10>8, ..7+8=..15
    //          ..15+10=..25

When we reach the number 9, we see the gap between the rightmost border 6 and 9, so we fill it with the next number after border 7. After this operation, the filled range becomes [1..6+7] and we can take the number 9.

Approach

Look for the tips in the discussion section.

Complexity

  • Time complexity: \(O(mlog(n))\), each time we doubling the border, so it takes log(n)

  • Space complexity: \(O(1)\)

Code


    fun minPatches(nums: IntArray, n: Int): Int {
        var count = 0; var border = 0L; var i = 0
        while (border < n) {
            if (i < nums.size && nums[i] <= border + 1) {
                border += nums[i]
                i++
            } else {
                border += border + 1
                count++
            }
        }
        return count
    }


    pub fn min_patches(nums: Vec<i32>, n: i32) -> i32 {
        let (mut border, mut i, mut cnt) = (0, 0, 0);
        while border < n as _ {
            if i < nums.len() && nums[i] as u64 <= border + 1 {
                border += nums[i] as u64;
                i += 1
            } else {
                border += border + 1;
                cnt += 1
            }
        }; cnt
    }