LeetCode 350周赛


2739. 总行驶距离

卡车有两个油箱。给你两个整数,mainTank 表示主油箱中的燃料(以升为单位),additionalTank 表示副油箱中的燃料(以升为单位)。

该卡车每耗费 1 升燃料都可以行驶 10 km。每当主油箱使用了 5 升燃料时,如果副油箱至少有 1 升燃料,则会将 1 升燃料从副油箱转移到主油箱。

返回卡车可以行驶的最大距离。

注意:从副油箱向主油箱注入燃料不是连续行为。这一事件会在每消耗 5 升燃料时突然且立即发生。

 

示例 1:

输入:mainTank = 5, additionalTank = 10
输出:60
解释:
在用掉 5 升燃料后,主油箱中燃料还剩下 (5 - 5 + 1) = 1 升,行驶距离为 50km 。
在用掉剩下的 1 升燃料后,没有新的燃料注入到主油箱中,主油箱变为空。
总行驶距离为 60km 。
示例 2:

输入:mainTank = 1, additionalTank = 2
输出:10
解释:
在用掉 1 升燃料后,主油箱变为空。
总行驶距离为 10km 。
 

提示:

1 <= mainTank, additionalTank <= 100

解答:数据量比较小,直接按照题意一次次模拟

class Solution {
    public int distanceTraveled(int mainTank, int additionalTank) {
        int ans = 0;
        while (mainTank >= 5) {
            ans += 50;
            mainTank -= 5;
            if (additionalTank > 0) {
                additionalTank--;
                mainTank++;
            }
        }

        return ans + mainTank * 10;
    }
}

2740. 找出分区值

给你一个 正 整数数组 nums 。

将 nums 分成两个数组:nums1 和 nums2 ,并满足下述条件:

数组 nums 中的每个元素都属于数组 nums1 或数组 nums2 。
两个数组都 非空 。
分区值 最小 。
分区值的计算方法是 |max(nums1) - min(nums2)| 。

其中,max(nums1) 表示数组 nums1 中的最大元素,min(nums2) 表示数组 nums2 中的最小元素。

返回表示分区值的整数。

 

示例 1:

输入:nums = [1,3,2,4]
输出:1
解释:可以将数组 nums 分成 nums1 = [1,2] 和 nums2 = [3,4] 。
- 数组 nums1 的最大值等于 2 。
- 数组 nums2 的最小值等于 3 。
分区值等于 |2 - 3| = 1 。
可以证明 1 是所有分区方案的最小值。
示例 2:

输入:nums = [100,1,10]
输出:9
解释:可以将数组 nums 分成 nums1 = [10] 和 nums2 = [100,1] 。 
- 数组 nums1 的最大值等于 10 。 
- 数组 nums2 的最小值等于 1 。 
分区值等于 |10 - 1| = 9 。 
可以证明 9 是所有分区方案的最小值。
 

提示:

2 <= nums.length <= 10^5
1 <= nums[i] <= 10^9

解答:排序,取相邻两个元素的最小差值

class Solution {
    public int findValueOfPartition(int[] nums) {
       Arrays.sort(nums);
       int res=Integer.MAX_VALUE;
       int n=nums.length;
       for(int i=1;i<n;i++)res=Math.min(nums[i]-nums[i-1],res);
       return res;
    }
}

2741. 特别的排列

给你一个下标从 0 开始的整数数组 nums ,它包含 n 个 互不相同 的正整数。如果 nums 的一个排列满足以下条件,我们称它是一个特别的排列:

对于 0 <= i < n - 1 的下标 i ,要么 nums[i] % nums[i+1] == 0 ,要么 nums[i+1] % nums[i] == 0 。
请你返回特别排列的总数目,由于答案可能很大,请将它对 109 + 7 取余 后返回。

 

示例 1:

输入:nums = [2,3,6]
输出:2
解释:[3,6,2][2,6,3] 是 nums 两个特别的排列。
示例 2:

输入:nums = [1,4,3]
输出:2
解释:[3,1,4][4,1,3] 是 nums 两个特别的排列。
 

提示:

2 <= nums.length <= 14
1 <= nums[i] <= 10^9

解答:状态压缩dp解法


class Solution {
    private int MOD = (int) 1e9 + 7;
    public int specialPerm(int[] nums) {
        var n = nums.length;
        var f = new int[1 << n][n];
        for (int i = 0; i < n; ++ i) f[0][i] = 1;
        for (int i = 0; i < 1 << n; ++ i) {
            for (int j = 0; j < n; ++ j) {
                for (int k = 0; k < n; ++ k) {
                    if (((i >> k) & 1) == 1 && (nums[j] % nums[k] == 0 || nums[k] % nums[j] == 0)) {
                        f[i][j] = (f[i][j] + f[i ^ (1 << k)][k]) % MOD;
                    }
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < n; ++ i) ans = (ans + f[((1 << n) - 1) ^ (1 << i)][i]) % MOD;
        return ans;
    }
}

2742. 给墙壁刷油漆

给你两个长度为 n 下标从 0 开始的整数数组 cost 和 time ,分别表示给 n 堵不同的墙刷油漆需要的开销和时间。你有两名油漆匠:

一位需要 付费 的油漆匠,刷第 i 堵墙需要花费 time[i] 单位的时间,开销为 cost[i] 单位的钱。
一位 免费 的油漆匠,刷 任意 一堵墙的时间为 1 单位,开销为 0 。但是必须在付费油漆匠 工作 时,免费油漆匠才会工作。
请你返回刷完 n 堵墙最少开销为多少。

 

示例 1:

输入:cost = [1,2,3,2], time = [1,2,3,2]
输出:3
解释:下标为 01 的墙由付费油漆匠来刷,需要 3 单位时间。同时,免费油漆匠刷下标为 23 的墙,需要 2 单位时间,开销为 0 。总开销为 1 + 2 = 3 。
示例 2:

输入:cost = [2,3,4,2], time = [1,1,1,1]
输出:4
解释:下标为 03 的墙由付费油漆匠来刷,需要 2 单位时间。同时,免费油漆匠刷下标为 12 的墙,需要 2 单位时间,开销为 0 。总开销为 2 + 2 = 4 。
 

提示:

1 <= cost.length <= 500
cost.length == time.length
1 <= cost[i] <= 10^6
1 <= time[i] <= 500

解答:使用0/1背包求解

class Solution {
    int n;
    int[][] memo;
    int[] cost, time;
    public int paintWalls(int[] cost, int[] time) {
        this.n = cost.length;
        this.cost = cost;
        this.time = time;
        this.memo = new int[n][2 * n + 1];// 免费时长可以为负数,因此需要加偏移量
        for (int i = 0; i < n; i++){
            Arrays.fill(memo[i], -1);
        }
        return dfs(n - 1, n);// 偏移量防止负数
    }
    // 免费时长为j,刷前i片墙需要的最小花费
    public int dfs(int i, int j){
        if (i < j - n) return 0;// 剩余所有墙都可以由免费油漆工刷
        if (i < 0) return 0x3f3f3f3f;
        if (memo[i][j] != -1) return memo[i][j];
        // 免费油漆工刷
        int res = dfs(i - 1, j - 1);
        // 付费油漆工刷
        res = Math.min(res, dfs(i - 1, j + time[i]) + cost[i]);
        return memo[i][j] = res;
    }
}

  目录