Sword finger offer_008 and the shortest subarray greater than target

Posted by ashben on Tue, 21 Dec 2021 22:55:41 +0100

Title:

Given an array containing n , positive integers and a positive integer target.

Find out the continuous sub array [numsl, numsl + 1,..., numsr-1, numsr] with the smallest length satisfying its sum ≥ target in the array, and return its length. If there is no eligible subarray, 0 is returned.

Example 1:

Input: target = 7, Num = [2,3,1,2,4,3]
Output: 2
Explanation: subarray [4,3] is the subarray with the smallest length under this condition.

Example 2:

Input: target = 4, Num = [1,4,4]
Output: 1


Example 3:

Input: target = 11, Num = [1,1,1,1,1,1,1]
Output: 0
 

Tips:

(1)1 <= target <= 109
(2)1 <= nums.length <= 105
(3)1 <= nums[i] <= 105

Code 1: prefix and plus binary search


import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] nums = {2, 3, 1, 2, 4, 3};
        int target = 7;
        System.out.println(minSubArrayLen(7, nums));

    }
    public static int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int minLength = Integer.MAX_VALUE;
        int[] sums = new int[nums.length+1];

        // The prefix and of the array are stored in the sums array. Because they are all positive numbers, the array is an incremental array
        for (int i = 1; i <= n; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }

        for (int i = 1; i <= n; i++) {
            int s = target + sums[i - 1];
            int index = Arrays.binarySearch(sums, s);
            if (index < 0) {
                index = -index - 1;
            }
            if (index <= n) {
                minLength = Math.min(minLength, index - (i - 1));
            }
        }
        return minLength == Integer.MAX_VALUE ? 0 : minLength;
    }
}

Problem solving ideas:

In order to use binary lookup, you need to create an additional array \ text{sums}sums to store the prefix and of the array \ text{nums}nums, where \ text{sums}[i]sums[i] represents the elements and from \ text{nums}[0]nums[0] to \ text{nums}[i-1]nums[i − 1]. After the prefix sum is obtained, for each starting subscript ii, the minimum subscript \ textit{bound}bound greater than or equal to ii can be obtained through binary search, so that \ text {sums} [\ textit {bound}] - [text {sums} [I-1] \ Ge ssums [bound] − sums[i − 1] ≥ s, and the minimum length of the sub array is updated (at this time, the length of the sub array is \ textit{bound}-(i-1)bound − (I − 1)).

Because this problem ensures that each element in the array is positive, the prefix and must be incremented, which ensures the correctness of dichotomy. If the title doesn't say that every element in the array is positive, you can't use bisection to find this position.

In many languages, there are ready-made libraries and functions to realize the function of binary search for the first position greater than or equal to a certain number, such as the lower in C + +_ Bound, arrays in Java Binarysearch, array in c# Binarysearch, bisect. In Python bisect_ left. But sometimes the interviewer may let us implement such a binary search function ourselves

Complexity analysis

Time complexity: O(n \log n)O(nlogn), where nn is the length of the array. Each subscript needs to be traversed as the starting subscript of the sub array. The traversal time complexity is O(n)O(n). For each starting subscript, the sub array with the smallest length needs to be obtained through binary search. The time complexity of binary search is O(\log n)O(logn), so the total time complexity is O(n \log n)O(nlogn).

Space complexity: O(n)O(n), where nn is the length of the array. Create additional arrays \ text{sums}sums store prefixes and.

Code 2: sliding window

package jianzhioffer;

import java.util.Arrays;

public class offer_08 {
    public static void main(String[] args) {
        int[] nums = {2, 3, 1, 2, 4, 3};
        int target = 7;
        System.out.println(minSubArrayLen(7, nums));

    }
    public static int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int minLength = Integer.MAX_VALUE;
        int start = 0;
        int end = 0;
        int sum = 0;
        while (end < n) {
            sum += nums[end];
            while (sum >= target) {
                minLength = Math.min(minLength, end - start + 1);
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return minLength == Integer.MAX_VALUE ? 0 : minLength;
    }
}

Problem solving ideas:

In method 1, the starting subscript of the sub array is determined each time, and then the sub array with the smallest length is obtained, so the time complexity is high. In order to reduce the time complexity, the sliding window method can be used.

Define two pointers \ textit{start}start and \ textit{end}end to represent the start position and end position of the subarray (sliding window window) respectively. The maintenance variable \ textit{sum}sum stores the elements and in the subarray (that is, the elements and from \ text{nums}[\textit{start}]nums[start] to \ text{nums}[\textit{end}]nums[end]).

In the initial state, \ textit{start}start and \ textit{end}end both point to the subscript 00, and the value of \ textit{sum}sum is 00.

For each iteration, add \ text {num} [End] num [End] to \ textit{sum}sum. If \ textit{sum} \ge ssum ≥ s, Then update the minimum length of the subarray (at this time, the length of the subarray is \ textit{end}-\textit{start}+1end − start+1), then subtract \ text {num} [start] num [start] from \ textit{sum}sum, and move \ textit{start}start right until \ textit {sum} < SSUM < S. in this process, also update the minimum length of the subarray. At the end of each round of iteration, delete \ textit{end}end shift right.

Complexity analysis:

Time complexity: O(n)O(n), where nn is the length of the array. The pointers \ textit{start}start and \ textit{end}end can be moved up to nn times each.

Spatial complexity: O(1)O(1).

Reference link:

Force buckle

Topics: C++ Algorithm leetcode