6 String exercises, can you do it?

Keywords: Java string

preface

String string is a data structure that appears very frequently in our development. I have prepared several small questions here. Whether you are a beginner or an expert, you can try whether you can easily solve the following questions. If you have better solutions, you are welcome to communicate in the comments!

  1. How to invert a string without using Java built-in methods?
  2. Write a java program to check whether two strings are ectopic words? [ectopic words refer to different positions of the same character]
  3. Judge whether all characters in a string appear only once?
  4. How do I find duplicate characters in a string?
  5. Find all substrings of the string?
  6. Find all possible permutations of an input string?

Before starting to look at the following solutions, you might as well think about how to solve these problems, and then see if the following methods are consistent with what you think. If your method is better, you are welcome to leave a message in the comment area.

How to invert a string without using Java built-in methods?

There are three ways to solve this problem:

  • Use cycle
  • Use recursion
  • Use StringBuilder, StringBuffer

Using the for loop

Idea:

  1. Declare an empty String variable to save the final inverted String;
  2. Use the for loop to traverse the string to be reversed, from the last position to the 0th position;
  3. Adds characters to the declared empty String variable during traversal.
public class ReverseStringForMain {
    public static void main(String[] args) {
        String blogName = "Xiao Hei said Java";
        String reverse = "";
        for (int i = blogName.length() - 1; i >= 0; i--) {
            reverse = reverse + blogName.charAt(i);
        }
        System.out.println("Reverse of Xiao Hei said Java is: " + reverse);
    }
}

Use recursion

Idea:

  1. If the string length is 1, the inversion result is the string itself;
  2. If the string length is greater than 1, the inversion result is the last character of the string plus the inversion result of the remaining strings.
public class ReverseStringRecursive {
    public static void main(String[] args) {
        ReverseStringRecursive rsr = new ReverseStringRecursive();
        String blogName = "Xiao Hei said Java";
        String reverse = rsr.recursiveReverse(blogName);
        System.out.println("Reverse of Xiao Hei said Java is:" + reverse);
    }
 
    public String recursiveReverse(String orig) {
        if (orig.length() == 1){
            return orig;
        }else{
            return orig.charAt(orig.length() - 1) + 
                          recursiveReverse(orig.substring(0, orig.length() - 1));
        }
    }
}

Use StringBuffer

Using the reverse method of StringBuffer, you can also reverse the string.

public class StringBufferReverse {
    public static void main(String[] args) {
        String blogName = "Xiao Hei said Java";
        StringBuffer sb = new StringBuffer(blogName);
        System.out.println("Reverse of Xiao Hei said Java is:" + sb.reverse());
    }
}

Write a java program to check whether two strings are ectopic words?

Note: ectopic words refer to two words with the same letters but in different order, such as Angel and Angle.

There are many ways to solve this problem:

  • Methods using the String class
  • Use Arrays.sort()
  • Use count array
  • Use Guava's Multiset

Using String class methods

Idea:

  1. Establish a method to receive two string variables to judge whether it is an ectopic word;
  2. Iterate over the first String word and use the charAt() method to get char c from it;
  3. If the value of indexOf(c) of the second String word is equal to - 1, then the two strings are not puzzles;
  4. If the value of indexOf(c) of the second String word is not equal to - 1, delete the character c from the second word;
  5. If the second String word ends with an empty String, it means that the two words are ectopic words.
public class StringAnagramMain {
 
    public static void main(String[] args) {
        String word = "Xiao Hei said Java";
        String anagram = "Xiao Hei said JAVA";
        System.out.println("Xiao Hei said Java and Xiao Hei said JAVA are anagrams :" + isAnagramUsingStringMethods(word, anagram));
    }
 
    public static boolean isAnagramUsingStringMethods(String word, String anagram) {
        if (word.length() != anagram.length())
            return false;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            int index = anagram.indexOf(c);
            if (index != -1) {
                anagram = anagram.substring(0, index) 
                    + anagram.substring(index + 1, anagram.length());
            } else{
                 return false;
            }
        }
        return anagram.isEmpty();
    }
}

Use Arrays.sort()

Idea: sort the two strings directly. If the two strings are equal after sorting, it means that the two strings are ectopic words.

public class AnagramUsingSort {
 
    public static void main(String[] args) {
        String word = "Xiao Hei said Java";
        String anagram = "Xiao Hei said JAVA";
        System.out.println("Xiao Hei said Java and Xiao Hei said JAVA are anagrams :" + isAnagramUsingArraySort(word, anagram));
    }
 
    public static boolean isAnagramUsingArraySort(String word, String anagram) {
        String sortedWord = sortChars(word);
        String sortedAnagram = sortChars(anagram);
        return sortedWord.equals(sortedAnagram);
    }
 
    public static String sortChars(String word) {
        char[] wordArr = word.toLowerCase().toCharArray();
        Arrays.sort(wordArr);
        return String.valueOf(wordArr);
    }
}

Use count array

Idea:

  1. If the two strings are different in length, they are not ectopic words;
  2. Create an array with a length of 256;
  3. Iterate over the first string str1;
  4. In each iteration, we increase the count of the first String str1 and decrease the count of the second String str2;
  5. If the count of any character is not 0 at the end, it means that the two string s are not a puzzle.

The time complexity of this method is O(n), but it requires an additional space count array.

public class AnagramCountingMain {
 
    public static void main(String args[])
    {
        boolean isAnagram = isAnagram("Angle","Angel");
        System.out.println("Are Angle and Angel anangrams: "+isAnagram);
    }
 
    public static boolean isAnagram(String str1, String str2) {
        if (str1.length() != str2.length()) {
            return false;
        }
        int count[] = new int[256];
        for (int i = 0; i < str1.length(); i++) {
            count[str1.charAt(i)]++;
            count[str2.charAt(i)]--;
        }
        for (int i = 0; i < 256; i++) {
            if (count[i] != 0) {
                return false;
            }
        }
        return true;
    }
}

Use Guava's Multiset

If you prefer to use the Guava library, you can use MultiSet to check whether the two strings are ectopic words.

MultiSet allows each element to appear multiple times and records the count of each element.

Of course, in this way, you need to add Guava dependency in pom.xml.

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.1-jre</version>
</dependency>

The code is as follows:

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
 
public class AnagramMultiSet {
 
    public static void main(String args[])
    {
        boolean isAnagram = isAnagramMultiset("Angle","Angel");
        System.out.println("Are Angle and Angel anangrams: "+isAnagram);
    }
 
    public static boolean isAnagramMultiset(String str1, String str2) {
        if (str1.length() != str2.length()) {
            return false;
        }
        Multiset<Character> ms1 = HashMultiset.create();
        Multiset<Character> ms2 = HashMultiset.create();
        for (int i = 0; i < str1.length(); i++) {
            ms1.add(str1.charAt(i));
            ms2.add(str2.charAt(i));
        }
        return ms1.equals(ms2);
    }
}

Judge whether all characters in a string appear only once?

Note: for example, the character p appears many times in Apple words, so it does not meet the requirements; All words in the world appear only once, so they meet the requirements.

There are several solutions to this problem:

  • Using HashSet
  • Use indexOf and lastIndexOf methods
  • ascii value using characters

Using HashSet

Depending on the add() method of HashSet, if the element already exists, it will return false.

Steps:

  1. Traverse each character and add it to HashSet;
  2. If the add method of HashSet returns false, it is not all unique characters.
public class StringAllUniqueCharMain {
 
 public static void main(String[] args) {
  System.out.println("Apple has all unique chars :"+ hasAllUniqueChars("apple"));
  System.out.println("index has all unique chars :"+ hasAllUniqueChars("index"));
  System.out.println("world has all unique chars :"+ hasAllUniqueChars("world"));
 }
 
 public static boolean hasAllUniqueChars (String word) {
     HashSet alphaSet=new HashSet();
     for(int index=0;index < word.length(); index ++)   {
         char c =word.charAt(index);
         if(!alphaSet.add(c))
              return false;
     }
     return true;
 }
}

Use indexOf and lastIndexOf methods

Idea: if indexOf and lastIndexOf return the same value for characters, they will not be repeated in the string.

public class StringAllUniqueCharMain {
 
 public static void main(String[] args) {
  System.out.println("Apple has all unique chars : "+ hasAllUniqueChars("apple"));
  System.out.println("index has all unique chars : "+ hasAllUniqueChars("index"));
  System.out.println("world has all unique chars : "+ hasAllUniqueChars("world"));
 }
 
 public static boolean hasAllUniqueChars (String word) {
     for(int index=0;index < word.length(); index ++)   {
         char c =word.charAt(index);
         if(word.indexOf(c)!=word.lastIndexOf(c))
              return false;
     }
     return true;
 }
}

ascii value using characters

This method is the most efficient.

Idea:

  1. Create a Boolean array with a length of 26;
  2. Convert char to uppercase and obtain its ascii value;
  3. Subtract 64 from the ascii value to obtain an index between 0 and 25;
  4. If the characters are not repeated, there should be false in the Boolean array;
public class StringAllUniqueCharMain {
 
 public static void main(String[] args) {
  System.out.println("Apple has all unique chars : "+ hasAllUniqueChars("apple"));
  System.out.println("index has all unique chars : "+ hasAllUniqueChars("index"));
  System.out.println("world has all unique chars : "+ hasAllUniqueChars("world"));
 }
 
 public static boolean hasAllUniqueChars (String word) {
     boolean[] charMap = new boolean[26];
     for(int index=0;index < word.length(); index ++)   {
      // we are substracting char's ascii value to 64, so we get all index
      // from 0 to 25.
         int asciiCode = (int) word.toUpperCase().charAt(index) - 64;
         if(!charMap[asciiCode])
          charMap[asciiCode] = true;
          else
             return false;
     }
     return true;
 }
 
}

How do I find duplicate characters in a string?

Idea:

  1. Create a HashMap, create a HashMap, insert string characters as key s, and insert their counts as value s;
  2. If the HashMap already contains a char, increase its count by 1, otherwise put the char into the HashMap;
  3. If the value of Char is greater than 1, it means that it is a duplicate character in the string.
import java.util.HashMap;

public class StringFindDuplicatesMain {
    public static void main(String[] args) {
        String str = "juejin.com ";
        HashMap<Character, Integer> charCountMap = new HashMap<>();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (charCountMap.containsKey(c)) {
                charCountMap.put(c, charCountMap.get(c) + 1);
            } else {
                charCountMap.put(c, 1);
            }
        }
        for (Character c : charCountMap.keySet()) {
            if (charCountMap.get(c) > 1)
                System.out.println("duplicate character : " + c + " ====== " + " count : " + charCountMap.get(c));
        }
    }
}

Find all substrings of the string?

For example, if the input is abb, the output should be a, b, b, ab, bb, abb

Idea: use the subString method of String class to find all substrings.

class SubstringsOfStringMain{
    public static void main(String args[]){
        String str="abbc";
        System.out.println("All substring of abbc are:");
        for (int i = 0; i < str.length(); i++) {
            for (int j = i+1; j <= str.length(); j++) {
                System.out.println(str.substring(i,j));
            }
        }
    }
}

The time complexity of this solution is O(n^3). Because we have two loops and the time complexity of the substring method of String is O(n)

If you want to find all the different substrings of a String, you need to use HashSet to remove duplicate strings.

Find all possible permutations of an input string?

For example, enter "AB" to output ["AB","BA"], enter "ABC" to output ["ABC","ACB","BAC","BCA","CBA","CAB"].

Idea:

  1. Take out the first character of the String and recursively input the different positions of the arrangement of the remaining strings;
  2. Assuming that the input String is ABC, take out the first character "A";
  3. Take out B from BC and recursively input the remaining string "C";
  4. When the String length is 1, it returns, so "C" is returned;
  5. Insert the extracted "B" into each position of the string returned recursively;
  6. At this time, BC and CB are obtained and returned;
  7. Insert the extracted character "A" into each position of the string returning the result;
  8. At this time, [ABC,BAC,BCA] and [ACB,CAB,CBA] are obtained;
  9. The final result is all sorts of ABC.
import java.util.HashSet;
import java.util.Set;

public class PermutationOfStringJava {

    public static void main(String[] args) {
        Set<String> set = permutationOfString("ABC");
        System.out.println("Permutations of String ABC are:");
        for (String str : set) {
            System.out.println(str);
        }
    }

    public static Set<String> permutationOfString(String str) {
        Set<String> permutationSet = new HashSet<>();
        if (str.length() == 1) {
            permutationSet.add(str);
            return permutationSet;
        }
        char c = str.charAt(0);
        String rem = str.substring(1);
        Set<String> permutatedSetForRemainingString = permutationOfString(rem);
        for (String permutedString : permutatedSetForRemainingString) {
            for (int j = 0; j <= permutedString.length(); j++) {
                String permutation = insertFirstCharAtDiffPlaces(permutedString, c, j);
                permutationSet.add(permutation);
            }
        }
        return permutationSet;

    }
    public static String insertFirstCharAtDiffPlaces(String perm, char firstChar, int index) {
        return perm.substring(0, index) + firstChar + perm.substring(index);
    }
}

Summary

The above is all the content of this issue. How about these methods? Have you thought of them? If you have a better way, welcome to leave a message.

If it helps you, a compliment is my greatest encouragement.

 

Posted by alex57 on Thu, 04 Nov 2021 07:28:15 -0700