From 2cac4654424c48b7b8dc39ff8a2bb0783f50dc75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=8B=D1=82=D0=BA=D0=BE=D0=B2=20=D0=A0=D0=BE=D0=BC?= =?UTF-8?q?=D0=B0=D0=BD?= Date: Thu, 26 Mar 2026 13:33:38 +0300 Subject: [PATCH] 3548. Equal Sum Grid Partition II --- .../3548. Equal Sum Grid Partition II.csproj | 11 ++ 3548. Equal Sum Grid Partition II/Program.cs | 139 ++++++++++++++++++ 3548. Equal Sum Grid Partition II/Solution.cs | 130 ++++++++++++++++ Leetcode.sln | 14 ++ 4 files changed, 294 insertions(+) create mode 100644 3548. Equal Sum Grid Partition II/3548. Equal Sum Grid Partition II.csproj create mode 100644 3548. Equal Sum Grid Partition II/Program.cs create mode 100644 3548. Equal Sum Grid Partition II/Solution.cs diff --git a/3548. Equal Sum Grid Partition II/3548. Equal Sum Grid Partition II.csproj b/3548. Equal Sum Grid Partition II/3548. Equal Sum Grid Partition II.csproj new file mode 100644 index 0000000..f026990 --- /dev/null +++ b/3548. Equal Sum Grid Partition II/3548. Equal Sum Grid Partition II.csproj @@ -0,0 +1,11 @@ + + + + Exe + net10.0 + _3548._Equal_Sum_Grid_Partition_II + enable + enable + + + diff --git a/3548. Equal Sum Grid Partition II/Program.cs b/3548. Equal Sum Grid Partition II/Program.cs new file mode 100644 index 0000000..5afba82 --- /dev/null +++ b/3548. Equal Sum Grid Partition II/Program.cs @@ -0,0 +1,139 @@ +var sol = new Solution(); + +var cases = new (int[][] grid, bool expected, string name)[] +{ + ( + new[] + { + new[] { 1, 4 }, + new[] { 2, 3 } + }, + true, + "Example 1" + ), + ( + new[] + { + new[] { 1, 2 }, + new[] { 3, 4 } + }, + true, + "Example 2" + ), + ( + new[] + { + new[] { 1, 2, 4 }, + new[] { 2, 3, 5 } + }, + false, + "Example 3" + ), + ( + new[] + { + new[] { 4, 1, 8 }, + new[] { 3, 2, 6 } + }, + false, + "Example 4" + ), + ( + new[] + { + new[] { 5, 5, 6, 2, 2, 2 } + }, + true, + "Example 5" + ), + ( + new[] + { + new[] { 100000 }, + new[] { 86218 }, + new[] { 100000 } + }, + true, + "Example 6" + ), + ( + new[] + { + new[] { 1, 2, 4 }, + new[] { 1, 6, 6 }, + new[] { 5, 6, 7 } + }, + true, + "Example 7" + ), + ( + new[] + { + new[] { 1, 2, 1, 1, 1 }, + new[] { 1, 1, 1, 2, 1 } + }, + true, + "Example 8" + ), + ( + new[] + { + new[] { 1, 1 }, + new[] { 2, 1 }, + new[] { 1, 1 }, + new[] { 1, 2 }, + new[] { 1, 1 } + }, + true, + "Example 9" + ), + ( + new[] + { + new[] { 10, 5, 4, 5 } + }, + false, + "Example 10" + ), + ( + new[] + { + new[] { 1, 1 }, + new[] { 2, 1 }, + new[] { 4, 3 } + }, + false, + "Example 11" + ), + ( + new[] + { + new[] { 4 }, + new[] { 3 }, + new[] { 4 }, + new[] { 4 }, + new[] { 4 } + }, + false, + "Example 12" + ), + ( + new[] + { + new[] { 100000 }, + new[] { 100000 }, + new[] { 100000 }, + new[] { 100000 }, + new[] { 1 } + }, + true, + "Example 13" + ), + +}; + +foreach (var (grid, expected, name) in cases) +{ + var actual = sol.CanPartitionGrid(grid); + Console.WriteLine($"{name}: {actual} (expected: {expected})"); +} diff --git a/3548. Equal Sum Grid Partition II/Solution.cs b/3548. Equal Sum Grid Partition II/Solution.cs new file mode 100644 index 0000000..be0a639 --- /dev/null +++ b/3548. Equal Sum Grid Partition II/Solution.cs @@ -0,0 +1,130 @@ +public class Solution +{ + struct SumInfo + { + public long Left; + public long Right; + public long Value; + // ключ - число, значение - индексы, где оно встречается + public Dictionary> Nums; + } + + public bool CanPartitionGrid(int[][] grid) + { + var height = grid.Length; + var width = grid[0].Length; + + var colSums = new SumInfo[width]; + var rowSums = new SumInfo[height]; + for (var i = 0; i < height; i++) + { + for (var j = 0; j < width; j++) + { + var num = grid[i][j]; + colSums[j].Value += num; + rowSums[i].Value += num; + rowSums[i].Nums ??= new Dictionary>(); + colSums[j].Nums ??= new Dictionary>(); + + rowSums[i].Nums.TryAdd(num, new SortedSet()); + rowSums[i].Nums[num].Add(j); + + colSums[j].Nums.TryAdd(num, new SortedSet()); + colSums[j].Nums[num].Add(i); + } + rowSums[i].Left = rowSums[i].Value; + if (i > 0) + rowSums[i].Left += rowSums[i - 1].Left; + } + for (var i = height - 1; i >= 0; i--) + { + rowSums[i].Right = rowSums[i].Value; + if (i < height - 1) + rowSums[i].Right += rowSums[i + 1].Right; + } + for (var j = 0; j < width; j++) + { + colSums[j].Left = colSums[j].Value; + if (j > 0) + colSums[j].Left += colSums[j - 1].Left; + } + for (var j = width - 1; j >= 0; j--) + { + colSums[j].Right = colSums[j].Value; + if (j < width - 1) + colSums[j].Right += colSums[j + 1].Right; + } + var answer = false; + for (var i = 0; i < rowSums.Length - 1 && !answer; i++) + { + var row = rowSums[i]; + var nextRow = rowSums[i + 1]; + var diff = Math.Abs(row.Left - nextRow.Right); + + var edgesOnly = colSums.Length == 1; + var colLen = height; + if (diff == 0 || + (row.Left < nextRow.Right && CanDelete(diff, colSums, i, true, i + 1 == rowSums.Length - 1, edgesOnly, colLen)) || + (row.Left > nextRow.Right && CanDelete(diff, colSums, i, false, i == 0, edgesOnly, colLen))) + answer |= true; + } + for (var j = 0; j < colSums.Length - 1 && !answer; j++) + { + var col = colSums[j]; + var nextCol = colSums[j + 1]; + var diff = Math.Abs(col.Left - nextCol.Right); + // тут проход по колонкам, значит поиск элемента для удаления надо выполнять по строкам + // если j == 0 и отрезаем в левой части, то надо смотреть только первую и последнюю строку + // если j+1 == colSums.Len-1 и отрезаем в правой части, то надо смотреть только первую и последнюю строку + var edgesOnly = rowSums.Length == 1; + var rowLen = width; + if (diff == 0 || + (col.Left < nextCol.Right && CanDelete(diff, rowSums, j, true, j + 1 == colSums.Length - 1, edgesOnly, rowLen)) || + (col.Left > nextCol.Right && CanDelete(diff, rowSums, j, false, j == 0, edgesOnly, rowLen))) + answer |= true; + } + return answer; + } + + /// + /// + /// + /// Целевое число для поиска + /// Что перебирать + /// Индекс отсечения (для удаления справа строго больше, для удаления слева включительно) + /// Удалять ли спарва от индекса + /// Посмотреть только первый и последний SumInfo + /// В sumInfo брать только крайние элементы + /// Количество чисел в SumInfo + /// + private static bool CanDelete(long target, SumInfo[] infos, int idx, bool deleteAfterIdx, bool firstAndLastOnly, bool edgesOnly, int len) + { + for (var i = 0; i < infos.Length; i++) + { + var nums = infos[i].Nums; + + if (nums.TryGetValue(target, out var indexes)) + { + var before = false; + var after = false; + if (edgesOnly) + { + before = indexes.Contains(0) || indexes.Contains(idx); + after = indexes.Contains(len - 1) || indexes.Contains(idx+1); + } + else + { + before = indexes.GetViewBetween(int.MinValue, idx).Count > 0; + after = indexes.GetViewBetween(idx + 1, int.MaxValue).Count > 0; + } + if ((before && !deleteAfterIdx) || (after && deleteAfterIdx)) + return true; + } + + // если только границы, перейти сразу к последнему элементу + if (firstAndLastOnly && i == 0) + i = Math.Max(i, infos.Length - 2); + } + return false; + } +} \ No newline at end of file diff --git a/Leetcode.sln b/Leetcode.sln index 25d7a63..0d16be9 100644 --- a/Leetcode.sln +++ b/Leetcode.sln @@ -197,6 +197,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "114. Flatten Binary Tree to EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "30. Substring with Concatenation of All Words", "30. Substring with Concatenation of All Words\30. Substring with Concatenation of All Words.csproj", "{DC410457-B769-4597-857D-5AAD2BDBAAC3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3548. Equal Sum Grid Partition II", "3548. Equal Sum Grid Partition II\3548. Equal Sum Grid Partition II.csproj", "{D4C2B514-1A13-495A-8627-8B40AD8B2770}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1371,6 +1373,18 @@ Global {DC410457-B769-4597-857D-5AAD2BDBAAC3}.Release|x64.Build.0 = Release|Any CPU {DC410457-B769-4597-857D-5AAD2BDBAAC3}.Release|x86.ActiveCfg = Release|Any CPU {DC410457-B769-4597-857D-5AAD2BDBAAC3}.Release|x86.Build.0 = Release|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Debug|x64.ActiveCfg = Debug|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Debug|x64.Build.0 = Debug|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Debug|x86.ActiveCfg = Debug|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Debug|x86.Build.0 = Debug|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Release|Any CPU.Build.0 = Release|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Release|x64.ActiveCfg = Release|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Release|x64.Build.0 = Release|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Release|x86.ActiveCfg = Release|Any CPU + {D4C2B514-1A13-495A-8627-8B40AD8B2770}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE