В этом уроке ты:
- Узнаешь, как применять технику накопительных массивов в двумерных массивах.
- Освоишь построение массивов сумм для строк, столбцов и диагоналей.
- Решишь оптимально задачу уровня собеседования из крупной технологической компании.
Задача с собеседования
Время перейти на новый уровень сложности! Эта задача может занять до 30 минут на реальном интервью, и многим кандидатам не удаётся найти решение вовремя.
Условие
Дан двумерный массив целых чисел . Нужно найти максимальную сумму клеток, которые находятся под боем шахматного ферзя, включая клетку, на которой он стоит.board
Пример 1
Ввод: board = [[3, 2, 5, 1], [4, 9, 1, 3], [2, 9, 2, 1]] Вывод: 40 Объяснение: максимальная сумма 40 получается, если поставить ферзя на клетку [1, 1] (индексация с 0).
Пример 2
Ввод: board = [[1, 2, 3]] Вывод: 6
В чем сложность задачи?
Наивное решение выглядит так:
- Поставить ферзя в каждую клетку поля.
- Для каждой позиции подсчитать сумму всех клеток, которые он бьёт.
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public static int MaxQueenSum(List<List<int>> board)
{
int n = board.Count;
int m = board[0].Count;
int maxSum = 0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
int currSum = 0;
// Прибавляем сумму всех элементов в строке i
currSum += board[i].Sum();
// Прибавляем сумму всех элементов в колонке j
for (int k = 0; k < n; ++k)
{
currSum += board[k][j];
}
// Прибавляем сумму всех элементов в главной диагонали
for (int k = -Math.Min(i, j); k < Math.Min(n - i, m - j); ++k)
{
currSum += board[i + k][j + k];
}
// Прибавляем сумму всех элементов в побочной диагонали
for (int k = -Math.Min(i, m - j - 1); k < Math.Min(n - i, j + 1); ++k)
{
currSum += board[i + k][j - k];
}
// Элемент board[i][j] просуммирован 4 раза в предыдущих циклах
// Вычитаем лишние разы
currSum -= 3 * board[i][j];
// Обновляем ответ
if (i == 0 && j == 0)
{
maxSum = currSum; // Инициализируем maxSum, если это первая итерация
}
maxSum = Math.Max(maxSum, currSum);
}
}
return maxSum;
}
}
#include <vector>
#include <algorithm>
using namespace std;
int maxQueenSum(const vector<vector<int>>& board) {
int n = board.size();
int m = board[0].size();
int maxSum = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int currSum = 0;
// Прибавляем сумму всех элементов в строке i
currSum += accumulate(board[i].begin(), board[i].end(), 0);
// Прибавляем сумму всех элементов в колонке j
for (int k = 0; k < n; ++k) {
currSum += board[k][j];
}
// Прибавляем сумму всех элементов в главной диагонали
for (int k = -min(i, j); k < min(n - i, m - j); ++k) {
currSum += board[i + k][j + k];
}
// Прибавляем сумму всех элементов в побочной диагонали
for (int k = -min(i, m - j - 1); k < min(n - i, j + 1); ++k) {
currSum += board[i + k][j - k];
}
// Элемент board[i][j] просуммирован 4 раза в предыдущих циклах
// Вычитаем лишние разы
currSum -= 3 * board[i][j];
// Обновляем ответ
if (i == 0 && j == 0) {
maxSum = currSum; // Инициализируем max_sum, если это первая итерация
}
maxSum = max(maxSum, currSum);
}
}
return maxSum;
}
package main
import "math"
func maxQueenSum(board [][]int) int {
n := len(board)
m := len(board[0])
maxSum := math.MinInt // Инициализируем переменную минимально возможным значением
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
currSum := 0
// Прибавляем сумму всех элементов в строке i
for _, val := range board[i] {
currSum += val
}
// Прибавляем сумму всех элементов в колонке j
for k := 0; k < n; k++ {
currSum += board[k][j]
}
// Прибавляем сумму всех элементов в главной диагонали
for k := -min(i, j); k < min(n-i, m-j); k++ {
currSum += board[i+k][j+k]
}
// Прибавляем сумму всех элементов в побочной диагонали
for k := -min(i, m-j-1); k < min(n-i, j+1); k++ {
currSum += board[i+k][j-k]
}
// Элемент board[i][j] мы просуммировали 4 раза в предыдущих циклах
// Вычитаем лишние разы
currSum -= 3 * board[i][j]
// Обновляем ответ в любом случае, если это первая итерация
if i == 0 && j == 0 {
maxSum = currSum
}
// Обновляем ответ
if currSum > maxSum {
maxSum = currSum
}
}
}
return maxSum
}
// Функция min для получения минимального значения
func min(a, b int) int {
if a < b {
return a
}
return b
}
import java.util.List;
public class Solution {
public static int maxQueenSum(List<List<Integer>> board) {
int n = board.size();
int m = board.get(0).size();
int maxSum = Integer.MIN_VALUE; // Инициализируем переменную минимально возможным значением
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int currSum = 0;
// Прибавляем сумму всех элементов в строке i
for (int val : board.get(i)) {
currSum += val;
}
// Прибавляем сумму всех элементов в колонке j
for (int k = 0; k < n; k++) {
currSum += board.get(k).get(j);
}
// Прибавляем сумму всех элементов в главной диагонали
for (int k = -Math.min(i, j); k < Math.min(n - i, m - j); k++) {
currSum += board.get(i + k).get(j + k);
}
// Прибавляем сумму всех элементов в побочной диагонали
for (int k = -Math.min(i, m - j - 1); k < Math.min(n - i, j + 1); k++) {
currSum += board.get(i + k).get(j - k);
}
// Элемент board[i][j] мы просуммировали 4 раза в предыдущих циклах
// Вычитаем лишние разы
currSum -= 3 * board.get(i).get(j);
// Обновляем ответ в любом случае, если это первая итерация
// Без этого не будет правильно работать, если только отрицательные числа в board
if (i == 0 && j == 0) {
maxSum = currSum;
}
// Обновляем ответ
maxSum = Math.max(maxSum, currSum);
}
}
return maxSum;
}
}
from typing import *
def max_queen_sum(board: List[List[int]]) -> int:
n = len(board)
m = len(board[0])
max_sum = 0
for i in range(n):
for j in range(m):
curr_sum = 0
# прибавляем сумму всех элементов в строке i
curr_sum += sum(board[i])
# прибавляем сумму всех элементов в колонке j
for k in range(n):
curr_sum += board[k][j]
# прибавляем сумму всех элементов в главной диагонали
for k in range(-min(i, j), min(n - i, m - j)):
curr_sum += board[i + k][j + k]
# прибавляем сумму всех элементов в побочной диагонали
for k in range(-min(i, m - j - 1), min(n - i, j + 1)):
curr_sum += board[i + k][j - k]
# элемент board[i][j] мы просуммировали 4 раза в предыдущих циклах
# вычитаем лишние разы
curr_sum -= 3 * board[i][j]
# обновляем ответ в любом случае, если это первая итерация
# без этого не будет правильно работать если только отрицательные
# числа в board
if i == 0 and j == 0:
max_sum = curr_sum
# обновляем ответ
max_sum = max(max_sum, curr_sum)
return max_sum
function maxQueenSum(board) {
const n = board.length;
const m = board[0].length;
let maxSum = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
let currSum = 0;
// Прибавляем сумму всех элементов в строке i
currSum += board[i].reduce((a, b) => a + b, 0);
// Прибавляем сумму всех элементов в колонке j
for (let k = 0; k < n; k++) {
currSum += board[k][j];
}
// Прибавляем сумму всех элементов в главной диагонали
for (let k = -Math.min(i, j); k < Math.min(n - i, m - j); k++) {
currSum += board[i + k][j + k];
}
// Прибавляем сумму всех элементов в побочной диагонали
for (let k = -Math.min(i, m - j - 1); k < Math.min(n - i, j + 1); k++) {
currSum += board[i + k][j - k];
}
// Элемент board[i][j] мы просуммировали 4 раза в предыдущих циклах
// Вычитаем лишние разы
currSum -= 3 * board[i][j];
// Обновляем ответ в любом случае, если это первая итерация
// Без этого не будет правильно работать если только отрицательные
// числа в board
if (i === 0 && j === 0) {
maxSum = currSum;
}
// Обновляем ответ
maxSum = Math.max(maxSum, currSum);
}
}
return maxSum;
}
Однако такой подход имеет сложность по времени O(n * m * (n + m)), что неэффективно для больших массивов.
Оптимальное решение
Чтобы оптимизировать решение по времени до , используем суммы для строк, столбцов и диагоналей.O(n * m)
Суммы для строк и столбцов
- Суммы строк:
rowsSum[i]— сумма всех элементов строкиi. - Суммы столбцов:
colsSum[j]— сумма всех элементов столбцаj.
Подсчет rowsSum и colsSum в решении выглядит так:
function maxQueenSum(board) {
// rows_sum[i] будет содержать сумму всех элементов для i-ой строки
const rowsSum = new Array(board.length).fill(0);
// cols_sum[j] будет содержать сумму всех элементов для j-ой колонки
const colsSum = new Array(board[0].length).fill(0);
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
const val = board[i][j];
rowsSum[i] += val;
colsSum[j] += val;
// ...
}
}
}
public class Solution
{
public static int MaxQueenSum(List<List<int>> board)
{
// rowsSum[i] - будет содержать сумму всех элементов для i-ой строки
List<int> rowsSum = new List<int>(new int[board.Count]);
// colsSum[i] - будет содержать сумму всех элементов для i-ой колонки
List<int> colsSum = new List<int>(new int[board[0].Count]);
// делаем предподсчет, чтобы быстро находить позицию
for (int i = 0; i < board.Count; ++i)
{
for (int j = 0; j < board[i].Count; ++j)
{
int val = board[i][j];
rowsSum[i] += val;
colsSum[j] += val;
// ...
}
}
}
#include <vector>
#include <algorithm>
using namespace std;
int maxQueenSum(const vector<vector<int>>& board) {
// rowsSum[i] будет содержать сумму всех элементов для i-ой строки
vector<int> rowsSum(board.size(), 0);
// colsSum[j] будет содержать сумму всех элементов для j-ой колонки
vector<int> colsSum(board[0].size(), 0);
for (int i = 0; i < board.size(); ++i) {
for (int j = 0; j < board[i].size(); ++j) {
int val = board[i][j];
rowsSum[i] += val;
colsSum[j] += val;
// ...
}
}
}
import java.util.List;
public class Solution {
public static int maxQueenSum(List<List<Integer>> board) {
// rows_sum[i] будет содержать сумму всех элементов для i-ой строки
int[] rowsSum = new int[board.size()];
// cols_sum[j] будет содержать сумму всех элементов для j-ой колонки
int[] colsSum = new int[board.get(0).size()];
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board.get(i).size(); j++) {
int val = board.get(i).get(j);
rowsSum[i] += val;
colsSum[j] += val;
// ...
}
}
}
}
from typing import *
def max_queen_sum(board: List[List[int]]) -> int:
# rows_sum[i] - будет содержать сумму всех элементов для i-ой строки
rows_sum = [0] * len(board)
# cols_sum[i] - будет содержать сумму всех элементов для i-ой колонки
cols_sum = [0] * len(board[0])
# ...
for i in range(len(board)):
for j in range(len(board[i])):
val = board[i][j]
rows_sum[i] += val
cols_sum[j] += val
# ...
# ...
function maxQueenSum(board) {
// rows_sum[i] будет содержать сумму всех элементов для i-ой строки
const rowsSum = new Array(board.length).fill(0);
// cols_sum[j] будет содержать сумму всех элементов для j-ой колонки
const colsSum = new Array(board[0].length).fill(0);
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
const val = board[i][j];
rowsSum[i] += val;
colsSum[j] += val;
// ...
}
}
}
Суммы для главных диагоналей
- Главная диагональ: Индекс для неё вычисляется как
(n - 1 - i) + j, гдеn- число строк. Подсчетd1Sumв решении выглядит так:
public class Solution
{
public static int MaxQueenSum(List<List<int>> board)
{
// ...
List<int> d1Sum = new List<int>(new int[board.Count + board[0].Count - 1]);
for (int i = 0; i < board.Count; ++i)
{
for (int j = 0; j < board[i].Count; ++j)
{
int val = board[i][j];
d1Sum[(board.Count - 1 - i) + j] += val;
}
}
// ...
return 0;
}
}
#include <vector>
using namespace std;
int maxQueenSum(const vector<vector<int>>& board) {
// ...
vector<int> d1_sum(board.size() + board[0].size() - 1, 0);
for (size_t i = 0; i < board.size(); ++i) {
for (size_t j = 0; j < board[i].size(); ++j) {
int val = board[i][j];
d1_sum[(board.size() - 1 - i) + j] += val;
}
}
// ...
return 0;
}
#include <vector>
using namespace std;
int maxQueenSum(const vector<vector<int>>& board) {
// ...
vector<int> d1_sum(board.size() + board[0].size() - 1, 0);
for (size_t i = 0; i < board.size(); ++i) {
for (size_t j = 0; j < board[i].size(); ++j) {
int val = board[i][j];
d1_sum[(board.size() - 1 - i) + j] += val;
}
}
// ...
return 0;
}
package main
func maxQueenSum(board [][]int) int {
// ...
d1Sum := make([]int, len(board)+len(board[0])-1)
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[i]); j++ {
val := board[i][j]
d1Sum[(len(board)-1-i)+j] += val
}
}
// ...
}
from typing import *
def max_queen_sum(board: List[List[int]]) -> int:
# ...
d1_sum = [0] * (len(board) + len(board[0]) - 1)
for i in range(len(board)):
for j in range(len(board[i])):
# ...
val = board[i][j]
d1_sum[(len(board) - 1 - i) + j] += val
# ...
function maxQueenSum(board) {
// ...
const d1Sum = new Array(board.length + board[0].length - 1).fill(0);
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
const val = board[i][j];
d1Sum[(board.length - 1 - i) + j] += val;
}
}
// ...
}
Суммы для побочных диагоналей
- Побочная диагональ: индекс в массиве
d2Sumвычисляется какi + j.
Подсчет d2Sum в решении выглядит так:
public class Solution
{
public static int MaxQueenSum(List<List<int>> board)
{
// ...
List<int> d2Sum = new List<int>(new int[board.Count + board[0].Count - 1]);
// делаем предподсчет, чтобы быстро находить позицию
for (int i = 0; i < board.Count; ++i)
{
for (int j = 0; j < board[i].Count; ++j)
{
int val = board[i][j];
d2Sum[i + j] += val;
}
}
// ...
}
}
#include <vector>
using namespace std;
int maxQueenSum(const vector<vector<int>>& board) {
// ...
vector<int> d2_sum(board.size() + board[0].size() - 1, 0);
for (size_t i = 0; i < board.size(); ++i) {
for (size_t j = 0; j < board[i].size(); ++j) {
int val = board[i][j];
d2_sum[i + j] += val;
}
}
// ...
}
package main
func maxQueenSum(board [][]int) int {
// ...
d2Sum := make([]int, len(board)+len(board[0])-1)
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[i]); j++ {
val := board[i][j]
d2Sum[i + j] += val
}
}
// ...
}
import java.util.List;
public class Solution {
public static int maxQueenSum(List<List<Integer>> board) {
// ...
int[] d2Sum = new int[board.size() + board.get(0).size() - 1];
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board.get(i).size(); j++) {
int val = board.get(i).get(j);
d2Sum[i + j] += val;
}
}
// ...
}
}
from typing import *
def max_queen_sum(board: List[List[int]]) -> int:
# ...
d2_sum = [0] * (len(board) + len(board[0]) - 1)
for i in range(len(board)):
for j in range(len(board[i])):
# ...
val = board[i][j]
d2_sum[i + j] += val
# ...
function maxQueenSum(board) {
// ...
const d2Sum = new Array(board.length + board[0].length - 1).fill(0);
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
const val = board[i][j];
d2Sum[i + j] += val;
}
}
// ...
}
Подсчет текущей суммы для каждой позиции ферзя
После построения массивов rowsSum, colsSum, d1Sum и d2Sum можно легко вычислить сумму клеток под боем ферзя:
- Для каждой клетки
(i, j)суммируем:current_sum = rowsSum[i] + colsSum[j] + d1_sum[(len(board) - 1 - i) + j] + d2_sum[i + j] - Вычитаем значение текущей клетки трижды, так как оно было учтено в каждой из сумм.
- Сравниваем
currentSumсmaxSumи обновляем максимум, если нужно.
Итоговое решение будет таким:
public class Solution
{
public static int MaxQueenSum(List<List<int>> board)
{
// rowsSum[i] - будет содержать сумму всех элементов для i-ой строки
List<int> rowsSum = new List<int>(new int[board.Count]);
// colsSum[i] - будет содержать сумму всех элементов для i-ой колонки
List<int> colsSum = new List<int>(new int[board[0].Count]);
// d1Sum, d2Sum - содержат сумму элементов на диагоналях
List<int> d1Sum = new List<int>(new int[board.Count + board[0].Count - 1]);
List<int> d2Sum = new List<int>(new int[board.Count + board[0].Count - 1]);
// делаем предподсчет, чтобы быстро находить позицию
for (int i = 0; i < board.Count; ++i)
{
for (int j = 0; j < board[i].Count; ++j)
{
int val = board[i][j];
rowsSum[i] += val;
colsSum[j] += val;
d1Sum[(board.Count - 1 - i) + j] += val;
d2Sum[i + j] += val;
}
}
int maxSum = 0;
for (int i = 0; i < board.Count; ++i)
{
for (int j = 0; j < board[i].Count; ++j)
{
// при подсчете суммы складываем сумму текущей строки, столбца,
// двух диагоналей и не забываем вычитать общий серединный элемент
int currSum = rowsSum[i] + colsSum[j];
currSum += d1Sum[(board.Count - 1 - i) + j] + d2Sum[i + j];
currSum -= 3 * board[i][j];
// обновляем максимальную сумму
if (i == 0 && j == 0)
{
// сумма может быть меньше 0, поэтому
// важно инициализировать начальным значением
maxSum = currSum;
}
maxSum = Math.Max(maxSum, currSum);
}
}
return maxSum;
}
}
#include <vector>
using namespace std;
int maxQueenSum(vector<vector<int>>& board) {
// rows_sum[i] - будет содержать сумму всех элементов для i-ой строки
vector<int> rowsSum(board.size(), 0);
// cols_sum[i] - будет содержать сумму всех элементов для i-ой колонки
vector<int> colsSum(board[0].size(), 0);
// d1_sum, d2_sum - содержат сумму элементов на диагоналях
vector<int> d1Sum(board.size() + board[0].size() - 1, 0);
vector<int> d2Sum(board.size() + board[0].size() - 1, 0);
// делаем предподсчет, чтобы быстро находить позицию
for (int i = 0; i < board.size(); ++i) {
for (int j = 0; j < board[i].size(); ++j) {
int val = board[i][j];
rowsSum[i] += val;
colsSum[j] += val;
d1Sum[(board.size() - 1 - i) + j] += val;
d2Sum[i + j] += val;
}
}
int maxSum = 0;
for (int i = 0; i < board.size(); ++i) {
for (int j = 0; j < board[i].size(); ++j) {
// при подсчете суммы складываем сумму текущей строки, столбца,
// двух диагоналей и не забываем вычитать общий серединный элемент
int currSum = rowsSum[i] + colsSum[j];
currSum += d1Sum[(board.size() - 1 - i) + j] + d2Sum[i + j];
currSum -= 3 * board[i][j];
// обновляем максимальную сумму
if (i == 0 && j == 0) {
// сумма может быть меньше 0, поэтому
// важно инициализировать начальным значением
maxSum = currSum;
}
maxSum = max(maxSum, currSum);
}
}
return maxSum;
}
package main
func maxQueenSum(board [][]int) int {
rowsSum := make([]int, len(board))
colsSum := make([]int, len(board[0]))
d1Sum := make([]int, len(board)+len(board[0])-1)
d2Sum := make([]int, len(board)+len(board[0])-1)
// делаем предподсчет, чтобы быстро находить позицию
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[i]); j++ {
val := board[i][j]
rowsSum[i] += val
colsSum[j] += val
d1Sum[(len(board)-1-i)+j] += val
d2Sum[i+j] += val
}
}
maxSum := 0
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[i]); j++ {
// при подсчете суммы складываем сумму текущей строки, столбца,
// двух диагоналей и не забываем вычитать общий серединный элемент
currSum := rowsSum[i] + colsSum[j]
currSum += d1Sum[(len(board)-1-i)+j] + d2Sum[i+j]
currSum -= 3 * board[i][j]
// обновляем максимальную сумму
if i == 0 && j == 0 {
// сумма может быть меньше 0, поэтому
// важно инициализировать начальным значением
maxSum = currSum
}
if currSum > maxSum {
maxSum = currSum
}
}
}
return maxSum
}
import java.util.*;
public class Solution {
public int maxQueenSum(List<List<Integer>> board) {
// rows_sum[i] - будет содержать сумму всех элементов для i-ой строки
int[] rowsSum = new int[board.size()];
// cols_sum[i] - будет содержать сумму всех элементов для i-ой колонки
int[] colsSum = new int[board.get(0).size()];
// d1_sum, d2_sum - содержат сумму элементов на диагоналях
int[] d1Sum = new int[board.size() + board.get(0).size() - 1];
int[] d2Sum = new int[board.size() + board.get(0).size() - 1];
// делаем предподсчет, чтобы быстро находить позицию
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board.get(i).size(); j++) {
int val = board.get(i).get(j);
rowsSum[i] += val;
colsSum[j] += val;
d1Sum[(board.size() - 1 - i) + j] += val;
d2Sum[i + j] += val;
}
}
int maxSum = 0;
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board.get(i).size(); j++) {
// при подсчете суммы складываем сумму текущей строки, столбца,
// двух диагоналей и не забываем вычитать общий серединный элемент
int currSum = rowsSum[i] + colsSum[j];
currSum += d1Sum[(board.size() - 1 - i) + j] + d2Sum[i + j];
currSum -= 3 * board.get(i).get(j);
// обновляем максимальную сумму
if (i == 0 && j == 0) {
// сумма может быть меньше 0, поэтому
// важно инициализировать начальным значением
maxSum = currSum;
}
maxSum = Math.max(maxSum, currSum);
}
}
return maxSum;
}
}
from typing import *
def max_queen_sum(board: List[List[int]]) -> int:
# rows_sum[i] - будет содержать сумму всех элементов для i-ой строки
rows_sum = [0] * len(board)
# cols_sum[i] - будет содержать сумму всех элементов для i-ой колонки
cols_sum = [0] * len(board[0])
# d1_sum, d2_sum - содержат сумму элементов на диагоналях
d1_sum = [0] * (len(board) + len(board[0]) - 1)
d2_sum = [0] * (len(board) + len(board[0]) - 1)
# делам предподсчет, чтобы быстро находить позицию
for i in range(len(board)):
for j in range(len(board[i])):
val = board[i][j]
rows_sum[i] += val
cols_sum[j] += val
d1_sum[(len(board) - 1 - i) + j] += val
d2_sum[i + j] += val
max_sum = 0
for i in range(len(board)):
for j in range(len(board[i])):
# при подсчете суммы складываем сумму текущей строки, столбца,
# двух диагоналей и не забываем вычитать общий серединный элемент
curr_sum = rows_sum[i] + cols_sum[j]
curr_sum += d1_sum[(len(board) - 1 - i) + j] + d2_sum[i + j]
curr_sum -= 3 * board[i][j]
# обновляем максимальную сумму
if i == 0 and j == 0:
# сумма может быть меньше 0, поэтому
# важно инициализировать начальным значением
max_sum = curr_sum
max_sum = max(max_sum, curr_sum)
return max_sum
export function maxQueenSum(board) {
// rowsSum[i] - будет содержать сумму всех элементов для i-ой строки
let rowsSum = new Array(board.length).fill(0);
// colsSum[i] - будет содержать сумму всех элементов для i-ой колонки
let colsSum = new Array(board[0].length).fill(0);
// d1Sum, d2Sum - содержат сумму элементов на диагоналях
let d1Sum = new Array(board.length + board[0].length - 1).fill(0);
let d2Sum = new Array(board.length + board[0].length - 1).fill(0);
// делам предподсчет, чтобы быстро находить позицию
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
let val = board[i][j];
rowsSum[i] += val;
colsSum[j] += val;
d1Sum[(board.length - 1 - i) + j] += val;
d2Sum[i + j] += val;
}
}
let maxSum = 0;
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
// при подсчете суммы складываем сумму текущей строки, столбца,
// двух диагоналей и не забываем вычитать общий серединный элемент
let currSum = rowsSum[i] + colsSum[j];
currSum += d1Sum[(board.length - 1 - i) + j] + d2Sum[i + j];
currSum -= 3 * board[i][j];
// обновляем максимальную сумму
if (i === 0 && j === 0) {
// сумма может быть меньше 0, поэтому
// важно инициализировать начальным значением
maxSum = currSum;
}
maxSum = Math.max(maxSum, currSum);
}
}
return maxSum;
}
Оценка по времени и памяти:
- Время:
O(n*m), гдеn— количество строк,m— количество столбцов. - Память:
O(n + m), так как храним суммы для строк, столбцов и диагоналей.
Что дальше?
Теперь, когда ты освоил применение массивов сумм как в одномерном, так и в двумерном формате, не стесняйся применять свои знания на практике!