# 第 255 场周赛题解

# Q1 1979. 找出数组的最大公约数 (opens new window)

直接求就完了!

class Solution5850 {
    fun findGCD(nums: IntArray): Int {
        nums.sort()
        return gcd(nums.max()!!, nums.min()!!)
    }
}

/**
 * GCD 最大公约数
 * */
tailrec fun gcd(a: Int, b: Int): Int {
    return if (b == 0) a else gcd(b, a % b)
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# Q2 1980. 找出不同的二进制字符串 (opens new window)

直接遍历,筛出不在集合内的。

class Solution5851 {
    fun findDifferentBinaryString(nums: Array<String>): String {
        val n = nums[0].length
        val set = nums.map {
            var cur = 0
            var step = 1
            for (i in it.indices.reversed()) {
                cur += (it[i] - '0') * step
                step *= 2
            }
            cur
        }
        // set.joinToString().print()
        for (i in 0 until (1 shl n)) {
            if (i !in set) return i.toString(2).padStart(n, '0')
        }
        return ""
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# Q3 1981. 最小化目标值与所选元素的差 (opens new window)

大于target的只需要一个最小值,因此每次可以把过多的数据从SetSetRemoveRemove掉。其他的都交给TreeSetTreeSet就好了,符合逻辑。

class Solution5852 {
    fun minimizeTheDifference(mat: Array<IntArray>, target: Int): Int {
        var set = TreeSet<Int>()
        for (i in mat.indices) {
            val nxtSet = TreeSet<Int>()
            for (j in mat[0].indices) {
                var large = Int.MAX_VALUE / 2
                if (i == 0) {
                    nxtSet.add(mat[i][j])
                } else {
                    set.forEach { s ->
                        val nxt = s + mat[i][j]
                        if (nxt > target) {
                            if (nxt < large) {
                                nxtSet.remove(large)
                                nxtSet.add(nxt)
                                large = nxt
                            }
                        } else {
                            nxtSet.add(nxt)
                        }
                    }
                }
            }
            set = nxtSet
        }

//        set.print()
        return minOf(
            (set.ceiling(target) ?: Int.MAX_VALUE / 4) - target,
            target - (set.floor(target) ?: Int.MIN_VALUE / 4)
        )
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# Q4 1982. 从子集的和还原数组 (opens new window)

有意思的题目,排序后,最大值和次大值得差dd(非负值差),一定能保证ddd-d在原数组中(可以通过反证法证明)。

  1. dd是由两个更小的正数组合起来的,那么原次大值则不符合逻辑。
  2. dd是有一个更大的正数与一个负数组合起来的,那么这个负数也会让原次大值不符合逻辑。

因此,可以BackTrackBackTrack遍历使用ddd-d来填充数组,看是否能构造出来。

每次构造,可以将原数组拆分成两部分aabb,并且对于所有的biai==db_{i} - a_{i} == d,这样,根据我们选择的是dd就将aa数组进行下一轮迭代,选择的是d-d就使用bb数组进行下一轮迭代。直至迭代出一个结果位置。

该题主要是第一步不容易想到,之后的回溯其实就比较简单了。

class Solution5853 {
    fun recoverArray(n: Int, sums: IntArray): IntArray {
        sums.sort()
        fun checkDiff(diff: Int, arr: ArrayList<Int>, pos: Boolean): ArrayList<Int> {
            if (pos && diff !in arr) return arrayListOf()
            if (!pos && -diff !in arr) return arrayListOf()
            var l = 0
            var r = 0
            val s = arrayListOf<Int>()
            val t = arrayListOf<Int>()
            val used = BooleanArray(arr.size)
            while (l in arr.indices) {
                if (used[l]) {
                    l++
                    continue
                }
                s.add(arr[l])
                used[l] = true
                while (used[r] || arr[r] != arr[l] + diff) {
                    r++
                    if (r !in arr.indices) return arrayListOf<Int>()
                }
                t.add(arr[r])
                used[r] = true
                l++
            }
            return if (pos) s else t
        }

        val ans = ArrayList<Int>()
        val tmp = ArrayList<Int>()
        fun dfs(cur: ArrayList<Int>) {
            if (cur.isEmpty() || ans.isNotEmpty()) return
            if (tmp.size == n) {
                ans.addAll(tmp)
                return
            }
            val d = cur[cur.lastIndex] - cur[cur.lastIndex - 1]
            tmp.add(d)
            dfs(checkDiff(d, cur, true))
            tmp.remove(d)
            tmp.add(-d)
            dfs(checkDiff(d, cur, false))
            tmp.remove(-d)
        }

        dfs(ArrayList(sums.sorted()))
        return ans.toIntArray()
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50