1. 程式人生 > >[程式設計師程式碼面試指南] 求最大子矩陣的大小

[程式設計師程式碼面試指南] 求最大子矩陣的大小

[程式設計師程式碼面試指南] 求最大子矩陣的大小

題目描述:

給定一個整型的矩陣,其中只有0和1兩種值.

求其中 最大的全是1 的 矩形 區域的大小

如:
	1 1 1 0
	最大區域為 3
再如:
	1 0 1 1 
	1 1 1 1
	1 1 1 0
	最大矩陣區域為 6

分析:

  1. 將矩陣看做一行一行的.求每一行為底的,每個位置往上 1 的個數.用高度陣列 height 表示.

    这里写图片描述

  2. 對於每一次切割獲得的 height 陣列,求其中每一個柱子,求能向左以及向右擴充套件到第一個比它小的地方.

使用棧來實現第二點:

從左到右遍歷陣列height,遍歷到i元素:

  • i 位置的值大於棧頂位置所代表的值,直接將 i 入棧

    那麼,這個棧保持的就是 遞增 的.

  • 若當前元素 小於或者等於 當前元素 棧頂 位置所代表的值,

    那麼就是要不斷地出棧,直至棧頂元素所代表的值小於 i 表示的值.再把 i入棧.

    在彈出的過程中,

    假設當前彈出的棧頂位置為 j. 彈出之後,棧頂為 k

    1. 對於柱子 j 向右最遠能擴到 i-1 .

      若所有元素入棧之後,那麼棧不為空,則向右最遠可以到 height.size ;

    2. 對於柱子 j ,向左最遠可以擴充套件到 k+1 . (為什麼是 k+1 呢,因為 k 位置肯定比j 位置的小,入棧時候的規則,保證了這個棧是遞增的)

      若棧此時為空,那麼它可以最遠擴充套件到0.

實現:

int maxRecSize(vector<vector<int>> map) {
	// 異常處理
	if (map.size() == 0) {
		return 0;
	}
	if (map[0].size() == 0) {
		return 0;
	}

	int rows = map.size();
	int cols = map[0].size();

	vector<int> height(cols, 0);

	int res = 0;
	// 更新每一層為底的最大矩陣大小
	for (int i = 0; i < rows; ++i) {
		for (int j = 0; j < cols; ++j) {
			// 更新height陣列
			height[j] = map[i][j] == 0 ? 0 : height[j] + 1;
		}
		res = max(res, maxRecFromBottom(height));
	}
	return res;

}

// 考察每一根柱子最大能擴散到哪裡,找到柱子左邊比它小的位置,以及找到右邊比他小的位置.
int maxRecFromBottom(vector<int> height) {
	int res = 0;
	stack<int> m_stack; // 存放的是索引
	for (int i = 0; i < height.size(); i++) {
		while (!m_stack.empty() && height[i] <= height[m_stack.top]) {
			int j = m_stack.top(); m_stack.pop();
			int k = m_stack.empty() ? -1 : m_stack.top(); // 若為空,表示向左最遠可以到0位置
			int curArea = height[j] * ((i - 1) - (k + 1) + 1);
			// 其是 height[j] * (i-k-1);
			res = max(res, curArea);
		}
		m_stack.push(i);
	}

	while (!m_stack.empty()) { // 若棧不為空,表示向右最遠可以到height.size()的位置
		int j = m_stack.top(); m_stack.pop();
		int k = m_stack.empty() ? -1 : m_stack.top(); 
		int curArea = height[j] * ((height.size() - 1) - (k + 1) + 1);
		// 其是 height[j] * (i-k-1);
		res = max(res, curArea);
	}

	return res;
}

體會:

  • 經常用來儲存保證一個遞增或者遞減的性質,然後不滿足性質,就通過出棧來更新要輸出的資訊.
  • 切割陣列的方法,將二維矩陣看做一層層的.

參考文件

求最大子矩陣的大小+棧