LeetCode Weekly Competition 351 (2023/06/25) T2 is interesting

This article has included AndroidFamily , technical and workplace issues, please pay attention to the public account [Peng Xurui] and [BaguTree Pro] Knowledge Planet to ask questions.

T1. The number of beautiful subscript pairs (Easy)

  • Tags: counting+math

T2. Minimum number of operations to perform to get the integer zero (Medium)

  • Tags: math

T3. Minimum number of operations to perform to get the integer zero (Medium)

  • Tags: principle of multiplication

T4. Robot Collision (Hard)

  • Tags: stack


T1. The number of beautiful subscript pairs (Easy)

https://leetcode.cn/problems/number-of-beautiful-pairs/

Solution 1 (violence)

Two layers are scanned, simultaneously checking the number of matched pairs in the prodromal.

class Solution {
    
    
    fun countBeautifulPairs(nums: IntArray): Int {
    
    
        var ret = 0
        for (i in nums.indices) {
    
    
            var x = nums[i]
            while (x >= 10) x /= 10
            for (j in i + 1 until nums.size) {
    
    
                if (gcb(nums[j] % 10, x) == 1) ret++
            }
        }
        return ret
    }

    private fun gcb(x: Int, y: Int) : Int {
    
    
        var a = x
        var b = y
        while (b != 0) {
    
    
            val temp = a % b
            a = b
            b = temp
        }
        return a
    }
}

Complexity analysis:

  • Time complexity: O ( n 2 ) O(n^2)O ( n2)
  • Space complexity: O ( 1 ) O(1)O(1)

Solution 2 (Counting + Math)

Scan the array linearly while checking the number of matching pairs in the predecessor. Since the question only considers the highest digit of the predecessor number and the lowest digit of the current position, we can maintain the number of occurrences of the highest digit of the predecessor number.

class Solution {
    
    
    fun countBeautifulPairs(nums: IntArray): Int {
    
    
        var ret = 0
        val cnt = IntArray(10)
        for (i in nums.indices) {
    
    
            for (j in 1 .. 9) {
    
    
                if (cnt[j] > 0 && gcb(nums[i] % 10, j) == 1) ret += cnt[j]
            }
            var x = nums[i]
            while (x >= 10) x /= 10
            cnt[x]++
        }
        return ret
    }

    private fun gcb(x: Int, y: Int) : Int {
    
    
        var a = x
        var b = y
        while (b != 0) {
    
    
            val temp = a % b
            a = b
            b = temp
        }
        return a
    }
}

Complexity analysis:

  • Time complexity: O ( C ⋅ n ) O(C n)O(Cn ) where C = 10;
  • Space Complexity: O ( C ) O(C)O(C)

T2. Minimum number of operations to perform to get the integer zero (Medium)

https://leetcode.cn/problems/minimum-operations-to-make-the-integer-zero/

The thinking difficulty of this question is relatively high.

Considering that 2^i and nums2 are not easy to handle at the same time, we can try to deal with them separately: observe example 1 (the minimum number of operations is 3), if we first subtract nums2 from num1 3 times, we will get binary 1101, which can be obtained by subtracting 3 Times 2^i are cleared (-1, -4 and -8).

// 0011 + 2
// => 0101 + 2
// => 0111 + 2
// => 1101 (-1 - 4 - 8)

Therefore, we assume that num1 can be eliminated after k times of operations, then exactly k 1s need to exist in the binary bits of nums1 - k num2, and then k times of 2^i can be used to eliminate them. Then our question is converted to whether there is k such that the number of 1s in the binary bits of nums1 - k nums2 is k.

if (k == (nums1 - k * nums2).bitCount()) return true

However, this idea has traps. For example, the number of 1s in the binary digits after 4 operations is only 3. According to the above idea, it is illegal, but in fact we can still clear it by operating 4 times (- 1, -4, -8 ⇒ split -8 into 2 times -4, the total number of operations is -1, -4, -4, -4);

  • Minimum number of operations: eliminate 1 in the binary bit each time;
  • Maximum number of operations: minus 1 each time.

To sum up, let x be num1 - k * num2, y be the number of 1s in the binary bits of x, and enumerate k starting from 1, then when y ≤ k and x ≥ k are satisfied, k operations must be possible cleared.

// 0001 + 2
// => 0011 + 2
// => 0101 + 2
// => 0111 + 2
// => 1101

The last question, how to calculate the complexity, obviously depends on the upper bound of k:

  • When num2 == 0, the number of operations is directly equal to the number of 1s in num1 binary bits, and the maximum number of operations is log(num1);
  • When num2 > 0 or num2 < 0, the algorithm terminates when k ≥ bitCount(x), and the maximum number of operations is log(x).
class Solution {
    
    
    fun makeTheIntegerZero(num1: Int, num2: Int): Int {
    
    
        var k = 1
        while (true) {
    
    
            val x = num1 - 1L * k * num2
            if (k > x) return -1
            if (k >= java.lang.Long.bitCount(x)) return k
            k++
        }
    }
}
class Solution {
    
    
    fun makeTheIntegerZero(num1: Int, num2: Int): Int {
    
    
        var k = 1
        var x = 1L * num1
        while (true) {
    
    
            x -= num2
            if (k > x) return -1
            if (k >= java.lang.Long.bitCount(x)) return k
            k++
        }
    }
}

Complexity analysis:

  • Time Complexity: O ( lgx ) O(lgx)O ( lgx ) _
  • Space complexity: O ( 1 ) O(1)O(1)

T3. Minimum number of operations to perform to get the integer zero (Medium)

https://leetcode.cn/problems/ways-to-split-array-into-good-subarrays/

Solution (grouping + multiplication principle)

Use the number 1 as the dividing line, divide each continuous 0 into a group, and then use the multiplication principle to calculate the total number of schemes.

class Solution {
    
    
    fun numberOfGoodSubarraySplits(nums: IntArray): Int {
    
    
        // 分组 + 乘法原理
        val MOD = 1000000007
        var ret = 1L
        var pre1 = -1
        for ((i, num) in nums.withIndex()) {
    
    
            if (num == 0) continue
            if (pre1 != -1) ret = ret * (i - pre1) % MOD
            pre1 = i
        }
        return if (pre1 == -1) 0 else ret.toInt()
    }
}

Complexity analysis:

  • Time complexity: O ( n ) O(n)O ( n )
  • Space complexity: O ( 1 ) O(1)O(1)

T4. Robot Collision (Hard)

https://leetcode.cn/problems/robot-collisions/

Solution (stack)

 This question is almost the same as the classic question  735. Planetary collision .

We use the stack to simulate the reserved robots, enumerate the robots, and eliminate the robots according to the rules when they conflict with the direction of the top of the stack, and finally output the remaining robots in the stack.

class Solution {
    
    
    fun survivedRobotsHealths(positions: IntArray, healths: IntArray, directions: String): List<Int> {
    
    
        // 排序
        val indexs = Array(positions.size) {
    
     it }
        Arrays.sort(indexs) {
    
     i1, i2 ->
            positions[i1] - positions[i2]
        }
        // 模拟 <index>
        val stack = ArrayDeque<Int>()
        outer@ for (id in indexs) {
    
    
            // 当前机器人向右,不会发生碰撞
            if (directions[id] == 'R') {
    
    
                stack.push(id)
                continue
            }
            while (!stack.isEmpty() && directions[stack.peek()] == 'R') {
    
    
                var topId = stack.peek()
                if (healths[topId] > healths[id]) {
    
    
                    // 栈顶健康度 -1
                    if (--healths[topId] == 0) stack.poll()
                    continue@outer
                } else if(healths[topId] < healths[id]) {
    
    
                    // 弹出栈顶
                    healths[id] -= 1
                    stack.poll()
                } else {
    
    
                    // 弹出栈顶
                    stack.poll()
                    continue@outer
                }
            }
            if (healths[id] > 0) stack.push(id)
            // println(stack.joinToString())
        }
        // 输出
        val ret = stack.toMutableList()
        ret.sort() // 题目要求按照原位置顺序输出
        for (i in ret.indices) {
    
    
            ret[i] = healths[ret[i]]
        }
        return ret
    }
}

Complexity analysis:

  • Time complexity: O ( nlgn ) O(nlgn)O ( n l g n ) bottleneck on sorting;
  • Space Complexity: O ( n ) O(n)O ( n ) stack space.

Past review

Guess you like

Origin blog.csdn.net/pengxurui/article/details/131389066