From cda1afda7206288e64d22db2dd05b4d359c99ba2 Mon Sep 17 00:00:00 2001 From: Gonzalo Diaz Date: Wed, 4 Sep 2024 12:00:15 -0400 Subject: [PATCH] =?UTF-8?q?[Hacker=20Rank]=20Interview=20Preparation=20Kit?= =?UTF-8?q?:=20Arrays:=20Array=20Manipulation.=20Solved=20=E2=9C=85.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../arrays/CrushBruteForce.cs | 46 ++++++++++ .../arrays/CrushOptimized.cs | 49 +++++++++++ .../arrays/crush.testcases.json | 73 ++++++++++++++++ .../algorithm_exercises_csharp_test.csproj | 1 + .../arrays/CrushBruteForce.Test.cs | 36 ++++++++ .../arrays/CrushOptimized.Test.cs | 36 ++++++++ .../interview_preparation_kit/arrays/crush.md | 85 +++++++++++++++++++ .../arrays/crush_optimized-solution-notes.md | 37 ++++++++ 8 files changed, 363 insertions(+) create mode 100644 algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.cs create mode 100644 algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.cs create mode 100644 algorithm_exercises_csharp_test/Resources/hackerrank/interview_preparation_kit/arrays/crush.testcases.json create mode 100644 algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.Test.cs create mode 100644 algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.Test.cs create mode 100644 docs/hackerrank/interview_preparation_kit/arrays/crush.md create mode 100644 docs/hackerrank/interview_preparation_kit/arrays/crush_optimized-solution-notes.md diff --git a/algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.cs b/algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.cs new file mode 100644 index 0000000..9cb1936 --- /dev/null +++ b/algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.cs @@ -0,0 +1,46 @@ +/** + * Crush (Brute Force). + * + * @link Problem definition [[docs/hackerrank/interview_preparation_kit/arrays/crush.md]] + * @link Solution notes [[docs/hackerrank/interview_preparation_kit/arrays/crush_optimized-solution-notes.md]] + */ + +namespace algorithm_exercises_csharp.hackerrank.interview_preparation_kit; + +using System.Diagnostics.CodeAnalysis; + +public class CrushBruteForce +{ + [ExcludeFromCodeCoverage] + protected CrushBruteForce() { } + + private const int INITIALIZER = 0; + + public static long arrayManipulation(int n, List> queries) + { + // why adding 1? + // first slot to adjust 1-based index and + int[] result = new int[n + 1]; + Array.Fill(result, INITIALIZER); + int maximum = INITIALIZER; + + foreach (List query in queries) + { + int start = query[0]; + int end = query[1]; + int value = query[2]; + + for (int i = start; i < end + 1; i++) + { + result[i] += value; + } + + foreach (int current in result) + { + maximum = Math.Max(current, maximum); + } + } + + return maximum; + } +} diff --git a/algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.cs b/algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.cs new file mode 100644 index 0000000..f979fbd --- /dev/null +++ b/algorithm_exercises_csharp/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.cs @@ -0,0 +1,49 @@ +/** + * Crush (Optimized). + * + * @link Problem definition [[docs/hackerrank/interview_preparation_kit/arrays/crush.md]] + * @link Solution notes [[docs/hackerrank/interview_preparation_kit/arrays/crush_optimized-solution-notes.md]] + */ + +namespace algorithm_exercises_csharp.hackerrank.interview_preparation_kit; + +using System.Diagnostics.CodeAnalysis; + +public class CrushOptimized +{ + [ExcludeFromCodeCoverage] + private CrushOptimized() { } + + /** + * arrayManipulation. + */ + public static long arrayManipulation(int n, List> queries) + { + // why adding 2? + // first slot to adjust 1-based index and + // last slot for storing accumSum result + int[] result = new int[n + 2]; + Array.Fill(result, 0); + int maximum = 0; + + foreach (List query in queries) + { + int a = query[0]; + int b = query[1]; + int k = query[2]; + + // Prefix + result[a] += k; + result[b + 1] -= k; + + int accumSum = 0; + foreach (int value in result) + { + accumSum += value; + maximum = Math.Max(maximum, accumSum); + } + } + + return maximum; + } +} diff --git a/algorithm_exercises_csharp_test/Resources/hackerrank/interview_preparation_kit/arrays/crush.testcases.json b/algorithm_exercises_csharp_test/Resources/hackerrank/interview_preparation_kit/arrays/crush.testcases.json new file mode 100644 index 0000000..b447a0d --- /dev/null +++ b/algorithm_exercises_csharp_test/Resources/hackerrank/interview_preparation_kit/arrays/crush.testcases.json @@ -0,0 +1,73 @@ +[ + { + "title": "Sample Test Case 0", + "n": 5, + "queries": [ + [ + 1, + 2, + 100 + ], + [ + 2, + 5, + 100 + ], + [ + 3, + 4, + 100 + ] + ], + "expected": 200 + }, + { + "title": "Sample Test Case 1", + "n": 10, + "queries": [ + [ + 1, + 5, + 3 + ], + [ + 4, + 8, + 7 + ], + [ + 6, + 9, + 1 + ] + ], + "expected": 10 + }, + { + "title": "Sample Test Case 3", + "n": 10, + "queries": [ + [ + 2, + 6, + 8 + ], + [ + 3, + 5, + 7 + ], + [ + 1, + 8, + 1 + ], + [ + 5, + 9, + 15 + ] + ], + "expected": 31 + } +] \ No newline at end of file diff --git a/algorithm_exercises_csharp_test/algorithm_exercises_csharp_test.csproj b/algorithm_exercises_csharp_test/algorithm_exercises_csharp_test.csproj index 58159fe..fee1aab 100644 --- a/algorithm_exercises_csharp_test/algorithm_exercises_csharp_test.csproj +++ b/algorithm_exercises_csharp_test/algorithm_exercises_csharp_test.csproj @@ -60,6 +60,7 @@ + diff --git a/algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.Test.cs b/algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.Test.cs new file mode 100644 index 0000000..7c7baf9 --- /dev/null +++ b/algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushBruteForce.Test.cs @@ -0,0 +1,36 @@ +namespace algorithm_exercises_csharp.hackerrank.interview_preparation_kit; + +[TestClass] +public class CrushBruteForceTest +{ + public class CrushBruteForceTestCase + { + public string title { get; set; } = default!; + public List> queries { get; set; } = default!; + public int n { get; set; } = default!; + public long expected { get; set; } = default!; + } + + private List testCases { get; set; } = default!; + + [TestInitialize] + public void testInitialize() + { + testCases = JsonLoader.resourceLoad>( + "hackerrank/interview_preparation_kit/arrays/crush.testcases.json" + ) ?? []; + } + + [TestMethod] + public void testArrayManipulation() + { + long result; + + foreach (CrushBruteForceTestCase test in testCases) + { + result = CrushBruteForce.arrayManipulation(test.n, test.queries); + Assert.AreEqual(test.expected, result); + } + } +} + diff --git a/algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.Test.cs b/algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.Test.cs new file mode 100644 index 0000000..411485a --- /dev/null +++ b/algorithm_exercises_csharp_test/src/hackerrank/interview_preparation_kit/arrays/CrushOptimized.Test.cs @@ -0,0 +1,36 @@ +namespace algorithm_exercises_csharp.hackerrank.interview_preparation_kit; + +[TestClass] +public class CrushOptimizedTest +{ + public class CrushOptimizedTestCase + { + public string title { get; set; } = default!; + public List> queries { get; set; } = default!; + public int n { get; set; } = default!; + public long expected { get; set; } = default!; + } + + private List testCases { get; set; } = default!; + + [TestInitialize] + public void testInitialize() + { + testCases = JsonLoader.resourceLoad>( + "hackerrank/interview_preparation_kit/arrays/crush.testcases.json" + ) ?? []; + } + + [TestMethod] + public void testArrayManipulation() + { + long result; + + foreach (CrushOptimizedTestCase test in testCases) + { + result = CrushOptimized.arrayManipulation(test.n, test.queries); + Assert.AreEqual(test.expected, result); + } + } +} + diff --git a/docs/hackerrank/interview_preparation_kit/arrays/crush.md b/docs/hackerrank/interview_preparation_kit/arrays/crush.md new file mode 100644 index 0000000..5cd1f3b --- /dev/null +++ b/docs/hackerrank/interview_preparation_kit/arrays/crush.md @@ -0,0 +1,85 @@ +# [Arrays: Array Manipulation](https://www.hackerrank.com/challenges/crush) + +Perform m operations on an array and print the maximum of the values. + +- Difficulty: `#hard` +- Category: `#ProblemSolvingIntermediate` `#arrays` + +Starting with a 1-indexed array of zeros and a list of operations, for each +operation add a value to each the array element between two given indices, +inclusive. Once all operations have been performed, return the maximum +value in the array. + +## Example + +Queries are interpreted as follows: + +```text + a b k + 1 5 3 + 4 8 7 + 6 9 1 +``` + +Add the values of between the indices and inclusive: + +```text +index-> 1 2 3 4 5 6 7 8 9 10 + [0,0,0, 0, 0,0,0,0,0, 0] + [3,3,3, 3, 3,0,0,0,0, 0] + [3,3,3,10,10,7,7,7,0, 0] + [3,3,3,10,10,8,8,8,1, 0] +``` + +The largest value is `10` after all operations are performed. + +## Function Description + +Complete the function arrayManipulation in the editor below. + +arrayManipulation has the following parameters: + +- `int n` - the number of elements in the array +- `int queries[q][3]` - a two dimensional array of queries where +each `queries[i]` contains three integers, `a`, `b`, and `k`. + +## Returns + +- int - the maximum value in the resultant array + +## Input Format + +The first line contains two space-separated integers `n` and `m`, the size of +the array and the number of operations. +Each of the next `m` lines contains three space-separated integers +`a`, `b` and `k`, the left index, right index and summand. + +## Constraints + +- $ 3 \leq n \leq 10^7 $ +- $ 1 \leq m \leq 2*10^5 $ +- $ 1 \leq a \leq b \leq n $ +- $ 0 \leq k \leq 10^9 $ + +## Sample Input + +```text +5 3 +1 2 100 +2 5 100 +3 4 100 +``` + +## Sample Output + +```text +200 +```` + +## Explanation + +After the first update the list is `100 100 0 0 0`. +After the second update list is `100 200 100 100 100`. +After the third update list is `100 200 200 200 100`. + +The maximum value is `200`. diff --git a/docs/hackerrank/interview_preparation_kit/arrays/crush_optimized-solution-notes.md b/docs/hackerrank/interview_preparation_kit/arrays/crush_optimized-solution-notes.md new file mode 100644 index 0000000..72141a5 --- /dev/null +++ b/docs/hackerrank/interview_preparation_kit/arrays/crush_optimized-solution-notes.md @@ -0,0 +1,37 @@ +# [Array Manipulation](https://www.hackerrank.com/challenges/crush) + +Perform m operations on an array and print the maximum of the values. + +- Difficulty: `#hard` +- Category: `#ProblemSolvingIntermediate` `#arrays` + +## Solution sources + +### Brute force idea + +The first solution attempt is based on the idea of going through: + +> each row and then, +> > each sub-set of elements affected by the operation. + +With this principle, the algorithm becomes O(N^2) + +### Optimized + +Reading about posible optimizations, +I found the possibility of summarizing the interior traversal with +addition operations for each element in each row of operations, +in only 2 constant operations, which represents the necessary values so that +in a single final traversal, the sum values can be obtained "by drag". +The algorithm is called "prefix sum." + +Some sources about "prefix sum" + +- +- +- + +Some sources about implementation in: + +- [HackerRank Array Manipulation — beat the clock using Prefix Sum (JavaScript)](https://medium.com/@mlgerardvla/hackerrank-array-manipulation-beat-the-clock-using-prefix-sum-92471060035e) +- [Hackerrank Discussions Forums: Array Manipulation](https://www.hackerrank.com/challenges/one-month-preparation-kit-crush/forum)