【问题标题】:Kth element in a spiral traversal of a special matrix特殊矩阵的螺旋遍历中的第 K 个元素
【发布时间】:2016-11-27 13:31:26
【问题描述】:

我们得到一个方阵,它以行主要形式填充了 [1,n*n] 中的数字。当我们以螺旋顺序遍历它时,我们必须找到第 k 个元素。我能想到的唯一解决方案是进行螺旋遍历并为遍历的元素数量维护一个计数器。什么时候 计数器值变为 k,我们打印该实例的数字。

这可以在少于 O(n*n) 的时间内解决吗?如果是,那么 矩阵元素带有随机元素时如何解决同样的问题?

Link to the question

【问题讨论】:

  • 每个环的元素个数与前一个环相差8个。
  • 你可以在大约O(1)内解决这个问题;你需要找到n*n-k 的整数平方根。例如,使用巴比伦方法,您可以在 log log n*n 迭代中解决这个问题(即 O(log log n)
  • 这个问题有严格的常数时间解决方案。见这里:stackoverflow.com/questions/10094745/…

标签: algorithm matrix


【解决方案1】:

这里是O(1) 解决方案。我试图为 cmets 中的每个步骤留下解释。

// takes q as zero based number in spiral traversal on square array n*n
// and returns zero based x, y coordinates in rectangular array with center
// at left top corner
public void SpiralToRect(int n, int q, out int x, out int y)
{
    // partial sum for rings count is 4 * k * (n - k)
    // ring counts go like this: 4 * (n - 1), 4 * (n - 3), ..., 4 * (n - 2k + 1)
    // partial sum is 4 * k * n - 4 * k * k

    // consider equation partial sum on k rings = q
    int k = (int)Math.Floor((n - Math.Sqrt(n * n - q)) / 2);

    // offset of element inside the ring is q - partial sum for k
    int ringOffset = q - 4 * k * (n - k);

    // it's easy to see how len of segments for k-th ring are calculated
    int[] l = new[]
    {
        n - 2 * k, // top
        n - 2 * k - 1, // right
        n - 2 * k - 1, // bottom
        n - 2 * k - 2, // left
    };

    // notice how kth ring starts at (k, k)

    if (ringOffset < l[0]) // top row
    {
        x = k + ringOffset;
        y = k;
    }
    else if (ringOffset < l[0] + l[1]) // right col
    {
        x = k + l[0] - 1;
        y = k + ringOffset - l[0] + 1;
    }
    else if (ringOffset < l[0] + l[1] + l[2]) // bottom row
    {
        x = k + 2 * l[0] + l[1] - ringOffset - 2;
        y = k + l[1];
    }
    else // left column
    {
        x = k;
        y = k + l[0] + 2 * l[1] + l[2] - ringOffset - 1;
    }
}

对于下面的示例数组,它返回数字1, 2, ..., 35, 36

void Main()
{
    int[,] spiral = new int[,]
    {
        { 01, 02, 03, 04, 05, 06, },
        { 20, 21, 22, 23, 24, 07, },
        { 19, 32, 33, 34, 25, 08, },
        { 18, 31, 36, 35, 26, 09, },
        { 17, 30, 29, 28, 27, 10, },
        { 16, 15, 14, 13, 12, 11, },
    };

    for (int q = 0; q < 36; q++)
    {
        int x, y;
        SpiralToRect(6, q, out x, out y);

        spiral[y, x].Dump();
    }
}

【讨论】:

    【解决方案2】:

    第一个圈子有4(n - 1)个节点,

    第二个圈有4(n - 2)节点,

    ...

    最后一个圆圈有1 个节点。

    第 1 步:找到您找到的元素是哪个圆圈。 O(n) 第二步:使用遍历的方法来确定这个元素。 O(4n)

    最后,O(n)

    【讨论】:

    • 第二个圆圈有 4(n-3) 个节点(不是 4(n-2))。剥离第一个圆圈后,您将得到一个 (n-2)X(n-2) 大小的子矩阵。所以,这个圆上的元素数将是 4*(n-3)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    • 2012-04-23
    • 2013-02-17
    • 1970-01-01
    • 2014-02-02
    相关资源
    最近更新 更多