Checking Anagram of a String array input - java

This is my code below to check anagram of a given string array.
It always gives me false even in the simplest case with only one input.
I don't understand am I not converting string array into string correctly or my algorithm is plain wrong.
public class anagram
{
static boolean isAnagram(String[] s1, String[] s2) {
String str = s1.toString();
String str2 = s2.toString();
if (str.length() != str2.length())
return false;
for (int i =0; i<str.length();i++)
{
for (int j = 0;j<str2.length();j++)
{
if (s1[i] == s2[j]) {
return true;
}
return false;
}
}
return true;
}
public static void main(String [] args){
String [] s1 = {"shot"};
String [] s2 = {"host"};
System.out.println(isAnagram(s1,s2));
}
}
Can you please help me identify what is wrong?

Your algorithm for checking seems to be a little incorrect.
Edited the isAnagram function here:
public static void main(String[] args)
{
String s1 = "shotaabb";
String s2 = "hostbaba";
System.out.printf("String s1: %s, String s2: %s%n", s1, s2);
System.out.println(isAnagram(s1, s2) ?
"Is anagram" : "Is not an anagram");
}
static boolean isAnagram(String s1, String s2)
{
String str1 = new String(s1);
String str2 = new String(s2);
// Ensures that both strings are of the same length
if (str1.length() != str2.length())
return false;
int str1Len = str1.length();
for (int i = 0; i < str1Len; i++)
{
int charIndex = str2.indexOf(str1.charAt(i));
if(charIndex == -1) // Not found in str2
return false;
else
{
// Remove the character from str2
str2 = str2.substring(0, charIndex) +
str2.substring(charIndex + 1);
}
}
return true;
}
What the code does is:
Gets a character from s1, finds the index of that character inside s2
If the index is -1, character not found inside s2, return false
If the character can be found inside s2, remove it from s2
At the end, if all characters inside s1 can be found in s2, return true
Based on the fact that both strings are of the same length, if all character in s1 can be found & removed from s2, s1 is an anagram of s2 & vice versa.
Output:
String s1: shotaabb, String s2: hostbaba
Is anagram
Update (Comparing String arrays):
String[] strArr1 = {"shot", "dcba"};
String[] strArr2 = {"host", "abcd"};
for(String s1 : strArr1)
{
for(String s2 : strArr2)
{
System.out.printf("%nString s1: %s, String s2: %s%n", s1, s2);
System.out.println(isAnagram(s1, s2) ?
"Is anagram" : "Is not an anagram");
}
}
Output for updated code:
String s1: shot, String s2: host
Is anagram
String s1: shot, String s2: abcd
Is not an anagram
String s1: dcba, String s2: host
Is not an anagram
String s1: dcba, String s2: abcd
Is anagram

Strings are not primitive variables in Java, therefore you must use the .equals() method instead of checking for equality using '==' to perform a thorough comparison.

public static bool IsAnagram(string firstString, string secondString)
{
firstString = firstString.Replace(" ", "").ToLower();
secondString = secondString.Replace(" ", "").ToLower();
var firstStringArray = firstString.OrderBy(x => x);
var secondStringArray = secondString.OrderBy(x => x);
string s1 = new string(firstStringArray.ToArray());
string s2 = new string(secondStringArray.ToArray());
if (s1.Equals(s2))
{
return true;
} else {
return false;
}
}

To check if two String are anagram, case not sensitive, here the method:
public boolean isAnagram(String s1, String s2) {
class SortChars{
String sort(String source) {
char[] chars = source.toLowerCase().toCharArray();
Arrays.sort(chars);
return new String(chars);
}
}
SortChars sc = new SortChars();
return sc.sort(s1).equals(sc.sort(s2));
}
The solution is taken from the book "cracking the coding interview", Authored by Gayle Laakmann McDowell

Related

if condition in Java Anagram Class not validating the String properly. getting not an anagram for anagram string

The below code working without error but it not getting proper result for anagram. The if condition is return false for correct value.
import java.util.*;
public class Anagram{
public boolean solve(String s1, String s2){
if(s1.length() != s2.length()) return false;
String[] s11 = s1.split("");
String[] s12 = s2.split("");
Arrays.sort(s11);
System.out.println(Arrays.toString(s11));
Arrays.sort(s12);
System.out.println(Arrays.toString(s12));
for(int i = 0; i < s1.length(); i++){
if(s11[i] != s12[i])
System.out.println(s11[i]);
System.out.println(s12[i]);
return false;
}
return true;
}
public static void main(String[] args){
String s1 = "restful";
String s2 = "fluster";
Anagram v = new Anagram();
if(v.solve(s1, s2)){
System.out.println(s2 + " is anagram of the " + s1);
}else{
System.out.println("not an anagram");
}
}
}
Please let me know why it is not working
Ideally here no need to check individual character from both the Array
You can directly check both the Sorted Arrays are equals or not. Replace your for loop with the below code :
if(!Arrays.equals(s11, s12)){
return false ;
}
Also your code is not working because == is comparing the reference and not the value in Java

I have to check pallindrome string.I am getting a wrong answer when I enter String having numeric values.For ex."0P"

I have to ignore all special characters in the string.I have created a new string s1 including only alphanumerics characters.Then,made a reverse string s2 and then checked if they are pallindrome or not.
class Solution
{
public boolean isPalindrome(String s)
{
char c,ch;
String s1="";
String s2="";
s=s.trim();
s=s.toLowerCase();
if(s=="")
return true;
for(int i=0;i<s.length();i++)
{
c=s.charAt(i);
if(c>=97&&c<=122||c>=0&&c<=9)
s1=s1+c;
}
for(int j=s1.length()-1;j>=0;j--)
{
ch=s1.charAt(j);
s2=s2+ch;
}
if(s1.equals(s2))
return true;
else
return false;
}
}
String str = "# Test!##!#!#92432432";
String tmp = str.replaceAll("[^a-zA-Z0-9]", "");
System.out.println(tmp);
Prints
Test92432432
Ref:
How to ignore special characters and spaces in string?
As I understand, you are using c>=0&&c<=9 for checking c for digit. It is wrong, cause '0' == 48 and '9' == 57 and you have to use c>=48 && c<=57
And I want to give you some comments about your code:
String is an immutable object in java and a lot of string
concatenating - is a very bad practice. Please use StringBuilder.
You can use s.isEmpty() instead of s==""
Character class has static methods isDigit and isAlphabetic, whic are checks char for digit or alphabetic
If you will use StringBuilder, you can invert string just by stringBuilder.reverse() method
At the end of the method, you return true if s1.equals(s2) and false - overwise. You can just use return s1.equals(s2);
And you can iterating through the string with for (char c : s.toCharArray()) cycle
And the final code is
public static boolean isPalindrome(String s)
{
s=s.trim();
s=s.toLowerCase();
if(s.isEmpty())
return true;
StringBuilder sanitizedString = new StringBuilder();
for (char c : s.toCharArray()) {
if(Character.isAlphabetic(c) || Character.isDigit(c))
sanitizedString.append(c);
}
String s1 = sanitizedString.toString();
String s2 = sanitizedString.reverse().toString();
return s1.equals(s2)
}
And you can use regexp from #RR_IL answer for avoiding the cycle.
You can use something like this:
public static boolean isPalindrome(String s)
{
int i = 0;
int j = s.length() - 1;
while (i < j) {
if (s.charAt(i) != s.charAt(j))
return false;
i++;
j--;
}
return true;
}

Java String utility/method to union two strings

Is there any helper method or utility that actually gives me union of two strings.
For instance, if i have two strings as below:
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
I'm looking for a solution which will take above two strings as input and outputs the result as below:
General syntax: s1.{method/utility}(s2);
output : Isabella,tom,hardy,victor,smith
First, there is no method or utility provided by JDK to address the problem so straight forward.
Second, just for this simple utility importing a 3rd party jar or dependency is not a wise choice.
In this case its always a wise choice to write your own method of purpose.
public static String mergeString(String s1, String s2) {
//check for null as the method doesnt fall in NPE
if(s1 == null || s2 == null) {
return null;
}
//split the given String to some list
List<String> s1List = Arrays.asList(s1.split(","));
List<String> s2List = Arrays.asList(s2.split(","));
//get a Set and add the list items to it. LinkedHashSet
//is used to maintain the given order.
Set<String> stringSet = new LinkedHashSet<>(s1List);
stringSet.addAll(s2List);
//Then join them using java 8 provided Utility
return String.join(",", stringSet);
}
NB: as you mentioned in the comments you may need this type of utility only once in your project. But despite, this logic should be separated from out of your business method. This will make your code more clean and readable.
You can use org.springframework.util.StringUtils
Add a maven dependency spring-core:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
Use StringUtils:
public static void main(String[] args) {
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
String[] outputArr=StringUtils.mergeStringArrays(s1.split(","),s2.split(","));
String output=StringUtils.arrayToCommaDelimitedString(outputArr);
System.out.println(output);
}
Output:
Isabella,tom,hardy,victor,smith
public void unionString(String s1, String s2){
String[] s1Ar = s1.split(",");
String[] s2Ar = s2.split(",");
HashSet<String> set = new HashSet<String>();
for(int i=0;i<s1Ar.length;i++){
set.add(s1Ar[i]);
}
for(int i=0;i<s2Ar.length;i++){
set.add(s2Ar[i]);
}
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
Here's a method that will do the union of two strings. You can also pass it a boolean flag to dictate case sensitivity.
public static String union (String s1, String s2, boolean caseInsensitive)
{
// if either string is null, union is the other string
if (s1 == null)
return s2;
if (s2 == null)
return s1;
// use linked set to keep ordering
Set<String> unique = new LinkedHashSet<>();
// put all words from string 1 into the set
for (String word : s1.split(","))
{
word = word.trim(); // remove surrounding space on word
if (caseInsensitive)
{
word = word.toLowerCase();
}
unique.add(word);
}
// put all words from string 2 into the set
for (String word : s2.split(","))
{
word = word.trim(); // remove surrounding space on word
if (caseInsensitive)
{
word = word.toLowerCase();
}
unique.add(word);
}
// get back the format of comma delimiter for the union
String ret = unique.toString().replaceAll("[\\[\\] ]", "");
return ret;
}
Usage:
public static void main(String args[])
{
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
String union = union(s1, s2, false);
System.out.println(union);
}
Outputs:
Isabella,tom,hardy,victor,smith
You Can Use LinkedHashSet which maintains the insertion Order to get desired output.Below is my code:
public class UnionJava {
static LinkedHashSet<String> hashSetString = new LinkedHashSet<>();
static String s1 = "Isabella,tom,hardy"; static String s2 = "Isabella,tom,hardy,victor,smith";
public static void main(String args[]){
String[] set1 = s1.split(","); String[] set2 = s2.split(",");
for(int i=0; i< set1.length;i++){
hashSetString.add(set1[i]);
}
for(int i=0;i<set2.length;i++){
hashSetString.add(set2[i]);
}
int j=0;
for(Iterator i = hashSetString.iterator(); i.hasNext();){
if(j==0){
System.out.print(i.next());
j++;
}else{
System.out.print(","+i.next());
}
}
}
}
A short version with no sanity checks using LinkedHashSet.
public void printUnion() {
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
Set<String>mySet = new LinkedHashSet<>();
mySet.addAll(Arrays.asList(s1.split(",")));
mySet.addAll(Arrays.asList(s2.split(",")));
mySet.stream().forEach(System.out::println);
}
With the java api, you might try :
public class StringTest {
private String string1 ="";
private String string2 ="";
private List<String> array1 = new ArrayList<String>();
private List<String> array2 = new ArrayList<String>();
private String[] stringa1;
private String[] stringa2;
private int output3 = 0;
private int output4 = 0;
public static void main(String[] args) {
new StringTest().startApp();
}
private void startApp() {
string1 = "Isabella,tom,hardy";
stringa1 = string1.split("\\s+"); //array to split
string2 = "Isabella,tom,hardy,victor,smith";
stringa2 = string2.split("\\s+");
for(int o = 0; o<stringa1.length; o++) {
array1.add(stringa1[o]); //adding to arraylist
}
for(int o = 0; o<stringa2.length; o++) {
array2.add(stringa2[o]);
}
for(int outP = 0; outP<array2.size()+array1.size(); outP++) {
for(output4 = 0; output4<array2.size(); output4++) { //iterating and removing double elements
for(output3 = 0; output3<array1.size(); output3++) {
if(array1.size() > array2.size() && array2.get(output4).equalsIgnoreCase(array1.get(output3))) {
array1.remove(array1.get(output3));
}
if(array1.size() < array2.size() && array2.get(output4).equalsIgnoreCase(array1.get(output3))) {
array2.remove(array2.get(output4));
}
}
}
}
array1.addAll(array2); //merging the lists
for(String outPres1 : array1) {
result += " " + outPres1;
}
System.out.println("This is the output: " + result);
}
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
Set<String> result = new TreeSet<String>();
result.addAll(Arrays.asList(s1.split((","))));
result.addAll(Arrays.asList(s2.split((","))));
System.out.println(result);
Well, someone's got to provide a streams solution:
Stream.of(s1, s2)
.flatMap(Pattern.compile(",")::splitAsStream)
.distinct()
.collect(Collectors.joining(","))

How to increment a particular character in string (Java)

suppose i have a string s1 = "abcd";
output should be s1 = "abca";
I want to decrement/increment the last character in the string so that it matches the first character of the string .
Since String doesn't allow to modify the data
How can I achieve this.
Since, as you noted, String is immutable you will have to perform an assignment. I'd do a substring() and then concatenate the first letter. Something like
String s1 = "abcd";
s1 = s1.substring(0, s1.length() - 1) + s1.charAt(0);
System.out.println(s1);
Output is (as requested)
abca
JLS-4.2.1. Integral Types and Values does document that char is an integral type. That allows you to do something like
public static String modifyCharInString(String in, int index, int ammount) {
if (in == null || in.isEmpty() || index < 0 || index >= in.length()) {
return in;
}
StringBuilder sb = new StringBuilder(in);
sb.setCharAt(index, (char) (in.charAt(index) + ammount));
return sb.toString();
}
And then you an call it like
public static void main(String[] args) {
String s1 = "abcd";
s1 = modifyCharInString(s1, s1.length() - 1, -3);
System.out.println(s1);
}
Output is (again)
abca
For editing Strings you can use StringBuilder class. This allows you to get better performance, than using substring().
String oldString = "abcd";
StringBuilder sb = new StringBuilder(oldString);
sb.setCharAt(sb.length() - 1, sb.charAt(0));
String newString = sb.toString();

String permutation with recursion

I am a java beginner and trying to do a string permutation practice from java programming book. I am defining two method:
public static void displayPermutation(String s)
public static void displayPermutation(String s1, String s2)
The first method simply invokes displayPermutation(" ", s). The second method uses a loop to move a character from s2 to s1 and recursively invokes it with a new s1 and s2. The base case is that s2 is empty and prints s1 to the console.
Can anyone help me to find what is the problem of the following code?
Her's example:
public static void displayPermutation(String s) {
displayPermuatation("", s);
}
private static void displayPermuatation(String s1, String s2) {
//base case: when s2 is empty, print s1
if (s2.isEmpty()) {
System.out.println(s1);
}
else {
for (int i = 0; i < s2.length(); i++) {
//move a char from s1 to s2, and recursively invokes it with
//new s1 and s2
s1 = s1 + s2.charAt(i);
s2 = s2.substring(0, i) + s2.substring(i+1);
displayPermuatation(s1, s2);
}
}
}
if s = "abc",
it prints only:
abc
acb
it seems that in the first call of displayPermuatation("", "abc"), it does not finish the for loop....
any comments?
Thanks for all the comments below. I think the mistakes I made is because that passing object as argument to a method is actually passing the reference. it is not like primitive data (passing by value). When changing the object, it will affect following method call using that object.
Do not alter s1 and s2 in the loop, that causes the error. Simply pass those definitions as arguments to recursive function. Like this:
.
.
for (int i = 0; i < s2.length(); i++) {
displayPermuatation(s1 + s2.charAt(i), s2.substring(0, i) + s2.substring(i+1));
}
.
.
Problem with your code is that you are changing value of s1 and s2 in the loop which affects the following iterations in the loop, see the following code where I have fixed this issue.
public static void displayPermutation(String s) {
displayPermuatation("", s);
}
private static void displayPermuatation(String s1, String s2) {
// base case: when s2 is empty, print s1
if (s2.isEmpty()) {
System.out.println(s1);
} else {
for (int i = 0; i < s2.length(); i++) {
// move a char from s1 to s2, and recursively invokes it with
// new s1 and s2
displayPermuatation(s1 + s2.charAt(i), s2.substring(0, i) + s2.substring(i + 1));
}
}
}
Don't change the original values for s1, s2 in the loop:
private static void displayPermuatation(String s1, String s2) {
//base case: when s2 is empty, print s1
if (s2.isEmpty()) {
System.out.println(s1);
}
else {
for (int i = 0; i < s2.length(); i++) {
//move a char from s1 to s2, and recursively invokes it with
//new s1 and s2
string new_s1 = s1 + s2.charAt(i);
string new_s2 = s2.substring(0, i) + s2.substring(i+1);
displayPermuatation(new_s1 , new_s2 );
}
}

Categories