题解 | #长度最小的连续子数组#

长度最小的连续子数组

https://www.nowcoder.com/practice/10dd5f8c5d984aa3bd69788d86aaef23

import java.util.*;

/**
 * NC202 长度最小的连续子数组
 * @author d3y1
 */
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型一维数组 
     * @param target int整型 
     * @return int整型
     */
    public int minSubarray (int[] nums, int target) {
        // return solution1(nums, target);
        // return solution2(nums, target);
        return solution3(nums, target);
        // return solution4(nums, target);
    }

    /**
     * 前缀和 + 双指针(滑动窗口)
     * @param nums
     * @param target
     * @return
     */
    private int solution1(int[] nums, int target){
        int n = nums.length;

        // 前缀和: pre[i]表示前i项的和
        int[] pre = new int[n+1];
        int val;
        for(int i=1; i<=n; i++){
            val = nums[i-1];
            if(val >= target){
                return 1;
            }
            pre[i] = pre[i-1]+val;
        }
        if(pre[n] < target){
            return 0;
        }

        int sum;
        int result = Integer.MAX_VALUE;
        // 双指针(滑动窗口)
        for(int i=0,j=1; i<=j&&j<=n;){
            sum = pre[j]-pre[i];
            if(sum >= target){
                result = Math.min(result, j-i);
                i++;
            }else{
                j++;
            }
        }

        return result;
    }

    /**
     * 前缀和 + 双指针(滑动窗口) + 二分
     * @param nums
     * @param target
     * @return
     */
    private int solution2(int[] nums, int target){
        int n = nums.length;

        // 前缀和: pre[i]表示前i项的和
        int[] pre = new int[n+1];
        int val;
        for(int i=1; i<=n; i++){
            val = nums[i-1];
            if(val >= target){
                return 1;
            }
            pre[i] = pre[i-1]+val;
        }
        if(pre[n] < target){
            return 0;
        }

        // 二分 <- 前缀数组pre 单调增
        // 快速找到第一个满足条件的位置
        int left = 1;
        int right = n;
        int mid;
        while(left <= right){
            mid = (left+right)/2;
            if(pre[mid] < target){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }

        int sum;
        int result = Integer.MAX_VALUE;
        // 双指针(滑动窗口)
        for(int i=0,j=left; i<=j&&j<=n;){
            sum = pre[j]-pre[i];
            if(sum >= target){
                result = Math.min(result, j-i);
                i++;
            }else{
                j++;
            }
        }

        return result;
    }

    /**
     * 前缀和 + 二分
     * @param nums
     * @param target
     * @return
     */
    private int solution3(int[] nums, int target){
        int n = nums.length;

        // 前缀和: pre[i]表示前i项的和
        int[] pre = new int[n+1];
        int val;
        for(int i=1; i<=n; i++){
            val = nums[i-1];
            if(val >= target){
                return 1;
            }
            pre[i] = pre[i-1]+val;
        }
        if(pre[n] < target){
            return 0;
        }

        // 二分 <- 前缀数组pre 单调增
        int result = Integer.MAX_VALUE;
        for(int i=0; i<n; i++){
            int left = i;
            int right = n;
            int mid;
            while(left <= right){
                mid = (left+right)/2;
                // 关键
                if(pre[mid] < pre[i]+target){
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }
            if(left <= n){
                result = Math.min(result, left-i);
            }
        }

        return result;
    }

    /**
     * 前缀和 + 二分
     * @param nums
     * @param target
     * @return
     */
    private int solution4(int[] nums, int target){
        int n = nums.length;

        // 前缀和: pre[i]表示前i项的和
        int[] pre = new int[n+1];
        int val;
        for(int i=1; i<=n; i++){
            val = nums[i-1];
            if(val >= target){
                return 1;
            }
            pre[i] = pre[i-1]+val;
        }
        if(pre[n] < target){
            return 0;
        }

        // 二分 <- 子数组长度
        int left = 1;
        int right = n;
        int mid;
        while(left <= right){
            mid = (left+right)/2;
            boolean found = false;
            for(int i=0,j=i+mid; j<=n; i++,j++){
                if(pre[j]-pre[i] >= target){
                    found = true;
                    break;
                }
            }
            if(!found){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }

        // left>n => 不存在满足条件的子数组
        int result = left>n?0:left;

        return result;
    }
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-07 18:05
哈哈哈哈哈感觉朋友找工作的已经疯掉了,直接上图
码农索隆:真老板娘:“我嘞个去,这不我当年的套路吗
点赞 评论 收藏
分享
06-17 00:26
门头沟学院 Java
程序员小白条:建议换下项目,智能 AI 旅游推荐平台:https://github.com/luoye6/vue3_tourism_frontend 智能 AI 校园二手交易平台:https://github.com/luoye6/vue3_trade_frontend GPT 智能图书馆:https://github.com/luoye6/Vue_BookManageSystem 选项目要选自己能掌握的,然后最好能自己拓展的,分布式这种尽量别去写,不然你只能背八股文了,另外实习的话要多投,尤其是学历不利的情况下,多找几段实习,最好公司title大一点的
无实习如何秋招上岸
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-07 11:30
仁者伍敌:kpi都懒得刷了属于是
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务