考虑这个数组:
[
["B", "C", "C", "C", "C", "B", "B", "C", "A", "A"],
["B", "A", "C", "B", "B", "A", "B", "B", "A", "A"],
["B", "C", "B", "C", "A", "A", "A", "B", "C", "B"],
["B", "B", "B", "A", "C", "B", "A", "C", "B", "A"],
["A", "A", "A", "C", "A", "C", "C", "B", "A", "C"],
["A", "B", "B", "A", "A", "C", "B", "C", "C", "C"],
["C", "B", "A", "A", "C", "B", "B", "C", "A", "A"]
]
我正在尝试获取此2D阵列中面积最大的矩形的宽度和高度。答案应该是8 * 4 = 32(坐标(1,1),(1,8),(4,1)和(4,8)),因为它具有相同角落的最大区域{{1} }。
答案 0 :(得分:3)
只是因为很有趣:
var l = [
["B", "C", "C", "C", "C", "B", "B", "C", "A", "A"],
["B", "A", "C", "B", "B", "A", "B", "B", "A", "A"],
["B", "C", "B", "C", "A", "A", "A", "B", "C", "B"],
["B", "B", "B", "A", "C", "B", "A", "C", "B", "A"],
["A", "A", "A", "C", "A", "C", "C", "B", "A", "C"],
["A", "B", "B", "A", "A", "C", "B", "C", "C", "C"],
["C", "B", "A", "A", "C", "B", "B", "C", "A", "A"]];
var squares = [];
//for each position
for (var column=0; column< l[0].length; column++)
for (var row=0; row< l.length ; row++ )
//look for all scuares from this position:
for (var next_column = column+1; next_column < l[0].length; next_column++ )
if ( l[row][next_column] == l[row][column] )
for (var next_row = row+1; next_row < l.length; next_row++)
//if it is a square
if (l[next_row][column] == l[row][column] &&
l[next_row][next_column] == l[row][column])
//annotate square
squares.push( [ column, row, next_column, next_row ] );
//get areas from squares
var area_l = squares.map(function(an_square) {
return (an_square[2]-an_square[0]+1)*(an_square[3]-an_square[1]+1);
});
//search for big area
var max_area_index = area_l.indexOf(Math.max( ...area_l ));
//here it is
console.log( squares[max_area_index] );
结果:数组(4)[1,1,8,4]
答案 1 :(得分:1)
如果我们考虑:
小矩形具有相同的概率具有与大矩形相同的4个角
一个点可以是与任何其他点一样多的矩形的角落,无论其位置如何(N = (width-1)*(height-1)
)
所以我们确认了直观的算法:我们希望首先寻找更大的矩形,它们更有可能在两侧而不是在中心有角,并在我们找到它们时快速停止
此解决方案计算大矩形的形状以便查找它们。
困难的部分是按区域排序矩形并不像缩小方块或圆圈那么容易。区域12的矩形可以具有[1,12],[2,6],[3,4],[4,3],[6,2]或[12,1]的形状,而区域11的矩形只能是具有[1,11]或[11,1]的形状。
function getGreatestRectangleStrict () {
let hMax = tab.length - 1,
wMax = tab[0].length - 1;
// Search valid rectangle by decreasing area
for (let area = (hMax+1)*(wMax+1); area >= 0; --area) {
// Compute rectangle shapes that fit in tab with given area
let kMax = Math.min(area, hMax + 1);
for (let k = 1; k <= kMax ; ++k)
if (area % k === 0) {
let height = k - 1,
width = area / k - 1;
if ( width <= wMax ) {
// New fitting shape found, test rectangles
for (let top = 0; top <= hMax - height; ++top)
for (let left = 0; left <= wMax - width; ++left) {
let bottom = top + height,
right = left + width,
a = tab[top][left];
if ( a === tab[bottom][left] &&
a === tab[bottom][right] &&
a === tab[top][right])
// Valid rectangle: stop search
return [top, left, bottom, right];
}
}
}
}
}
它在小型阵列上表现很好,但在大型阵列上表现不佳。我认为需要一种启发式方法来快速找到形状,并在找到解决方案时仍然停止。
此解决方案会查找矩形,并在找到一些大矩形时加速。
function getGreatestRectangleMixed () {
let greatestArea = 0;
let greatestRectangle = [];
// Get horizontal pairs of corners of same color
// and their vertical positions (y)
let pairs = {};
for (let k = 0; k < tab.length; ++k) {
// Heuristic: alternately search top and bottom
let y = ( !(k % 2) ? k/2 : tab.length - (k+1)/2);
let line = tab[y];
if ( line.length * Math.max(tab.length-y,y+1) < greatestArea )
break; // Heuristic: height too small
for (let i = 0; i < line.length - 1; ++i) {
let color = line[i];
for (let j = line.length - 1; j > i; --j) {
if ( (j-i+1) * tab.length < greatestArea )
break; // Heuristic: width too small
if (line[i] === line[j]) {
// Pair of corners found
let pairKey = i+" "+j;
let cornerPair = {
corners: [i,j],
width: j-i+1,
y: y
};
if (! (color in pairs) )
pairs[color] = {};
if (! (pairKey in pairs[color]) )
// New pair of corners found, keep only first one
pairs[color][pairKey] = cornerPair;
else {
// Rectangle found, check area
let isCurrentBottom = pairs[color][pairKey].y < cornerPair.y;
let top = (isCurrentBottom ? pairs[color][pairKey] : cornerPair);
let bottom = (isCurrentBottom ? cornerPair : pairs[color][pairKey]);
let area = top.width * (bottom.y - top.y + 1);
if (area > greatestArea) {
greatestArea = area;
greatestRectangle = [
[top.corners[0], top.y],
[top.corners[1], top.y],
[bottom.corners[0], bottom.y],
[bottom.corners[1], bottom.y]
];
}
}
}
}
}
}
return greatestRectangle;
}
这个解决方案在OP大小的矩形上比前一个慢一点,但是对于更大的矩形更稳定。
答案 2 :(得分:0)
您可以在依赖数组中获得所有相同的字母位置,并迭代数组以找到最右和最低位置。然后检查另外两个点是否具有所需值。
如果是这样,将找到的rectangel推到临时结果集。稍后对该数组进行排序或直接选择最大区域。
var array = [["B", "C", "C", "C", "C", "B", "B", "C", "A", "A"], ["B", "A", "C", "B", "B", "A", "B", "B", "A", "A"], ["B", "C", "B", "C", "A", "A", "A", "B", "C", "B"], ["B", "B", "B", "A", "C", "B", "A", "C", "B", "A"], ["A", "A", "A", "C", "A", "C", "C", "B", "A", "C"], ["A", "B", "B", "A", "A", "C", "B", "C", "C", "C"], ["C", "B", "A", "A", "C", "B", "B", "C", "A", "A"]],
points = {},
rectangles = [],
count=0;
array.forEach((a, i) => a.forEach((b, j) => (points[b] = points[b] || []).push({ j, i })));
Object
.keys(points)
.forEach(k => {
points[k].slice(0,-1).forEach((p, m) => {
var n = points[k].length,
q;
while (n--) {
q = points[k][n];
if (p.i < q.i && p.j < q.j && k === array[p.i][q.j] && k === array[q.i][p.j]) {
rectangles.push({ key: k, top: p.i, left: p.j, bottom: q.i, right: q.j, size: (q.i - p.i + 1) * (q.j - p.j + 1) });
}
}
});
});
rectangles.sort((a, b) => b.size - a.size);
console.log(rectangles);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;