1.4.19

1.4.19 #

解答 #

问题类似于 POJ 上的一道题「滑雪」,从数值较高的一侧向周围数值较小的一侧移动,直到到达「山谷」(局部最小)。

首先在中间行搜索最小值,再将最小值与其上下两个元素比较,如果不满足题意,则“滑向”较小的一侧,矩阵被分为了两半(上下两侧)。

在较小的一侧,找到中间列的最小值,再将最小值与其左右两个元素比较,如果不满足题意,类似的移动到较小的一侧(左右两侧)。

现在查找范围缩小到了原来矩阵的四分之一,递归的进行上述操作,最后可以得到答案。

每次查找最小值都是对行/列进行遍历,遍历耗时和 N 成正比。

代码 #

// 先查找 N/2 行中的最小元素,并令其与上下元素比较,
// 如果不满足题意,则向相邻的最小元素靠近再次查找
var matrix = new[,]
{
    { 26, 3, 4, 10, 11 },
    { 5, 1, 6, 12, 13 },
    { 7, 8, 9, 14, 15 },
    { 16, 17, 18, 27, 20 },
    { 21, 22, 23, 24, 25 }
};

Console.WriteLine(MinimumRow(matrix, 0, 5, 0, 5));

static int MinimumRow(int[,] matrix, int rowStart, int rowLength, int colStart, int colLength)
{
    var min = int.MaxValue;
    if (rowLength < 3)
        return int.MaxValue;
    var mid = rowStart + rowLength / 2;
    var minCol = 0;
    // 获取矩阵中间行的最小值
    for (var i = 0; i < colLength; i++)
    {
        if (min > matrix[mid, colStart + i])
        {
            min = matrix[mid, colStart + i];
            minCol = i;
        }
    }

    // 检查是否满足条件
    if (matrix[mid, minCol] < matrix[mid - 1, minCol] && matrix[mid, minCol] < matrix[mid + 1, minCol])
    {
        return matrix[mid, minCol];
    }

    // 如果不满足则向较小一侧移动
    if (matrix[mid - 1, minCol] > matrix[mid + 1, minCol])
    {
        return MinimumCol(matrix, rowStart, rowLength, mid + 1, colLength / 2 + 1);
    }

    return MinimumCol(matrix, rowStart, rowLength, colStart, colLength / 2 + 1);
}

static int MinimumCol(int[,] matrix, int rowStart, int rowLength, int colStart, int colLength)
{
    var min = int.MaxValue;
    var n = matrix.GetLength(0);
    var mid = n / 2;
    var minRow = 0;

    // 获取矩阵中间列最小值
    for (var i = 0; i < n; i++)
    {
        if (min > matrix[i, mid])
        {
            min = matrix[i, mid];
            minRow = i;
        }
    }

    // 检查是否满足条件
    if (matrix[minRow, mid] < matrix[minRow, mid - 1] && matrix[minRow, mid] < matrix[minRow, mid + 1])
    {
        return matrix[minRow, mid];
    }

    // 如果不满足则向较小一侧移动
    if (matrix[minRow, mid - 1] > matrix[minRow, mid + 1])
    {
        return MinimumRow(matrix, mid + 1, rowLength / 2 + 1, colStart, colLength);
    }

    return MinimumRow(matrix, rowStart, rowLength / 2 + 1, colStart, colLength);
}

另请参阅 #

POJ-滑雪