Checking if two strings are permutations of each other - java

How to determine if two strings are permutations of each other

Sort the two strings's characters.
Compare the results to see if they're identical.
Edit:
The above method is reasonably efficient - O(n*log(n)) and, as others have shown, very easy to implement using the standard Java API. Even more efficient (but also more work) would be counting and comparing the occurrence of each character, using the char value as index into an array of counts.
I do not thing there is an efficient way to do it recursively. An inefficient way (O(n^2), worse if implemented straightforwardly) is this:
If both strings consist of one identical character, return true
Otherwise:
remove one character from the first string
Look through second string for occurrence of this character
If not present, return false
Otherwise, remove said character and apply algorithm recursively to the remainders of both strings.

To put #Michael Borgwardt's words in to code:
public boolean checkAnagram(String str1, String str2) {
if (str1.length() != str2.length())
return false;
char[] a = str1.toCharArray();
char[] b = str2.toCharArray();
Arrays.sort(a);
Arrays.sort(b);
return Arrays.equals(a, b);
}

Create a Hashmap with the characters of the first string as keys and the number of occurances as value; then go through the second string and for each character, look up the hash table and decrement the number if it is greater than zero. If you don't find an entry or if it is already 0, the strings are not a permutation of each other. Obviously, the string must have the same length.

Linear Time solution in HashMap. Traverse and put first String in HashMap, keep the count of each character. Traverse second String and if it is already in the hashmap decrease the count by 1. At the end if all character were in the string the value in hashmap will be 0 for each character.
public class StringPermutationofEachOther {
public static void main(String[] args)
{
String s1= "abc";
String s2 ="bbb";
System.out.println(perm(s1,s2));
}
public static boolean perm(String s1, String s2)
{ HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int count =1;
if(s1.length()!=s2.length())
{
return false;
}
for(Character c: s1.toCharArray())
{
if(!map.containsKey(c))
map.put(c, count);
else
map.put(c, count+1);
}
for(Character c: s2.toCharArray())
{
if(!map.containsKey(c))
return false;
else
map.put(c, count-1);
}
for(Character c: map.keySet())
{
if(map.get(c)!=0)
return false;
}
return true;
}
}

You can try to use XOR, if one string is a permeation of the other, they should have essentially identical chars. The only difference is just the order of chars. Therefore using XOR trick can help you get rid of the order and focus only on the chars.
public static boolean isPermutation(String s1, String s2){
if (s1.length() != s2.length()) return false;
int checker = 0;
for(int i = 0; i < s1.length();i++ ){
checker ^= s1.charAt(i) ^ s2.charAt(i);
}
return checker == 0;
}

Sort the 2 strings by characters and compare if they're the same (O(n log n) time, O(n) space), or
Tally the character frequency of the 2 strings and compare if they're the same (O(n) time, O(n) space).

You might take a look at String.toCharArray and Arrays.sort

First you check the lengths (n), if they are not same, they cannot be permutations of each other. Now create two HashMap<Character, Integer>. Iterate over each string and put the number of times each character occur in the string. E.g. if the string is aaaaa, the map will have just one element with key a and value 5. Now check if the two maps are identical. This is an O(n) algorithm.
EDIT with code snippet :
boolean checkPermutation(String str1, String str2) {
char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();
Map<Character, Integer> map1 = new HashMap<Character, Integer>();
Map<Character, Integer> map2 = new HashMap<Character, Integer>();
for (char c : chars1) {
int occ = 1;
if (map1.containsKey(c) {
occ = map1.get(c);
occ++;
}
map1.put(c, occ);
}
// now do the same for chars2 and map2
if (map1.size() != map2.size()) {
return false;
}
for (char c : map1.keySet()) {
if (!map2.containsKey(c) || map1.get(c) != map2.get(c)) {
return false;
}
}
return true;
}

I'm working on a Java library that should simplify your task. You can re-implement this algorithm using only two method calls:
boolean arePermutationsOfSameString(String s1, String s2) {
s1 = $(s1).sort().join();
s2 = $(s2).sort().join();
return s1.equals(s2);
}
testcase
#Test
public void stringPermutationCheck() {
// true cases
assertThat(arePermutationsOfSameString("abc", "acb"), is(true));
assertThat(arePermutationsOfSameString("bac", "bca"), is(true));
assertThat(arePermutationsOfSameString("cab", "cba"), is(true));
// false cases
assertThat(arePermutationsOfSameString("cab", "acba"), is(false));
assertThat(arePermutationsOfSameString("cab", "acbb"), is(false));
// corner cases
assertThat(arePermutationsOfSameString("", ""), is(true));
assertThat(arePermutationsOfSameString("", null), is(true));
assertThat(arePermutationsOfSameString(null, ""), is(true));
assertThat(arePermutationsOfSameString(null, null), is(true));
}
PS
In the case you can clone the souces at bitbucket.

I did this, and it works well and quickly:
public static boolean isPermutation(String str1, String str2)
{
char[] x = str1.toCharArray();
char[] y = str2.toCharArray();
Arrays.sort(x);
Arrays.sort(y);
if(Arrays.equals(x, y))
return true;
return false;
}

public boolean isPermutationOfOther(String str, String other){
if(str == null || other == null)
return false;
if(str.length() != other.length())
return false;
Map<Character, Integer> characterCount = new HashMap<Character, Integer>();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
int count = 1;
if(characterCount.containsKey(c)){
int k = characterCount.get(c);
count = count+k;
}
characterCount.put(c, count);
}
for (int i = 0; i < other.length(); i++) {
char c = other.charAt(i);
if(!characterCount.containsKey(c)){
return false;
}
int count = characterCount.get(c);
if(count == 1){
characterCount.remove(c);
}else{
characterCount.put(c, --count);
}
}
return characterCount.isEmpty();
}

Variation on other approaches but this one uses 2 int arrays to track the chars, no sorting, and you only need to do 1 for loop over the strings. The for loop I do over the int arrays to test the permutation is a constant, hence not part of N.
Memory is constant.
O(N) run time.
// run time N, no sorting, assume 256 ASCII char set
public static boolean isPermutation(String v1, String v2) {
int length1 = v1.length();
int length2 = v2.length();
if (length1 != length2)
return false;
int s1[] = new int[256];
int s2[] = new int[256];
for (int i = 0; i < length1; ++i) {
int charValue1 = v1.charAt(i);
int charValue2 = v2.charAt(i);
++s1[charValue1];
++s2[charValue2];
}
for (int i = 0; i < s1.length; ++i) {
if (s1[i] != s2[i])
return false;
}
return true;
}
}
Unit Tests
#Test
public void testIsPermutation_Not() {
assertFalse(Question3.isPermutation("abc", "bbb"));
}
#Test
public void testIsPermutation_Yes() {
assertTrue(Question3.isPermutation("abc", "cba"));
assertTrue(Question3.isPermutation("abcabcabcabc", "cbacbacbacba"));
}

If we do the initial length check, to determine if the two strings are of the same length or not,
public boolean checkIfPermutation(String str1, String str2) {
if(str1.length()!=str2.length()){
return false;
}
int str1_sum = getSumOfChars(str1);
int str2_sum = getSumOfChars(str2);
if (str1_sum == str2_sum) {
return true;
}
return false;
}
public int getSumOfChars(String str){
int sum = 0;
for (int i = 0; i < str.length(); i++) {
sum += str.charAt(i);
}
return sum;
}

The obligatory Guava one-liner:
boolean isAnagram(String s1, String s2) {
return ImmutableMultiset.copyOf(Chars.asList(s1.toCharArray())).equals(ImmutableMultiset.copyOf(Chars.asList(s2.toCharArray())));
}
(Just for fun. I don't recommend submitting this for your assignment.)

As you requested, here's a complete solution using recursion.
Now all you have to do is:
Figure out what language this is
Translate it to Java.
Good luck :-)
proc isAnagram(s1, s2);
return {s1, s2} = {''} or
(s2 /= '' and
(exists c = s1(i) |
s2(1) = c and
isAnagram(s1(1..i-1) + s1(i+1..), s2(2..))));
end isAnagram;

I did it using C#
bool Arepermutations(string string1, string string2)
{
char[] str1 = string1.ToCharArray();
char[] str2 = string2.ToCharArray();
if (str1.Length !=str2.Length)
return false;
Array.Sort(str1);
Array.Sort(str2);
if (str1.Where((t, i) => t!= str2[i]).Any())
{
return false;
}
return true;
}

public boolean permitation(String s,String t){
if(s.length() != t.length()){
return false;
}
int[] letters = new int[256];//Assumes that the character set is ASCII
char[] s_array = s.toCharArray();
for(char c:s_array){ /////count number of each char in s
letters[c]++;
}
for(int i=0;i<t.length();i++){
int c = (int)t.charAt(i);
if(--letters[c]<0){
return false;
}
}
return true;
}

import java.io.*;
public class permute
{
public static String sort(String s)
{
char[] str = s.toCharArray();
java.util.Arrays.sort(str);
return new String(str);
}
public static boolean permutation(String s,String t)
{
if(s.length()!=t.length())
{
return false;
}
return sort(s).equals(sort(t));
}
public static void main(String[] args) throws IOException
{
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String string = null;
boolean x=true;
System.out.println("Input String:");
string = bf.readLine();
System.out.println("Input another String:");
String result = bf.readLine();
String resultant = sort(string);
if(x==permutation(result,resultant))
{
System.out.println("String"+" "+"("+result+")"+"is a permutation of String"+" "+"("+string+")");
}
else
{
System.out.println("Sorry No anagram found");
}
}
}

public class TwoStrgPermutation {
public int checkForUnique(String s1, String s2)
{
int[] array1 = new int[256];
int[] array2 = new int[256];
array1 = arrayStringCounter(array1,s1);
array2 = arrayStringCounter(array2,s2);
if(Arrays.equals(array1, array2))
return 0;
else
return 1;
}
public int[] arrayStringCounter(int[] array,String s)
{
int val;
for(int i=0;i<s.length();i++)
{
val = (int)s.charAt(i);
array[val]++;
}
return array;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(in);
TwoStrgPermutation obj = new TwoStrgPermutation();
try {
String string1 = br.readLine();
String string2 = br.readLine();
int len1 = string1.length();
int len2 = string2.length();
if(len1==len2)
{
int result = obj.checkForUnique(string1,string2);
if (result == 0){
System.out.println("yes it is a permutation");
}
else if (result >0)
{
System.out.println("no it is not");
}
}
else
{
System.out.println("no it is not");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

>>>def isPermutation = lambda x, y: set([i for i in x]) == set([j for j in x])
>>>isPermutation("rasp", "spar")
>>>True

This is an O(N) solution, in which N is the length of the shorter string.
It has a disadvantage, which is that only ASCII characters are acceptable.
If we want better applicability, we may substitute a hash table for the int charNums[].
But it also means C wouldn't be a good choice, coz' there is no standard hash table implementation for C.
int is_permutation(char *s1, char *s2)
{
if ((NULL == s1) ||
(NULL == s2)) {
return false;
}
int static const
_capacity = 256; // Assumption
int
charNums[_capacity] = {0};
char
*cRef1 = s1,
*cRef2 = s2;
while ('\0' != *cRef1 && '\0' != *cRef2) {
charNums[*cRef1] += 1;
charNums[*cRef2] -= 1;
cRef1++;
cRef2++;
}
if ('\0' != *cRef1 || '\0' != *cRef2) {
return false;
}
for (int i = 0; i < _capacity; i++) {
if (0 != charNums[i]) {
return false;
}
}
return true;
}

Create two methods:
1. First method takes a string and returns a sorted string:
public String sort(String str) {
char char_set[] = str.toCharArray();
Arrays.sort(char_set);
return new String(char_set);
}
2. Second method takes two strings and return a boolean:
`public boolean sort(String x, String y) {
if (x.length() != y.length()) {
System.out.println("false");
return false;
}
System.out.println(sort(x).equals(sort(y)));
return sort(x).equals(sort(y));
}`

It can be done by using a Dictionary in C#. A basic implementation is like :
private static bool IsPermutation(string str1, string str2)
{
if (str1.Length != str2.Length)
return false;
var dictionary = new Dictionary<char, int>();
foreach(var x in str1)
{
if (dictionary.ContainsKey(x))
dictionary[x] += 1;
else
dictionary.Add(x, 1);
}
foreach (var y in str2)
{
if (dictionary.ContainsKey(y))
{
if (dictionary[y] > 0)
dictionary[y] -= 1;
else
return false;
}
else
return false;
}
foreach(var el in dictionary)
{
if (el.Value != 0)
return false;
}
return true;
}
Time Complexity is O(n), linear solution.

public static boolean isPermutation(String s1, String s2) {
if (s1.length() != s2.length()) {
return false;
}else if(s1.length()==0 ){
return true;
}
else if(s1.length()==1){
return s1.equals(s2);
}
char[] s = s1.toCharArray();
char[] t = s2.toCharArray();
for (int i = 0; i < s.length; i++) {
for (int j = 0; j < t.length; j++) {
if (s.length == s1.length() && (i == 0 && j == t.length - 1) && s[i] != t[j]) {
return false;
}
if (s[i] == t[j]) {
String ss = new String(s);
String tt = new String(t);
s = (ss.substring(0, i) + ss.substring(i + 1, s.length)).toCharArray();
t = (tt.substring(0, j) + tt.substring(j + 1, t.length)).toCharArray();
System.out.println(new String(s));
System.out.println(new String(t));
i = 0;
j = 0;
}
}
}
return s[0]==t[0] ;
}
This solution works for any charset. With an O(n) complexity.
The output for: isPermutation("The Big Bang Theory", "B B T Tehgiangyroeh")
he Big Bang Theory
B B Tehgiangyroeh
e Big Bang Theory
B B Tegiangyroeh
Big Bang Theory
B B Tgiangyroeh
Big Bang Theory
BB Tgiangyroeh
ig Bang Theory
B Tgiangyroeh
g Bang Theory
B Tgangyroeh
Bang Theory
B Tangyroeh
Bang Theory
B Tangyroeh
Bng Theory
B Tngyroeh
Bg Theory
B Tgyroeh
B Theory
B Tyroeh
BTheory
BTyroeh
Bheory
Byroeh
Beory
Byroe
Bory
Byro
Bry
Byr
By
By
B
B
true

Best Way to do this is by sorting the two strings first and then compare them. It's not the most efficient way but it's clean and is bound to the runtime of the sorting routine been used.
boolean arePermutation(String s1, String s2) {
if(s1.lenght() != s2.lenght()) {
return false;
}
return mySort(s1).equals(mySort(s2));
}
String mySort(String s) {
Char letters[] = s.toCharArray();
Arrays.sort(letters);
return new String(letters);
}

String str= "abcd";
String str1 ="dcazb";
int count=0;
char s[]= str.toCharArray();
char s1[]= str1.toCharArray();
for(char c:s)
{
count = count+(int)c ;
}
for(char c1:s1)
{
count=count-(int)c1;
}
if(count==0)
System.out.println("String are Anagram");
else
System.out.println("String are not Anagram");
}

Here is a simple program I wrote that gives the answer in O(n) for time complexity and O(1) for space complexity. It works by mapping every character to a prime number and then multiplying together all of the characters in the string's prime mappings together. If the two strings are permutations then they should have the same unique characters each with the same number of occurrences.
Here is some sample code that accomplishes this:
// maps keys to a corresponding unique prime
static Map<Integer, Integer> primes = generatePrimes(255); // use 255 for
// ASCII or the
// number of
// possible
// characters
public static boolean permutations(String s1, String s2) {
// both strings must be same length
if (s1.length() != s2.length())
return false;
// the corresponding primes for every char in both strings are multiplied together
int s1Product = 1;
int s2Product = 1;
for (char c : s1.toCharArray())
s1Product *= primes.get((int) c);
for (char c : s2.toCharArray())
s2Product *= primes.get((int) c);
return s1Product == s2Product;
}
private static Map<Integer, Integer> generatePrimes(int n) {
Map<Integer, Integer> primes = new HashMap<Integer, Integer>();
primes.put(0, 2);
for (int i = 2; primes.size() < n; i++) {
boolean divisible = false;
for (int v : primes.values()) {
if (i % v == 0) {
divisible = true;
break;
}
}
if (!divisible) {
primes.put(primes.size(), i);
System.out.println(i + " ");
}
}
return primes;
}

Based on the comment on this solution, https://stackoverflow.com/a/31709645/697935 here's that approach, revised.
private static boolean is_permutation(String s1, String s2) {
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int count = 1;
if(s1.length()!=s2.length()) {
return false;
}
for(Character c: s1.toCharArray()) {
if(!map.containsKey(c)) {
map.put(c, 1);
}
else {
map.put(c, map.get(c) + 1);
}
}
for(Character c: s2.toCharArray()) {
if(!map.containsKey(c)) {
return false;
}
else {
map.put(c, map.get(c) - 1);
}
}
for(Character c: map.keySet()) {
if(map.get(c) != 0) { return false; }
}
return true;
}

bool is_permutation1(string str1, string str2) {
sort(str1.begin(), str1.end());
sort(str2.begin(), str2.end());
for (int i = 0; i < str1.length(); i++) {
if (str1[i] != str2[i]) {
return false;
}
}
return true;
}

I wanted to give a recursive solution for this problem as I did not find any answer which was recursive. I think that this code seems to be tough but if you'll try to understand it you'll see the beauty of this code. Recursion is sometimes hard to understand but good to use! This method returns all the permutations of the entered String 's' and keeps storing them in the array 'arr[]'. The value of 't' initially is blank "" .
import java.io.*;
class permute_compare2str
{
static String[] arr= new String [1200];
static int p=0;
void permutation(String s,String t)
{
if (s.length()==0)
{
arr[p++]=t;
return;
}
for(int i=0;i<s.length();i++)
permutation(s.substring(0,i)+s.substring(i+1),t+s.charAt(i));
}
public static void main(String kr[])throws IOException
{
int flag = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the first String:");
String str1 = br.readLine();
System.out.println("Enter the second String:");
String str2 = br.readLine();
new permute_compare2str().permutation(str1,"");
for(int i = 0; i < p; ++i)
{
if(arr[i].equals(str2))
{
flag = 1;
break;
}
}
if(flag == 1)
System.out.println("True");
else
{
System.out.println("False");
return;
}
}
}
One limitation that I can see is that the length of the array is fixed and so will not be able to return values for a large String value 's'. Please alter the same as per the requirements. There are other solutions to this problem as well.
I have shared this code because you can actually use this to get the permutations of a string printed directly without the array as well.
HERE:
void permutations(String s, String t)
{
if (s.length()==0)
{
System.out.print(t+" ");
return;
}
for(int i=0;i<s.length();i++)
permutations(s.substring(0,i)+s.substring(i+1),t+s.charAt(i));
}
Value of 's' is the string whose permutations is needed and value of 't' is again empty "".
Reference: Introduction to Programming in Java

Related

Anagrams in java

package intials;
public class Anagrams {
public static void main(String[] args) {
String a = "cat";
String b = "act";
boolean isAnagram = false;
for (int i = 0; i < a.length(); i++) {
char c = a.charAt(i);
isAnagram = false;
for (int j = 0; j < b.length(); j++) {
if (b.charAt(j) == c) {
isAnagram = true;
break;
}
}
if (!isAnagram) {
break;
}
}
if (isAnagram) {
System.out.println("is anagram");
} else {
System.out.println("is not anagram");
}
}
}
Please tell me what is wrong in this code.
Also tell me what should be the changes should I make
A easy way to check if two words are anagram is to transform them in array, sort them and compare.
public boolean areAnagram(string str1, string str2)
{
// Transform strings in arrays
String[] arr1 = str1.split("");
String[] arr2 = str2.split("");
// Check if they have the same length
if (arr1.length != arr2.length)
return false;
// Sort array
Arrays.sort(arr1);
Arrays.sort(arr2);
// Compare value
for (int i = 0; i < arr1.length; i++)
if (arr1[i] != arr2[i])
return false;
return true;
}
boolean test = areAnagram("toto", "otot");
This is comparatively better for large characters range :
static boolean isAnagram(String text1, String text2){
if (text1.length() != text2.length())
return false;
// If you want to ignore case sensitivity of characters
text1 = text1.toLowerCase();
text2 = text2.toLowerCase();
Set<Character> set1 = new HashSet();
Set<Character> set2 = new HashSet();
for (int i = 0; i < text1.length(); i++) {
set1.add(text1.charAt(i));
set2.add(text2.charAt(i));
}
return set1.equals(set2);
}
First, the anagrams should have equal lengths, if this condition is not met, the words are not anagrams.
Next, as mentioned in the comments, not only the characters but their frequencies should be compared, that is, a map Map<Character, Integer> needs to be created containing frequency of each character in a string.
For one string the frequencies may be counted with + sign, and for the other with - sign. If all values in the map are 0, the words are anagrams.
The implementation may look as follows (using Map::merge to calculate frequencies and Stream::allMatch to detect the anagram):
public static boolean isAnagram(String a, String b) {
if (a.length() != b.length()) {
return false;
}
Map<Character, Integer> frequencies = new HashMap<>();
for (int i = 0, n = a.length(); i < n; i++) {
frequencies.merge(Character.toLowerCase(a.charAt(i)), 1, Integer::sum);
frequencies.merge(Character.toLowerCase(b.charAt(i)), -1, Integer::sum);
}
return frequencies.values().stream().allMatch(x -> x == 0);
}
Tests
String[][] tests = {
{"act", "tact"},
{"acta", "tact"},
{"Raca", "arca"}
};
for(String[] t : tests) {
System.out.printf("Are '%s' and '%s' anagrams? %s%n", t[0], t[1], isAnagram(t[0], t[1]));
}
Output
Are 'act' and 'tact' anagrams? false
Are 'acta' and 'tact' anagrams? false
Are 'Raca' and 'arca' anagrams? true
This solution is faster with the time complexity of O(n). However, it needs extra space for the counting array. At 256 integers, for ASCII that's not too bad. But increasing CHARACTER_RANGE to support multiple-byte character sets such as UTF-8, this would become very memory hungry. Therefore, it's only really practical when the number of possible characters is in a small range.
class Anagram {
static int CHARACTER_RANGE= 256;
static boolean isAnagram(String text1, String text2){
if (text1.length() != text2.length())
return false;
// if want to consider case sensitivity of char
//char str1[] = text1.toCharArray();
//char str2[] = text2.toCharArray();
// if don't want to consider case sensitivity of char
char str1[] = text1.toLowerCase().toCharArray();
char str2[] = text2.toLowerCase().toCharArray();
int count1[] = new int[CHARACTER_RANGE];
Arrays.fill(count1, 0);
int count2[] = new int[CHARACTER_RANGE];
Arrays.fill(count2, 0);
int i;
for (i = 0; i < str1.length && i < str2.length; i++) {
count1[str1[i]]++;
count2[str2[i]]++;
}
for (i = 0; i < CHARACTER_RANGE; i++)
if (count1[i] != count2[i])
return false;
return true;
}
}

check if two strings are permutation of each other?

I am solving this question as an assignment of the school. But the two of my test cases are coming out wrong when I submit the code? I don't know what went wrong. I have checked various other test cases and corner cases and it all coming out right.
Here is my code:
public static boolean isPermutation(String input1, String input2) {
if(input1.length() != input2.length())
{
return false;
}
int index1 =0;
int index2 =0;
int count=0;
while(index2<input2.length())
{
while(index1<input1.length())
{
if( input1.charAt(index1)==input2.charAt(index2) )
{
index1=0;
count++;
break;
}
index1++;
}
index2++;
}
if(count==input1.length())
{
return true;
}
return false;
}
SAMPLE INPUT
abcde
baedc
output
true
SAMPLE INPUT
abc
cbd
output
false
A simpler solution would be to sort the characters in both strings and compare those character arrays.
String.toCharArray() returns an array of characters from a String
Arrays.sort(char \[\]) to sort a character array
Arrays.equals(char \[\], char \[\]) to compare the arrays
Example
public static void main(String[] args) {
System.out.println(isPermutation("hello", "olleh"));
System.out.println(isPermutation("hell", "leh"));
System.out.println(isPermutation("world", "wdolr"));
}
private static boolean isPermutation(String a, String b) {
char [] aArray = a.toCharArray();
char [] bArray = b.toCharArray();
Arrays.sort(aArray);
Arrays.sort(bArray);
return Arrays.equals(aArray, bArray);
}
A more long-winded solution without sorting would to be check every character in A is also in B
private static boolean isPermutation(String a, String b) {
char[] aArray = a.toCharArray();
char[] bArray = b.toCharArray();
if (a.length() != b.length()) {
return false;
}
int found = 0;
for (int i = 0; i < aArray.length; i++) {
char eachA = aArray[i];
// check each character in A is found in B
for (int k = 0; k < bArray.length; k++) {
if (eachA == bArray[k]) {
found++;
bArray[k] = '\uFFFF'; // clear so we don't find again
break;
}
}
}
return found == a.length();
}
You have two ways to proceed
Sort both strings and then compare both strings
Count the characters in string and then match.
Follow the tutorial here
In case you String is ASCII you may use the next approach:
Create 256 elements int array
Increment element of corresponding character whenever it's found in string1
Decrement element of corresponding character whenever it's found in string2
If all elements are 0, then string2 is permutation of string1
Overall complexity of this approach is O(n). The only drawback is space allocation for charCount array:
public static boolean isPermutation(String s1, String s2) {
if (s1.length() != s2.length()) {
return false;
}
int[] charCount = new int[256];
for (int i = 0; i < s1.length(); i++) {
charCount[s1.charAt(i)]++;
charCount[s2.charAt(i)]--;
}
for (int i = 0; i < charCount.length; i++) {
if (charCount[i] != 0) {
return false;
}
}
return true;
}
If your strings can hold non-ASCII values, the same approach could be implemented using HashMap<String, Integer> as character count storage
I have a recursive method to solve the permutations problem. I think that this code will seem to be tough but if you will try to understand it you will see the beauty of this code. Recursion is always hard to understand but good to use! This method returns all the permutations of the entered String 's' and keeps storing them in the array 'arr[]'. The value of 't' initially is blank "" .
import java.io.*;
class permute_compare2str
{
static String[] arr= new String [1200];
static int p=0;
void permutation(String s,String t)
{
if (s.length()==0)
{
arr[p++]=t;
return;
}
for(int i=0;i<s.length();i++)
permutation(s.substring(0,i)+s.substring(i+1),t+s.charAt(i));
}
public static void main(String kr[])throws IOException
{
int flag = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the first String:");
String str1 = br.readLine();
System.out.println("Enter the second String:");
String str2 = br.readLine();
new permute_compare2str().permutation(str1,"");
for(int i = 0; i < p; ++i)
{
if(arr[i].equals(str2))
{
flag = 1;
break;
}
}
if(flag == 1)
System.out.println("True");
else
{
System.out.println("False");
return;
}
}
}
One limitation that I can see is that the length of the array is fixed and so will not be able to return values for a large String value 's'. Please alter the same as per the requirements. There are other solution to this problem as well.
I have shared this code because you can actually use this to get the permutations of a string printed directly without the array as well.
HERE:
void permutations(String s,String t)
{
if (s.length()==0)
{
System.out.print(t+" ");
return;
}
for(int i=0;i<s.length();i++)
permutations(s.substring(0,i)+s.substring(i+1),t+s.charAt(i));
}
Value of 's' is the string whose permutations is needed and value of 't' is again empty "".
it will take O(n log n) cuz i sort each string and i used more space to store each one
public static boolean checkPermutation(String a,String b){
return sortString(a).equals(sortString(b));
}
private static String sortString(String test) {
char[] tempChar = test.toCharArray();
Arrays.sort(tempChar);
return new String(tempChar);
}
String checkPermutation(String a,String b){
char[] aArr = a.toCharArray();
char[] bArr = b.toCharArray();
Arrays.sort(aArr);
Arrays.sort(bArr);
if(aArr.length != bArr.length){
return "NO";
}
int p = 0, q = 0;
while(p < aArr.length){
if(aArr[p] != bArr[q]){
return "NO";
}
p++;
q++;
}
return "YES";
}
public static boolean isStringArePermutate(String s1, String s2){
if(s1==null || s2==null) {
return false;
}
int len1 = s1.length();
int len2 =s2.length();
if(len1!=len2){
return false;
}
for(int i =0;i<len1;i++){
if(!s1.contains(String.valueOf(s2.charAt(i)))) {
return false;
}
s1=s1.replaceFirst(String.valueOf(s2.charAt(i)), "");
}
if(s1.equals("")) {
return true;
}
return false;
}

How to identify the number of common character between two strings?

Given 2 strings, str1 and str2, as input, return the count of the chars which are in the same position in str1 and str2.
Sample Input #1
count("New York","New Delhi")
Sample Output #1
4
Because the two strings share the same four leading characters: "New "
Sample Input #2
count("rhinoceroses","hippopotamus")
Sample Output #2
2
Because 'o' occupies the fourth position and 's' the eleventh position in both strings.
MyApproach
#Edit
public int count(String str1, String str2)
{
int p=0;
int k=0;
int count=0;
int l1=str1.length();
int l2=str2.length();
if(l1>=l2)
{
while(k<l2)
{
char ch1=str1.charAt(p);
char ch2=str2.charAt(k);
if(ch1==ch2)
{
p++;
k++;
count++;
}
else
{
p++;
k++;
}
}
}
else
{
char ch1=str1.charAt(p);
char ch2=str2.charAt(k);
while(k<l1)
{
if(ch1==ch2)
{
p++;
k++;
count++;
}
else
{
p++;
k++;
}
}
}
return count;
}
Parameters Actual Output Expected Output
'Trisect''Classes' 0 1
I am getting correct output now.
Thanku
This can be done more preciously using a single loop. Find the below code with the solution :-
class GetCount {
public static void main(String args[]) {
String myString = "rhinoceroses";
String myString1 = "hippopotamus";
count(myString, myString1);
}
/**
* #param myString
* #param myString1
*/
private static void count(String myString, String myString1) {
int i = 0;
int count = 0;
int length = myString.length() < myString1.length() ? myString.length() : myString1.length();
while(i < length) {
if(myString.charAt(i) == myString1.charAt(i)) {
count++;
}
i++;
}
System.out.println("Count is :: " + count);
}
}
Here is a compact solution, very easy to understand.
Solution
public static int count(String s1, String s2){
int count = 0;
for (int i = 0 ; i < (s1.length() > s2.length() ? s2 : s1).length() ; i++){
count += s1.charAt(i) == s2.charAt(i) ? 1 : 0;
}
return count;
}
Input
public static void main(String[] args) {
System.out.println(
"New York, New Delhi : "
+ count("New York", "New Delhi"));
System.out.println(
"Rhinoceroses, Hippopotamus : "
+ count ("Rhinoceroses", "Hippopotamus"));
}
Output
New York, New Delhi : 4
Rhinoceroses, Hippopotamus : 2
The solutions provided before are useless, as they work only if the characters are in the same sequence.
Here is my solution:
private int commonCharacterCount(String s1, String s2) {
int counter = 0;
List<Character> list = new LinkedList<>();
for (char aChar : s1.toCharArray()) {
list.add(aChar);
}
for (char c : s2.toCharArray()) {
if (list.contains(c)) {
list.remove(Character.valueOf(c));
counter++;
}
}
return counter;
}
You are welcome :)
You can also do something like this. (Try it) -
public int count(String s1, String s2) {
int result=0;
char[] ch1=s1.toCharArray();
char[] ch2=s2.toCharArray();
if(ch1.length>ch2.length){
for(int i=0;i<ch2.length;i++){
if(ch1[i]==ch2[i]){
result++;
}
}
}
else{
for(int i=0;i<ch1.length;i++){
if(ch2[i]==ch1[i]){
result++;
}
}
}
return result;
}
Typescript solution. Guaranteed constraints:
1 ≤ s1.length ≤ 15, 1 ≤ s2.length ≤ 15
function commonCharacterCount(s1: string, s2: string): number {
let count = 0;
let s_1 = s1.split("");
let s_2 = s2.split("");
for (let i = 0; i < s_1.length; i++) {
for (let j = 0; j < s_2.length; j++) {
if (s_1[i] == s_2[j]) {
count++;
s_2.splice(j, 1);
break;
}
}
}
return(count);
}
Since you need to count of the chars which are in the same position we can do it in a single loop checking at each iteration (string position) if the chars are equal or not. And the number of iteration should be the minimum length of str1 and str2 (maybe we could extract Math.min(str1.length(), str2.length()) in a variable). I compressed the if - else branches from your solution to a single loop using the minimum string length in loop condition.
public int countCommonChars(String str1, String str2) {
int commonCharsNumber = 0;
for(int i=0; i< Math.min(str1.length(), str2.length()); i++) {
if (str1.charAt(i) == str2.charAt(i)) {
commonCharsNumber++;
}
}
return commonCharsNumber;
}
int commonCharacterCount(String s1, String s2) {
Map<String, Integer> mapOfString1 = getOcuurances(s1);
Map<String, Integer> mapOfString2 = getOcuurances(s2);
int counter = 0;
for (Map.Entry<String, Integer> entry : mapOfString2.entrySet()) {
if (mapOfString1.get(entry.getKey()) != null) {
if (mapOfString1.get(entry.getKey()) > entry.getValue()) {
counter += entry.getValue();
} else {
counter += mapOfString1.get(entry.getKey());
}
}
}
return counter;
}
public Map<String, Integer> getOcuurances(String s) {
Map<String, Integer> hashMap = new HashMap<>();
String[] strings = s.split("");
for (int i = 0; i < strings.length; i++) {
if (hashMap.containsKey(strings[i])) {
hashMap.put(strings[i], hashMap.get(strings[i]) + 1);
} else {
hashMap.put(strings[i], 1);
}
}
return hashMap;
}
int count(String s1, String s2) {
Map<Character, Integer> charCountMap1 = getCharacterCount(s1);
Map<Character, Integer> charCountMap2 = getCharacterCount(s2);
return charCountMap1.entrySet().stream().map(charCountEntry ->
Math.min(charCountEntry.getValue(), charCountMap2.getOrDefault(charCountEntry.getKey(), 0))
).collect(Collectors.summingInt(value -> value));
}
private Map<Character, Integer> getCharacterCount(String str) {
Map<Character, Integer> charCountMap = new HashMap<>();
for (int i = 0; i < str.toCharArray().length; i++) {
Integer count = charCountMap.getOrDefault(str.charAt(i), 0);
charCountMap.put(str.charAt(i), ++count);
}
return charCountMap;
}
I would like to go with below:-
private static int solution(String s1, String s2) {
int count = 0;
List<Character> listChars = s1.chars().mapToObj(chr -> (char) chr)
.collect(Collectors.toCollection(LinkedList::new));
for (char c : s2.toCharArray()) {
if (listChars.contains(c)) {
listChars.remove(Character.valueOf(c));
count++;
}
}
return count;
}
Though there is already an accepted answer but I don't feel that answer is concise enough, hence I am giving mine (haven't compiled, treat it as psuedo-code please)
public static int count(String s1, String s2) {
if (s1 == null || s2==null ||s1.isEmpty() || s2.isEmpty()) {
return 0;
}
int minLength = Math.min(s1.length(), s2.length());
int count = 0;
for (int i < 0; i < minLength; ++i) {
if (s1.charAt(i) == s2.charAt(i)) {
++count;
}
}
return count;
}
public int count(String str1, String str2) {
int result = 0;
if (str1.length() == 0 || str2.length() == 0)
return result;
if (str1.length() > str2.length()) {
for (int i = 0; i < str2.length(); i++) {
if (str2.charAt(i) == str1.charAt(i))
result++;
}
}
else {
for (int i = 0; i < str1.length(); i++) {
if (str1.charAt(i) == str2.charAt(i))
result++;
}
}
return result;
}

Arranging word to formpalindrome

Hello i´ve been trying to form palindromes from this input:
String[] text ={"ivcci", "oyotta", "cecarar","bbb","babbbb"};
getPalindrome(text);
and i need to rearrange all words in array to produce this output
civic
-1
rececar
bbb
bbabb
the method expects to receive an array of Strings like
public static String getPalindrome(String[] text){}
"returning -1 means i.g "oyotta" in array can´t form a palíndrome
i´ve been testing this code and it works but i.g "cecarar" is not producing "racecar", as im a bit new in java i used an String intead an array of Strings, can anybody help to write this code properly please?
Thanks a lot!
public static String getPalindrome(String s) {
if (s == null)
return null;
Map<Character, Integer> letters = new HashMap<Character, Integer>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (!letters.containsKey(c))
letters.put(c, 1);
else
letters.put(c, letters.get(c) + 1);
}
char[] result = new char[s.length()];
int i = 0, j = result.length - 1;
Character middle = null;
for (Entry<Character, Integer> e : letters.entrySet()) {
int val = e.getValue();
char c = e.getKey();
if (val % 2 != 0) {
if (middle == null && s.length() % 2 != 0) {
middle = c;
val--;
} else
return "-1";
}
for (int k = 0; k < val / 2; k++) {
result[i++] = c;
result[j--] = c;
}
}
if (middle != null)
result[result.length / 2] = middle;
return new String(result);
}
In order for a set of characters to be able to produce a palindrome, only one of the letters can be repeated an odd number of times, so you can first weed that out.
Without writing actual code for you, here is the algorithm I would use:
Create a map of characters to a counter. Possible to do int[] counts = new int[26];
Go through each character in the input string, and increment the count: ++counts[Character.toLower(c)-'a'];
Then go through each character, and see if its odd if (counts[i] & 1 != 0) { if (oddIndex != -1) { return -1; } oddIndex=i; } This will return -1 if there is two or more odd counts.
Then, you can create a StringBuilder, and start with the oddIndex in the middle, if it exists.
Then go through the counts, and add count[i]/2 to the front and back of your string builder.
That'll give you a symmetric string from the original inputs.
Now, if you actually need words, then you'll have to have a dictionary of palindromes. You can actually preprocess all the palindromes to have a map of "sorted character string"=>"palindrome"
class PalindromeChecker
{
final Map<String, String> palindromes = new HashMap<String, String>();
public PalindromeChecker(Iterable<String> allPalindromes) {
for (String palindrome: allPalindromes) {
char[] chars = palindrome.getChars();
Arrays.sort(chars);
palindromes.put(String.valueOf(chars), palindromes);
}
}
public String getPalindrome(String input) {
char[] chars = input.getChars();
Arrays.sort(chars);
return palindromes.get(String.valueOf(chars));
}
}
As other users pointed out, a string can be rearranged as a palindrome only if there is at most one character that appears an odd number of times.
Once you have confirmed that a string can be converted to a palindrome, you can construct the palindrome as follows (this is just one of many methods of course):
place at the sides of the string all the pairs of characters that you can get
place at the middle of the string the single character that is left out, in case there is such a character.
Example:
public class Palindromes {
public static void main(String[] args) {
String[] text = {"ivcci", "oyotta", "cecarar","bbb","babbbb"};
for(String str : text){
evaluatePalindrome(str);
}
}
private static void evaluatePalindrome(String str){
PalindromeCandidate pc = new PalindromeCandidate(str);
if(pc.isPalindrome()){
System.out.println(pc.getPalindrome());
} else {
System.out.println("-1");
}
}
}
public class PalindromeCandidate {
private final CharacterCount characterCount;
public PalindromeCandidate(String originalString) {
this.characterCount = new CharacterCount(originalString);
}
public boolean isPalindrome(){
Collection<Integer> counts = characterCount.asMap().values();
int oddCountOccurrences = 0;
for(Integer count : counts){
oddCountOccurrences += (count%2);
}
return (oddCountOccurrences <= 1);
}
public String getPalindrome(){
if(!isPalindrome()){
throw new RuntimeException("Cannot be rearranged as a palindrome.");
}
Map<Character, Integer> counts = characterCount.asMap();
StringBuilder leftSide = new StringBuilder();
StringBuilder middle = new StringBuilder();
for(Character ch : counts.keySet()){
int occurrences = counts.get(ch);
while(occurrences > 1){
leftSide.append(ch);
occurrences -= 2;
}
if(occurrences > 0){
middle.append(ch);
}
}
StringBuilder rightSide = new StringBuilder(leftSide).reverse();
return leftSide.append(middle).append(rightSide).toString();
}
}
/**
* Thin wrapper around a Map<Character, Integer>. Used for counting occurences
* of characters.
*/
public class CharacterCount {
private final Map<Character, Integer> map;
public CharacterCount(String str) {
this.map = new HashMap<>();
for(Character ch : str.toCharArray()){
increment(ch);
}
}
private void increment(Character ch){
this.map.put(ch, getCount(ch) + 1);
}
private Integer getCount(Character ch){
if(map.containsKey(ch)){
return map.get(ch);
} else {
return 0;
}
}
public Map<Character, Integer> asMap(){
return new HashMap<>(map);
}
}

Java Alphabetizer

I'm trying to make a program in which I ask the user to input words, and then the program puts them in Alphabetical Order. Here's what I've got so far:
import java.util.Scanner;
public class WordAlphabeticalizer {
/**
* #param args
*/
public static void main(String[] args) {
// Variables and Objects
String arraylength;
Scanner input = new Scanner (System.in);
// Code
System.out.println("Please input how many terms you would like to alphabetize"):
arraylength = input.nextLine();
String[] words = new String[Integer.parseInt(arraylength)];
for(int index = 0; index < words.length; index ++){
System.out.println("Please input word number " + (index + 1) + ":");
words[index] = input.nextLine();
}
}
}
I would like to know how to go about comparing the first letters of each word in the array, and what logic I would use to keep going to compare the word to the first two, three, or how many ever spaces it needs to go in order to get which word goes first, and then the word that goes after it. Any ideas?
java.lang.String implements the java.lang.Comparable interface so you can sort them by adding them to a sorted collection (Try java.util.TreeSet)
Set<String> stringsToSort = new TreeSet<String>();
stringsToSort.add("Fish");
stringsToSort.add("Dog");
stringsToSort.add("Cat");
System.out.println(stringsToSort);
Though it's a bit verbose, this is a method I've used to alphabetise Strings:
public static String[] alphabetise(final String[] array)
{
Arrays.sort(array, new Comparator<String>()
{
#Override
public int compare(final String o1, final String o2)
{
if(o1 == null && o2 == null)
{
return 0;
}
else if(o1 == null)
{
return -1;
}
else if(o2 == null)
{
return 1;
}
else if(o1.equals(o2))
{
return 0;
}
else if(o1.isEmpty())
{
return -1;
}
else if(o2.isEmpty())
{
return 1;
}
final Character[] c1 = toCharacterArray(o1.toLowerCase());
final Character[] c2 = toCharacterArray(o2.toLowerCase());
final int max = Math.max(c1.length, c2.length);
for(int i = 0; i < max; i++)
{
if(i < c1.length && i < c2.length)
{
final int comp = c1[i].compareTo(c2[i]);
if(comp != 0)
{
return comp;
}
}
else return new Integer(c1.length).compareTo(new Integer(c2.length));
}
return 0;
}
});
return array;
}
static Character[] toCharacterArray(final String str)
{
if(str == null || str.isEmpty()) return new Character[0];
final Character[] array = new Character[str.length()];
int counter = 0;
for(final char c : str.toCharArray())
{
array[counter++] = c;
}
return array;
}
This will conform to proper alphabetical order, ignoring capitals and favouring shorter words over longer (e.g. "House" before "Houses").

Categories

Resources