【问题标题】:Number of different binary string with k flips具有 k 次翻转的不同二进制字符串的数量
【发布时间】:2016-10-07 10:40:09
【问题描述】:

我正在尝试一个问题,给定长度为 N(

示例: 考虑 N = 3 、 1 1 1 和 X = 2 的二进制字符串 应用 2 次翻转后可以形成的新二进制字符串是 1 1 1(翻转第一个/第二个/第三个位两次) 0 0 1(翻转第一位和第二位) 1 0 0(翻转第 2 位和第 3 位) 0 1 0(翻转第 1 位和第 3 位)

【问题讨论】:

  • X翻转是指可以翻转字符串的每个字符?
  • 是的一次翻转,字符将从0变为1,反之亦然
  • 当然!!我已经添加了示例

标签: string binary combinatorics counting


【解决方案1】:

这是在 c# 中。看看有没有帮助。

static class Program
{
    static void Main(string[] args)
    {
        string bnryStr = "111111";
        int x = 4;

        //here in this string merely the poistions of the binary string numbers are placed
        //if the binary string is "1111111", this fakeStr will hold "0123456"
        string fakeStr = String.Empty;
        for (int i = 0; i < bnryStr.Length; i++)
        {
            fakeStr += i.ToString();
        }
        char[] arr = fakeStr.ToCharArray();

        // gets all combinations of the input string altered in x ways
        IEnumerable<IEnumerable<char>> result = Combinations(arr, x);

        // this holds all the combinations of positions of the binary string at which flips will be made
        List<string> places = new List<string>();
        foreach (IEnumerable<char> elements in result)
        {
            string str = string.Empty;
            foreach (var item in elements)
            {
                str += item;
            }
            places.Add(str);
        }

        List<string> results = GetFlippedCombos(bnryStr, places);
        Console.WriteLine("The number of all possible combinations are: " + results.Count);
        foreach (var item in results)
        {
            Console.WriteLine(item);
        }
        Console.Read();
    }

    /// <summary>
    /// Gets a list of flipped strings
    /// </summary>
    /// <param name="bnryStr">binary string</param>
    /// <param name="placeList">List of strings containing positions of binary string at which flips will be made</param>
    /// <returns>list of all possible combinations of flipped strings</returns>
    private static List<string> GetFlippedCombos(string bnryStr, List<string> placeList)
    {
        List<string> rtrnList = new List<string>();
        foreach (var item in placeList)
        {
            rtrnList.Add(Flip(bnryStr, item));
        }
        return rtrnList;
    }

    /// <summary>
    /// Flips all the positions (specified in 'places') of a binary string  from 1 to 0 or vice versa
    /// </summary>
    /// <param name="bnryStr">binary string</param>
    /// <param name="places">string holding the position values at which flips are made</param>
    /// <returns>a flipped string</returns>
    private static string Flip(string bnryStr, string places)
    {
        StringBuilder str = new StringBuilder(bnryStr);
        foreach (char place in places)
        {
            int i = int.Parse(place.ToString());
            char ch = str[i];
            str.Replace(ch, '0' == ch ? '1' : '0', i, 1);
        }
        return str.ToString();
    }

    /// <summary>
    /// Gets all combinations of k items from a  collection with n elements 
    /// </summary>
    /// <param name="elements">collection having n elements</param>
    /// <param name="k">no of combinations</param>
    /// <returns>all possible combinations of k items chosen from n elements</returns>
    private static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
    {
        if (k == 0)
        {
            return new[] { new T[0] };
        }
        else
        {
            IEnumerable<T> elements1 = elements as IList<T> ?? elements.ToList();
            IEnumerable<IEnumerable<T>> enumerable = elements1.SelectMany((e, i) =>
            {
                IEnumerable<T> enumerable1 = elements as IList<T> ?? elements1.ToList();
                return enumerable1.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c));
            });
            return enumerable;
        }
    }
}






Result:
Binary String: 111111
No. of Flips: 4
The number of all possible combinations are: 15
000011
000101
000110
001001
001010
001100
010001
010010
010100
011000
100001
100010
100100
101000
110000

【讨论】:

  • 你能解释一下逻辑吗,因为我没有 C# 经验。我通常用 C++ 或 Python 编写代码
  • 我添加了 cmets 以便您更轻松地理解代码。输出也添加在底部
【解决方案2】:

查找 X 翻转字符串

考虑例如N=10, X=4 且初始字符串为:

initial: 0011010111  

那么这将是一个 X 翻转字符串的示例:

flipped: 0000111111  

因为 4 位不同。如果你对这两个字符串进行异或,你会得到:

initial: 0011010111  
flipped: 0000111111  
XOR-ed:  0011101000  

异或字符串中的 4 个设置位(1)表示已翻转的 4 个位的位置。

现在反过来想。如果您有一个初始字符串和一个具有 4 个设置位的字符串,那么您可以通过对它们进行异或运算来生成一个 X 翻转字符串:

initial: 0011010111  
4 bits : 0011101000  
XOR-ed:  0000111111  

因此,如果您生成每个长度为 N 且带有 X 个设置位的二进制字符串,并将它们与初始字符串进行异或,您将得到所有 X 翻转的字符串。

initial     4 bits      XOR-ed  
0011010111  0000001111  0011011000
            0000010111  0011000000
            0000100111  0011110000
            ...
            1110010000  1101000111
            1110100000  1101110111
            1111000000  1100010111

可以生成所有具有 X 组位的 N 长度字符串,例如与Gosper's Hack。在下面的代码示例中,我使用了我最初为this answer 编写的反向字典顺序函数。

双翻转

如果位可以翻转两次,那么X翻转的字符串可能与初始字符串没有X位不同,而只有X-2位,因为一位被翻转,然后又翻转回原来的状态.或 X-4,如果该位被翻转 4 次,或者两个不同的位被翻转两次。事实上,不同位的数量可以是 X、X-2、X-4、​​X-6 ... 到 1 或 0(取决于 X 是奇数还是偶数)。

因此,要生成所有 X 翻转的字符串,您首先生成所有具有 X 翻转位的字符串,然后生成所有具有 X-2 翻转位的字符串,然后将 X-4、X-6 ... 降至 1 或 0。

如果 X > N

如果 X 大于 N,那么显然有些位会被翻转不止一次。生成它们的方法是相同的:从 X 开始,倒数到 X-2、X-4、​​X-6 ......但只为值 ≤ N 生成字符串。所以实际上,你从 N 或 N- 开始1,取决于 XN 是偶数还是奇数。

字符串总数

具有 X 个翻转位的 N 长度字符串的数量等于具有 X 个设置位的 N 长度字符串的数量,即Binomial CoefficientN choose X。当然你还得考虑X-2, X-4, X-6 ...翻转位的字符串,所以总数是:

(N 选择 X) + (N 选择 X-2) + (N 选择 X-4) + (N 选择 X-6) + ... + (N 选择 (1 或 0))

在 X 大于 N 的情况下,您从 N choose NN choose N-1 开始,具体取决于 X-N 是偶数还是奇数。

对于 N=3 和 X=2 的示例,总数为:

(3 choose 2) + (3 choose 0) = 3 + 1 = 4  

对于上面 N=10 和 X=4 的示例,总数为:

(10 choose 4) + (10 choose 2) + (10 choose 0) = 210 + 45 + 1 = 256  

对于另一个答案中 N=6 和 X=4 的示例,正​​确的数字是:

(6 choose 4) + (6 choose 2) + (6 choose 0) = 15 + 15 + 1 = 31  

示例代码

此 JavaScript 代码 sn-p 以相反的字典顺序生成二进制字符串序列(以便设置位从左到右移动),然后打印出结果翻转字符串和上述示例的总数:

function flipBits(init, x) {
    var n = init.length, bits = [], count = 0;
    if (x > n) x = n - (x - n) % 2;   // reduce x if it is greater than n
    for (; x >= 0; x -= 2) {          // x, x-2, x-4, ... down to 1 or 0
        for (var i = 0; i < n; i++) bits[i] = i < x ? 1 : 0;    // x ones, then zeros
        do {++count;
            var flip = XOR(init, bits);
            document.write(init + " &oplus; " + bits + " &rarr; " + flip + "<br>");
        } while (revLexi(bits));
    }
    return count;
    function XOR(a, b) {              // XOR's two binary arrays (because JavaScript)
        var c = [];
        for (var i = 0; i < a.length; i++) c[i] = a[i] ^ b[i];
        return c;
    }
    function revLexi(seq) {           // next string in reverse lexicographical order
        var max = true, pos = seq.length, set = 1;
        while (pos-- && (max || !seq[pos])) if (seq[pos]) ++set; else max = false;
        if (pos < 0) return false;
        seq[pos] = 0;
        while (++pos < seq.length) seq[pos] = set-- > 0 ? 1 : 0;
        return true;
    }
}
document.write(flipBits([1,1,1], 2) + "<br>");
document.write(flipBits([0,0,1,1,0,1,0,1,1,1], 4) + "<br>");
document.write(flipBits([1,1,1,1,1,1], 4) + "<br>");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 2010-09-25
    相关资源
    最近更新 更多