给定一个正整数和负整数组成的N*N矩阵,编写代码找出元素总和最大的子矩阵。

    题目:《程序员面试金典(第5版)》P348

    给定一个正整数和负整数组成的N*N矩阵,编写代码找出元素总和最大的子矩阵。

    提示:按照书本P350的优化后的解法,借鉴了“连续子数组的最大和” 的思想,时间复杂度为O(n^3)。

//结构result是函数MaxSubMatrix()返回的数据类型
struct result
{
	int rows;//子矩阵的行数
	int cols;//子矩阵的列数
	int x;//子矩阵左上角的点的行数
	int y;//子矩阵左上角的点的列数
	result(){ rows = 0; cols = 0; x = -1; y = -1; }
};

//求数组a的最大连续子数组和,res_start返回最大连续子数组的开头位置,res_end返回结尾位置,res_sum返回最大的和
void MaxSubArraySum(vector a, int &res_start, int &res_end, int &res_sum)
{
	res_start = 0;
	res_end = a.size();
	res_sum = a[0];
	int sum = a[0];
	int biggest = a[0];
	for (int i = 1; i < a.size(); i++)
	{
		if (sum <= 0)
		{
			sum = a[i];
			if (biggest < sum)
			{
				res_start = i;
				res_end = i;
				biggest = sum;
			}
		}
		else
		{
			sum += a[i];
			if (biggest < sum)
			{
				res_end = i;
				biggest = sum;
			}
		}
	}
	res_sum = biggest;
}

//输入的矩阵m是N*N的方阵
result MaxSubMatrix(vector> m)
{
	result res;
	if (m.empty() || m[0].empty() || m.size() != m[0].size())
		return res;

	int N = m.size();
	int biggestsum = m[0][0];
	res.cols = 1; res.rows = 1; res.x = 0; res.y = 0;

	for (int rowstart = 0; rowstart < N; rowstart++)
	{
		for (int rowend = rowstart; rowend < N; rowend++)
		{
			vector tmp;
			int cola, colb, cursum, SumOfCols = 0;
			for (int coltmp = 0; coltmp < N; coltmp++)
			{
				SumOfCols = 0;
				for (int j = rowstart; j <= rowend; j++)
				{
					SumOfCols += m[j][coltmp];
				}
				tmp.push_back(SumOfCols);
			}
			MaxSubArraySum(tmp,cola, colb, cursum);
			if (cursum > biggestsum)
			{
				biggestsum = cursum;
				res.rows = rowend - rowstart + 1;
				res.cols = colb - cola + 1;
				res.x = rowstart;
				res.y = cola;
			}
		}
	}
	return res;
}


你可能感兴趣的:(程序员面试题)