How can I find the minimum index of the array in this case?

后端 未结 3 1116
长情又很酷
长情又很酷 2020-12-14 05:04

We are given an array with n values.

Example: [1,4,5,6,6]

For each index i of the array a ,we construct a

3条回答
  •  离开以前
    2020-12-14 05:40

    This probably cannot reach the efficiency of David Eisenstat's answer but since I spent quite a long time figuring out an implementation, I thought I'd leave it up anyway. As it is, it seems about O(n^2).

    The elements of b[i] may be out of order, but sections of them are not:

    [a[1]/1] + [a[2]/2] + [a[3]/3]
               |------ s2_1 -----|
                          |-s1_1-|
    
               [a[2]/1] + [a[3]/2]
               |------ s2_2 -----|
                          |-s1_2-|
    
                          [a[3]/1]
                          |-s1_3-|
    
    
    s2_1 < s2_2
    
    s1_1 < s1_2 < s1_3
    

    Binary search for k on s1. Any result with an s1_i greater than k will rule out a section of ordered rows (rows are b_is).

    Binary search for k on s2 on the remaining rows. Any result with an s2_i greater than k will rule out a section of ordered rows (rows are b_is).

    This wouldn't help much since in the worst case, we'd have O(n^2 * log n) complexity, greater than O(n^2).

    But we can also search horizontally. If we know that b_i ≤ k, then it will rule out both all rows with greater or equal length and the need to search smaller s(m)s, not because smaller s(m)s cannot produce a sum >= k, but because they will necessarily produce one with a higher i and we are looking for the minimum i.

    JavaScript code:

    var sum_width_iterations = 0
    var total_width_summed = 0
    
    var sum_width_cache = {}
    
    function sum_width(A, i, width){
      let key = `${i},${width}`
      
      if (sum_width_cache.hasOwnProperty(key))
        return sum_width_cache[key]
        
      sum_width_iterations++
      total_width_summed += width
    
      let result = 0
      for (let j=A.length-width; j> 1)
      let s = sum_width(A, mid, width)
      while (low <= high){
        mid = low + ((high - low) >> 1)
        s = sum_width(A, mid, width)
        if (s > k)
          high = mid - 1
        else
          low = mid + 1
      }
      return [mid, s]
    }
    
    function f(A, k, l, r){
      let n = A.length
      
      if (l > r){
      
    console.log(`l > r: l, r: ${l}, ${r}`)
      
        return [n + 1, Infinity]
      }
      
      let width = n - l
      
    console.log(`\n(call) width, l, r: ${width}, ${l}, ${r}`)
    
      let mid = l + ((r - l) >> 1)
      let mid_width = n - mid
      
    console.log(`mid: ${mid}`)
    console.log('mid_width: ' + mid_width)
    
      let highest_i = n - mid_width
      let [i, s] = find_s_greater_than_k(A, mid_width, 0, highest_i, k)
    
    console.log(`hi_i, s,i,k: ${highest_i}, ${s}, ${i}, ${k}`)
    
      if (mid_width == width)
        return [i, s]
    
      // either way we need to look left
      // and down
    
    console.log(`calling left`)
    
      let [li, ls] = f(A, k, l, mid - 1)
    
      // if i is the highest, width is
      // the width of b_i
    
    console.log(`got left: li, ls, i, high_i: ${li}, ${ls}, ${i}, ${highest_i}`)
    
      if (i == highest_i){
    
    console.log(`i == highest_i, s <= k: ${s <= k}`)
    
        // b_i is small enough
        if (s <= k){
          if (ls <= k)
            return [li, ls]
          else
            return [i, s]
    
        // b_i is larger than k
        } else {
    
    console.log(`b_i > k`)
    
          let [ri, rs] = f(A, k, mid + 1, r)
    
    console.log(`ri, rs: ${ri}, ${rs}`)
    
          if (ls <= k)
            return [li, ls]
          else if (rs <= k)
            return [ri, rs]
          else
            return [i, s]
        }
        
      // i < highest_i
      } else {
    
      console.log(`i < highest_i: high_i, i, s, li, ls, mid, mid_width, width, l, r: ${highest_i}, ${i}, ${s}, ${li}, ${ls}, ${mid}, ${mid_width}, ${width}, ${l}, ${r}`)
      
        // get the full sum for this b
        let b_i = sum_width(A, i, n - i)
          
    console.log(`b_i: ${b_i}`)
      
        // suffix sum is less than k
        // so we cannot rule out either side
        if (s < k){
        
    console.log(`s < k`)
    
          let ll = l
          let lr = mid - 1
          let [lli, lls] = f(A, k, ll, lr)
          
    console.log(`ll, lr, lli, lls: ${ll}, ${lr}, ${lli}, ${lls}`)
          
          // b_i is a match so we don't
          // need to look to the right
          if (b_i <= k){
          
    console.log(`b_i <= k: i, b_i: ${i}, ${b_i}`)
          
            if (lls <= k)
              return [lli, lls]
            else
              return [i, b_i]
          
          // b_i > k
          } else {
          
    console.log(`b_i > k: i, b_i: ${i}, ${b_i}`)
          
            let rl = mid + 1
            let rr = r
            let [rri, rrs] = f(A, k, rl, rr)
          
    console.log(`rl, rr, rri, rrs: ${rl}, ${rr}, ${rri}, ${rrs}`)
          
            // return the best of right
            // and left sections
            if (lls <= k)
              return [lli, lls]
            else if (rrs <= k)
              return [rri, rrs]
            else
              return [i, b_i]
          }
        
        // suffix sum is greater than or
        // equal to k so we can rule out
        // this and all higher rows (`b`s)
        // that share this suffix
        } else {
        
    console.log(`s >= k`)
    
          let ll = l
          // the suffix rules out b_i
          // and above
          let lr = i - 1
          let [lli, lls] = f(A, k, ll, lr)
          
    console.log(`ll, lr, lli, lls: ${ll}, ${lr}, ${lli}, ${lls}`)
    
          let rl = highest_i + 1
          let rr = r
          let [rri, rrs] = f(A, k, rl, rr)
          
    console.log(`rl, rr, rri, rrs: ${rl}, ${rr}, ${rri}, ${rrs}`)
    
          // return the best of right
          // and left sections
          if (lls <= k)
            return [lli, lls]
          else if (rrs <= k)
            return [rri, rrs]
          else
            return [i, b_i]
        }
      }
    }
    
    let lst = [1, 2, 3, 1]
         // b [3, 3, 3, 1]
         
    lst = [ 1, 34,  3,  2,  9, 21, 3, 2, 2, 1]
    //  b [23, 41, 12, 13, 20, 22, 4, 3, 2, 1]
    
    console.log(
      JSON.stringify(f(lst, 20, 0, lst.length)))
    
    console.log(`sum_width_iterations: ${sum_width_iterations}`)
    
    console.log(`total_width_summed: ${total_width_summed}`)

提交回复
热议问题