Add a new implementation for CheckAnagrams (#4231)

This commit is contained in:
Albina Gimaletdinova 2023-07-06 16:56:59 +03:00 committed by GitHub
parent 2456d86432
commit 9ecc3aae59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 105 additions and 16 deletions

View File

@ -8,13 +8,6 @@ import java.util.Map;
* differently (ignoring the case).
*/
public class CheckAnagrams {
public static void main(String[] args) {
assert isAnagrams("Silent", "Listen");
assert isAnagrams("This is a string", "Is this a string");
assert !isAnagrams("There", "Their");
}
/**
* Check if two strings are anagrams or not
*
@ -50,4 +43,66 @@ public class CheckAnagrams {
}
return true;
}
/**
* If given strings contain Unicode symbols.
* The first 128 ASCII codes are identical to Unicode.
* This algorithm is case-sensitive.
*
* @param s1 the first string
* @param s2 the second string
* @return true if two string are anagrams, otherwise false
*/
public static boolean isAnagramsUnicode(String s1, String s2) {
int[] dict = new int[128];
for (char ch : s1.toCharArray()) {
dict[ch]++;
}
for (char ch : s2.toCharArray()) {
dict[ch]--;
}
for (int e : dict) {
if (e != 0) {
return false;
}
}
return true;
}
/**
* If given strings contain only lowercase English letters.
* <p>
* The main "trick":
* To map each character from the first string 's1' we need to subtract an integer value of 'a' character
* as 'dict' array starts with 'a' character.
*
* @param s1 the first string
* @param s2 the second string
* @return true if two string are anagrams, otherwise false
*/
public static boolean isAnagramsOptimised(String s1, String s2) {
// 26 - English alphabet length
int[] dict = new int[26];
for (char ch : s1.toCharArray()) {
checkLetter(ch);
dict[ch - 'a']++;
}
for (char ch : s2.toCharArray()) {
checkLetter(ch);
dict[ch - 'a']--;
}
for (int e : dict) {
if (e != 0) {
return false;
}
}
return true;
}
private static void checkLetter(char ch) {
int index = ch - 'a';
if (index < 0 || index >= 26) {
throw new IllegalArgumentException("Strings must contain only lowercase English letters!");
}
}
}

View File

@ -1,35 +1,69 @@
package com.thealgorithms.strings;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class CheckAnagramsTest {
private static final String MESSAGE = "Strings must contain only lowercase English letters!";
// CHECK METHOD isAnagrams()
@Test
public void CheckAnagrams() {
public void testCheckAnagrams() {
String testString1 = "STUDY";
String testString2 = "DUSTY";
assertTrue(CheckAnagrams.isAnagrams(testString1, testString2));
Assertions.assertTrue(CheckAnagrams.isAnagrams(testString1, testString2));
}
@Test
public void CheckFalseAnagrams() {
public void testCheckFalseAnagrams() {
String testString1 = "STUDY";
String testString2 = "random";
assertFalse(CheckAnagrams.isAnagrams(testString1, testString2));
Assertions.assertFalse(CheckAnagrams.isAnagrams(testString1, testString2));
}
@Test
public void CheckSameWordAnagrams() {
public void testCheckSameWordAnagrams() {
String testString1 = "STUDY";
assertTrue(CheckAnagrams.isAnagrams(testString1, testString1));
Assertions.assertTrue(CheckAnagrams.isAnagrams(testString1, testString1));
}
@Test
public void CheckDifferentCasesAnagram() {
public void testCheckDifferentCasesAnagram() {
String testString1 = "STUDY";
String testString2 = "dusty";
assertTrue(CheckAnagrams.isAnagrams(testString1, testString2));
Assertions.assertTrue(CheckAnagrams.isAnagrams(testString1, testString2));
}
// CHECK METHOD isAnagramsUnicode()
// Below tests work with strings which consist of Unicode symbols & the algorithm is case-sensitive.
@Test
public void testStringAreValidAnagramsCaseSensitive() {
Assertions.assertTrue(CheckAnagrams.isAnagramsUnicode("Silent", "liSten"));
Assertions.assertTrue(CheckAnagrams.isAnagramsUnicode("This is a string", "is This a string"));
}
@Test
public void testStringAreNotAnagramsCaseSensitive() {
Assertions.assertFalse(CheckAnagrams.isAnagramsUnicode("Silent", "Listen"));
Assertions.assertFalse(CheckAnagrams.isAnagramsUnicode("This is a string", "Is this a string"));
}
// CHECK METHOD isAnagramsOptimised()
// Below tests work with strings which consist of only lowercase English letters
@Test
public void testOptimisedAlgorithmStringsAreValidAnagrams() {
Assertions.assertTrue(CheckAnagrams.isAnagramsOptimised("silent", "listen"));
Assertions.assertTrue(CheckAnagrams.isAnagramsOptimised("mam", "amm"));
}
@Test
public void testOptimisedAlgorithmShouldThrowExceptionWhenStringsContainUppercaseLetters() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> CheckAnagrams.isAnagramsOptimised("Silent", "Listen"));
Assertions.assertEquals(exception.getMessage(), MESSAGE);
exception = assertThrows(IllegalArgumentException.class, () -> Assertions.assertFalse(CheckAnagrams.isAnagramsOptimised("This is a string", "Is this a string")));
Assertions.assertEquals(exception.getMessage(), MESSAGE);
}
}