leetcode day 16: longest palindrome

Given a set of upper and lowercase letters, what is the longest possible palindrome for this set of letters?

I chose to do this with a pair of hashes to count the letters overall; the even counts can just be added. For the odd counts, add the largest count, then for the remaining counts, reduce them by one (since there has to be an even number of them to preserve symmetry), and add those to the total.

func longestPalindrome(s string) int {
// More breaking down into runes
letters := []rune(s)
letterMap := map[rune]int{}
for _,c :=range(letters) {
letterMap[c]++
}
// any letter with an even count can be included
// any letter with an odd number of occurrences
// can be included if:
// - it's even (so it's always symmetric)
// - it's the letter with the largest odd count (also symmetric)
// - it's a letter with at least a 3 count (once the largest odd
// count is removed, reduce odd counts by 1 and they're
// also symmetric)
// Walk through the map and record
// - the even counts
// - the largest odd count
// - the smaller odd counts, reduced by one
palindromeLength := 0
largestOddCount := 0
var largestOddKey rune
oddKeys := map[rune] int{}
for k, v :=range(letterMap) {
if v % 2 == 0 {
palindromeLength += v
} else {
// odd. is this the largest odd count yet?
if v > largestOddCount {
largestOddKey = k
largestOddCount = v
}
// Store the letter with it's count reduced by 1
// so it can be added symmetrically.
oddKeys[k] = v-1
}
}
if largestOddCount != 0 {
// there's at least one odd count.
// delete the key of the max odd count, and add the count
// to the palindrome length.
palindromeLength += largestOddCount
delete(oddKeys, largestOddKey)
// the rest of the odd count letters can now be added.
// the one-occurence letters/odd-occurrence letters
// have been reduced by one, so either a) the count is
// now zero, because there was only one occurrence of
// the letter, or it's an even numer now (it would not
// have been added if it was odd, and we reduced it by 1,
// so it HAS to be even now -- whether zero or another even
// number).
for _, v :=range(oddKeys) {
palindromeLength += v
}
} else {
// there was no odd-numbered count, and we've already
// added the even count. Nothing else to do.
}
return palindromeLength
}

Scorewise, it’s not that great – top 67% in time, bottom 10% in memory, but it was done fairly fast, so I’m grading it acceptable. I think you could do better with arrays and converting the rune values to indexes, but this falls into the “yes, I could optimize it that way, but this will always work” category.

Tags:

Reply