0

Here is the question: Given two strings s and goal, return true if and only if s can become goal after some number of shifts on s.

A shift on s consists of moving the leftmost character of s to the rightmost position.

For example, if s = "abcde", then it will be "bcdea" after one shift.

  • Input: s = "abcde", goal = "cdeab" Output: true
  • Input: s = "abcde", goal = "abced" Output: false

Here is the code I wrote:

public static void main(String[] args) {

    System.out.println(rotateString("abcd","cdab"));

    }

public static boolean rotateString(String s, String goal) {
        Boolean flag = false;
        StringBuilder builder = new StringBuilder(s);

            for (int i=0;i<=s.length()-1;i++){
            if (builder.toString() == goal) {
                flag= true;
                break;
            }

            char temp = builder.charAt(builder.length()-1);
            for (int j=s.length()-1;j>=0;j--){

                if (j==0) continue;
                builder.setCharAt(j, builder.charAt(j-1));

            }
            builder.setCharAt(0,temp);
            }

        return flag;
    }

I don't know how the flag is still false I also tried debugging it, it shows value of builder.toString() and goal is same.

I was expecting the flag to be true but it always stays false.

  • 2
    You are not using the correct method to compare two strings in Java. See https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java – Malcolm Jul 28 '23 at 17:39
  • Actually that answer is not the best as you don't need to reference the Object method. You really want "if(goal.equals(builder.toString())){" – Malcolm Jul 28 '23 at 17:43
  • It's perhaps worth pointing out that you don't need to rotate the StringBuilder at all - or even use a StringBuilder. You can efficiently compare regions of a String using [`regionMatches`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#regionMatches-int-java.lang.String-int-int-): just compare `s.regionMatches(0, goal, i, goal.length() - i) && s.regionMatches(i, goal, 0, s.length() - i)` (or something like that). – Andy Turner Jul 28 '23 at 19:24

3 Answers3

0

The reason the flag remains false even when builder.toString() and goal seem to have the same value is because you are using the "==" operator to compare the two strings.

In Java, the "==" operator checks for reference equality, not the content equality of strings.

You should do this way:

public static void main(String[] args) {

    System.out.println(rotateString("abcd", "cdab"));

}

public static boolean rotateString(String s, String goal) {
    Boolean flag = false;
    StringBuilder builder = new StringBuilder(s);

    for (int i = 0; i <= s.length() - 1; i++) {
        
        // Use equals() to compare strings.
        if (builder.toString().equals(goal)) {
            flag = true;
            break;
        }

        char temp = builder.charAt(builder.length() - 1);
        for (int j = s.length() - 1; j >= 0; j--) {

            if (j == 0)
                continue;
            builder.setCharAt(j, builder.charAt(j - 1));

        }
        builder.setCharAt(0, temp);
    }

    return flag;
}

Check this out: What is the difference between == and equals() in Java?

Diego Borba
  • 1,282
  • 8
  • 22
0

Since your question already has been answered, this is just to give you some more context.

In Java primitive types (like int, char, and double) can be compared using == no problem, but you generally will want to use the object's classInstance.equals() method for comparisons. This is because == returns true if and only if the objects being compared refer to the same memory address. The StringBuilder and String s are referring to different objects so they are different in the eyes of ==.

Think about it this way:

Let's make a class called Data as follows

public class Data {
    public int value;

    public Data(int value) {
        this.value = value;
    }
}

and let's add an override to Data's inherited .equals method (which it inherits from Object's)

public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
        return false;
    }
    Data otherData = (Data) obj;
    return this.value == otherData.value;
}

Now if we run the following code:

public class Main {
    public static void main(String[] args) {
        Data data1 = new Data(0);
        Data data2 = new Data(0);

        boolean usingDoubleEquals = data1 == data2;
        boolean usingEqualsMethod = data1.equals(data2);
    }
}

We will get usingDoubleEquals = false and usingEqualsMethod = true. Note how we are using == in the return statement of the .equals method, but now it's evaluating two primitives: int value of the Data instance that is calling the method and int value of the Data instance that is being passed to the method.

Now, if you want to have even more fun, look into Java's String Pool for some exceptions to this rule that are unique to String types, and look up the Knuth–Morris–Pratt algorithm for a faster solution to the algorithm!

suape
  • 1
  • 1
  • 1
    Hi, while your answer can be useful in a different context, it is not a direct anser to OP's question. I highly recommend reading [What is an acceptable answer?](https://meta.stackexchange.com/a/118694/387003) to learn about answering to-the-point when needed. –  Jul 28 '23 at 18:05
  • 1
    Thanks @Rakib, will do! New to the platform, so I gotta get up to speed. – suape Jul 29 '23 at 19:16
0

"... I don't know how the flag is still false I also tried debugging it, it shows value of builder.toString() and goal is same. ..."

Since you're comparing String values you'll need to use the equals method.

If you change the conditional statement to the following, the flag value returns true.

if (builder.toString().equals(goal))

Additionally, you can rotate the string much simpler.

public static boolean rotateString(String s, String goal) {
    StringBuilder builder = new StringBuilder(s);
    for (int count = 0; count < s.length(); count++) {
        builder.insert(builder.length(), builder.charAt(0));
        builder.deleteCharAt(0);
        if (builder.toString().equals(goal)) return true;
    }
    return false;
}
Reilas
  • 3,297
  • 2
  • 4
  • 17