题解 | #手套#

手套

https://www.nowcoder.com/practice/365d5722fff640a0b6684391153e58d8

思路:贪心算法。本题两个数组有两个特点:

1.left 和 right 里都有可能有为零元素。这意味着总数count必须加上对应为0的元素的值,比如left[0]=0,right[0]=8,count就要加8,因为最坏情况从right里取8个可能都取到right[0]了,也就相当于无效组不成一对。所以双方先把这些无效的排了。

贪心算法就是算上最坏情况求最优解,第二步算最优解,由第一个特点知有0的元素对应另一边的元素相当于无效,已经计入count所以我们不再考虑,我们将其设为0。得到新的left和right数组。

2.最优解:从两边总数小的一方入手。这时数组元素都有效(所谓有效就是两边都可能抽中成对),我们只需要考虑到总值小的一方的所有情况。这里又是数学问题,比如从 [2,3,5,8] 最少取多少个能确保4种都取到?思路是涵盖除了最小的三种后再取一个必定能取到第四种,为什么是涵盖除了最小的三种不是留下最大的?比如 [2,3,5,8]这里面我们留下最大的8,取2+3+5+1=11个,可是如果取到的11按最坏情况其他三种不能都取到,我们需要确保4种一定能取到,要取最坏情况,因此应该取8+5+3+1=17个。

考虑了总值小的最坏情况,最后结果+1也就是任意从总值大的一方取一个手套必定能成对。

比如输入 4, [0,7,1,6],[1,5,0,6]。

第一步按最坏情况考虑无效的“0”,count+=1+1. 经过第一步让left变成[0,7,0,6], right变成 [0,5,0,6]。由于7+6>5+6,我们考虑右边即right一方的最坏情况,我们需要排序从大到小取,[0,0,5,6],由于前两个无效所以不用取,结果就是从right里再取 6+1个,

最后再从left里任意取一个必定能成一对。

import java.util.*;

public class Gloves {
    public int findMinimum(int n, int[] left, int[] right) {
        // write code here
        int count = 0;//总数
	  //count计入无效元素,考虑最坏情况,将为0的对称元素也设为0.
        for (int i = 0; i < n; i++) {
            if(left[i]==0){
                count+=right[i];
                right[i]=0;
            }
            if(right[i]==0){
                count+=left[i];
                left[i]=0;
            }
        }
	    int a = 0;
        int b = 0;
        for (int i = 0; i < n; i++) {
            a+=left[i];
            b+=right[i];
        }
	  //这里为了方便后面做个判断,默认设为 left>right 统一对right做处理。
        if(a<b){
            int[] x = left;
            left = right;
            right = x;
        }
        Arrays.sort(right);//对right排序
	  //对 right 数组取值确保有效值都能涵盖,最坏情况right无0取到right[1]。
        for (int i = n-1; i > 0; i--) {
            if(right[i-1]!=0) count+=right[i];
            else break;
        }
        count++;//从 right 的最后一种任意取一个,确保right每种手套都涵盖
        count++;//从 left 里任意取一个
        return count;
    }
}

总结:

其实就两步:1.排除干扰最优选择的无效元素。2.进行贪心取最优。

全部评论

相关推荐

我见java多妩媚:大外包
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务