3443. Maximum Manhattan Distance After K Changes
Problem Description
You are given a string s
consisting of the characters 'N'
, 'S'
, 'E'
, and 'W'
, where s[i]
indicates movements in an infinite grid:
'N'
: Move north by 1 unit.'S'
: Move south by 1 unit.'E'
: Move east by 1 unit.'W'
: Move west by 1 unit.
Initially, you are at the origin (0, 0)
. You can change at most k
characters to any of the four directions.
Find the maximum Manhattan distance from the origin that can be achieved at any time while performing the movements in order.
The Manhattan Distance between two cells (xi, yi)
and (xj, yj)
is |xi - xj| + |yi - yj|
.
Intuition
To find the maximum Manhattan distance from the origin after potentially changing some of the directions, we can consider the possible primary movement axes. The Manhattan distance can be influenced most by focusing mainly on movements in two selected directions out of the four possible: N
, S
, E
, and W
.
The solution involves enumerating four scenarios (SE
, SW
, NE
, NW
) that represent choosing two opposing directional movements (one vertical and one horizontal). For each scenario, we simulate the best possible sequence of moves to maximize the Manhattan distance.
The calc(a, b)
function is crucial as it determines the maximum achievable Manhattan distance when effectively considering only two directions a
and b
. During the traversal of the string s
, if a character matches a
or b
, the simulated distance increases by 1. If a character does not match and we still have changes available (cnt < k
), we treat it as if it can be converted to a
or b
to maximize the distance. Otherwise, it moves back toward the origin, reducing distance.
By traversing the string in this manner for each scenario and choosing the maximum result among them, we can determine the greatest possible distance from the origin given the constraints.
Learn more about Math patterns.
Solution Approach
The solution utilizes an enumeration and greedy approach to determine the maximum Manhattan distance from the origin by changing at most k
movements in the string s
.
Step-by-Step Implementation:
-
Enumeration of Cases: We consider four potential primary movement directions:
- "SE": moving east or south.
- "SW": moving west or south.
- "NE": moving east or north.
- "NW": moving west or north.
-
Defining the
calc(a, b)
Function: The functioncalc(a, b)
is responsible for calculating the maximum Manhattan distance when focusing on two directions,a
andb
. It simulates the maximum gain in distance from the origin by iterating over the strings
.-
Initialize three variables:
ans
to store the maximum distance found.mx
to record the current Manhattan distance as moves are simulated.cnt
to count the number of changes made to directions.
-
Traversal of
s
:- For each character
c
in the strings
, check if it matches eithera
orb
. - If
c
matches, incrementmx
as this movement contributes to increasing the distance. - If
c
does not match and changes are available (cnt < k
), treat this as a potential change toa
orb
, increment bothmx
andcnt
. - If no changes are available, decrement
mx
to account for moving back towards the origin.
- For each character
-
Update
ans
to be the maximum of itself ormx
after each iteration, ensuring that the largest achievable distance is stored.
-
-
Compute and Compare Results:
- Calculate the maximum distance for each of the four scenarios using the
calc
function. - Use
max(a, b, c, d)
to select the greatest distance achievable among the scenarios "SE", "SW", "NE", and "NW".
- Calculate the maximum distance for each of the four scenarios using the
This approach efficiently uses enumeration and greedy selection to find the best possible solution under the constraints given.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's illustrate the solution approach with an example.
Example Input:
s = "NESWN"
,k = 1
Initial Position:
- Start at origin
(0, 0)
.
Objective:
- Maximize the Manhattan distance from the origin by changing at most
k
movements.
Approach:
-
Enumerate scenarios:
- "SE": Focus on maximizing distance using moves 'S' and 'E'.
- "SW": Focus on 'S' and 'W'.
- "NE": Focus on 'N' and 'E'.
- "NW": Focus on 'N' and 'W'.
-
Calculate Maximum Distance for Each Scenario:
-
Scenario "SE":
- Traverse
s
: "N", "E", "S", "W", "N". - Focus Directions: 'S', 'E'.
- Initial
mx = 0
,cnt = 0
. - "N": Not in "SE", potential to change,
mx = 1
,cnt = 1
. - "E": Matches 'E',
mx = 2
. - "S": Matches 'S',
mx = 3
. - "W": Not in "SE", no changes left,
mx = 2
. - "N": Not in "SE", no changes left,
mx = 1
. - Max Distance for "SE": 3.
- Traverse
-
Scenario "SW":
- Traverse
s
: "N", "E", "S", "W", "N". - Focus Directions: 'S', 'W'.
- Initial
mx = 0
,cnt = 0
. - "N": Not in "SW", potential to change,
mx = 1
,cnt = 1
. - "E": Not in "SW", no changes left,
mx = 0
. - "S": Matches 'S',
mx = 1
. - "W": Matches 'W',
mx = 2
. - "N": Not in "SW", no changes left,
mx = 1
. - Max Distance for "SW": 2.
- Traverse
-
Scenario "NE":
- Traverse
s
: "N", "E", "S", "W", "N". - Focus Directions: 'N', 'E'.
- Initial
mx = 0
,cnt = 0
. - "N": Matches 'N',
mx = 1
. - "E": Matches 'E',
mx = 2
. - "S": Not in "NE", potential to change,
mx = 3
,cnt = 1
. - "W": Not in "NE", no changes left,
mx = 2
. - "N": Matches 'N',
mx = 3
. - Max Distance for "NE": 3.
- Traverse
-
Scenario "NW":
- Traverse
s
: "N", "E", "S", "W", "N". - Focus Directions: 'N', 'W'.
- Initial
mx = 0
,cnt = 0
. - "N": Matches 'N',
mx = 1
. - "E": Not in "NW", potential to change,
mx = 2
,cnt = 1
. - "S": Not in "NW", no changes left,
mx = 1
. - "W": Matches 'W',
mx = 2
. - "N": Matches 'N',
mx = 3
. - Max Distance for "NW": 3.
- Traverse
-
-
Select Maximum Distance:
- Maximum distance among scenarios "SE", "SW", "NE", "NW":
max(3, 2, 3, 3) = 3
.
- Maximum distance among scenarios "SE", "SW", "NE", "NW":
The greatest Manhattan distance achievable by selectively changing directions is 3.
Solution Implementation
1class Solution:
2 def maxDistance(self, s: str, k: int) -> int:
3 # Calculates the maximum distance for a given pair of directions (a and b)
4 def calc(primary: str, secondary: str) -> int:
5 # Initialize variables: max distance and current count of 'wrong' directions
6 max_dist = 0
7 current_dist = 0
8 wrong_count = 0
9
10 # Iterate through the string to calculate distances
11 for char in s:
12 if char == primary or char == secondary:
13 # If the current character matches one of the target directions, increase distance
14 current_dist += 1
15 elif wrong_count < k:
16 # If it is a different direction but we can replace (wrong_count < k), increase distance and wrong_count
17 wrong_count += 1
18 current_dist += 1
19 else:
20 # If we can't replace it, decrease the current distance
21 current_dist -= 1
22
23 # Update the maximum distance found
24 max_dist = max(max_dist, current_dist)
25
26 return max_dist
27
28 # Calculate maximum distance for each pair of directions
29 distance_se = calc("S", "E")
30 distance_sw = calc("S", "W")
31 distance_ne = calc("N", "E")
32 distance_nw = calc("N", "W")
33
34 # Return the maximum distance from all pairs
35 return max(distance_se, distance_sw, distance_ne, distance_nw)
36
1class Solution {
2 // Class level variables to store the character array and the integer k
3 private char[] directionArray;
4 private int k;
5
6 // Main method to find the maximum distance based on the given conditions
7 public int maxDistance(String s, int k) {
8 // Initialize the class variables
9 this.directionArray = s.toCharArray();
10 this.k = k;
11
12 // Calculate maximum distances for each pair of directions
13 int max_SE = calculateDistance('S', 'E');
14 int max_SW = calculateDistance('S', 'W');
15 int max_NE = calculateDistance('N', 'E');
16 int max_NW = calculateDistance('N', 'W');
17
18 // Return the maximum distance among all calculated distances
19 return Math.max(Math.max(max_SE, max_SW), Math.max(max_NE, max_NW));
20 }
21
22 // Helper method to calculate the distance for a given pair of directions
23 private int calculateDistance(char direction1, char direction2) {
24 int currentMax = 0; // Current running max distance
25 int maxDistance = 0; // Overall max distance found
26 int replacementCount = 0; // Count of non-direction characters replaced
27
28 // Iterate over each character in the direction array
29 for (char currentDirection : directionArray) {
30 // Increment the current max if the character matches one of the interested directions
31 if (currentDirection == direction1 || currentDirection == direction2) {
32 ++currentMax;
33 } else if (replacementCount < k) { // Replace non-direction chars if replacements are available
34 ++currentMax;
35 ++replacementCount;
36 } else {
37 --currentMax; // Decrement the current max if no more replacements can be made
38 }
39 // Update the max distance if the current calculated distance is greater
40 maxDistance = Math.max(maxDistance, currentMax);
41 }
42 return maxDistance; // Return the calculated max distance
43 }
44}
45
1#include <string>
2#include <algorithm>
3using namespace std;
4
5class Solution {
6public:
7 int maxDistance(string s, int k) {
8 // Helper lambda function to calculate the maximum distance given two specific characters
9 auto calc = [&](char a, char b) {
10 int answer = 0; // Overall maximum distance
11 int maxDistance = 0; // Current maximum distance while iterating
12 int count = 0; // Count of non-a/b characters used
13
14 // Iterate through each character in the string
15 for (char c : s) {
16 if (c == a || c == b) {
17 // If the character is one of the target characters, increase maxDistance
18 ++maxDistance;
19 } else if (count < k) {
20 // If we have not used the allowed modifications, increase both maxDistance and count
21 ++maxDistance;
22 ++count;
23 } else {
24 // If we cannot modify or characters do not match, decrease maxDistance
25 --maxDistance;
26 }
27 // Update the overall maximum distance
28 answer = max(answer, maxDistance);
29 }
30
31 return answer;
32 };
33
34 // Calculate the maximum distances for each pair of directional characters
35 int a = calc('S', 'E');
36 int b = calc('S', 'W');
37 int c = calc('N', 'E');
38 int d = calc('N', 'W');
39
40 // Return the maximum distance from all calculated pairs
41 return max({a, b, c, d});
42 }
43};
44
1// Calculate the maximum distance based on characters 'a' and 'b', allowing at most 'k' substitutions of other characters
2function maxDistance(s: string, k: number): number {
3
4 // Helper function to calculate the maximum possible distance
5 const calc = (a: string, b: string): number => {
6 let maxDistance = 0; // To store the maximum distance found
7 let currentDistance = 0; // To track distance temporarily during iteration
8 let substitutionCount = 0; // To count how many substitutions have been used
9
10 // Iterate over each character in the string 's'
11 for (const char of s) {
12 if (char === a || char === b) {
13 // Increment the current distance if the character matches 'a' or 'b'
14 ++currentDistance;
15 } else if (substitutionCount < k) {
16 // If the character doesn't match but we can substitute, increment distance and substitutions
17 ++currentDistance;
18 ++substitutionCount;
19 } else {
20 // If neither condition is met, reset the current distance
21 --currentDistance;
22 }
23 // Update the maximum distance after each character
24 maxDistance = Math.max(maxDistance, currentDistance);
25 }
26 return maxDistance;
27 };
28
29 // Calculate maximum distances for the four different combinations of the directional pairings
30 const maxSE = calc('S', 'E');
31 const maxSW = calc('S', 'W');
32 const maxNE = calc('N', 'E');
33 const maxNW = calc('N', 'W');
34
35 // Return the highest of all calculated distances
36 return Math.max(maxSE, maxSW, maxNE, maxNW);
37}
38
Time and Space Complexity
The time complexity of the code is O(n)
, where n
is the length of the string s
. This is because the calc
function iterates once through the entire string s
for each of the four calls. Therefore, each call takes O(n)
time, and since there are a constant number of calls (four), the overall time complexity remains O(n)
.
The space complexity of the code is O(1)
. This is because it uses a fixed amount of additional space, regardless of the input size, as it only maintains a few integer variables for calculation, and does not use any data structures that grow with the input.
Learn more about how to find time and space complexity quickly.
How does merge sort divide the problem into subproblems?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!