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 );
}
}
Related
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
I have this code where I am printing a string variable. The first output is showing what is expected but the second time it prints some unreadable output(I think its reference id). Please explain: Why does this happen?
public class Str3 {
public String frontBack(String str) {
char c[] = str.toCharArray();
char temp = c[0];
c[0] = c[c.length - 1];
c[c.length - 1] = temp;
return c.toString();
}
public static void main(String args[]) {
Str3 s = new Str3();
String s1 = new String("boy");
System.out.println(s1);
String s2 = s.frontBack("boy");
System.out.println(s2);
}
}
Output:
boy
[C#60aeb0
the frontToBack() method is calling toString() on a character array object char[] which is why you see the [C#60aebo. Instead of calling toString() return with new String(c); or String.valueOf(c)
Array types in Java do not override Object#toString(). In other words, array types inherit Object's implementation of toString() which is just
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
which is the output you see
[C#60aeb0
If you want to see a representation of the contents of an array, use Arrays.toString(..).
In your case, you seem to want to switch the first and last characters and return the corresponding string. In that case, just create a new String instance by passing the char[] to the constructor.
You don't need to implement a custom class to do this. The functionality is already in java.
This question has already been answered # Reverse a string in Java
(duplicate thread)
use new String(c) to c.toString();
c.toString() c mean array of chars toString() print hash method
public class Str3 {
public String frontBack(String str) {
char c[] = str.toCharArray();
char temp = c[0];
c[0] = c[c.length - 1];
c[c.length - 1] = temp;
return new String(c);
}
public static void main(String args[]) {
Str3 s = new Str3();
String s1 = new String("boy");
System.out.println(s1);
String s2 = s.frontBack("boy");
System.out.println(s2);
} }
public class StringEx {
public static void main(String[] args){
String s1 ="abcc";
String s2 = "cbaa";
getCommon(s1,s2);
}
private static void getCommon(String s1, String s2) {
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
char[] commonAry = new char[10];
for(int i=0;i < (c1.length)-1;i++){
for(int j=0;j<(c2.length)-1;j++){
if(c1[i]==c2[j]){
int k=0;
commonAry[k]=c1[i];
k++;
}
}
}
System.out.println(commonAry);
}
}
the above program is giving an output like "c n some square boxer after that".. what is wrong in above code.
Use Set<character> retainAll() method to get the intersect between the two String
public static void getCommon(String s1,String s2){
char[] s1Array = s1.toCharArray();
char [] s2Array = s2.toCharArray();
Set<Character>s1CharSet = new HashSet<Character>();
Set<Character>s2CharSet = new HashSet<Character>();
for(char c:s1Array){
s1CharSet.add(c);
}
for(char c: s2Array){
s2CharSet.add(c);
}
s1CharSet.retainAll(s2CharSet);
if(s1CharSet.size()==0){
System.out.println("There are no common characters between the two strings");
}
else{
System.out.println(s1CharSet);
}
}
output
[b, c, a]
Demo
firstly, you are not looping over all the char array, your looping
should be:
for(int i=0;i < (c1.length);i++)
secondly, you must initialize the index k out of your loops,
thirdly, this operation is not commutative, that means
getCommon(String s1, String s2)
and
getCommon(String s2, String s1)
won't give the same results,
and finally, because you're trying to get common letters, so why not
break the inner loop just after finding any similar character in the
other array?
Note: you should omit any redundancy in your first string, or in the
result, after calculation.
and for square letters, I refer you to this post https://stackoverflow.com/a/13505323/1951298
I am required to write a method, compress to do the following;
The objective of the
method compress is to remove all null elements from the stack s1. The remaining (non-null)
elements should be kept on s1 in their initial order. The auxiliary stack s2 should be used as
a temporary storage for the elements from s1. At the end of the computation of this method,
stack s2 should have the same content as at the beginning of the computation. See the method
main for an example of the expected behaviour of the method compress.
So far I have;
import net.datastructures.ArrayStack;
import net.datastructures.Stack;
public class Stacks {
public static <E> void compress(Stack<E> S1, Stack<E> S2) {
int counter = 0;
while (!S1.isEmpty()) {
}
if (S1.top() == null) {
S1.pop();
} else if (S1.top() != null) {
S2.push(S1.pop());
counter++;
}
for (int i = counter; i < counter; i++) {
S2.push(S1.pop());
}
}
public static void main(String[] args) {
// test method compress
Stack<Integer> S1 = new ArrayStack<Integer>(10);
S1.push(2);
S1.push(null);
S1.push(null);
S1.push(4);
S1.push(6);
S1.push(null);
Stack<Integer> S2 = new ArrayStack<Integer>(10);
S2.push(7);
S2.push(9);
System.out.println("stack S1: " + S1);
// prints: "stack S1: [2, null, null, 4, 6, null]"
System.out.println("stack S2: " + S2);
// prints: "stack s2: [7, 9]"
compress(S1, S2);
System.out.println("stack S1: " + S1);
// should print: "stack S1: [2, 4, 6]"
System.out.println("stack S2: " + S2);
// should print: "stack S2: [7, 9]"
}
}
I can't figure out where I'm going wrong, the code prints the two lines before the compress method and then prints nothing.
while (!S1.isEmpty()) {
}
Right there, you have an infinite loop.
i guess writing the if...else inside your while() as below
while (!S1.isEmpty()) {
if (S1.top() == null) {
S1.pop();
} else if (S1.top() != null) {
S2.push(S1.pop());
counter++;
}
}
and inside your for it must be something like
for (int i = counter; i < counter; i++) {
S1.push(S2.pop());
}
guess it should work
I spotted two mistakes in your code. One on each of your cycles.
Your while loop should be wrapping the conditionals right after
it.
Your for loop has its increment variable badly assigned.
Correct version should be:
public static <E> void compress(Stack<E> S1, Stack<E> S2) {
int counter = 0;
while (!S1.isEmpty()) {
if (S1.top() == null) {
S1.pop();
} else {
S2.push(S1.pop());
counter++;
}
}
for (int i = 0; i < counter; i++) {
S1.push(S2.pop());
}
}
Edit: An equivalent for loop (maybe you were trying to write this one) may be as follows.
for (int i = counter; i > 0; i--) {
S1.push(S2.pop());
}
2nd edit: The variables in the for loops were switched (S2 was in S1's place and vice versa).
I have two strings with me:
s1="MICROSOFT"
s2="APPLESOFT"
I need to compare the strings and remove the duplicate part (always towards the end) from the second string. So I should get "MICROSOFT" and "APPLE" as output.
I have compared both the strings character by character.
String s1 = "MICROSOFT";
String s2 = "APPLESOFT";
for(int j=0; j<s1.length(); j++)
{
char c1 = s1.charAt(j);
char c2 = s2.charAt(j);
if(c1==c2)
System.out.println("Match found!!!");
else
System.out.println("No match found!");
}
It should check the strings and if the two strings have same characters until the end of string, then I need to remove that redundant part, SOFT in this case, from the second string. But I can't think of how to proceed from here.
There can be more duplicates...but we have to remove only those which are continuously identical. if i have APPWWSOFT and APPLESOFT, i should get APPLE again in the second string since we got LE different than WW in between
Can you guys please help me out here?
Search and read about Longest Common Subsequence, you can find efficient algorithms to find out the LCS of two input strings. After finding the LCS of the input strings, it is easy to manipulate the inputs. For example, in your case an LCS algorithm will find "SOFT" as the LCS of these two strings, then you might check whether the LCS is in the final part of the 2nd input and then remove it easily. I hope this idea helps.
An example LCS code in Java is here, try it: http://introcs.cs.princeton.edu/java/96optimization/LCS.java.html
Example scenario (pseudocode):
input1: "MISROSOFT";
input2: "APPLESOFT";
execute LCS(input1, input2);
store the result in lcs, now lcs = "SOFT";
iterate over the characters of input2,
if a character exists in lcs then remove it from input2.
As far as I understand, you want to remove any identical characters from the two strings. By identical I mean: same position and same character(code). I think the following linear complexity solution is the simplest:
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder(); //if you want to remove the identical char
//only from one string you don't need the 2nd sb
char c;
for(int i = 0; i<Math.min(s1.length,s2.length);i++){
if((c = s1.charAt(i)) != s2.charAt(i)){
sb1.append(c);
}
}
return sb1.toString();
Try this algo- Create characters sequences of your first string and find it in second string.
performance -
Average case = (s1.length()-1)sq
public class SeqFind {
public static String searchReplace(String s1,String s2) {
String s3;
boolean brk=false;
for(int j=s1.length();j>0&&!brk;j--){
for (int i = j-4; i > 0; i--) {
String string = s1.substring( i,j);
if(s2.contains(string)){
System.out.println(s2+" - "+string+" "+s2.replace( string,""));
brk=true;
break;
}
}
}
return s3;
}
public static void main(String[] args) {
String s1 = "MICROSOFT";
String s2 = "APPLESOFT";
String s3 = searchReplace(s1,s2);
}
}
Out put -
APPLESOFT - SOFT - APPLE
public class Match {
public static void main(String[] args)
{
String s1="MICROSOFT";
String s2="APPLESOFT";
String[] s=new String[10];
String s3;
int j=0,k=0;
for(int i=s2.length();i>0;i--)
{
s[j]=s2.substring(k,s2.length());
if(s1.contains(s[j]))
{
s3=s2.substring(0,j);
System.out.println(s1+""+s3);
System.exit(0);
}
else
{
System.out.println("");
}
j++;
k++;
}
}
}
I have edited the code you can give it an another try.
try this, not tested thou
String s1 = "MICROSOFT";
String s2 = "APPLESOFT";
String s3="";
for(int j=0; j<s1.length(); j++)
{
if(s1.charAt(j)==s2.charAt(j)){
s3+=s1.charAt(j);
}
}
System.out.println(s1.replace(s3, " ") + " \n"+ s2.replace(s3, " "));
You should rather use StringBuffer if you want your String to be modified..
And in this case, you can have one extra StringBuffer, in which you can keep on appending non-matching character: -
StringBuffer s1 = new StringBuffer("MICROSOFT");
StringBuffer s2 = new StringBuffer("APPLESOFT");
StringBuffer s3 = new StringBuffer();
for(int j=0; j<s1.length(); j++)
{
char c1 = s1.charAt(j);
char c2 = s2.charAt(j);
if(c1==c2) {
System.out.println("Match found!!!");
} else {
System.out.println("No match found!");
s3.append(c1);
}
}
s1 = s3;
System.out.println(s1); // Prints "MICRO"
I have solved my problem after racking some brains off. Please feel free to correct/improve/refine my code. The code not only works for "MICROSOFT" and "APPLESOFT" inputs, but also for inputs like "APPWWSOFT" and "APPLESOFT" (i needed to remove the continuous duplicates from the end - SOFT in both the above inputs). I'm in the learning stage and I'll appreciate any valuable inputs.
public class test
{
public static void main(String[] args)
{
String s1 = "MICROSOFT";
String s2 = "APPLESOFT";
int counter1=0;
int counter2=0;
String[] test = new String[100];
test[0]="";
for(int j=0; j<s1.length(); j++)
{
char c1 = s1.charAt(j);
char c2 = s2.charAt(j);
if(c1==c2)
{
if(counter1==counter2)
{
//System.out.println("Match found!!!");
test[0]=test[0]+c2;
counter2++;
//System.out.println("Counter 2: "+counter2);
}
else
test[0]="";
}
else
{
//System.out.print("No match found!");
//System.out.println("Counter 2: "+counter2);
counter2=counter1+1;
test[0]="";
}
counter1++;
//System.out.println("Counter 1: "+counter1);
}
System.out.println(test[0]);
System.out.println(s2.replaceAll(test[0]," "));
}
}