anonymous
anonymous

Reputation: 65

Trying to find the longest palindrome for this input

Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters.

This is case sensitive, for example "Aa" is not considered a palindrome here.

Note:

Assume the length of given string will not exceed 1,010.

Example:

Input: "abccccdd"

Output: 7

Explanation:

One longest palindrome that can be built is "dccaccd", whose length is 7.

My code works for simple inputs such as "abccccdd" and "banana" but fails for "civilwartestingwhetherthatnaptionoranynartionsoconceivedandsodedicatedcanlongendureWeareqmetonagreatbattlefiemldoftzhatwarWehavecometodedicpateaportionofthatfieldasafinalrestingplaceforthosewhoheregavetheirlivesthatthatnationmightliveItisaltogetherfangandproperthatweshoulddothisButinalargersensewecannotdedicatewecannotconsecratewecannothallowthisgroundThebravelmenlivinganddeadwhostruggledherehaveconsecrateditfaraboveourpoorponwertoaddordetractTgheworldadswfilllittlenotlenorlongrememberwhatwesayherebutitcanneverforgetwhattheydidhereItisforusthelivingrathertobededicatedheretotheulnfinishedworkwhichtheywhofoughtherehavethusfarsonoblyadvancedItisratherforustobeherededicatedtothegreattdafskremainingbeforeusthatfromthesehonoreddeadwetakeincreaseddevotiontothatcauseforwhichtheygavethelastpfullmeasureofdevotionthatweherehighlyresolvethatthesedeadshallnothavediedinvainthatthisnationunsderGodshallhaveanewbirthoffreedomandthatgovernmentofthepeoplebythepeopleforthepeopleshallnotperishfromtheearth". I'm not sure how to debug it.

class Solution {
    public int longestPalindrome(String s) {
        Map<Character, Integer> map = new HashMap<>();
        char[] carr = s.toCharArray();
        Arrays.sort(carr);
        int leftInd = 0;
        int rightInd = 0;
        for(int i=0; i<carr.length; i++){
            if(map.containsKey(carr[i]))
                continue;
            else
                map.put(carr[i], 1);
        }
        for(int i=0; i<carr.length-1; i++){
            for(int j=i+1; j<carr.length; j++){
                if(carr[i]==carr[j]){
                    if(map.get(carr[i])==null)
                        continue;
                    carr[j] = Character.MIN_VALUE;
                    int count = map.get(carr[i]);
                    map.put(carr[i], count + 1);
                }
            }
        }
        int ans = 0;
        int[] oddValArr = new int[map.size()];
        int oddInd = 0;
        for (Map.Entry<Character, Integer> entry : map.entrySet()) {
            Character key = entry.getKey();
            Integer value = entry.getValue();
            if(value % 2 == 0){
                ans += value;
            }
            else{
                oddValArr[oddInd] = value;
                oddInd++;
            }
        }
        int biggestOddNum = 0;
        for(int i=0; i<oddValArr.length; i++){
            if(oddValArr[i] > biggestOddNum)
                biggestOddNum = oddValArr[i];
        }
        return ans + biggestOddNum;
     }
}

Output 655

Expected 983

Upvotes: 2

Views: 1320

Answers (2)

Lev Leontev
Lev Leontev

Reputation: 2615

Your mistake here, is that you use only the biggest odd group out of your oddValArr. For example, if the input is "aaabbb", the biggest palindrome is "abbba", so group a had length 3, which is an odd number, and we used 3 - 1 = 2 letters of it.

Also, those nested for loops can be replaced with one for, using Map:

public int longestPalindrome(String s) {
    Map<Character, Integer> map = new HashMap<>();  // letter groups
    for(int i=0; i<s.length(); i++){
        char c = s.charAt(i));
        if(map.containsKey(c))
            map.put(c, map.get(i) + 1);
        else
            map.put(c, 1);
    }

    boolean containsOddGroups = false;
    int ans = 0;
    for(int count : map.values()){
        if(count % 2 == 0)  // even group
            ans += count;
        else{  // odd group
            containsOddGroups = true;
            ans += count - 1;
        }
    }
    if(!containOddGroups)
        return ans;
    else
        return ans + 1;  // we can place one letter in the center of palindrome
}

Upvotes: 2

luk2302
luk2302

Reputation: 57204

You are almost there but have over complicated it quite a bit. My solution by almost only deleting code from your solution:

public static int longestPalindrome(String s) {
    Map<Character, Integer> map = new HashMap<>();
    char[] carr = s.toCharArray();
    for (int i = 0; i < carr.length; i++) {
        if (map.containsKey(carr[i]))
            map.put(carr[i], map.get(carr[i]) + 1);
        else
            map.put(carr[i], 1);
    }

    int ans = 0;
    int odd = 0;
    for (Integer value : map.values()) {
        if (value % 2 == 0) {
            ans += value;
        } else {
            ans += value - 1;
            odd = 1;
        }
    }
    return ans + odd;
}

Explanation:

  • the second loop has been removed, together with the sorting - it has been merged into the first loop. There was no need for sorting at all.
  • then you iterate over the counts of how often a character appeared
    • if it is even you increase ans as before
    • if it is odd you can use count - 1 chars of it for the palindrome of even length
  • if you found at least one odd occurrence you can put that single odd char into the center of the palindrome and increase its length by one

Upvotes: 0

Related Questions