01矩陣中最大子矩陣

問題:一個矩陣只含有0 1兩種元素,求只包含1的最大子矩陣大小(大小用包含的1的個數表示)
假設矩陣大小爲N x M, 要求時間複雜度爲O(N x M)
例如給定如下矩陣:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 6

1 1 1 1 1
1 0 0 1 0
Return 5

1 0 1 0 0
1 0 1 1 1
Return 3

這個問題和求直方圖最大矩陣面積類似。將矩陣從第一行開始,把每列的元素加起來,存在arr數組中,新加入的元素如果爲0直接爲0,把得到的數組求直方圖最大矩陣面積。
例:用數組arr來記錄
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
第一行對應arr爲1 0 1 0 0求得最大直方圖最大矩陣面積爲1。
加上第二行arr變爲2 0 2 1 1 求得最大直方圖最大矩陣面積爲3。
加上第三行變爲3 1 2 2 2 求得最大直方圖最大矩陣面積爲6。
加上第四行變爲4 1 0 3 0 求得最大直方圖最大矩陣面積爲4。
最終結果爲6

//直方圖面積
int maxarea(vector<int>&obj){
	stack<list<int>>help;
	int ret = 0;
	for (int i = 0; i < obj.size(); i++){
		while (!help.empty() && obj[i] < obj[help.top().back()]){
			int temp = help.top().front();
			help.pop();
			int left = help.empty() ? -1 : help.top().back();
			int ret_temp = obj[temp] * (i - left - 1);
			ret = ret>ret_temp ? ret : ret_temp;
		}
		if (!help.empty()&&obj[i] < obj[help.top().back()])
			help.top().push_back(i);
		else{
			list<int>l;
			l.push_back(i);
			help.push(l);
		}
	}
	while (!help.empty()){
		int temp = help.top().front();
		help.pop();
		int left = help.empty() ? -1 : help.top().back();
		int ret_temp = obj[temp] * (obj.size() - left - 1);
		ret = ret>ret_temp ? ret : ret_temp;
	}
	return ret;
}
//arr的變化
vector<int>& getarr(vector<int>&help, vector<vector<int>>&obj, int i){
	for (int j = 0; j < obj[0].size(); j++){
		help[j] = obj[i][j] == 0 ? 0 : help[j] + obj[i][j];
	}
	return help;
}
//求最大子矩陣
int maxrec(vector<vector<int>>&obj){
	vector<int>help(obj[0].size(),0);
	int ret = 0;
	for (int i = 0; i < obj.size(); i++){
	//arr的變化
		getarr(help, obj, i);
		//求直方圖面積
		int temp = maxarea(help);
		ret = ret>temp ? ret : temp;
	}
	return ret;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章