Search code examples
arraysalgorithmrangesub-array

Length of minimum subsequence that spans entire length of array?


I'm given an integer array of length N, with elements representing the spans it could cover from 0 to N-1. so for an element a[i] the element spans a range from max(i-a[i],0) to min(i+a[i],N-1).

How to find the length of smallest subsequence that spans entire space ie from 0 to N-1;

Example : For this array [1,1,1,3,2,1,1,4] answer should be 2

This is what i've got so far, It doesn't work for all cases

int arr[] = {2,2,1,3,2,1,1,4,1,1,1,1,1,1,1,1,1,1}; // Fails for this case
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        int[] sortedIndices = IntStream.range(0, arr.length)
                .boxed().sorted((i, j) -> span(arr[j],j,arr.length) - span(arr[i],i,arr.length))
                .mapToInt(ele -> ele).toArray();

        int i=0;
        int ans = 0;
        while (min>0 || max<arr.length-1) {
            int ind = sortedIndices[i++];
            int val = arr[ind];

            int tmin = Math.max(0,ind-val);
            int tmax = Math.min(arr.length - 1, ind+val);
            if(tmin < min || tmax > max)
                ans++;

            min = Math.min(min, tmin);
            max = Math.max(max, tmax);
        }

        System.out.println(ans);

Solution

  • Seems that problem might solved with simple greedy algorithm.

    For every array entry create interval with start and finish fields (a[i].start = i-arr[i] etc)

    Sort intervals by start field.

    Find interval with the most right finish among those covering 0, make maxx=a[i].finish.

    Scan intervals with start in 0..maxx range, choose one with the rightmost finish.

    Continue.

    Quick-made Python implementation (perhaps some more checks are needed)

    ar = [2,2,1,3,2,1,4,4]
    n = len(ar)
    a = [(max(0, i-ar[i]), min(i+ar[i], n-1)) for i in range(n)]
    print(ar)
    a.sort()
    print(a)
    cnt = 0
    maxx = -1
    left = 0
    i = 0
    while i < n and maxx < n - 1:
        while i < n and a[i][0] <= left and maxx < n - 1:
            maxx = max(a[i][1], maxx)
            i+=1
        print("maxx ", maxx)
        left = maxx
        cnt += 1
    
    print("cover ", cnt)
    
    [2, 2, 1, 3, 2, 1, 4, 4]
    [(0, 2), (0, 3), (0, 6), (1, 3), (2, 6), (2, 7), (3, 7), (4, 6)]
    maxx  6
    maxx  7
    cover  2