Skip to content

Commit 4b283b2

Browse files
committed
Add valid anagram problem
1 parent a60ade3 commit 4b283b2

File tree

9 files changed

+159
-56
lines changed

9 files changed

+159
-56
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ List of Programs related to data structures and algorithms
8686

8787
3. Minimum window substring: [Source](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/3.minWindowSubstring/minWindowSubstring.js) [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/3.minWindowSubstring/minWindowSubstring.js) [Documentation](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/3.minWindowSubstring/minWindowSubstring.md)
8888

89-
4. Valid anagram: [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/validAnagram.js)
89+
4. Valid anagram: [Source](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/4.validAnagram/validAnagram.js) [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/4.validAnagram/validAnagram.js) [Documentation](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/4.validAnagram/validAnagram.md)
9090

91-
5. Group anagrams: [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/groupAnagrams.js)
91+
5. Group anagrams: [Source](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/5.groupAnagrams/groupAnagrams.js) [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/5.groupAnagrams/groupAnagrams.js) [Documentation](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/5.groupAnagrams/groupAnagrams.md)
9292

9393
6. Valid parentheses: [JavaScript]()
9494

src/java1/algorithms/strings/GroupAnagrams.java src/java1/algorithms/strings/groupAnagrams/GroupAnagrams.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package java1.algorithms.strings;
1+
package java1.algorithms.strings.groupAnagrams;
22

33
import java.util.*;
44

src/java1/algorithms/strings/groupAnagrams/GroupAnagrams.md

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,44 @@
1-
package java1.algorithms.strings;
1+
package java1.algorithms.strings.validAnagram;
22

3+
import java.util.Arrays;
34
import java.util.HashMap;
45

56
public class ValidAnagram {
67

7-
//HashMap:- TC:O(n) SC:O(n)
8+
//Using Array: TC:O(n) SC:O(1)
9+
810
private static boolean validAnagram1(String str1, String str2) {
11+
if(str1.length() != str2.length()) return false;
12+
13+
int[] chars = new int[26];
14+
15+
for(int i=0; i< str1.length(); i++) {
16+
char ch1 = str1.charAt(i);
17+
char ch2 = str2.charAt(i);
18+
chars[ch1 - 'a']++;
19+
chars[ch2 - 'a']--;
20+
}
21+
22+
for(int ch: chars) {
23+
if(ch !=0) return false;
24+
}
25+
26+
return true;
27+
}
28+
29+
//HashMap:- TC:O(n) SC:O(n)
30+
private static boolean validAnagram2(String str1, String str2) {
931
if(str1.length() != str2.length()) {
1032
return false;
1133
}
1234

1335
HashMap<Character, Integer> hashMap = new HashMap<>();
1436

15-
for(int i = 0; i< str1.length(); i++) {
16-
char ch = str1.charAt(i);
37+
for(char ch: str1.toCharArray()) {
1738
hashMap.put(ch, hashMap.getOrDefault(ch, 0) + 1);
1839
}
1940

20-
for(int j=0; j< str2.length(); j++) {
21-
char ch = str2.charAt(j);
41+
for(char ch: str2.toCharArray()) {
2242
if(hashMap.containsKey(ch)) {
2343
if(hashMap.get(ch) == 1) {
2444
hashMap.remove(ch);
@@ -30,34 +50,38 @@ private static boolean validAnagram1(String str1, String str2) {
3050
}
3151
}
3252

33-
if(hashMap.size() == 0) {
34-
return true;
35-
} else {
36-
return false;
37-
}
53+
return hashMap.size() == 0;
3854
}
3955

40-
//Using Array: TC:O(n) SC:O(1)
56+
//Sorting and compare built-in methods:- TC:O(n logn) SC:O(n)
57+
private static boolean validAnagram3(String str1, String str2) {
58+
if(str1.length() != str2.length()) {
59+
return false;
60+
}
4161

42-
private static boolean validAnagram2(String str1, String str2) {
43-
if(str1.length() != str2.length()) return false;
62+
char[] chars1 = str1.toCharArray();
63+
char[] chars2 = str2.toCharArray();
64+
65+
Arrays.sort(chars1);
66+
Arrays.sort(chars2);
4467

45-
int[] chars = new int[26];
68+
return Arrays.equals(chars1, chars2);
69+
}
4670

47-
for(int i=0; i< str1.length(); i++) {
48-
char ch1 = str1.charAt(i);
49-
char ch2 = str2.charAt(i);
50-
chars[ch1 - 'a']++;
51-
chars[ch2 - 'a']--;
71+
//Using Sort, split and join methods:- TC:O(n logn) SC:O(n)
72+
private static boolean validAnagram4(String str1, String str2) {
73+
if(str1.length() != str2.length()) {
74+
return false;
5275
}
5376

54-
for(int ch: chars) {
55-
if(ch !=0) return false;
56-
}
77+
String[] splitStr1 = str1.split("");
78+
String[] splitStr2 = str2.split("");
5779

58-
return true;
59-
}
80+
Arrays.sort(splitStr1);
81+
Arrays.sort(splitStr2);
6082

83+
return String.join("", splitStr1).equals(String.join("", splitStr2));
84+
}
6185
public static void main(String[] args) {
6286
String s1 = "anagram", s2="nagaram";
6387
System.out.println(validAnagram1(s1, s2));
@@ -67,6 +91,16 @@ public static void main(String[] args) {
6791
String a1 = "anagram", a2="nagaram";
6892
System.out.println(validAnagram2(a1, a2));
6993
String b1 = "cat", b2="rat";
70-
System.out.println(validAnagram1(b1, b2));
94+
System.out.println(validAnagram2(b1, b2));
95+
96+
String x1 = "anagram", x2="nagaram";
97+
System.out.println(validAnagram3(x1, x2));
98+
String y1 = "cat", y2="rat";
99+
System.out.println(validAnagram3(y1, y2));
100+
101+
String c1 = "anagram", c2="nagaram";
102+
System.out.println(validAnagram4(c1, c2));
103+
String d1 = "cat", d2="rat";
104+
System.out.println(validAnagram4(d1, d2));
71105
}
72106
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
**Description:**
2+
Given two strings `str1` and `str2`, return `true` if `str2` is an anagram of `str1`, and `false` otherwise.
3+
4+
**Note:**An Anagram is defined as a word or phrase formed by rearranging the letters of a different word or phrase, using all the original letters exactly once.
5+
6+
### Examples
7+
Example 1:
8+
Input: str1 = "anagram", str2 = "nagaram"
9+
Output: true
10+
11+
Example 2:
12+
Input: str1 = "rat", str2 = "cat"
13+
Output: false
14+
15+
**Algorithmic Steps**
16+
This problem is solved with the help of **frequency counting** approach using an array. The algorithmic approach can be summarized as follows:
17+
18+
1. Add a preliminary check whether both string lengths are equal or not. If they are not equal, return `false` because they cannot be anagrams anymore.
19+
20+
2. Create an array named `charcharFrequencyArr` to hold the alphabetic(i.e, a-z) letter frequencies. By default, their count is initialized with 0.
21+
22+
3. Iterate any of the input string to find the unicode of each character.
23+
24+
4. Find the unicode for each index in both the strings.
25+
26+
5. Calculate the index position of frequency array by substring the letter's ASCII value from unicode. Increment the frequency for first string and decrement the frequency for second string to balance the frequencies.
27+
28+
6. Repeat steps 4-5 until there are no more characters in the string.
29+
30+
7. Return `true` if every element's frequency is zero. Otherwise return `false` indicating that those two strings are not anagrams.
31+
32+
**Time and Space complexity:**
33+
This algorithm takes a time complexity of `O(n)`, where `n` represents length of the string. This is because we are traversing the string at most once.
34+
35+
Also, it requires space complexity of `O(1)`(i.e, `O(26)`) due to no other data structure used except fixed 26 letter array for the character frequencies.

src/javascript/algorithms/strings/validAnagram.js src/javascript/algorithms/strings/4.validAnagram/validAnagram.js

+26-27
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,53 @@
1-
// Sort and compare:- TC: O(n logn) SC: O(n)
2-
function validAnagram1(str1, str2) {
3-
if(str1.length !== str2.length) return false;
4-
5-
return reorderStr(str1) === reorderStr(str2);
6-
}
7-
8-
const reorderStr = (str) =>
9-
str.split("")
10-
.sort((a, b) => a.localeCompare(b))
11-
.join("");
12-
13-
141
// Using array:- TC:O(n) SC:O(1)
15-
function validAnagram2(str1, str2) {
2+
function validAnagram1(str1, str2) {
163
if(str1.length !== str2.length) return false;
174

18-
let chars = new Array(26).fill(0);
5+
let charFrequencyArr = new Array(26).fill(0);
196

207
for(let i=0; i< str1.length; i++) {
21-
let ch1 = str1.charCodeAt(i);
22-
let ch2 = str2.charCodeAt(i);
23-
chars[ch1-97]++;
24-
chars[ch2-97]--;
8+
let charCode1 = str1.charCodeAt(i);
9+
let charCode2 = str2.charCodeAt(i);
10+
charFrequencyArr[charCode1-97]++;
11+
charFrequencyArr[charCode2-97]--;
2512
}
2613

27-
return chars.every((n) => n === 0);
14+
return charFrequencyArr.every((n) => n === 0);
2815
}
2916

3017
// Using Map:- TC:O(n) SC: O(n)
31-
function validAnagram3(str1, str2) {
18+
function validAnagram2(str1, str2) {
3219
if(str1.length != str2.length) return false;
3320

34-
let map = new Map();
21+
let charMap = new Map();
3522

3623
for(let ch of str1) {
37-
map.set(ch, (map.get(ch) || 0) + 1);
24+
charMap.set(ch, (charMap.get(ch) || 0) + 1);
3825
}
3926

4027
for(let ch of str2) {
41-
if(map.has(ch)) {
42-
map.set(ch, map.get(ch)-1);
43-
if(map.get(ch) === 0) map.delete(ch);
28+
if(charMap.has(ch)) {
29+
charMap.set(ch, charMap.get(ch)-1);
30+
if(charMap.get(ch) === 0) charMap.delete(ch);
4431
} else {
4532
return false;
4633
}
4734
}
4835

49-
if(map.size === 0) return true;
36+
return charMap.size === 0;
37+
}
38+
39+
// Sort and compare:- TC: O(n logn) SC: O(n)
40+
function validAnagram3(str1, str2) {
41+
if(str1.length !== str2.length) return false;
42+
43+
return reorderStr(str1) === reorderStr(str2);
5044
}
5145

46+
const reorderStr = (str) =>
47+
str.split("")
48+
.sort((a, b) => a.localeCompare(b))
49+
.join("");
50+
5251

5352
let a1="anagram", a2="nagaram";
5453
console.log(validAnagram1(a1, a2));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
**Description:**
2+
Given two strings `str1` and `str2`, return `true` if `str2` is an anagram of `str1`, and `false` otherwise.
3+
4+
**Note:**An Anagram is defined as a word or phrase formed by rearranging the letters of a different word or phrase, using all the original letters exactly once.
5+
6+
### Examples
7+
Example 1:
8+
Input: str1 = "anagram", str2 = "nagaram"
9+
Output: true
10+
11+
Example 2:
12+
Input: str1 = "rat", str2 = "cat"
13+
Output: false
14+
15+
**Algorithmic Steps**
16+
This problem is solved with the help of **frequency counting** approach using an array. The algorithmic approach can be summarized as follows:
17+
18+
1. Add a preliminary check whether both string lengths are equal or not. If they are not equal, return `false` because they cannot be anagrams anymore.
19+
20+
2. Create an array named `charcharFrequencyArr` to hold the alphabetic(i.e, a-z) letter frequencies. By default, their count is initialized with 0.
21+
22+
3. Iterate any of the input string to find the unicode of each character.
23+
24+
4. Find the unicode for each index in both the strings.
25+
26+
5. Calculate the index position of frequency array by substring the letter's ASCII value from unicode. Increment the frequency for first string and decrement the frequency for second string to balance the frequencies.
27+
28+
6. Repeat steps 4-5 until there are no more characters in the string.
29+
30+
7. Return `true` if every element's frequency is zero. Otherwise return `false` indicating that those two strings are not anagrams.
31+
32+
**Time and Space complexity:**
33+
This algorithm takes a time complexity of `O(n)`, where `n` represents length of the string. This is because we are traversing the string at most once.
34+
35+
Also, it requires space complexity of `O(1)`(i.e, `O(26)`) due to no other data structure used except fixed 26 letter array for the character frequencies.

src/javascript/algorithms/strings/5.groupAnagrams/groupAnagrams.md

Whitespace-only changes.

0 commit comments

Comments
 (0)