当前位置: 首页 > 知识库问答 >
问题:

被动扩展:获取二进制数的“光圈”

孔运珧
2023-03-14

一个朋友提出了这个挑战。只是为了训练,我试图使用反应式扩展来解决它,但我没有运气。这并不奇怪,因为我还是Rx的新手。

这就是问题所在:

正整数N内的孔径是其二进制表示中的任意连续零的最大序列,其两端被1包围。

例如,数字9具有二进制表示1001,并且包含长度为2的光圈。数字529具有二进制表示100001001,包含两个光圈:一个是长度4,一个是长度3。数字20具有二进制表示10100,包含一个长度为1的光圈。数字15有二进制表示1111,没有光圈。编写一个函数:类Aperture{public int Aperture(int N);}给定正整数N,返回其最长光圈的长度。如果N不包含光圈,则函数应返回0。  假设:N是[1..2147483647]复杂度范围内的整数:算法时间复杂度为O(log(N));

算法空间复杂度为O(1)(最坏情况——不计算输入参数)

为了简化,我尝试将其应用于“100001001”之类的字符串,而不是二进制表示。

不管怎样,我不介意复杂的部分,只是我想知道一种“优雅”的方法来做这件事。

共有3个答案

奚正谊
2023-03-14

我同意用Rx来做这件事是愚蠢的。使用LINQ解决这个问题同样愚蠢,但既然它是Rx的老大哥,你也可以这么做。

正如詹姆斯·沃尔德的回答一样,这只是出于娱乐目的。

public int Aperture(int input)
{
    var binaryString = Convert.ToString(input, 2);

    // The accumulator is an integer array maintaining
    // the count of '0's since the last seen '1'.
    // Whenever a '1' is encountered, a new count
    // of zero is added at the end of the array.
    // Whenever a '0' is encountered, the last
    // count is incremented by one.
    var segments = binaryString.Aggregate(
        new [] { 0 },
        (acc, c) =>
            c == '0'
            ? acc
                .Take(acc.Length - 1)
                .Concat(new [] { acc[acc.Length - 1] + 1 })
                .ToArray()
            : acc
                .Concat(new [] { 0 })
                .ToArray()
    );

    return segments
        // If last segment count is non-zero, it was not
        // closed with a '1' and we want to exclude it.
        .Take(segments.Length - 1)
        .Max();
}

[TestMethod]
public void ApertureTest()
{
    Assert.AreEqual(2, Aperture(9));   // 1001,       Segments: 0, 2, 0
    Assert.AreEqual(4, Aperture(529)); // 1000010001, Segments: 0, 4, 3, 0
    Assert.AreEqual(1, Aperture(20));  // 10100,      Segments: 0, 1, 2
    Assert.AreEqual(0, Aperture(15));  // 1111,       Segments: 0, 0, 0, 0
}

现在我觉得脏兮兮的。

融唯
2023-03-14

我不知道怎么用Rx。我的解决方案展示了一种经典方法:

private static int Aperture(int n)
{
    int max = 0;
    int index = 0;
    int lastIndex = int.MaxValue;
    while (n != 0)
    {
        int bit;
        n = Math.DivRem(n, 2, out bit);
        if (bit != 0)
        {
            int length = index - lastIndex - 1;
            if (length > max)
                max = length;
            lastIndex = index;
        }
        index++;
    }
    return max;
}

测试结果:

Aperture(9)   = 2
Aperture(529) = 4
Aperture(20)  = 1
Aperture(15)  = 0
皇甫树
2023-03-14

显然,在RX中解决这个问题没有太多意义,因为答案只能通过检查整个数字来推断——而且由于其他许多原因,它的效率非常低。。。

...但是为了你的娱乐:),这里有一个非常愚蠢的RX方式(不要在家里这样做!):

public int Aperture(int input)
{
    var cs = Convert.ToString(input,2).ToCharArray().ToObservable();     

    return cs.Publish(ps => ps.Buffer(() => ps.Where(c => c == '1')))
    .Where(x => x.LastOrDefault() == '1')
    .Select(x => x.Count - 1).StartWith(0)
    .Max().Wait();
}

Aperture(9)   = 2
Aperture(529) = 4
Aperture(20)  = 1
Aperture(15)  = 0

我不知道我为什么要这样做:)但这里有另一种方式,有点朋克。我基本上是用一个2元组作为累加器。我在一边存储0的运行计数。如果我看到一个1,我会将计数复制到结果槽,如果它高于那里的值,然后重置计数。结果槽包含末端的光圈。

public int Aperture(int input)
{    
    var cs = Convert.ToString(input,2).ToCharArray().ToObservable();

    return cs.Aggregate(
        Tuple.Create(0,0), (acc, c) => c == '0'
            ? Tuple.Create(acc.Item1 + 1, acc.Item2)
            : Tuple.Create(0, Math.Max(acc.Item1, acc.Item2)
        )).Wait().Item2;
}

另外,只需删除ToCharArray()。ToObservable()和上面的Wait(),您就有了一个IEnumerable

 类似资料:
  • 问题内容: 我正在尝试从Firefox扩展程序中下载一些二进制数据。当我尝试将创建的XMLHttpRequest设置为arraybuffer模式时: 错误 被抛出。 还有另一种在Firefox扩展中下载二进制数据的方法吗? 问题答案: 您必须先调用该方法。

  • 要安装 Ceph 及其依赖软件,你需要参考本手册从 Ceph 软件库下载,然后继续看安装 Ceph 对象存储。 获取软件包 有两种方法获取软件包: 增加源: 增加源是获取二进制包的最简方法,因为多数情况下包管理工具都能自动下载、并解决依赖关系。然而,这种方法要求各 Ceph 节点都能连接互联网。 手动下载: 如果你的环境不允许 Ceph 节点访问互联网,手动下载软件包安装 Ceph 也不复杂。 准

  • 问题内容: 我想在Swift中扩展Array,以在2D数组的每个数组或列中返回单个元素。到目前为止,我有: 我相信我需要在之后指定2D数组,但是我一直无法找出正确的方法。 在?之后指定2D数组的正确语法是什么? 我也很好奇,如果有很好的文档说明如何指定扩展后的可用内容。我在Apple的Swift扩展文档中找不到 提前致谢。 问题答案: 您需要限制数组的类型。下标方法在协议中定义: 因此,您可以为元

  • var_dump(xlswriter_get_version()); ​ // 输出:string(5) "1.3.7"

  • 问题内容: 我为数据库中的存储过程生成了完整的脚本集。当我创建Mercurial存储库并添加这些文件时,它们都以二进制形式添加。显然,我仍然可以获得版本控制的好处,但是会损失很多效率,文本文件的“差异化”等。我验证了这些文件的确只是文本。 为什么这样做呢? 我应该怎么做才能避免这种情况? 有没有办法让汞改变他们对这些文件的看法? 这是变更集日志的片段: 预先感谢您的帮助吉姆 问题答案: 为了符合M

  • 我有一张时间和二进制值的表, 我想在一秒钟后检查二进制列中的值是1还是0,然后创建新值的新列。这里的时间没有继续。例如,这里的第一个值是(358.214),二进制值是1,如果我添加第二个值,它将是(359.214),基于上一个值,该值仍然是1,因为(359.214)不在数据集中。 我想添加两个新列,一个用于秒递增,一个用于新的二进制值。 我如何在R中做到这一点? 数据集, 更新我的尝试: 首先,我