lintcode - 循环单词

本文介绍了一种高效算法用于统计字典中不同旋转词组的数量。通过利用Python中的字典结构存储已检查过的单词及其长度,确保了算法的高效执行。文章详细解释了如何判断两个单词是否为旋转关系,并分享了作者在实现过程中的调试经验和优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:The words are same rotate words if rotate the word to the right by loop, and get another. Count how many different rotate word sets in dictionary.

E.g. picture and turepic are same rotate words.

样例:
Given dict = [“picture”, “turepic”, “icturep”, “word”, “ordw”, “lint”]
return 3.

“picture”, “turepic”, “icturep” are same ratote words.
“word”, “ordw” are same too.
“lint” is the third word that different from the previous two words.

解题思路:

说来惭愧,这道题我解了好久。一直在88%出遇到时间瓶颈。我反复优化了代码,也在网上查阅了大家的解法。无奈,本来用python解题的人就少,少数的答案又多少有点问题。所以一直难以解决。不过好在是最终还是AC了。

首先说明一个问题:如何判断两个单词是否一个是另一个旋转得到。基本思路是要让两个单词(记为w1, w2吧)依次满足如下2个条件:

  • 长度相等
  • w2在单词(w1 + w1)当中。这是一个非常重要的性质,用Python中的in操作符可直接完成这种包含关系的判断,从而省去了循环遍历所消耗的时间。举个例子来说,”turepic” + “turepic” = “turepicturepic”,而单词”picture”正好在”turepicturepic”中。

解决了两个单词是否为旋转关系的问题,剩下的就是对单词列表遍历检查了。当然我们需要存储记录已经遍历过的单词信息。这里我用Python中字典的数据结构,key为单词,值为该词的长度。之所以记录长度是为了后面提高运行的效率,避免大量的计算单词长度的运算。给出代码如下:

class Solution:
    """
    @param: words: A list of words
    @return: Return how many different rotate words
    """

    def countRotateWords(self, words):
        if len(words) == 0:
            return 0
        record = {words[0]:len(words[0])}
        for word in words[1:]:
            exist = False
            temp = len(word)
            newWord = word + word
            for key in record:
                if len(key) == temp:
                    if key in newWord:
                        exist = True
                        break
            if not exist:
                record[word] = len(word)
        return len(record)

观察到第13,14两行引用变量的目的都是节省运行时间的措施。但是上面的代码虽然运行结果正确,却不能在lintcode上AC!!!在此,我想了很久,我觉得代码效率和算法的时间复杂度确实不能再提高了。后来看到一个博主的文章,其算法和我的一致,代码写的也差不多,但是少了第16行判断长度的语句,导致的结果是运行时间大幅缩减,在我的笔记本上跑的结果大约为加上判断长度时的一半。

当然他的这种算法是错的,但是却启发了我。也就是说主要的耗时在于频繁判断长度字符长度是否相等。在lintcode的测试数据中,我发现我不能AC的测试数据有着长度相等,数量多的特点,因此,我在这里稍作调整:

for key in record:
    if key in newWord and len(key) == temp:
        exist = True
        break

这样时间上就对了。因此我基本可以判断Python中,if a and b这种语句当是先判断a,倘若a为False,就不再判断b了。最后给出可以AC的代码:

class Solution:
    """
    @param: words: A list of words
    @return: Return how many different rotate words
    """

    def countRotateWords(self, words):
        if len(words) == 0:
            return 0
        record = {words[0]:len(words[0])}
        for word in words[1:]:
            exist = False
            temp = len(word)
            newWord = word + word
            for key in record:
                if key in newWord and len(key) == temp:
                    exist = True
                    break
            if not exist:
                record[word] = len(word)
        return len(record)

有关于lintcode题目的答案代码,我打算整理一个完整的版本,并放在我的github上。已经在博客中写过的,我也会在后期慢慢加入。另外,一些我觉得过于简单的题目就不再博客中特别记录了。不过github上会有相关的代码。欢迎大家批评指正。网址:Lintcode-Answer

LintCode 1817 - 分享巧克力 是一道经典的算法题目,通常涉及动态规划、贪心算法等知识。这道题的核心思想是如何将一块巧克力分成若干块,并让每块满足一定的条件。 ### 题目概述: 假设有一块 `m x n` 的巧克力网格图,每个格子表示一小块巧克力。你需要将其分给 K 个人,每个人获得连续的一段巧克力(可以横着切或竖着切)。目标是使得所有人的巧克力总和的最大值尽可能小。 --- ### 解法思路: #### 方法一:二分查找 + 模拟验证 我们可以采用“二分查找”的策略来解决这个问题。核心在于设定一个范围 `[min_val, sum_of_chocolate]`,其中 `min_val` 表示单个巧克力单元的最小值,而 `sum_of_chocolate` 则是整个巧克力表的所有数值之和。 步骤如下: 1. **确定搜索区间**:左边界设为数组中的最大元素 (因为至少一人要拿到这个数),右边界设为总和 (即所有人都拿一样的情况)。 2. **验证中间值是否可行**:对于当前猜测的最大值 mid,检查能否通过合理的切割分配方案,使得每个人的份额都不超过该值。 3. 根据结果调整左右边界直至找到最优解。 时间复杂度大约为 O(log(total_sum) * m * n) #### 示例代码片段(Python版): ```python def minimizeMaxShare(chocoGrid, k): def canSplit(max_allowed): # 实现判断是否能按照规则分割函数 total = sum(map(sum,chocogrid)) low , high= max([max(row) for row in chocogrid]),total while(low<high): mid=(low+high)//2 if(canSplit(mid)): high=mid else: low=mid+1 return low ``` --- ### 关键点总结: - 使用了高效的二分查找技巧降低暴力枚举的时间开销; - 结合实际场景构建辅助判定功能完成对潜在解答的有效评估;
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值