【问题标题】:minimum flips to get a binary string af all ones最小翻转以获得所有二进制字符串
【发布时间】:2022-01-04 16:52:23
【问题描述】:

问题:给定一个二进制字符串(仅包含“1”或“0”),求获得所有“1”的二进制字符串所需的最少翻转次数。

执行翻转时,该索引处的值将从“0”变为“1”或从“1”变为“0”。 您可以进行的唯一翻转是双打或三打。这意味着当执行翻转时,必须在两个或三个相邻索引上执行。 示例:

对于二进制字符串“1010”,所需的最小翻转次数为 2。“1010”=>“1001”=>“1111”(结束) 对于“10001”,所需的最小翻转次数为 1。“10001”=>“11111”(结束)

这个问题已经在 StackOverflow 上的一篇文章中讨论过了。但逻辑并没有得到适当的讨论。这是那里存在的唯一解决方案,并且解释不足以正确理解它。有人可以解释解决方案背后的逻辑吗 或任何其他解决此问题的方法。

    def minFlips(s):
     if "0" not in s:      return 0  # all 1s, no flip needed
     if s in ("00","000"): return 1  # last flip for whole string
     
     def flip(n): # flip 1st n bits
          return s[:n].translate({48:49,49:48})+s[n:]
     
     result = [float('inf')] # track minimum flips
     if s.startswith("0"):   # must flip if starting with a zero
         if len(s)>2:        # first 2 + recursion
             result.append(1+minFlips(flip(2)[1:])) 
         if len(s)>3:        # first 3 + recursion
             result.append(1+minFlips(flip(3)[1:])) 
     else: # starts with "1"
         result.append(minFlips(s[1:])) # 0 flip + recursion
         if "0" in s[:2]: # can flip zero at 2nd position
             result.append(1+minFlips(flip(2))) # first 2 + recursion
         if "0" in s[:3]: # can flip zero at 2nd or 3rd position
             result.append(1+minFlips(flip(3))) # first 3 + recursion
     return min(result)

print(minFlips("1010"))       # 2
print(minFlips("10001"))      # 1
print(minFlips("1010110101")) # 4

有人可以帮我简化一下吗? 非常感谢

【问题讨论】:

  • 这似乎不是java代码而是python代码
  • 为什么这个标签是java?也许您应该通过实际标记您想要帮助的适当语言来使您期望帮助的人更容易。
  • @OHGODSPIDERS 我对 python 不是很熟悉,这就是为什么我认为有人可以用 Java 或 c++ 回答它,这对我来说更容易理解。
  • 能否提供您找到此代码的链接?

标签: java algorithm recursion greedy


【解决方案1】:

算法:

结果与翻转的顺序无关。
此外,执行 3 次翻转相当于 1 次翻转。

因此,我们可以从头开始,迭代地执行操作。
如果一个元素等于0,那么这个元素和下一个元素必须翻转。
但是,我们可以选择索引i + 2的元素:可以翻转或不翻转。

因此,根据我们可以推迟的决定,最后一个元素处于不确定状态 X01

如果在索引i,我们遇到X,则不需要翻转。

此过程不能应用于最后一个元素(索引n-1)。 对于最后一个元素,如果前一个元素(索引 n-2)处于状态 X,则只需要额外的 1 次翻转。
但是,如果不是这种情况(然后在状态1),则需要两次额外的翻转。 (110 -> 111 需要 2 次翻转)。

复杂度:O(n),比蛮力更快。

代码:

#include <iostream>
#include <vector>
#include <string>

//  3-state (soft) inversion
// 0 -> 1
//  1 -> 0
/// x -> X

char soft_invers (char c) {
    switch (c) {
        case ('0'): return '1';
        case ('1'): return '0';
        
        default: return 'X';
    }
    return 'X';
}

int count_flips (std::string &input) {
    int count = 0;
    int n = input.size();
    if (n == 0) return 0;
    if (n == 1) {
        if (input[0] == '1') return 0;
        return -1;
    }
    for (int i = 0; i < n-1; ++i) {
        if (input[i] == '0') {
            count++;
            input[i+1] = soft_invers(input[i+1]);
            if ((i+2) < n) input[i+2] = 'X';
        }
    }
    if (input[n-1] == '0') {
        if (input[n-2] == 'X') count++;
        else count += 2;
    }
    return count;
}

int main() {
    std::vector<std::string> input = {"1010", "10001"};
    for (std::string &s: input) {
        std::cout << s << " : ";
        auto ans = count_flips(s);
        std::cout << ans << " flips\n";
    }
    return 0;
}

【讨论】:

  • 谢谢@Damien。非常感谢您的解决方案。
  • 欢迎您。如果此答案满足您的需求(花点时间检查一下),您可以接受(如果以后发布,请接受更好的答案)。
  • 您能否举例说明为什么执行 3 次翻转等于 1 次翻转。
  • 3 次翻转:0 -&gt; 1 -&gt; 0 -&gt; 1 和 1 次翻转 0 -&gt; 1。你测试过这段代码吗?
猜你喜欢
  • 2019-12-08
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 2023-04-03
  • 2013-09-20
  • 2017-03-22
  • 2016-10-07
相关资源
最近更新 更多