From 8432721bc46faa9a5ec863f16b00c8c7412e50ae Mon Sep 17 00:00:00 2001 From: Azad Date: Sat, 31 Oct 2020 16:19:33 +0530 Subject: [PATCH 1/2] New Codes --- DataStructures/Graphs/TopoSortKahn.java | 121 ++++++++++++++++++ Maths/HappyNumber.java | 35 +++++ Misc/generateBalancedParenthesis.java | 49 +++++++ Misc/largestRange.java | 45 +++++++ Misc/rangeInSortedArray.java | 103 +++++++++++++++ Misc/wordBoggle.java | 119 +++++++++++++++++ strings/CheckAnagrams.java | 32 ----- .../LongestSubstringWithoutDuplication.java | 34 +++++ strings/MinSubstrContainingChars.java | 96 ++++++++++++++ strings/longestPalindromicSubstring.java | 47 +++++++ .../longestPalindromicSubstringManacher.java | 82 ++++++++++++ 11 files changed, 731 insertions(+), 32 deletions(-) create mode 100644 DataStructures/Graphs/TopoSortKahn.java create mode 100644 Maths/HappyNumber.java create mode 100644 Misc/generateBalancedParenthesis.java create mode 100644 Misc/largestRange.java create mode 100644 Misc/rangeInSortedArray.java create mode 100644 Misc/wordBoggle.java delete mode 100644 strings/CheckAnagrams.java create mode 100644 strings/LongestSubstringWithoutDuplication.java create mode 100644 strings/MinSubstrContainingChars.java create mode 100644 strings/longestPalindromicSubstring.java create mode 100644 strings/longestPalindromicSubstringManacher.java diff --git a/DataStructures/Graphs/TopoSortKahn.java b/DataStructures/Graphs/TopoSortKahn.java new file mode 100644 index 000000000000..f76745999334 --- /dev/null +++ b/DataStructures/Graphs/TopoSortKahn.java @@ -0,0 +1,121 @@ +package DataStructures.Graphs; + +import java.util.*; +// A graph with nodes as jobs and edges as dependencies +class jobGraph2 +{ + ArrayList nodes; + //ArrayList jobs; + HashMap graph=new HashMap<>(); + + jobGraph2(ArrayList jobs) + { + //this.jobs=jobs; + this.nodes=new ArrayList<>(); + for(int job:jobs) + this.addNode(job); + } + + void addDep(int job, int dep) + { + jobNode2 j=this.getNode(job); + jobNode2 depNode=this.getNode(dep); + j.deps.add(depNode); + depNode.prereqCount++; + } + + void addNode(int job) + { + this.graph.put(job,new jobNode2(job)); + nodes.add(graph.get(job)); + } + + jobNode2 getNode(int job) + { + if(!graph.containsKey(job)) + addNode(job); + return graph.get(job); + } +} +// Nodes of a job-graph consisting of the job and its number of pre-requisites +class jobNode2 +{ + int job, prereqCount; + ArrayList deps; + jobNode2(int job) + { + this.job = job; + this.deps = new ArrayList(); + this.prereqCount=0; + } +} +public class TopoSortKahn +{ + // Gives the topological ordering given a set of jobs and their prerequisites + public static ArrayList topoSort(ArrayList jobs, ArrayList deps) + { + jobGraph2 graph=createJobGraph(jobs, deps); + return getOrderedJobs(graph); + } + + public static jobGraph2 createJobGraph(ArrayList jobs, ArrayList deps) + { + jobGraph2 j= new jobGraph2(jobs); + for(Integer[] t : deps) + j.addDep(t[0], t[1]); + return j; + } + + public static ArrayList getOrderedJobs(jobGraph2 graph) + { + ArrayList orderedJobs=new ArrayList<>(); + ArrayList nodesWithNoPrereqs=new ArrayList<>(); + for(jobNode2 x:graph.nodes) + { + if(x.prereqCount==0) + nodesWithNoPrereqs.add(x); + } + while(nodesWithNoPrereqs.size()!=0) + { + jobNode2 temp = nodesWithNoPrereqs.remove(nodesWithNoPrereqs.size() - 1); + orderedJobs.add(temp.job); + removeDeps(temp,nodesWithNoPrereqs); + } + boolean graphHasEdges=false; + for(jobNode2 t:graph.nodes) + { + if (t.prereqCount != 0) { + graphHasEdges = true; + break; + } + } + return graphHasEdges ?new ArrayList<>():orderedJobs; + } + + public static void removeDeps(jobNode2 node, ArrayList nodesWithNoprereqs) + { + while(node.deps.size()!=0) + { + jobNode2 dep=node.deps.remove(node.deps.size()-1); + dep.prereqCount--; + if(dep.prereqCount==0) + nodesWithNoprereqs.add(dep); + } + } + + public static void main(String[] args) + { + // Sample Testcase + Scanner s=new Scanner(System.in); + ArrayList jobs=new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7)); + ArrayList deps=new ArrayList<>(); + deps.add(new Integer[]{2,3}); // (2, 3) indicates that job 2 has to be completed before starting job 3 + deps.add(new Integer[]{2,5}); + deps.add(new Integer[]{1,3}); + deps.add(new Integer[]{3,4}); + deps.add(new Integer[]{4,6}); + deps.add(new Integer[]{5,6}); + deps.add(new Integer[]{6,7}); + System.out.println(topoSort(jobs,deps)); + } +} diff --git a/Maths/HappyNumber.java b/Maths/HappyNumber.java new file mode 100644 index 000000000000..7a2cfd47cd2c --- /dev/null +++ b/Maths/HappyNumber.java @@ -0,0 +1,35 @@ +package Maths; + +public class HappyNumber { + + // Check if a number is happy or not. Refer : https://mathworld.wolfram.com/HappyNumber.html + public static boolean isHappy(int num) + { + int slow=num, fast=num; + do + { + slow = digitSquareSum(slow); // Move one step + fast = digitSquareSum(digitSquareSum(fast)); // Move 2 steps + } while(slow != fast); + return slow == 1; // See if the cycle is stuck on number 1 + } + + public static int digitSquareSum(int num) + { + int sum = 0, digit; + while(num > 0) + { + digit = num % 10; + sum += digit * digit; + num /= 10; + } + return sum; + } + + public static void main(String[] args) + { + // Testcases + System.out.println(isHappy(23)); + System.out.println(isHappy(11)); + } +} diff --git a/Misc/generateBalancedParenthesis.java b/Misc/generateBalancedParenthesis.java new file mode 100644 index 000000000000..5f207e5ccbc6 --- /dev/null +++ b/Misc/generateBalancedParenthesis.java @@ -0,0 +1,49 @@ +package Misc; + +import java.util.*; +class ParenthesisString{ + String str; + int openCount, closedCount; // Open & Closed Parenthesis count respectively + + public ParenthesisString(String str, int openCount, int closedCount) + { + this.str =str; + this.openCount = openCount; + this.closedCount = closedCount; + } +} + +public class generateBalancedParenthesis { + // Follows a BFS-based approach to generate all combinations of balanced paranthesis with 'A' number of pairs + // Time complexity : O(4^n/sqrt(n)) Refer this : https://en.wikipedia.org/wiki/Central_binomial_coefficient + // Space complexity : O(n*2^n) + public static List generateParenthesis(int A) + { + List res=new ArrayList<>(); + Queue queue=new ArrayDeque<>(); + queue.add(new ParenthesisString("", 0, 0)); + while(!queue.isEmpty()) + { + ParenthesisString ps = queue.poll(); + // Add to the result if the max open & closed parenthesis count is reached + if(ps.openCount == A && ps.closedCount == A) + res.add(ps.str); + else + { + if(ps.openCount < A) // Add if we can add an open parenthesis + queue.add(new ParenthesisString(ps.str + "(", ps.openCount+1, ps.closedCount)); + + if(ps.openCount > ps.closedCount) // Add if we can add a closed parenthesis + queue.add(new ParenthesisString(ps.str + ")", ps.openCount, ps.closedCount+1)); + } + } + return res; + } + + public static void main(String[] args) + { + // Testcases + System.out.println(generateParenthesis(4)); + System.out.println(generateParenthesis(8)); + } +} \ No newline at end of file diff --git a/Misc/largestRange.java b/Misc/largestRange.java new file mode 100644 index 000000000000..54a900dadf48 --- /dev/null +++ b/Misc/largestRange.java @@ -0,0 +1,45 @@ +package Misc; + +import java.util.*; +public class largestRange +{ + // Finds the length of longest occurring consecutive numbers range in an array + public static int longestRange(int[] nums) + { + int longestRange = 0; + HashMap num = new HashMap<>(); + for(int x : nums) + num.put(x,true); + for(int x : nums) + { + if(!num.get(x)) + continue; + num.replace(x, false); + int currentRange=1; + int left = x-1; + int right = x+1; + while(num.containsKey(left)) + { + num.replace(left, false); + currentRange+=1; + left--; + } + while(num.containsKey(right)) + { + num.replace(right, false); + currentRange+=1; + right++; + } + if(currentRange > longestRange) + longestRange = currentRange; + } + return longestRange; + } + + public static void main(String[] args) { + // Testcases + System.out.println(longestRange(new int[]{1, 2, 3, 4, -1, 11, 10})); + System.out.println(longestRange(new int[]{-1, 1, 3, 5, 7})); + System.out.println(longestRange(new int[]{0, 1, 2, 3, 4, 7, 6, 5})); + } +} diff --git a/Misc/rangeInSortedArray.java b/Misc/rangeInSortedArray.java new file mode 100644 index 000000000000..8b4109fc2d53 --- /dev/null +++ b/Misc/rangeInSortedArray.java @@ -0,0 +1,103 @@ +package Misc; + +import java.util.*; +public class rangeInSortedArray +{ + public static void main(String[] args) + { + // Testcases + System.out.println(Arrays.toString(sortedRange(new int[]{1 ,2 ,3, 3, 3, 4, 5}, 3))); + System.out.println(Arrays.toString(sortedRange(new int[]{1 ,2 ,3, 3, 3, 4, 5}, 4))); + System.out.println(Arrays.toString(sortedRange(new int[]{0, 1, 2}, 3))); + } + + // Get the 1st and last occurrence index of a number 'key' in a non-decreasing array 'nums' + // Gives [-1, -1] in case element doesn't exist in array + public static int[] sortedRange(int[] nums, int key) + { + int[] range=new int[]{-1,-1}; + alteredBinSearchIter(nums,key,0,nums.length-1,range,true); + alteredBinSearchIter(nums,key,0,nums.length-1,range,false); + return range; + } + + // Recursive altered binary search which searches for leftmost as well as rightmost occurrence of 'key' + public static void alteredBinSearch(int[] nums, int key, int left, int right, int[] range, boolean goLeft) + { + if(left>right) + return; + int mid=(left+right)/2; + if(nums[mid]>key) + alteredBinSearch(nums,key,left,mid-1,range,goLeft); + else if(nums[mid] key) + right = mid - 1; + else if (nums[mid] < key) + left = mid + 1; + else { + if (goLeft) { + if (mid == 0 || nums[mid - 1] != key) { + range[0] = mid; + return; + } + else + right = mid - 1; + } else { + if (mid == nums.length - 1 || nums[mid + 1] != key) { + range[1] = mid; + return; + } + else + left = mid + 1; + } + } + } + } + + public static int getCountLessThan(int[] nums, int key) + { + return getLessThan(nums,key,0,nums.length-1); + } + + public static int getLessThan(int[] nums, int key, int left, int right) + { + int count = 0; + while (left <=right) + { + int mid = (left + right) / 2; + if (nums[mid] > key) + right=mid - 1; + else if (nums[mid] <= key) + { + count = mid + 1;//Atleast mid+1 elements exist which are <= key + left=mid+1; + } + } + return count; + } +} diff --git a/Misc/wordBoggle.java b/Misc/wordBoggle.java new file mode 100644 index 000000000000..2e7f8fa5e05e --- /dev/null +++ b/Misc/wordBoggle.java @@ -0,0 +1,119 @@ +package Misc; + +import java.util.*; +public class wordBoggle +{ + //O(nm * 8^s + ws) time where n=width of boggle board, m=height of boggle board, s=length of longest + // word in string array, w= length of string array, 8 is due to 8 explorable neighbours + // O(nm + ws) space + public static List boggleBoard(char[][] board, String[] words) { + Trie trie = new Trie(); + for (String word : words) + trie.add(word); + Set finalWords = new HashSet<>(); + boolean[][] visited = new boolean[board.length][board.length]; + for(int i = 0; i < board.length; i++) + for(int j = 0; j < board[i].length; j++) + explore(i, j, board, trie.root, visited, finalWords); + return new ArrayList<>(finalWords); + } + + public static void main(String[] args) + { + // Testcase + System.out.println(boggleBoard(new char[][]{ + {'t', 'h', 'i', 's', 'i', 's', 'a'}, + {'s', 'i', 'm', 'p', 'l', 'e', 'x'}, + {'b', 'x', 'x', 'x', 'x', 'e', 'b'}, + {'x', 'o', 'g', 'g', 'l', 'x', 'o'}, + {'x', 'x', 'x', 'D', 'T', 'r', 'a'}, + {'R', 'E', 'P', 'E', 'A', 'd', 'x'}, + {'x', 'x', 'x', 'x', 'x', 'x', 'x'}, + {'N', 'O', 'T', 'R', 'E', '_', 'P'}, + {'x', 'x', 'D', 'E', 'T', 'A', 'E'}}, + new String[] {"this", "is", "not", "a", "simple", "test", "boggle", "board", "REPEATED", "NOTRE_PEATED"})); + } + + public static void explore( + int i, + int j, + char[][] board, + TrieNode trieNode, + boolean[][] visited, + Set finalWords) { + if (visited[i][j]) + return; + + char letter = board[i][j]; + if (!trieNode.children.containsKey(letter)) { + return; + } + visited[i][j] = true; + trieNode = trieNode.children.get(letter); + if (trieNode.children.containsKey('*')) + finalWords.add(trieNode.word); + + List neighbors = getNeighbors(i, j, board); + for (Integer[] neighbor : neighbors) + explore(neighbor[0], neighbor[1], board, trieNode, visited, finalWords); + + visited[i][j] = false; + } + + public static List getNeighbors(int i, int j, char[][] board) { + List neighbors = new ArrayList<>(); + if (i > 0 && j > 0) + neighbors.add(new Integer[] {i - 1, j - 1}); + + if (i > 0 && j < board[0].length - 1) + neighbors.add(new Integer[] {i - 1, j + 1}); + + if (i < board.length - 1 && j < board[0].length - 1) + neighbors.add(new Integer[] {i + 1, j + 1}); + + if (i < board.length - 1 && j > 0) + neighbors.add(new Integer[] {i + 1, j - 1}); + + if (i > 0) + neighbors.add(new Integer[] {i - 1, j}); + + if (i < board.length - 1) + neighbors.add(new Integer[] {i + 1, j}); + + if (j > 0) + neighbors.add(new Integer[] {i, j - 1}); + + if (j < board[0].length - 1) + neighbors.add(new Integer[] {i, j + 1}); + + return neighbors; + } + +} + +// Trie used to optimize string search +class TrieNode { + Map children = new HashMap<>(); + String word = ""; +} +class Trie { + TrieNode root; + char endSymbol; + public Trie() { + this.root = new TrieNode(); + this.endSymbol = '*'; + } + public void add(String str) { + TrieNode node = this.root; + for (int i = 0; i < str.length(); i++) { + char letter = str.charAt(i); + if (!node.children.containsKey(letter)) { + TrieNode newNode = new TrieNode(); + node.children.put(letter, newNode); + } + node = node.children.get(letter); + } + node.children.put(this.endSymbol, null); + node.word = str; + } +} diff --git a/strings/CheckAnagrams.java b/strings/CheckAnagrams.java deleted file mode 100644 index 20ab715acede..000000000000 --- a/strings/CheckAnagrams.java +++ /dev/null @@ -1,32 +0,0 @@ -package strings; - -import java.util.Arrays; - -/** - * Two strings are anagrams if they are made of the same letters arranged 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 - * - * @param s1 the first string - * @param s2 the second string - * @return {@code true} if two string are anagrams, otherwise {@code false} - */ - public static boolean isAnagrams(String s1, String s2) { - s1 = s1.toLowerCase(); - s2 = s2.toLowerCase(); - char[] values1 = s1.toCharArray(); - char[] values2 = s2.toCharArray(); - Arrays.sort(values1); - Arrays.sort(values2); - return new String(values1).equals(new String(values2)); - } -} diff --git a/strings/LongestSubstringWithoutDuplication.java b/strings/LongestSubstringWithoutDuplication.java new file mode 100644 index 000000000000..214bdd24880a --- /dev/null +++ b/strings/LongestSubstringWithoutDuplication.java @@ -0,0 +1,34 @@ +package strings; + +import java.util.*; + +public class LongestSubstringWithoutDuplication +{ + public static void main(String[] args) + { + // Testcases + System.out.println(longestUniqueSubstring("lmnoppqrrsss")); + System.out.println(longestUniqueSubstring("falafel")); + System.out.println(longestUniqueSubstring("krishnamachari")); + } + + // Finds the longest substring within a string with unique characters + public static String longestUniqueSubstring(String str) + { + if(str.equals("")) + return ""; + HashMap lastSeenAt = new HashMap<>(); + int[] longest = new int[]{0, 1}; + int start = 0; + for(int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if(lastSeenAt.containsKey(c)) + start = Math.max(start,lastSeenAt.get(c) + 1); + if(longest[1] - longest[0] < i + 1 - start) + longest=new int[]{start, i+1}; + lastSeenAt.put(c, i); + } + return str.substring(longest[0], longest[1]); + } +} diff --git a/strings/MinSubstrContainingChars.java b/strings/MinSubstrContainingChars.java new file mode 100644 index 000000000000..cab38813f024 --- /dev/null +++ b/strings/MinSubstrContainingChars.java @@ -0,0 +1,96 @@ +package strings; + +import java.util.*; +public class MinSubstrContainingChars +{ + public static void main(String[] args) + { + // Testcases + System.out.println(smallestSubstrContaining("workforcode","wfc")); + System.out.println(smallestSubstrContaining("abcdeklmhactr", "abcl")); + System.out.println(smallestSubstrContaining("SachinTendulkar", "SrT")); + + } + + // Find the smallest length substring of a string containing all the characters in smaller string + public static String smallestSubstrContaining(String bigString, String smallString) + { + HashMap targetCharCounts = getCharCounts(smallString); + int[] substrBounds = getSubstringBounds(bigString, targetCharCounts); + return getStringFromBounds(bigString, substrBounds); + } + + // Builds HashMap of characters to its counts + public static HashMap getCharCounts(String str) + { + HashMap charCounts = new HashMap<>(); + for(char x : str.toCharArray()) + { + increaseCharCount(x, charCounts); + } + return charCounts; + } + + public static void increaseCharCount(Character x, HashMap charCounts) + { + charCounts.put(x, charCounts.getOrDefault(x,0)+1); + } + + public static void decreaseCharCount(char x, HashMap charCounts) + { + charCounts.put(x, charCounts.get(x)-1); + } + + // Gets the bounds of substring occurrence + public static int[] getSubstringBounds(String str, HashMap charCounts) + { + int[] substrBounds = new int[]{0, (int)Double.POSITIVE_INFINITY}; + HashMap substrCharCounts = new HashMap<>(); + int numUniqueChars = charCounts.size(); + int numUniqueCharsDone = 0; + int left = 0, right = 0; + while(right < str.length()) + { + char rightChar = str.charAt(right); + if(!charCounts.containsKey(rightChar)) + { + right++; + continue; + } + increaseCharCount(rightChar,substrCharCounts); + if(substrCharCounts.get(rightChar).equals(charCounts.get(rightChar))) + numUniqueCharsDone++; + while(numUniqueCharsDone == numUniqueChars && left <= right) + { + substrBounds = getCloserBounds(left, right, substrBounds[0], substrBounds[1]); + char leftChar = str.charAt(left); + if(!charCounts.containsKey(leftChar)) + { + left++; + continue; + } + if(substrCharCounts.get(leftChar).equals(charCounts.get(leftChar))) + numUniqueCharsDone--; + decreaseCharCount(leftChar, substrCharCounts); + left++; + } + right++; + } + + //System.out.println((int)Double.POSITIVE_INFINITY+" "+Arrays.toString(substrBounds)); + return substrBounds; + } + + public static int[] getCloserBounds(int index1, int index2, int index3, int index4) + { + return (index2-index1 < index4-index3) ? new int[]{index1, index2} : new int[]{index3, index4}; + } + + public static String getStringFromBounds(String str, int[] bounds) + { + int start = bounds[0], end = bounds[1]; + if(end == (int)Double.POSITIVE_INFINITY) + return ""; + return str.substring(start, end+1); + } +} diff --git a/strings/longestPalindromicSubstring.java b/strings/longestPalindromicSubstring.java new file mode 100644 index 000000000000..925fa1f559b4 --- /dev/null +++ b/strings/longestPalindromicSubstring.java @@ -0,0 +1,47 @@ +package strings; + +import java.util.*; +import java.io.*; + +// Finds the longest palindromic substring in O(n^2) time and O(1) space +public class longestPalindromicSubstring { + public static String getLPS(String s) + { + if(s.length() == 0) + return ""; + + if(s.replace(String.valueOf(s.charAt(0)), "").length() == 0) // If string has same character, no computations needed. + return s; + + String current = s.substring(0,1); + for(int i = 1; i < s.length(); i++) + { + String odd = getLPSFrom(s, i-1, i+1); + String even = getLPSFrom(s, i-1, i); + //Comparator strlenComp = (a, b) -> Integer.compare(a.length(), b.length()); + //int longest=strlenComp.compare(odd,even); + String longest = (odd.length()>even.length()) ? odd : even; + if(longest.length() > current.length()) + current = longest; + } + return current; + } + + public static String getLPSFrom(String s, int left, int right) + { + while(left >= 0&&right < s.length()) + { + if(s.charAt(left) != s.charAt(right)) + break; + left--; + right++; + } + return s.substring(left+1, right); + } + + public static void main(String[] args) + { + // Testcases + System.out.println(getLPS("")); + } +} diff --git a/strings/longestPalindromicSubstringManacher.java b/strings/longestPalindromicSubstringManacher.java new file mode 100644 index 000000000000..de4b12e7e288 --- /dev/null +++ b/strings/longestPalindromicSubstringManacher.java @@ -0,0 +1,82 @@ +package strings; + +import java.util.*; +public class longestPalindromicSubstringManacher { + // Finds the longest palindromic substring in a string s in O(n) time using Manacher's algorithm. + // An explanation of Manacher's algorithm can be found here : https://cp-algorithms.com/string/manacher.html + public static String findLongestPalindrome(String s) { + if (s == null || s.length()==0) + return ""; + + char[] s2 = addBoundaries(s.toCharArray()); + int[] p = new int[s2.length]; + int c = 0, r = 0; // Here the first element in s2 has been processed. + int m = 0, n = 0; // The walking indices to compare if two elements are the same. + for (int i = 1; ir) { + p[i] = 0; + m = i-1; + n = i+1; + } + else { + int i2 = c*2-i; + if (p[i2]<(r-i-1)) { + p[i] = p[i2]; + m = -1; // This signals bypassing the while loop below. + } else { + p[i] = r-i-1; + n = r; m = i*2-n; + } + } + while (m>=0 && nr) { + c = i; + r = i+p[i]; + } + } + int len = 0; c = 0; + for (int i = 1; i Date: Sat, 31 Oct 2020 16:26:48 +0530 Subject: [PATCH 2/2] Added missing code CheckAnagrams.java --- strings/CheckAnagrams.java | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 strings/CheckAnagrams.java diff --git a/strings/CheckAnagrams.java b/strings/CheckAnagrams.java new file mode 100644 index 000000000000..6b890fe3b813 --- /dev/null +++ b/strings/CheckAnagrams.java @@ -0,0 +1,32 @@ +package strings; + +import java.util.Arrays; + +/** + * Two strings are anagrams if they are made of the same letters arranged 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 + * + * @param s1 the first string + * @param s2 the second string + * @return {@code true} if two string are anagrams, otherwise {@code false} + */ + public static boolean isAnagrams(String s1, String s2) { + s1 = s1.toLowerCase(); + s2 = s2.toLowerCase(); + char[] values1 = s1.toCharArray(); + char[] values2 = s2.toCharArray(); + Arrays.sort(values1); + Arrays.sort(values2); + return new String(values1).equals(new String(values2)); + } +} \ No newline at end of file