柠檬微趣笔试题

题目

  对于给定正整数数组A和给定正整数T,请在A中找出两个连续子数组,这两个子数组不能相交,并且两个子数组的和相等且为 T。可能会有多种方案,请返回两个子数组长度和的最小值。如果无法找到这样的方案,请返回 -1。

 

 

思路

利用滑动窗口,记录窗口内的和 sum、窗口的左指针 left ,当窗口内的和大于给的 T 值,停下来,利用移动滑动窗口的方式当 sum > T,将 sum - A[ left ] ,并且将左指针 left 往右移一格,当 sum < T 的时候,停止左边滑动窗口的移动,变成将滑动窗口的右指针往右移。因为,只需要子数组的长度,所以结果集 res 中,记录子数组的长度即可。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class lingMengWeiQu3 {
    public static void main(String[] args) {
        int[] nums = {7,3,2,5};
        System.out.println(minSumOfLengths(nums, 7));
    }
    public static int minSumOfLengths (int[] A, int T){
        if(A == null || A.length == 0) return -1;
        List<Integer> res = new ArrayList<>(); //存放子数组的长度
        int sum = 0, left = 0; // 窗口内的和,窗口的左指针
        for(int i = 0; i < A.length; i++){ // i 作为滑动窗口的右指针
            sum += A[i];
            if(sum >= T){ //窗口内的和 >= T,停下来判断是否移动窗口、还是加入结果
                while(sum >= T){
                    if(sum > T){
                        sum -= A[left]; //窗口内的和,减去最左的元素
                        left += 1; //窗口往右移一格
                    }else{ //sum == T
                        res.add(i - left + 1); //窗口长度放入结果集
                        left = i + 1; //窗口左指针重置
                        sum = 0; //窗口和清零
                    }
                }
            }
        }
        if(res.size() < 2) return -1;
        Collections.sort(res); //结果集排序
        return res.get(0) + res.get(1); // 返回最小的2个
    }
}

注:由于是结束考试后,下来才重新写的代码,不知道 OJ 是否能通过,不过感觉应该是没问题,解题思想是用这个方法。

原文地址:https://www.cnblogs.com/luo-c/p/13719741.html