【每日一题见微知著】分割数组的最多方案数

给你一个下标从 0 开始且长度为 n 的整数数组 nums 。分割 数组 nums 的方案数定义为符合以下两个条件的 pivot 数目:

    1 <= pivot < n nums[0] + nums[1] + ... + nums[pivot - 1] == nums[pivot] + nums[pivot + 1] + ... + nums[n - 1]

同时给你一个整数 k 。你可以将 nums 中 一个 元素变为 k 或 不改变 数组。

请你返回在 至多 改变一个元素的前提下,最多 有多少种方法 分割 nums 使得上述两个条件都满足。

class Solution {
          
   
    public int waysToPartition(int[] nums, int k) {
          
   
        int n = nums.length;
        int[] preSum = new int[n + 1];
        Map<Integer, Integer> m1 = new HashMap<>();
        Map<Integer, Integer> m2 = new HashMap<>();
        for (int i = 1; i <= n; i++) {
          
   
            preSum[i] = nums[i - 1] + preSum[i - 1];
            // 一开始除了最后一个前缀和,其余均在m2中
            if (i != n) m2.put(preSum[i], m2.getOrDefault(preSum[i], 0) + 1);
        }
        int ans = 0;
        if (preSum[n] % 2 == 0) {
          
   
            // 若一个元素都不修改
            ans = m2.getOrDefault(preSum[n] / 2, 0);
        }
        for (int i = 0; i < n; i++) {
          
   
            // 修改下标为i的元素变成k
            int change = k - nums[i];
            // 所有元素总和的变化量也是change
            int pn = preSum[n] + change;
            if (pn % 2 == 0) {
          
   
                // 在m1中我们要找的目标是 target1 = 总和/2 的数量
                int t1 = pn / 2;
                // 在m2中我们要找的目标是 target2 = target1 - change 的数量
                int t2 = t1 - change;
                int found = m1.getOrDefault(t1, 0) + m2.getOrDefault(t2, 0);
                ans = Math.max(ans, found);
            }
            // 不断减少m2中的计数,增加m1对应的计数
            if (i != n - 1) {
          
   
                m1.put(preSum[i + 1], m1.getOrDefault(preSum[i + 1], 0) + 1);
                int tmp = m2.get(preSum[i + 1]);
                if (tmp == 1) {
          
   
                    m2.remove(preSum[i + 1]);
                } else {
          
   
                    m2.put(preSum[i + 1], tmp - 1);
                }
            }
        }
        return ans;
    }

}

//
class Solution {
          
   
    public int waysToPartition(int[] nums, int k) {
          
   
        int n=nums.length;

        Map<Long,Integer> pre=new HashMap<>();
        Map<Long,Integer> curA=new HashMap<>();

        long[] prefix=new long[n];
        for(int i=0;i<n;i++){
          
   
            if(i!=0){
          
   
                prefix[i]+=(prefix[i-1]+nums[i]);
            }
            else{
          
   
                prefix[i]=nums[i];
            }
        }
        
        int max=0;
        int count0=0;
        
        pre.put((long)(k-nums[0]),0);

        for(int i=1;i<n;i++){
          
   
            
            long left=prefix[i-1];
            long right=prefix[n-1]-left;
            
            long c=right-left;
            if(c==0){
          
   
                count0++;
                if(count0>max){
          
   
                    max=count0;
                }
            }
            
            curA.put(c,curA.getOrDefault(c,0)+1);
            int curMid=curA.getOrDefault((long)(nums[i]-k),0);
            int preMid=pre.getOrDefault(c,-1)+1;
            if(preMid!=0)
                pre.put(c,preMid);

            pre.put((long)(k-nums[i]),Math.max(pre.getOrDefault((long)(k-nums[i]),0),curMid));

            if(max<Math.max(curMid,preMid)){
          
   
                max=Math.max(curMid,preMid);
            }
        }
        return max;
    }
}

结尾

经验分享 程序员 微信小程序 职场和发展