Skip to main content

Strings

  • Understanding the string data type
  • Solved problems are presented in alphabetical order
note

A string is not a data structure. It's one of the most important data types.

Find All Anagrams in a String

↗ See LeetCode Problem #438

import java.util.List;import java.util.ArrayList;import java.util.Map;import java.util.HashMap;public class Solution {    public static List<Integer> findAnagrams(String s, String p) {        int leftIndex = 0;        int matchedCharacterCount = 0;        List<Integer> matchedIndices = new ArrayList<>();        Map<Character, Integer> pHMap = new HashMap<>();        for (char pCharacter : p.toCharArray()) {            pHMap.put(pCharacter,                    pHMap.getOrDefault (pCharacter,0) + 1);        }        for (int rightIndex = 0; rightIndex < s.length() ; rightIndex++) {            char rightCharacter = s.charAt(rightIndex);            if (pHMap.containsKey(rightCharacter)) {                pHMap.put(rightCharacter,                    pHMap.get(rightCharacter) - 1);                if (pHMap.get(rightCharacter) == 0) {                    matchedCharacterCount++;                }            }            //  If found an anagram            if (matchedCharacterCount == pHMap.size()) {                //  Add leftIndex as the starting index                //      of the anagram                matchedIndices.add(leftIndex);            }            if (rightIndex >= p.length() - 1) {                //  leftIndex++ in the following lines means                //      give character at leftIndex                //      and THEN, increase leftIndex by 1;                //      meaning, leftIndex = leftIndex + 1                char leftCharacter = s.charAt(leftIndex++);                if (pHMap.containsKey(leftCharacter)) {                    //  Check if leftCharacter is already matched                    if(pHMap.get(leftCharacter) == 0) {                        //  Decrease matched index by 1 since leftCharacter                        //      is being removed                        matchedCharacterCount--;                    }                    //  Put leftCharacter back for future matching                    pHMap.put(leftCharacter, pHMap.get(leftCharacter) + 1);                }            }        }        return matchedIndices;    }    public static void main(String[] args) {        // Example 1:        String s1 = "cbaebabacd";        String p1 = "abc";        //  O/P: [0,6]        // Example 2:        String s2 = "abab";        String p2 = "ab";        //  O/P: [0,1,2]        System.out.println(findAnagrams(s1, p1));        System.out.println(findAnagrams(s2, p2));    }}
Group Anagrams

↗ See LeetCode Problem #49

import java.util.*;public class Solution {    static List<List<String>> groupAnagrams(String[] strs) {        //  Return empty list if given string array is empty        if (strs.length == 0) {            return new ArrayList<>();        }        //  Create HashMap to generate the required output        Map<String, List> hMap = new HashMap<>();        //  Create integer array of 26        //      to count the occurrence of each letter        int[] count = new int[26];        for (String s : strs) {            Arrays.fill(count, 0);            for (char c : s.toCharArray()) {                count[c - 'a']++;            }            StringBuilder sBuilder = new StringBuilder("");            for (int i = 0; i < 26; i++) {                sBuilder.append('#');                sBuilder.append(count[i]);            }            String hMapKey = sBuilder.toString();            if (!hMap.containsKey(hMapKey)){                hMap.put(hMapKey, new ArrayList<>());            }            hMap.get(hMapKey).add(s);        }        System.out.println(hMap.keySet());        System.out.println(hMap.values());        return new ArrayList(hMap.values());    }    public static void main(String[] args) {        // Example 1:        String[] strs1 = {"eat","tea","tan","ate","nat","bat"};        //  O/P: [["bat"],["nat","tan"],["ate","eat","tea"]]        // Example 2:        String[] strs2 = {""};        //  O/P: [[""]]        // Example 3:        String[] strs3 = {"a"};        //  O/P: [["a"]]        // Example 4:        String[] strs4 = {};        //  O/P: [["a"]]        System.out.println(groupAnagrams(strs1));        System.out.println(groupAnagrams(strs2));        System.out.println(groupAnagrams(strs3));        System.out.println(groupAnagrams(strs4));    }}
Longest Common Prefix

↗ See LeetCode Problem #14

public class Solution {    static String longestCommonPrefix(String[] strs) {        if (strs == null || strs.length == 0) {            return "";        }        for (int i = 0; i < strs[0].length(); i++) {            for (int j = 1; j < strs.length; j++) {                if (i == strs[j].length() ||                        strs[j].charAt(i) != strs[0].charAt(i)) {                    return strs[0].substring(0,i);                }            }        }        return strs[0];    }    public static void main(String[] args) {        // Example 1:        String[] strs1 = {"flower","flow","flight"};        //  O/P: "fl"        // Example 2:        String[] strs2 = {"dog","racecar","car"};        //  O/P: ""        System.out.println(longestCommonPrefix(strs1));        System.out.println(longestCommonPrefix(strs2));    }}
Longest Palindrome

↗ See LeetCode Problem #409

import java.util.Map;import java.util.HashMap;public class Solution {    static int longestPalindrome(String s) {                //  Approach #1 (Without HashSet)        //  result: lenght of the longest palindrome        int result = 0;        int[] characterCount = new int[128];        for (char c : s.toCharArray()) {            characterCount[c]++;        }        for (int countNumber : characterCount) {            //  Add total occurrences of paired character            //  Multiplied by 2 since both occurrences of the character            //      contribute to the length            result += countNumber / 2 * 2;        }        //  Find and add (if present) the central        //      unpaired charcter        if (result < s.length()) {            result++;        }        return result;        //  Approach #1 (With HashSet)//        if (s == null || s.length() < 1) {//            return 0;//        }////        Set<Character> characterSet = new HashSet<>();////        for (int i = 0; i < s.length(); i++) {////            char c = s.charAt(i);////            if (characterSet.contains(c)) {//                characterSet.remove(c);//            } else {//                characterSet.add(c);//            }//        }////        if (characterSet.size() <= 1) {//            return s.length();//        }////        //  Remove unpaired characters from s//        //  Add 1 to include the central unpaired character//        //  The if statement immediately above takes care of//        //     the case with only one unpaired character//        return s.length() - characterSet.size() + 1;    }    public static void main(String[] args) {        // Example 1:        String s1 = "abccccdd";        //Output: 7        // Example 2:        String s2 = "a";        //Output: 1        System.out.println(longestPalindrome(s1));        System.out.println(longestPalindrome(s2));    }}
Longest Palindromic Substring

↗ See LeetCode Problem #5

public class Solution {    private static int centralExpansion(int left, int right, String s) {        while (left >= 0 && right < s.length() &&                s.charAt(left) == s.charAt(right)) {            left--;            right++;        }        //  "- 1" because index starts from "0"        return right - left - 1;    }    static String longestPalindrome(String s) {        if (s == null || s.length() < 1) {            return "";        }        int leftBoundary = 0;        int rightBoundary = 0;        for (int i = 0; i < s.length(); i++) {            //  For strings with odd length (example: "abcba")            int oddLength = centralExpansion(i, i, s);            //  For strings with even length (example: "abba")            int evenLength = centralExpansion(i, i + 1, s);            int maxLength = Math.max(oddLength, evenLength);            //  To deal with index out of bound cases            if (maxLength > rightBoundary - leftBoundary) {                //  Because, indices range between 0 and length - 1                //  Example: string.length() = 5                //      0, 1, 2, 3, 4                //      (5 - 1) / 2 = 2                //      5 / 2 = 2                //  Example: string.length() = 6                //      0, 1, 2, 3, 4, 5                //      (6 - 1) / 2 = 2                //      6 / 2 = 3                leftBoundary = i - (maxLength - 1) / 2;                rightBoundary = i + maxLength / 2;            }        }        //  return longest substring that begins with leftBoundary        //      and ends in rightBoundary (inclusive)        return s.substring(leftBoundary, rightBoundary + 1);    }    public static void main(String[] args) {        // Example 1:        String s1 = "babad";        //  O/P: "bab"        // Example 2:        String s2 = "cbbd";        //  O/P: "bb"        // Example 3:        String s3 = "eracecarluhgouwqzyufg";        //  O/P: "racecar"        System.out.println(longestPalindrome(s1));        System.out.println(longestPalindrome(s2));        System.out.println(longestPalindrome(s3));    }}
Longest Substring Without Repeating Characters

↗ See LeetCode Problem #3

import java.util.Map;import java.util.HashMap;public class Solution {    public static int lengthOfLongestSubstring(String s) {            //  Start of the sliding window        int windowStart = 0;        //  Length of the window        int windowSize = 0;        //  HashMap to store characer frequencies        Map<Character, Integer> characterFrequency = new HashMap<>();        //  i = windowEnd        for (int i = 0; i < s.length() ; i++) {            char rightCharacter = s.charAt(i);            if (characterFrequency.containsKey(rightCharacter)) {                windowStart = Math.max(windowStart,                        characterFrequency.get(rightCharacter) + 1);            }            characterFrequency.put(rightCharacter, i);            //  Updates the maximum length/size of the substring            windowSize = Math.max(windowSize, i - windowStart + 1);        }        return windowSize;    }    public static void main(String[] args) {        // Example 1:        String s1 = "abcabcbb";        //  O/P: 3        // Example 2:        String s2 = "bbbbb";        //  O/P: 1        // Example 3:        String s3 = "pwwkew";        //  O/P: 3        System.out.println(lengthOfLongestSubstring(s1));        System.out.println(lengthOfLongestSubstring(s2));        System.out.println(lengthOfLongestSubstring(s3));    }}
Minimum Window Substring

↗ See LeetCode Problem #76

import java.util.HashMap;import java.util.Map;public class Solution {    static String minWindow(String s, String t) {        if (s.length() == 0 || t.length() == 0){            return "";        }        int windowStart = 0;        int windowEnd;        int matchedCharacters = 0;        int substringStart = 0;        int minWindowSize = s.length() + 1; //  Smallest (maximum) impossible size        Map<Character, Integer> patternMap = new HashMap<>();//        t.chars().mapToObj(c -> (char) c)//                .forEach(c -> patternMap.put(//                        c, patternMap.getOrDefault(c, 0) + 1));        for (int i = 0; i < t.length(); i++) {            char ch = t.charAt(i);            patternMap.put(ch,                    patternMap.getOrDefault(ch, 0) + 1);        }        for (windowEnd = 0; windowEnd < s.length(); windowEnd++) {            //  Declare and store current character at index windowEnd            char rightChar = s.charAt(windowEnd);            if (patternMap.containsKey(rightChar)) {                patternMap.put(rightChar, patternMap.get(rightChar) - 1);                if (patternMap.get(rightChar) >= 0) {                    //  Increase the count of matched characters                    //      for every encounter of a matching character                    //  However, ignore if patternMap.get(key) < 0,                    //      which means the required number matches                    //      for that key/rightChr have already been accounted for                    matchedCharacters++;                }            }            while (matchedCharacters == t.length()) {                //  + 1 b/c 0-indexed//                int windowLength = windowEnd - windowStart + 1;                if (minWindowSize > windowEnd - windowStart + 1) {                    //  Update minimum window size if                    //      current (properly matching) window length is smaller                    minWindowSize = windowEnd - windowStart + 1;                    //  Store the current windowStart as the                    //      starting index of the required minimum window substring                    substringStart = windowStart;                }                //  Store the character at the start of the window                //      and, after that increase windowStart by 1                char leftChar = s.charAt(windowStart++);                //  Check if the character at the start of the window                //      is present in the pattern map                if (patternMap.containsKey(leftChar)) {                    //  If present, it has already been accounted for                    //      in matchedCharacters count                    //  So, if its current count is 0,                    //      remove it from the count of matchedCharacters                    //      by decreasing the value of matchedCharacters by 1                    if (patternMap.get(leftChar) == 0) {                        matchedCharacters--;                    }                    //  If patternMap.get(key/leftchar) is > (i.e. !=) 0 or just 0                    //     put it back in the pattern map by increasing the value by 1,                    //     since leftchar is moving out of the window                    //     in the following/next iteration                    patternMap.put(leftChar, patternMap.get(leftChar) + 1);                }            }        }        //  return empty string if minimum substring doesn't exist        //      (i.e. length of given string > minWindowSize) or        //      return the minimum window substring        return minWindowSize > s.length() ?                "" : s.substring(substringStart, substringStart + minWindowSize);    }    public static void main(String[] args) {        // Example 1:        String s1 = "ADOBECODEBANC";        String t1 = "ABC";        //  O/P: "BANC"        // Example 2:        String s2 = "a";        String t2 = "a";        //  O/P: "a"        // Example 3:        String s3 = "a";        String t3 = "aa";        //  O/P: ""        System.out.println("Example 1: " + minWindow(s1,t1));        System.out.println("Example 2: " + minWindow(s2,t2));        System.out.println("Example 3: " + minWindow(s3,t3));    }}
String to Integer (atoi)

↗ See LeetCode Problem #8

public class Solution {    public static int myAtoi(String s) {        //  Initialize the index        int index = 0;        //  Sign of the output/result        int sign = 1;        //  The output        int result = 0;        //  Skip all leading whitespaces        while (index < s.length() && s.charAt(index) == ' ') {            index++;        }        //  Now, check if positive or negative        //  First check if positive        if (index < s.length() && s.charAt(index) == '+') {            //  Keep sign positive            sign = 1;            //  Move on to next character            index++;        //  Then check if negative        } else if (index < s.length() && s.charAt(index) == '-') {            //  Make the sign negative            sign = -1;            //  Move on to next character            index++;        }        //  Move forward only next characters are digits        //      End the loop if not digits        while (index < s.length() &&                Character.isDigit(s.charAt(index))) {            //  ASCII character '0' has a value of 48            //      and '1' is 49 and so on...            int sDigit = s.charAt(index) - '0';            //  Check overflow and underflow            //  Check if result is out of 32-bit range            if ((result > Integer.MAX_VALUE / 10) ||                    //  Check if result is in 32-bit range                    (result == Integer.MAX_VALUE / 10 &&                            sDigit > Integer.MAX_VALUE % 10)) {                // return maximum or minimum 32-bit integer value                //     depending on if sign == 1 is true or false                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;            }            // Build the result using the current digit            result = 10 * result + sDigit;            // Increase index by 1 and move on to next loop            index++;        }        return sign * result;    }    public static void main(String[] args) {        // Example 1:        String s1 = "42";        //Output: 42        // Example 2:        String s2 = "   -42";        //Output: -42        // Example 3:        String s3 = "4193 with words";        //Output: 4193        System.out.println(myAtoi(s1));        System.out.println(myAtoi(s2));        System.out.println(myAtoi(s3));    }}
Valid Anagram

↗ See LeetCode Problem #242

public class Solution {    static boolean isAnagram(String s, String t) {        if (s.length() != t.length()) {            return false;        }        java.util.Map<Character, Integer> sMap = new java.util.HashMap<>();        for (int i = 0; i < s.length(); i++) {            sMap.put(s.charAt(i), sMap.getOrDefault(s.charAt(i),0) + 1);            sMap.put(t.charAt(i), sMap.getOrDefault(t.charAt(i),0) - 1);        }        for (char c : sMap.keySet()) {            if (sMap.get(c) != 0) {                return false;            }        }        return true;    }    public static void main(String[] args) {        // Example 1:        String s1 = "anagram";        String t1 = "nagaram";        //  O/P: true        // Example 2:        String s2 = "rat";        String t2 = "car";        //  O/P: false        System.out.println("Example 1: " + isAnagram(s1,t1));        System.out.println("Example 2: " + isAnagram(s2,t2));    }}
Valid Palindrome

↗ See LeetCode Problem #125

public class Solution {    static boolean isPalindrome(String s) {        for (int i = 0, j = s.length() - 1; i < j; i++, j--) {            while (i < j && !Character.isLetterOrDigit(s.charAt(i))) {                i++;            }            while (i < j && !Character.isLetterOrDigit(s.charAt(j))) {                j--;            }            if (Character.toLowerCase(s.charAt(i)) !=                    Character.toLowerCase(s.charAt(j))) {                return false;            }        }        return true;    }    public static void main(String[] args) {        // Example 1:        String s1 = "A man, a plan, a canal: Panama";        //  O/P: true        // Example 2:        String s2 = "race a car";        //  O/P: false        // Example 3:        String s3 = " ";        //  O/P: true        System.out.println(isPalindrome(s1));        System.out.println(isPalindrome(s2));        System.out.println(isPalindrome(s3));    }}