LeetCode 2016. 增量元素之间的最大差值 / 553. 最优除法 / 1601. 最多可达成的换楼请求数目(枚举+回溯)

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 2016. 增量元素之间的最大差值 / 553. 最优除法 / 1601. 最多可达成的换楼请求数目(枚举+回溯)相关的知识,希望对你有一定的参考价值。

2016. 增量元素之间的最大差值

2022.2.26 每日一题

题目描述

给你一个下标从 0 开始的整数数组 nums ,该数组的大小为 n ,请你计算 nums[j] - nums[i] 能求得的 最大差值 ,其中 0 <= i < j < n 且 nums[i] < nums[j] 。

返回 最大差值 。如果不存在满足要求的 i 和 j ,返回 -1 。

示例 1:

输入:nums = [7,1,5,4]
输出:4
解释:
最大差值出现在 i = 1 且 j = 2 时,nums[j] - nums[i] = 5 - 1 = 4 。
注意,尽管 i = 1 且 j = 0 时 ,nums[j] - nums[i] = 7 - 1 = 6 > 4 ,但 i > j 不满足题面要求,所以 6 不是有效的答案。

示例 2:

输入:nums = [9,4,3,2]
输出:-1
解释:
不存在同时满足 i < j 和 nums[i] < nums[j] 这两个条件的 i, j 组合。

示例 3:

输入:nums = [1,5,2,10]
输出:9
解释:
最大差值出现在 i = 0 且 j = 3 时,nums[j] - nums[i] = 10 - 1 = 9 。

提示:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-difference-between-increasing-elements
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

记录当前最小值,然后记录最大的差值

class Solution 
    public int maximumDifference(int[] nums) 
        int n = nums.length;
        int min = nums[0];
        int diff = -1;
        for(int i = 1; i < n; i++)
            if(nums[i] < min)
                min = nums[i];
            else if(nums[i] > min)
                diff = Math.max(diff, nums[i] - min);
            
        
        return diff;
    

553. 最优除法

2022.2.27 每日一题

题目描述

给定一组正整数,相邻的整数之间将会进行浮点除法操作。例如, [2,3,4] -> 2 / 3 / 4 。

但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级。你需要找出怎么添加括号,才能得到最大的结果,并且返回相应的字符串格式的表达式。你的表达式不应该含有冗余的括号。

示例:

输入: [1000,100,10,2]
输出: “1000/(100/10/2)”
解释:
1000/(100/10/2) = 1000/((100/10)/2) = 200
但是,以下加粗的括号 “1000/((100/10)/2)” 是冗余的,
因为他们并不影响操作的优先级,所以你需要返回 “1000/(100/10/2)”。

其他用例:
1000/(100/10)/2 = 50
1000/(100/(10/2)) = 50
1000/100/10/2 = 0.5
1000/100/(10/2) = 2
说明:
输入数组的长度在 [1, 10] 之间。
数组中每个元素的大小都在 [2, 1000] 之间。
每个测试用例只有一个最优除法解。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/optimal-division
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

要使得除数最小,就是一直除就除数最小

class Solution 
    public String optimalDivision(int[] nums) 
        //要最大的结果,就是要最小的除数,
        //那么怎么才能让后面的除数最小呢,就是一直除就可以了

        int n = nums.length;
        if(n == 1)
            return nums[0] + "";
        if(n == 2)
            return nums[0] + "/" + nums[1];
        String res = nums[0] + "/" + "(";
        for(int i = 1; i < n - 1; i++)
            res = res + nums[i] + "/";
        
        res = res + nums[n - 1] + ")";

        return res;
    

1601. 最多可达成的换楼请求数目

2022.2.28 每日一题

题目描述

我们有 n 栋楼,编号从 0 到 n - 1 。每栋楼有若干员工。由于现在是换楼的季节,部分员工想要换一栋楼居住。

给你一个数组 requests ,其中 requests[i] = [fromi, toi] ,表示一个员工请求从编号为 fromi 的楼搬到编号为 toi 的楼。

一开始 所有楼都是满的,所以从请求列表中选出的若干个请求是可行的需要满足 每栋楼员工净变化为 0 。意思是每栋楼 离开 的员工数目 等于 该楼 搬入 的员工数数目。比方说 n = 3 且两个员工要离开楼 0 ,一个员工要离开楼 1 ,一个员工要离开楼 2 ,如果该请求列表可行,应该要有两个员工搬入楼 0 ,一个员工搬入楼 1 ,一个员工搬入楼 2 。

请你从原请求列表中选出若干个请求,使得它们是一个可行的请求列表,并返回所有可行列表中最大请求数目。

示例 1:


输入:n = 5, requests = [[0,1],[1,0],[0,1],[1,2],[2,0],[3,4]]
输出:5
解释:请求列表如下:
从楼 0 离开的员工为 x 和 y ,且他们都想要搬到楼 1 。
从楼 1 离开的员工为 a 和 b ,且他们分别想要搬到楼 2 和 0 。
从楼 2 离开的员工为 z ,且他想要搬到楼 0 。
从楼 3 离开的员工为 c ,且他想要搬到楼 4 。
没有员工从楼 4 离开。
我们可以让 x 和 b 交换他们的楼,以满足他们的请求。
我们可以让 y,a 和 z 三人在三栋楼间交换位置,满足他们的要求。
所以最多可以满足 5 个请求。

示例 2:


输入:n = 3, requests = [[0,0],[1,2],[2,1]]
输出:3
解释:请求列表如下:
从楼 0 离开的员工为 x ,且他想要回到原来的楼 0 。
从楼 1 离开的员工为 y ,且他想要搬到楼 2 。
从楼 2 离开的员工为 z ,且他想要搬到楼 1 。
我们可以满足所有的请求。

示例 3:

输入:n = 4, requests = [[0,3],[3,1],[1,2],[2,0]]
输出:4

提示:

1 <= n <= 20
1 <= requests.length <= 16
requests[i].length == 2
0 <= fromi, toi < n

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-number-of-achievable-transfer-requests
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

枚举所有情况 + 回溯

class Solution 
    int[] diff;     //每个楼人数变化
    int count;      //处理的请求个数
    int zero;       //人数变化的楼有几个
    int res;
    int n;
    public int maximumRequests(int n, int[][] requests) 
        //这个就相当于形成一个环,看哪几个环最大
        //那么这个该怎么搞呢,因为一个楼可以和多个形成环
        //而所给的n和数组长度也不大,意思是可以暴力做一下
        //但是暴力该怎么做呢,就是遍历所有的成环情况吗

        //判断成环是用拓扑排序,统计入度出度
        //实在有点想不到怎么统计几个环
        //然后就看了官解,官解给出的方法是枚举所有的情况,也就是遍历所有的请求,
        //如果这个请求被考虑,那么就给响应的房间人数发生变化,如果最后所有房间都没有发生变化,就返回当前统计到的请求数
        //如果有楼人数发生了变化,就返回
        
        int l = requests.length;
        this.n = n;
        diff = new int[n];
        zero = n;   //刚开始所有楼人数都没有变化
        dfs(requests, 0);   //处理第几个请求
        return res;
    

    public void dfs(int[][] requests, int idx)
        //如果遍历到最后一个请求了,同时楼中人数没有发生变化,那么就统计当前变化的请求个数
        if(idx == requests.length)
            if(zero == n)
                res = Math.max(res, count);
            
            return;
        
        
        //考虑当前请求
        int z = zero;
        int from =  requests[idx][0];
        int to = requests[idx][1];
        count++;
        
        diff[from]--;
        diff[to]++;
        if(diff[from] == 0)
            zero++;
        else if(diff[from] == -1)
            zero--;
        if(diff[to] == 0)
            zero++;
        else if(diff[to] == 1)
            zero--;
        //如果是自环,那么zero不变
        if(from == to)
            zero = z;
        dfs(requests, idx + 1);
        //回溯
        diff[from]++;
        diff[to]--;
        count--;
        zero = z;
        //不考虑当前请求
        dfs(requests, idx + 1);
    

用二进制表示

class Solution 
    public int maximumRequests(int n, int[][] requests) 
        //用二进制来枚举,就是用每一个二进制位代表当前requests是否被选择
        //如果被选择了,那么更新diff数组,最后查看当前mask下,是否diff数组还是没有变化,
        //如果没有变化,就记录当前结果
        //比回溯那种更简单高效

        int res = 0;
        int l = requests.length;
        int[] diff = new int[n];
        for(int mask = 0; mask < (1 << l); mask++)
            int count = Integer.bitCount(mask);
            if(count <= res)
                continue;
            Arrays.fill(diff, 0);
            //遍历所有为 1 的请求
            for(int i = 0; i < l; i++)
                if(((mask >> i) & 1) != 0)
                    diff[requests[i][0]]--;
                    diff[requests[i][1]]++;
                
            

            boolean flag = true;
            for(int t : diff)
                if(t != 0)
                    flag = false;
                    break;
                
            
            if(!flag)
                continue;
            res = count;
        
        return res;
    

以上是关于LeetCode 2016. 增量元素之间的最大差值 / 553. 最优除法 / 1601. 最多可达成的换楼请求数目(枚举+回溯)的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode刷题100天—5881. 增量元素之间的最大差值(数组)—day49

Leetcode刷题100天—5881. 增量元素之间的最大差值(数组)—day49

「 每日一练,快乐水题 」2016. 增量元素之间的最大差值

「 每日一练,快乐水题 」2016. 增量元素之间的最大差值

「 每日一练,快乐水题 」2016. 增量元素之间的最大差值

为什么我的代码不通过?​增量元素之间的最大差值