5

Problem:

Given a string of lower case letters in the range ascii[a-z], identify the index of character to be removed to change the string into a palindrome. If the string cannot be converted to palindrome or is already a palindrome just return -1 else return index of the character to be removed.

My Solution:

public static int palindromeIndex(String s) {

    if(p(s)){
        return -1;
    }

    StringBuilder sb = new StringBuilder(s);

    for(int i=0; i<s.length(); i++){

        sb.deleteCharAt(i);
        if(p(sb.toString())){
            return i;
        }
        sb.insert(i,s.charAt(i));
    }


    return -1;

}

private static boolean p(String s){

    for(int i=0; i<s.length()/2; i++){
        if(s.charAt(i) != s.charAt(s.length() - i - 1)){
            return false;
        }
    }

    return true;
}

It is failing for one or all below test cases (unable to determine for which one) according to hackerrank:

  1. quyjjdcgsvvsgcdjjyq
  2. hgygsvlfwcwnswtuhmyaljkqlqjjqlqkjlaymhutwsnwcflvsgygh
  3. fgnfnidynhxebxxxfmxixhsruldhsaobhlcggchboashdlurshxixmfxxxbexhnydinfngf
  4. bsyhvwfuesumsehmytqioswvpcbxyolapfywdxeacyuruybhbwxjmrrmjxwbhbyuruycaexdwyfpaloyxbcpwsoiqtymhesmuseufwvhysb
  5. fvyqxqxynewuebtcuqdwyetyqqisappmunmnldmkttkmdlnmnumppasiqyteywdquctbeuwenyxqxqyvf
  6. mmbiefhflbeckaecprwfgmqlydfroxrblulpasumubqhhbvlqpixvvxipqlvbhqbumusaplulbrxorfdylqmgfwrpceakceblfhfeibmm
  7. tpqknkmbgasitnwqrqasvolmevkasccsakvemlosaqrqwntisagbmknkqpt
  8. lhrxvssvxrhl
  9. prcoitfiptvcxrvoalqmfpnqyhrubxspplrftomfehbbhefmotfrlppsxburhyqnpfmqlaorxcvtpiftiocrp
  10. kjowoemiduaaxasnqghxbxkiccikxbxhgqnsaxaaudimeowojk

My Output:

  1. 1
  2. 8
  3. 33
  4. 23
  5. 24
  6. 43
  7. 20
  8. -1
  9. 14
  10. -1

I debugged to code locally, and according to my understanding, this test case is working fine. Please help me out understating, what is wrong with the code.

Note: I can do it with other alternative ways (more simpler ways), solutions are available online, but i am trying to understand, what is wrong with my piece of java code. Thanks.

Waleed
  • 63
  • 1
  • 1
  • 6
  • You can do this in a simpler way: modify the palindromicity test so that it counts mismatches when scanning both ways, and tolerates exactly one (in you can use the index for this purpose). –  Dec 28 '21 at 20:17
  • your code passed the submission! ..but didn't pass test case 7,12,14 due to: timeout! so it looks "correct"! but could be "more efficient"! ;) – xerx593 Dec 28 '21 at 20:50
  • try a "linear" algorithm in favor to a "quadratic" one... ( -> [discussions](https://www.hackerrank.com/challenges/palindrome-index/forum)) – xerx593 Dec 28 '21 at 21:06

1 Answers1

8

Your code times out on some test cases. It is not very efficient to try to delete each character and then check whether that is a palindrome.

By first checking whether the original string is a palindrome you can find the spot where it fails, which leaves you with just 2 possibilities for deletion. So you would only need to try those two. Moreover, you don't actually have to perform the deletion. You can just skip the concerned character and continue the palindrome check by skipping the corresponding index.

Here is a possible implementation:

    public static int palindromeIndex(String s) {
        int start = 0;
        int end = s.length() - 1;
        while (start < end && s.charAt(start) == s.charAt(end)) {
            start++;
            end--;
        }
        if (start >= end) return -1; // already a palindrome
        // We need to delete here
        if (isPalindrome(s, start + 1, end)) return start;
        if (isPalindrome(s, start, end - 1)) return end;
        return -1;
    }

    public static boolean isPalindrome(String s, int start, int end) {
        while (start < end && s.charAt(start) == s.charAt(end)) {
            start++;
            end--;
        }
        return start >= end;        
    }
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks for the great algorithm! But I guess the problem is in HakerRank testing system, not in execution time. For example see the case 6: s = mmbiefhflbeckaecprwfgmqlydfroxrblulpasumubq-hh-bvlqpixvvxipqlvbhqbumusaplulbrxorfdylqmgfwrpceakceblfhfeibmm Your code gives the answer 44, while topic-starter answer is 43 - and both are correct (I emphasise those letters with '-'). Task descriptions says that "in case of more than one solution any will do". _But it's not true_: to see this I hard-code the answer 43 for this case, and the test fails, although when I hard-code 44 it passes. – danek Nov 12 '22 at 13:36
  • I couldn't reproduce this, danek. I added `if (s.compareTo( "mmbiefhflbeckaecprwfgmqlydfroxrblulpasumubqhhbvlqpixvvxipqlvbhqbumusaplulbrxorfdylqmgfwrpceakceblfhfeibmm") == 0) return 43;` to the top of my function and the solution was accepted by HackerRank. I also submitted a version with a `return start-1` when possible, which would also cover this case: `if (isPalindrome(s, start + 1, end)) { if (start > 0 && s.charAt(start) == s.charAt(start-1)) return start - 1; return start; }`. This also was accepted by HackerRank. – trincot Nov 12 '22 at 14:20