Ambiguous Coordinates solution and explanation
9 more videos on this problem
Ambiguous Coordinates | Live Coding with Explanation | Leetcode - 816Algorithms Made Easy · 13:52 · 1K views
Ambiguous Coordinates | Leetcode 816 | String | GoogleNaresh Gupta · 13:54 · 606 views
Ambiguous Coordinates | Strings | Try All Possible Cases | 816 LeetCode | Day 13CodeWithSunny · 25:30 · 578 views
Ambiguous Coordinates | LeetCode 816 | Coders CampCoders Camp · 13:39 · 541 views
Ambiguous Coordinates | Leetcode 816 | Live coding session | May 13 | Coding interviewsCoding Decoded · 14:03 · 483 views
Ambiguous Coordinates (Leetcode 816)Coding Interviews · 13:35 · 478 views
LeetCode - 816. Ambiguous Coordinates | Day 13 May ChallengeAditya Mahajan · 11:55 · 430 views
Leetcode - Ambiguous Coordinates (Python)Timothy H Chang · 8:30 · 360 views
Daily Leetcode #408: May 13, 2021 - 816. Ambiguous CoordinatesProgramming Live with Larry · 23:11 · 266 views
816. Ambiguous Coordinates | May LeetCode Challenge 2021Anushka Bhagchandani · 9:16 · 57 views
The problem
We had some 2-dimensional coordinates, like "(1, 3)" or "(2, 0.5)". Then, we removed all commas, decimal points, and spaces and ended up with the string s.
- For example,
"(1, 3)"becomess = "(13)"and"(2, 0.5)"becomess = "(205)".
Return a list of strings representing all possibilities for what our original coordinates could have been.
Our original representation never had extraneous zeroes, so we never started with numbers like "00", "0.0", "0.00", "1.0", "001", "00.01", or any other number that can be represented with fewer digits. Also, a decimal point within a number never occurs without at least one digit occurring before it, so we never started with numbers like ".1".
The final answer list can be returned in any order. All coordinates in the final answer have exactly one space between them (occurring after the comma.)
Example 1:
Input: s = "(123)" Output: ["(1, 2.3)","(1, 23)","(1.2, 3)","(12, 3)"]
Example 2:
Input: s = "(0123)" Output: ["(0, 1.23)","(0, 12.3)","(0, 123)","(0.1, 2.3)","(0.1, 23)","(0.12, 3)"] Explanation: 0.0, 00, 0001 or 00.01 are not allowed.
Example 3:
Input: s = "(00011)" Output: ["(0, 0.011)","(0.001, 1)"]
Constraints:
4 <= s.length <= 12s[0] == '('ands[s.length - 1] == ')'.- The rest of
sare digits.
Approach overview
Problem Overview: The input is a string like "(123)" where commas, spaces, and decimal points were removed from the original coordinate pair. Your job is to reconstruct every valid coordinate in the form (x, y). Each side may contain a decimal point, but numbers cannot have leading zeros (except "0") or trailing zeros after a decimal.
Approach 1: Brute Force Split and Validate (O(n^3) time, O(n^2) space)
Remove the surrounding parentheses and try every possible split of the string into a left and right part. For each substring, generate all valid numeric representations by optionally inserting a decimal point. Validation follows two rules: integers cannot have leading zeros unless the value is exactly "0", and decimal numbers cannot end with zero. This produces all valid candidates for the left coordinate and all candidates for the right coordinate. Combine every left candidate with every right candidate to form valid coordinate strings. The approach relies heavily on string operations and systematic enumeration of decimal placements.
Approach 2: Dynamic Generation with String Manipulation (O(n^3) time, O(n^2) space)
Instead of generating all substrings first, dynamically build valid numbers while scanning the characters. For each split index, process the left and right substrings independently and construct possible numeric forms directly using string slicing and rule checks. For example, treat the whole substring as an integer candidate, then try inserting a decimal point at each internal position if it doesn't violate the leading or trailing zero constraints. This avoids unnecessary intermediate strings and keeps the validation logic localized. The technique resembles controlled backtracking over decimal placements while enforcing formatting rules.
Recommended for interviews: The brute force split‑and‑validate approach is what most interviewers expect. It clearly demonstrates how you enumerate splits, enforce numeric formatting rules, and combine candidate lists. The dynamic generation variant is cleaner in implementation but conceptually the same complexity. Showing the brute force first proves correctness; explaining how you reduce redundant checks shows deeper string‑handling skill.
Approach 1: Brute Force Split and Validate
This approach involves splitting the string at every possible position to generate potential x and y coordinate pairs, then validating each potential number. The validation checks ensure no extra leading zeros and proper placement of decimal points according to the problem constraints.
def ambiguousCoordinates(S):
def valid_parts(s):
n = len(s)
return [s[:i] + '.' + s[i:] for i in range(1, n)] + [s] if n == 1 or s[0] != '0' else []
S = S[1:-1]
res = []
for i in range(1, len(S)):
left, right = S[:i], S[i:]
valid_left = valid_parts(left)
valid_right = valid_parts(right)
for a in valid_left:
for b in valid_right:
res.append(f'({a}, {b})')
return res
# Example usage
assert ambiguousCoordinates('(123)') == ['(1, 2.3)', '(1, 23)', '(1.2, 3)', '(12, 3)']import java.util.ArrayList;
import java.util.List;
public class AmbiguousCoordinates {
public List<String> ambiguousCoordinates(String S) {
List<String> result = new ArrayList<>();
String s = S.substring(1, S.length() - 1);
for (int i = 1; i < s.length(); i++) {
List<String> leftParts = getValidParts(s.substring(0, i));
List<String> rightParts = getValidParts(s.substring(i));
for (String left : leftParts) {
for (String right : rightParts) {
result.add("(" + left + ", " + right + ")");
}
}
}
return result;
}
private List<String> getValidParts(String s) {
List<String> parts = new ArrayList<>();
if (s.length() == 1 || s.charAt(0) != '0') {
parts.add(s);
}
for (int i = 1; i < s.length(); i++) {
String left = s.substring(0, i);
String right = s.substring(i);
if ((left.length() == 1 || left.charAt(0) != '0') && right.charAt(right.length() - 1) != '0') {
parts.add(left + "." + right);
}
}
return parts;
}
public static void main(String[] args) {
AmbiguousCoordinates ac = new AmbiguousCoordinates();
System.out.println(ac.ambiguousCoordinates("(123)"));
}
}The Python solution first strips the parentheses and attempts to split the string at every possible place. For each possible split, it generates all valid decimal representations for both parts and combines them into coordinate pairs.
Time Complexity: O(n^3), where n is the length of the string without parentheses. The combination of each split leads to n^2 pairs, and validating each part could take O(n) time.
Space Complexity: O(n^3), accounts for storing all possible valid coordinates.
Approach 2: Dynamic Generation with String Manipulation
This approach entails directly manipulating potential placements of decimal points while adhering to constraints about digits and format validation. It dynamically generates valid representations of left and right parts without separately validating every substring.
function ambiguousCoordinates(s) {
function generateValidParts(str) {
let n = str.length;
let res = [];
if (n == 1 || str[0] !== '0') {
res.push(str);
}
for (let i = 1; i < n; i++) {
let left = str.substring(0, i);
let right = str.substring(i);
if ((left.length === 1 || left[0] !== '0') && right[right.length - 1] !== '0') {
res.push(left + '.' + right);
}
}
return res;
}
s = s.slice(1, -1);
let results = [];
for (let i = 1; i < s.length; i++) {
let left = s.substring(0, i);
let right = s.substring(i);
let validLeft = generateValidParts(left);
let validRight = generateValidParts(right);
for (let l of validLeft) {
for (let r of validRight) {
results.push(`(${l}, ${r})`);
}
}
}
return results;
}
console.log(ambiguousCoordinates('(123)'));using System;
using System.Collections.Generic;
public class Solution {
public IList<string> AmbiguousCoordinates(string S) {
List<string> result = new List<string>();
string s = S.Substring(1, S.Length - 2);
for (int i = 1; i < s.Length; i++) {
var leftParts = GetValidParts(s.Substring(0, i));
var rightParts = GetValidParts(s.Substring(i));
foreach (var left in leftParts) {
foreach (var right in rightParts) {
result.Add($"({left}, {right})");
}
}
}
return result;
}
private List<string> GetValidParts(string s) {
var parts = new List<string>();
if (s.Length == 1 || s[0] != '0') {
parts.Add(s);
}
for (int i = 1; i < s.Length; i++) {
var left = s.Substring(0, i);
var right = s.Substring(i);
if ((left.Length == 1 || left[0] != '0') && right[right.Length - 1] != '0') {
parts.Add(left + "." + right);
}
}
return parts;
}
public static void Main(string[] args) {
var solution = new Solution();
var coords = solution.AmbiguousCoordinates("(123)");
foreach (var coord in coords) {
Console.WriteLine(coord);
}
}
}The JavaScript solution directly generates valid parts by evaluating each possible division of the number string, and checking inline conditions for valid splitting, thus efficiently producing the valid coordinates.
Time Complexity: O(n^3), due to multiple levels of iterations and validations. Space Complexity: O(n^3), because all possible coordinates are stored.
Approach 3: Default Approach
class Solution {
public:
vector<string> ambiguousCoordinates(string s) {
int n = s.size();
vector<string> ans;
auto f = [&](int i, int j) {
vector<string> res;
for (int k = 1; k <= j - i; ++k) {
string l = s.substr(i, k);
string r = s.substr(i + k, j - i - k);
bool ok = (l == "0" || l[0] != '0') && r.back() != '0';
if (ok) {
res.push_back(l + (k < j - i ? "." : "") + r);
}
}
return res;
};
for (int i = 2; i < n - 1; ++i) {
for (auto& x : f(1, i)) {
for (auto& y : f(i, n - 1)) {
ans.emplace_back("(" + x + ", " + y + ")");
}
}
}
return ans;
}
};function ambiguousCoordinates(s: string): string[] {
s = s.slice(1, s.length - 1);
const n = s.length;
const dfs = (s: string) => {
const res: string[] = [];
for (let i = 1; i < s.length; i++) {
const t = `${s.slice(0, i)}.${s.slice(i)}`;
if (`${Number(t)}` === t) {
res.push(t);
}
}
if (`${Number(s)}` === s) {
res.push(s);
}
return res;
};
const ans: string[] = [];
for (let i = 1; i < n; i++) {
for (const left of dfs(s.slice(0, i))) {
for (const right of dfs(s.slice(i))) {
ans.push(`(${left}, ${right})`);
}
}
}
return ans;
}func ambiguousCoordinates(s string) []string {
f := func(i, j int) []string {
res := []string{}
for k := 1; k <= j-i; k++ {
l, r := s[i:i+k], s[i+k:j]
ok := (l == "0" || l[0] != '0') && (r == "" || r[len(r)-1] != '0')
if ok {
t := ""
if k < j-i {
t = "."
}
res = append(res, l+t+r)
}
}
return res
}
n := len(s)
ans := []string{}
for i := 2; i < n-1; i++ {
for _, x := range f(1, i) {
for _, y := range f(i, n-1) {
ans = append(ans, "("+x+", "+y+")")
}
}
}
return ans
}Complexity comparison
| Approach | Complexity |
|---|---|
| Brute Force Split and Validate | Time Complexity: O(n^3), where n is the length of the string without parentheses. The combination of each split leads to n^2 pairs, and validating each part could take O(n) time. |
| Dynamic Generation with String Manipulation | Time Complexity: O(n^3), due to multiple levels of iterations and validations. Space Complexity: O(n^3), because all possible coordinates are stored. |
| Default Approach | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Split and Validate | O(n^3) | O(n^2) | Best for clarity. Easy to reason about and commonly expected in interviews. |
| Dynamic Generation with String Manipulation | O(n^3) | O(n^2) | Cleaner implementation when generating decimal placements directly without extra validation passes. |
Frequently asked questions
Is Ambiguous Coordinates easy or hard?
Ambiguous Coordinates is rated Medium on LeetCode. The algorithm itself is straightforward enumeration, but handling edge cases such as leading zeros and trailing zeros after decimals often trips up candidates during interviews.
Ambiguous Coordinates Python/Java solution
Both Python and Java implementations follow the same structure: remove parentheses, iterate over split positions, generate valid numbers for each substring, and combine them into coordinate pairs. Helper functions usually validate leading zeros and decimal formatting before adding candidates.
How to solve Ambiguous Coordinates in O(n)?
An O(n) solution is not practical because every possible split and decimal placement must be checked to verify formatting rules. The problem inherently requires enumerating candidate numbers, which leads to roughly O(n^3) time in the worst case.
What is the best approach for Ambiguous Coordinates?
The standard solution splits the digits string at every possible index and generates all valid numeric representations for each side. Each substring can either stay an integer or contain one decimal point, while respecting leading and trailing zero rules. This brute force enumeration runs in O(n^3) time and is typically the approach expected in interviews.
Is Ambiguous Coordinates asked at Google/Amazon/Meta?
Ambiguous Coordinates is a medium-level string enumeration problem similar to interview questions asked at companies like Amazon and Google. It tests string manipulation, edge‑case validation, and systematic candidate generation rather than advanced data structures.
What data structure is used in Ambiguous Coordinates?
The solution primarily uses strings and arrays (or lists) to store candidate numbers generated from each substring. No complex data structures are required; the core difficulty lies in validating number formatting rules and combining candidates efficiently.
What is the time complexity of Ambiguous Coordinates?
The typical implementation runs in O(n^3) time. You try O(n) split positions, generate up to O(n) decimal placements for each substring, and build coordinate strings. Space complexity is about O(n^2) excluding the final output list.
