如何在 C# 中翻转位?

How to flip bits in C#?

我有一个字符串形式的二进制数作为

string input = "10110101101";

现在我需要翻转(0 to 11 to 0)它的 前 3 位

结果输出将是 01010101101

如何在 C# 中执行此操作?

解决方法很简单;只需将值与 1 进行异或(0 也可以)。

步数:

  1. 对于前 x 个字符,与 1 进行异或并得到 return 值(简单的 for 循环)。
  2. 用新字符串替换旧字符串。

从字符串中提取 StringBuilder,翻转前三个字符,然后将 StringBuilder 转换回 string:

var sb = new StringBuilder(input);
Debug.Assert(sb.Length >= 3);
for (int i = 0 ; i != 3 ; i++) {
    sb[i] = sb[i] == '0' ? '1' : '0';
}
var res = sb.ToString();

有多种 "smart" 方法可以无条件地翻转字符,但考虑到数字在一个 string 中,让翻转更智能不会给你带来太多 CPU 循环.

Demo.

这个有效:

string input = "10110101101";

string output =
    new string(
        input
            .Take(3)
            .Select(c => c == '0' ? '1' : '0')
            .Concat(input.Skip(3))
            .ToArray());

它给出了结果:

01010101101

另一种方法是这样做:

string input = "10110101101";
string flips = "11100000000";

int value = Convert.ToInt32(input, 2) ^ Convert.ToInt32(flips, 2);

string output = Convert.ToString(value, 2).PadLeft(input.Length, '0');

假设给定一个大小为 N 的数组 a。数组的元素是 a[0], a[1], ... a[N - 1],其中每个 a 是 01。您可以对数组执行一种转换:选择任意两个整数 LR,然后翻转第 L 位和第 R 位之间(包括在内)的所有元素。换句话说,L 和 R 代表 left-most 和 right-most 索引,它们划分了您将决定翻转其位的段的边界。 ('Flipping' 有点意思,0 转换为 11 转换为 0。) 你在最后的bit-string中最多可以获得多少个'1'位(用S表示)? 输入格式: 第一行有一个整数N 接下来的 N 行包含数组中的 N 个元素,a[0], a[1], ... a[N - 1],每行一个。

例如考虑

1 ≤ N ≤ 100,000. 

d can be either 0 or 1. It cannot be any other integer.
0 ≤ L ≤ R < N
Sample Input:
810010010
Sample Output:
6
Explanation:
We can get a maximum of 6 ones in the given binary array by performing either of the following operations:
Flip [1, 5] ⇒ 1 1 1 0 1 1 1 0
or 
Flip [1, 7] ⇒ 1 1 1 0 1 1 0 1

解法: bits 数组将只包含 0 和 1。所以我们可以将 0 视为 -1,那么任务就是找到 subArray 的最小总和(以位为单位),它是具有最大值的 subArray (0 的数量- 1 的数量)。 我们可以使用与查找最大和子数组相同的方法来查找最小和子数组。在那之前, 我们需要先遍历位来得到原来的 1 的个数。假设最小总和为 minRes 并且 1s的原始数量是currentOne。那么minRes应该是负数,所以returncurrentOne-minRes。 边缘案例: 所有边缘情况都可以使用上述方法处理。如果所有元素都是 0,那么我们将所有 -1 加在一起。 如果所有元素都是 1,那么 minRes 应该是 0,这意味着我们不翻转任何位。 时间:O(n)Space:O(1)

using System;
using System.Linq;

public class Test
{
    public static int FlippingBits(int[] bits){
        int currentOne = 0; //original number of 1s in bits
        foreach(int i in bits){
            if(i==1)
                currentOne++;
        }
        int minRes = MinSubArray(bits); //minRes is negative number
        return currentOne-minRes;
    }

    //find the min sum of subArray in bits
    private static int MinSubArray(int[] bits){
        int minRes = 0, minHere=0;
        foreach(int i in bits){
            if(i==0)
                minHere-=1;
            else
                minHere+=1;
            minHere = Math.Min(minHere,0); //keep minHere<=0
            minRes = Math.Min(minHere, minRes);
        }
        return minRes; //-minRes is the number of 1 can be added to the array after flipping
    }

    public static void Main()
    {
        int num = int.Parse(Console.ReadLine());
        for(int i=0;i<num;i++){
            string[] input = Console.ReadLine().Split();
            int[] bits = input.Select(y=>int.Parse(y)).ToArray();
            Console.WriteLine(FlippingBits(bits));
        }
    }
}

使用 Convert.ToInt32Convert.ToString(否则未知且未使用)和 bitwise-XOR

的替代方法
string input = "10110101101";
int flipNo = 3;
int output = Convert.ToInt32(input, 2);
for (int i = input.Length - 1; i >= input.Length - flipNo; --i)
    output ^= 1 << i;

只需使用output,或者如果你想在string中显示output,你可以这样做:

string display = Convert.ToString(output, 2).PadLeft(input.Length, '0');