LeetCode 周赛216C 5607. 生成平衡数组的方案数 (前缀和 + 模拟)

LeetCode周赛216C: 5607. 生成平衡数组的方案数

在这里插入图片描述



看了一下数据范围
在这里插入图片描述
这道题暴力应该是解不出来的, 最后用暴力试了一下,不出所料的超时了。

没关系。一般解法都是从暴力入手,找办法优化的。 沖(chong)


发现好像可以通过前缀和快速的进行结果的计算


思路:

先将给出的数组按下标的奇数位、偶数位的前缀和计算出来。

给定的数组nums: [ 1 , 1 , 1 , 1 , 1 ] [1,1,1,1,1] [1,1,1,1,1]
前缀和preSum: [ 1 , 1 , 2 , 2 , 3 ] [1,1,2,2,3] [1,1,2,2,3]


小贴士: 因为删掉了一个数,所以删掉的该数后面的所有下标都向前移动 1 , 奇变偶, 偶变奇

然后我们会发现: 删除当前位置的下标 ( i n d e x = 3 ) (index = 3) (index=3)

奇数位上的和就等于: i n d e x = 3 之 前 的 所 有 奇 数 位 和 + i n d e x = 3 之 后 的 所 有 偶 数 位 的 和 index = 3 之前的所有奇数位和 + index =3 之后的所有偶数位的和 index=3+index=3

偶数位上的和就等于: i n d e x = 2 之 前 的 所 有 偶 数 位 和 + i n d e x = 3 之 后 的 所 有 奇 数 位 的 和 index = 2 之前的所有偶数位和 + index = 3 之后的所有奇数位的和 index=2+index=3


整体由普通思路 >> 再考虑特定的边界条件


小贴士: 可以再同时计算给定数组的sum, 当删掉一个数后 sum - num 如果为奇数,奇数位和 and 偶数位和必不可能相等。
提前进入下一次循环


AC Code

奇偶前缀和


    public int waysToMakeFair(int[] nums) {
    
    
        if(nums.length == 1) return 1;
        int ans = 0;
        int sum = 0;
        int[] preSum = new int[nums.length];
        preSum[0] = nums[0]; preSum[1] = nums[1]; sum += (nums[0] + nums[1]);
        for (int i = 2; i < nums.length; i++) {
    
    
            sum += nums[i];
            if(i % 2 == 1) preSum[i] = preSum[i - 2] + nums[i];
            else preSum[i] = preSum[i - 2] + nums[i];
        }

        // System.out.println(Arrays.toString(preSum));

        for (int i = 0; i < nums.length; i++) {
    
    
            // 为奇数不可能相等
            if((sum - nums[i]) % 2 == 1) continue;
            int asum = 0, bsum = 0;

            // 2  1  8  5 
            // 0  1  2  3  (index
            if(i - 1 >= 0)
                asum += preSum[i - 1]; // 奇
            if(i - 2 >= 0) 
                bsum += preSum[i - 2];  // 偶
			
			
            if(i % 2 == (nums.length - 1) % 2){
    
    
            	// 当 i 为奇数的时候,那么 asum 之前就是偶位数的和 >> 后面就加 奇数位 的和
                asum += preSum[nums.length - 1] - preSum[i];
                if(i - 1 >= 0)
                    bsum += preSum[nums.length - 2] - preSum[i - 1];
                else bsum += preSum[nums.length - 2];
            } else {
    
    
            	// 当 i 为奇数的时候。asum 之前就是 偶位数的和, 且 nums.length - 1为偶数, 所以后面要加 奇数位 的和
                asum += preSum[nums.length - 2] - preSum[i];
                if(i - 1 >= 0)
                    bsum += preSum[nums.length - 1] - preSum[i - 1];
                else  bsum += preSum[nums.length - 1] ;
            }

            if(asum == bsum) ans++;
        }

        return ans;
    }


在这里插入图片描述






暴力不出意料的 超时了

超时数据: 超时样例

    public int waysToMakeFair(int[] nums) {
    
    
        int ans = 0;
        for (int i = 0; i < nums.length; i++) {
    
    
            int evenSum = 0, oddSum = 0;
            for (int j = 0; j < nums.length; j++) {
    
    
                if(j < i){
    
    
                    if(j % 2 == 0) evenSum += nums[j];
                    else oddSum += nums[j];
                } else if(j > i){
    
    
                    if((j -1) % 2 == 0) evenSum += nums[j];
                    else oddSum += nums[j];
                }
                // == 不管
            }
            if(oddSum == evenSum) ans++;
        }

        return ans;
    }



虽然花了两个小时, 但还是做出来了,问题不大.

这么久的原因是因为 生成前缀和数组的时候写错了 主干没啥问题。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43765535/article/details/109952139
今日推荐