最长回文leetcode挑战

Today’s Leetcode challenge was to figure out the maximum possible length a palindrome could be, given a string.

今天的Leetcode面临的挑战是在给定字符串的情况下找出回文的最大可能长度。

https://leetcode.com/explore/challenge/card/august-leetcoding-challenge/550/week-2-august-8th-august-14th/3423/

https://leetcode.com/explore/challenge/card/august-leetcoding-challenge/550/week-2-august-8th-august-14th/3423/

I started off by going right down a rabbit hole, and not even a CORRECT rabbit hole. I spent hours writing code to return the actual longest palindrome for the string, without changing the order of the characters in the string.

我从一个兔子洞一直走下去,甚至没有一个正确的兔子洞就开始了。 我花了几个小时编写代码来返回字符串的实际最长回文率,而没有更改字符串中字符的顺序。

RTFI (Read the F*ing Instructions), right?

RTFI(阅读F * ing说明),对吗?

The challenge was to find the maximum POSSIBLE length, given ANY order of the given string. Not only did the challenge not want a string back, it didn’t care about the order of the string.

面临的挑战是在给定字符串的任何顺序下找到最大可能的长度。 挑战不仅不希望返回字符串,而且也不在乎字符串的顺序。

Totally different challenge.On the upside, the fact that it took me hours to solve what the challenge WASN’T, means I learned something besides RTFI. :) Some other day I’ll post the code I started out with, which answered that completely unasked question. For today, I’ll post the correct answer.

完全不同的挑战。从积极的方面来看,我花了几个小时才能解决挑战所需要解决的事实,这意味着我在RTFI之外学到了一些东西。 :)某天,我将发布我开始的代码,它回答了这个完全未提出的问题。 今天,我将发布正确答案。

My first (correct) solution was 95% faster than other submissions. My new and improved second (correct) submission was 99+% faster, plus it used less memory. I’ll explain the logic, the first solution, and then why I changed what I did to create the second solution.

我的第一个(正确)解决方案比其他提交速度快95%。 我的新的和改进的第二(正确)提交速度提高了99%以上,并且使用的内存更少。 我将解释逻辑,第一个解决方案,然后解释为什么我更改了创建第二个解决方案的方式。

挑战与逻辑的解释: (Explanation of Challenge and Logic:)

Example Strings = “xxyyzzzzzzzaabcccdddde”

A palindrome is a string that’s the same forwards and backwards. Find out the longest possible palindrome.

回文是向前和向后相同的字符串。 找出最长的回文。

Each time there are 2 of the same characters in the string, that counts as 2 characters that could be arranged with others, to form a palindrome. For example, if the string is “aacc”, the palindrome could be “acca” or “caac”.

字符串中每有2个相同字符,就算是2个可以与其他字符排列的字符,形成回文。 例如,如果字符串是“ aacc”,则回文可以是“ acca”或“ caac”。

If, for example, there are 3 of the same characters, and two of another, one of the leftovers from the 3, could be the center of the palindrome. Once the center spot is taken, the odd leftovers aren’t counted for the rest of the string. This includes single instances of a character. For this string: “aaccddddbbb”, one palindrome could be “bdacdcadb”. The third “b” from the original string got discarded, because the “d” already had that center spot.

例如,如果有3个相同的字符,而另外2个,则是3个字符中剩下的一个,可能是回文的中心。 一旦占据了中心点,其余的字符串将不计入奇数剩余。 这包括一个字符的单个实例。 对于此字符串:“ aaccddddbbb”,一个回文可能是“ bdac d cadb”。 原始字符串中的第三个“ b”被丢弃了,因为“ d”已经具有该中心点。

So the code should find the duplicate character count, and then if there’s a leftover from dividing one of the characters by 2, it should add a 1 (but only once) to the total number of characters.

因此,该代码应找到重复的字符数,然后将一个字符除以2得到一个余数,则应在字符总数上加1(但仅一次)。

Example :
“abccccdd” returns 7
“cccc” = 4
“dd” = 2
and either “a”, or “ b” can be the center, but not both.
4 + 2 + 1 = 7Another Example:“aaaccccdd” returns 9
“cccc” = 4
“dd” = 2
“aa” = 2
There’s a leftover a, so
“a” = 1
4 + 2 + 2 + 1 = 9

Hopefully I’ve explained this in a way that makes sense but hasn’t put you to sleep.

希望我已经以一种有意义的方式解释了这一点,但并未让您入睡。

Solutions and Explanations:

解决方案和解释:

Solution 1 - (Not counting the Rabbit Hole Solution for some imaginary problem I wasn't given))from collections import Counterdef longestPalindromeOne(s):
countDict = dict(Counter(s))
numChars = 0
center = False
for key, value in countDict.items():
divs = divmod(value, 2)
if divs[0] > 0:
numChars += divs[0]*2
if divs[1] == 1 and center == False:
numChars += 1
center = True
return numChars
Image for post
Solution 1 results
解决方案1的结果

Solution 1 Explanation

解决方案1说明

The Counter module returns an iterable (an object that can be iterated through), that looks like this when printed:

Counter模块返回一个可迭代的对象(可以迭代的对象),在打印时如下所示:

Counter({'c': 4, 'd': 2, 'a': 1, 'b': 1})

After initializing center to False,I iterated through the Counter dictionary. (NOTE: I didn’t need to create a separate dictionary to do this. See Solution 2)

将center初始化为False后,我遍历了Counter字典。 (注意:我不需要创建单独的字典来执行此操作。请参阅解决方案2)

For each item in the dictionary, I used the built-in Python divmod function. divmod takes a value, and the amount to divide by, and returns a tuple with the result of the division, and the remainder. (divmod(5, 2) returns (2, 1)). I didn’t need to use this function, either, as you’ll see in Solution 2. So much learning.

对于字典中的每个项目,我都使用了内置的Python divmod函数。 divmod取一个值和要除以的量,然后返回一个除以除法运算结果和余数的元组。 (divmod(5,2)返回(2,1))。 正如您将在解决方案2中看到的那样,我也不需要使用此功能。

Then I examine the first part of each tuple. If it’s a 0, then there is only of that character. If it’s more than 1, the number is how many sets of 2 of that character there were. I re-multiplied the result by 2, (leaving out the remainder), and added that to the number of characters possible in the palindrome.

然后,我检查每个元组的第一部分。 如果它是0,则只有那个字符。 如果大于1,则数字是该字符中有2套的几套。 我将结果乘以2(省略了余数),并将其添加到回文中可能的字符数上。

Then I examined the remainder. If a possible center hasn’t already been found, and the remainder is 1 on the character, 1 gets added the numChars and the center is set to True so another leftover doesn’t get added.

然后,我检查了其余部分。 如果尚未找到可能的中心,并且字符上的余数为1,则将numChars添加为1,并且将中心设置为True,这样就不会再添加另一个剩余项。

I should have switched around the center == False check, and the divs[1] check, because it will likely fail more frequently on the center == False check, and therefore, the second part wouldn’t have been calculated. I’ll explain that more in a short bit.

我应该切换中心==错误检查和divs [1]检查,因为它可能在中心==错误检查上更频繁地失败,因此,第二部分将不会被计算出来。 我将在稍后详细说明。

Submission results for this solution: Even with the parts of this that weren’t ideal, the submission came in at 95+%. That’s not the worst result I’ve had. LOL.

此解决方案的提交结果:即使其中的部分内容不理想,提交的结果还是超过95%。 那不是我得到的最糟糕的结果。 大声笑。

Once I submit something, I don’t usually just leave it at that, though. I am there (and here in general) to learn, so I tinker.

但是,一旦我提交了一些内容,通常我就不会只保留它。 我在那里(通常在这里)学习,所以我动手了。

First, I realized I didn’t need to create a dictionary, because I could iterate through the Counter result items. So I took that out

首先,我意识到我不需要创建字典,因为我可以遍历Counter结果项。 所以我拿出来

Then, I realized I didn’t actually need to know the remainder every time, so why bother using divmod? I changed that to integer divide the value by 2, and then re-multiplied that by 2, as before, to get the even number of sets I needed.

然后,我意识到我实际上并不需要每次都知道余数,那么为什么还要麻烦使用divmod呢? 我将其更改为将值整数除以2,然后像以前一样将其再乘以2,以获得所需的偶数集。

Integer Division (//)
5 // 2 * 2 = 4. 4 of the 5 characters can be used in a palindrome.
6 // 2 * 2 = 6, All 6 of that character can be used.

Lastly, I rearranged the if test on the center and the remainder calculation, as once there’s an odd remainder, and the center is set, I don’t need the mod for any more numbers.

最后,我重新排列了中心的if检验和余数计算,因为一旦存在奇数余数,并且设定了中心,就不再需要mod来获取更多数字了。

original (still using divmod, and reversed):
if divs[1] == 1 and center == False:improved:if center == False and value % 2 == 1:

Here’s why this mattersIterating through “abbcddeffg”…

这就是为什么如此重要的原因通过“ abbcddeffg”进行迭代……

On ‘a’, the value of the center gets checked. On ‘a’, it’s False. Because of that, the mod is calculated for ‘a’. It comes back with 1, so center gets set to True.

在“ a”上,将检查中心的值。 在“ a”上,这是错误的。 因此,该mod是针对“ a”计算的。 它返回1,因此center设置为True。

When I get to “bb”, “c”, “dd”, etc…because the center is already set to True, there’s ZERO need to find out if the number of characters is odd or even.

当我到达“ bb”,“ c”,“ dd”等位置时…因为中心已经设置为True ,所以需要零来确定字符数是奇数还是偶数。

If the first part of an if test fails, the second part is never executed. Look at the savings!

如果if测试的第一部分失败,则永远不会执行第二部分。 看节省!

Comparison for "abbcddeffg"original (still using divmod, and reversed)
if divs[1] == 1 and center == Falseremainder test first, center test second
11 comparisons
7 remainder tests - once for each unique set of characters 4 center tests - once for each time there's a remainder (a, c, e, g)********improved:if center == False and value % 2 == 1center test first8 comparisons7 center tests - once for each unique set of characters1 remainder test - once for the first character, and then it's set
NOTE: If the center never gets set, then it could have done 7 center tests, and 7 remainder tests. This is where it's important to know your data. What are the odds each one of those tests will pass onto the second test? The one that's the most likely to stop execution of the second, is the one to put in the front.

The impact of them ordering is minimal in this scenario, but, depending on what the tests do, it could have a significant performance impact.

在这种情况下,它们排序的影响很小,但是根据测试的进行,可能会对性能产生重大影响。

Solution 2 (My final for now. I've stopped tinkering to write this post)from collections import Counterdef longestPalindromeTwo(s):
numChars = 0
center = False
for key, value in Counter(s).items():
numChars += (value // 2) * 2
if center == False and value % 2 == 1:
center = True
numChars += 1
return numChars
Image for post
Image for post
Solution 2 results
解决方案2结果

I suspect there are solutions that use bitwise operations to solve the challenge, or any other number of possible solutions…as there ALWAYS are. For now, it’s time to stop tinkering with this one.

我怀疑是否存在使用按位运算来解决挑战的解决方案,或者其他任何数量的可能解决方案……总是如此。 现在,是时候停止修补这个了。

BUT, if you have an answer for this challenge you’d like to share? Please do, cuz I’m definitely here to learn.

但是,如果您想对这个挑战有一个答案,您想分享吗? 请做,因为我绝对是在这里学习。

翻译自: https://medium.com/@binarybelle/longest-palindrome-leetcode-challenge-61b7ac197cad

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值