From b2815db5cd6d19d0a94424fbb27ea53201085a12 Mon Sep 17 00:00:00 2001 From: Alex Klymenko Date: Wed, 28 Aug 2024 18:40:27 +0200 Subject: [PATCH] refactor: `LongestNonRepetitiveSubstring` (#5421) * refactor: LongestNonRepetitiveSubstring * checkstyle: fix formatting --------- Co-authored-by: alxkm --- .../LongestNonRepetitiveSubstring.java | 55 ++++++++----------- .../LongestNonRepetitiveSubstringTest.java | 23 +++++--- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/LongestNonRepetitiveSubstring.java b/src/main/java/com/thealgorithms/strings/LongestNonRepetitiveSubstring.java index c113162f..6808cd50 100644 --- a/src/main/java/com/thealgorithms/strings/LongestNonRepetitiveSubstring.java +++ b/src/main/java/com/thealgorithms/strings/LongestNonRepetitiveSubstring.java @@ -3,47 +3,40 @@ package com.thealgorithms.strings; import java.util.HashMap; import java.util.Map; +/** + * Class for finding the length of the longest substring without repeating characters. + */ final class LongestNonRepetitiveSubstring { private LongestNonRepetitiveSubstring() { } + /** + * Finds the length of the longest substring without repeating characters. + * + * @param s the input string + * @return the length of the longest non-repetitive substring + */ public static int lengthOfLongestSubstring(String s) { - int max = 0; + int maxLength = 0; int start = 0; - int i = 0; - Map map = new HashMap<>(); + Map charIndexMap = new HashMap<>(); - while (i < s.length()) { - char temp = s.charAt(i); + for (int i = 0; i < s.length(); i++) { + char currentChar = s.charAt(i); - // adding key to map if not present - if (!map.containsKey(temp)) { - map.put(temp, 0); - } else if (s.charAt(start) == temp) { - start++; - } else if (s.charAt(i - 1) == temp) { - if (max < map.size()) { - max = map.size(); - } - map = new HashMap<>(); - start = i; - i--; - } else { - if (max < map.size()) { - max = map.size(); - } - while (s.charAt(start) != temp) { - map.remove(s.charAt(start)); - start++; - } - start++; + // If the character is already in the map and its index is within the current window + if (charIndexMap.containsKey(currentChar) && charIndexMap.get(currentChar) >= start) { + // Move the start to the position right after the last occurrence of the current character + start = charIndexMap.get(currentChar) + 1; } - i++; + // Update the last seen index of the current character + charIndexMap.put(currentChar, i); + + // Calculate the maximum length of the substring without repeating characters + maxLength = Math.max(maxLength, i - start + 1); } - if (max < map.size()) { - max = map.size(); - } - return max; + + return maxLength; } } diff --git a/src/test/java/com/thealgorithms/strings/LongestNonRepetitiveSubstringTest.java b/src/test/java/com/thealgorithms/strings/LongestNonRepetitiveSubstringTest.java index c6fd8c59..791c4ba3 100644 --- a/src/test/java/com/thealgorithms/strings/LongestNonRepetitiveSubstringTest.java +++ b/src/test/java/com/thealgorithms/strings/LongestNonRepetitiveSubstringTest.java @@ -1,15 +1,22 @@ package com.thealgorithms.strings; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; public class LongestNonRepetitiveSubstringTest { - @Test - public void palindrome() { - String input1 = "HelloWorld"; - String input2 = "javaIsAProgrammingLanguage"; - Assertions.assertEquals(LongestNonRepetitiveSubstring.lengthOfLongestSubstring(input1), 5); - Assertions.assertEquals(LongestNonRepetitiveSubstring.lengthOfLongestSubstring(input2), 9); + private static Stream provideTestCases() { + return Stream.of(Arguments.of("", 0), Arguments.of("a", 1), Arguments.of("abcde", 5), Arguments.of("aaaaa", 1), Arguments.of("abca", 3), Arguments.of("abcdeabc", 5), Arguments.of("a1b2c3", 6), Arguments.of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62), + Arguments.of("aabb", 2), Arguments.of("abcdefghijabc", 10)); + } + + @ParameterizedTest + @MethodSource("provideTestCases") + void testLengthOfLongestSubstring(String input, int expectedLength) { + assertEquals(expectedLength, LongestNonRepetitiveSubstring.lengthOfLongestSubstring(input)); } }