Advertisement

Last Substring in Lexicographical Order - LeetCode 1163 Solution

Last Substring in Lexicographical Order - Complete Solution Guide

Last Substring in Lexicographical Order is LeetCode problem 1163, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.

Problem Statement

Given a string s , return the last substring of s in lexicographical order . Example 1: Input: s = "abab" Output: "bab" Explanation: The substrings are ["a", "ab", "aba", "abab", "b", "ba", "bab"]. The lexicographically maximum substring is "bab". Example 2: Input: s = "leetcode" Output: "tcode" Constraints: 1 <= s.length <= 4 * 10 5 s contains only lowercase English letters.

Detailed Explanation

The problem asks us to find the lexicographically largest substring within a given string 's'. Lexicographical order is essentially dictionary order. For example, 'abc' comes before 'abd', and 'baa' comes before 'bab'. The task is to return the substring of 's' that would appear last in a dictionary if all substrings were listed.

Solution Approach

The provided solution employs a two-pointer approach to find the starting index of the lexicographically largest substring. It iteratively compares two substrings, indicated by indices 'i' and 'j', using a third index 'k' to track the matching prefix length. Based on the comparison, it updates 'i' and 'j' to converge towards the starting position of the last substring. This algorithm avoids generating and explicitly comparing all substrings, leading to an efficient solution.

Step-by-Step Algorithm

  1. Step 1: Initialize three pointers: 'i' to 0, 'j' to 1, and 'k' to 0. 'i' and 'j' represent the starting indices of two potential last substrings, and 'k' tracks the length of the matching prefix between the substrings starting at 'i' and 'j'.
  2. Step 2: Iterate while 'j + k' is within the bounds of the string length 'n'.
  3. Step 3: Compare the characters at 's[i + k]' and 's[j + k]'.
  4. Step 4: If 's[i + k]' equals 's[j + k]', increment 'k' to compare the next characters.
  5. Step 5: If 's[i + k]' is less than 's[j + k]', it means the substring starting at 'j' is lexicographically greater than the substring starting at 'i'. Update 'i' to 'j', 'j' to 'i + 1', and reset 'k' to 0.
  6. Step 6: If 's[i + k]' is greater than 's[j + k]', it means the substring starting at 'i' is lexicographically greater. Update 'j' to 'j + k + 1', and reset 'k' to 0. This effectively skips the portion of the string that has already been determined to be smaller.
  7. Step 7: After the loop finishes, 'i' will hold the starting index of the lexicographically last substring. Return the substring of 's' starting from index 'i'.

Key Insights

  • Insight 1: We don't need to generate all substrings. Comparing substrings directly would be inefficient. Instead, we can efficiently identify the starting index of the last substring.
  • Insight 2: The core idea is to maintain two pointers, 'i' and 'j', representing the starting indices of two potential candidates for the last substring. We compare the substrings starting at 'i' and 'j' character by character.
  • Insight 3: If s[i+k] == s[j+k], we increment k to compare the next characters. If s[i+k] < s[j+k], then the substring starting at 'j' is lexicographically larger, so we update i = j. If s[i+k] > s[j+k], the substring at 'i' is larger, so we advance 'j' beyond the matched portion.

Complexity Analysis

Time Complexity: O(n)

Space Complexity: O(1)

Topics

This problem involves: Two Pointers, String.

Companies

Asked at: Fastenal, MathWorks.