【问题标题】:Flip elements to minimize the maximum consecutive elements together翻转元素以将最大连续元素最小化在一起
【发布时间】:2017-03-08 15:41:44
【问题描述】:

我得到了一个由 1 和 0 组成的数组,以及一个数字 k。我最多可以翻转数组的元素 k 次。(0 到 1 或 1 到 0)。

我需要编写一个算法来翻转最多 K 个元素的状态,以使具有相同元素的最大连续元素块的大小最小化。

ex:

Array : 110001111 and k=2;
Solution is 2 , because: we can change the string to: 110101011, and the length of the maximum consecutive length is minimised to 2.

Array : 1001 k=1
Solution is 2, because: If we don't change the input string at all, the answer will be 2. It is the best value we can achieve under the given conditions.

有人可以为我提供解决此问题的方法吗?

【问题讨论】:

  • 对于希望标记此内容的用户,please read a consensus view 就与活跃竞赛相关的问题。仅根据其提出的质量来判断此问题,而不是根据其他网站的道德准则。

标签: arrays algorithm mathematical-optimization


【解决方案1】:

让我试着从简化这个问题开始: 我们有一个数字列表,代表相同类型的序列: [a1,a2,a3...a_m] 这样他们的总和就是n

k 操作是以下任意一种:

  1. a_i 替换为[a_i^1,1,a_i^2]
  2. a_i 更改为a_i-1a_{i-1} 更改为a_{i-1}+1
  3. a_i 更改为a_i+1a_{i-1} 更改为a_{i-1}-1

但很明显,如果a_i<=2,操作 2 和 3 仅比操作 1 更好,除非只有一个元素且总长度为 2,否则在这种情况下做任何事情都是没有意义的。所以我们可以认为这是如何拆分值的问题,这种情况下我们不关心a_is的顺序

对于k 操作,您需要执行哪些k 操作以使max(a1,a2,...) 最终最小化

很明显,如果我们不在最大值字符串内翻转一点,那么我们就没有改变最大值。同样清楚的是,我们翻转位的顺序并不重要(例如,如果我们先翻转第 7 位然后翻转第 4 位,或者从第 4 位开始然后翻转第 7 位,这无关紧要)。所以我们不妨决定从分割最大的连续块开始。

最大连续块的最大长度为n,因此我们已经找到了O(n^k) 算法。

【讨论】:

    【解决方案2】:

    f(i,len,k,state) 表示直到索引i 为止的最小序列,其中len 是当前序列长度,k 是到目前为止的翻转次数,statea[i] 的状态。

    然后:

    if a[i] == 0:
      // starting a new sequence
      f(i, 1, k, 0) = min( f(i-1, len, k, 1) for all len)
    
      // adding to a sequence (len > 1)
      f(i, len, k, 0) = max( len, f(i-1, len-1, k, 0) )
    
      // starting a new sequence
      f(i, 1, k, 1) = min( f(i-1, len, k-1, 0) for all len)
    
      // adding to a sequence (len > 1)
      f(i, len, k, 1) = max( len, f(i-1, len-1, k-1, 1) )
    
    if a[i] == 1:
      ...left as an exercise
    

    JavaScript 代码:

    function f(a,i,len,k,state){
      // We cannot change the state of a[i] if k is zero
      if (k === 0 && a[i] != state)
        return Infinity;
        
      // The first element is a sequence of length 1
      if (i === 0)
        return 1;
        
      var oppositeState = state == 0 ? 1 : 0;
      
      if (a[i] == state){
        // Starting a new sequence
        if (len === 1){
          var best = Infinity;
          
          for (var l=1; l<i+1; l++)
            best = Math.min( best, f(a, i-1, l, k, oppositeState) );
      
          return best;
          
        // Adding to a sequence (len > 1)
        } else {
          return Math.max( len, f(a, i-1, len-1, k, state) );
        }
    
      // a[i] does not equal state
      } else if (k > 0) {
        // Starting a new sequence
        if (len === 1){
          var best = Infinity;
          
          for (var l=1; l<i+1; l++)
            best = Math.min( best, f(a, i-1, l, k-1, oppositeState) );
      
          return best;
          
        // Adding to a sequence (len > 1)
        } else {
          return Math.max( len, f(a, i-1, len-1, k-1, state) );
        } 
    
      // If k is zero, we cannot change the state of a[i]
      } else {
        return Infinity;
      }
    }
    
    function g(arr,k){
      var best = Infinity;
      
      for (var l=1; l<=2*arr.length; l++)
        best = Math.min(best, f(arr, arr.length-1, Math.ceil(l/2), k, l % 2));
        
      return best;
    }
    
    console.log( g('110001111',2) ); // 2
    
    console.log( g('1001',1) ); // 2
    
    console.log( g('111111',0) ); // 6

    【讨论】:

    • 您的代码在某些情况下显示错误的结果。 111111 和 k = 0。答案应该是 6,但您的代码给出 1。
    • @KaranNagpal 不,我的代码为g('111111',0) 返回了正确的结果6。我在代码末尾添加了您的示例。
    • 请不要删除您投反对票的答案并重新发布。这样做被认为是不道德的。如果您已纠正错误,请等到您获得更多票数。
    • 对不起,我的立场是正确的。请继续。对于浪费您的时间,我深表歉意。
    • @BhargavRao 只是为了清楚一点:我确实删除并重新发布了这个答案,因为投反对票。在第二个答案被否决后(我猜是同一个人,您可能实际上可以看到),即使是讨厌的反对票,我也留下了这个答案。这是很久以前的事了。
    猜你喜欢
    • 2011-05-28
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    相关资源
    最近更新 更多