前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode笔记:Weekly Contest 199 比赛记录

LeetCode笔记:Weekly Contest 199 比赛记录

作者头像
codename_cys
发布2021-03-28 16:11:48
3280
发布2021-03-28 16:11:48
举报
文章被收录于专栏:我的充电站我的充电站

1. 题目一

给出题目一的试题链接如下:

1. 解题思路

这题的解题思路还是比较清晰的,无非就是将原先的string按照给定的indices进行排序即可。

因此,一种比较直观的实现方法就是:

  • 给出一个等长的string,然后将对应位置的字符按照indices中对应的内容进行替换。

2. 代码实现

下面,我们给出python的代码实现如下:

代码语言:javascript
复制
class Solution:
    def restoreString(self, s: str, indices: List[int]) -> str:
        ans = [c for c in s]
        for i, idx in enumerate(indices):
            ans[idx] = s[i]
        return "".join(ans)

提交代码之后得到评测结果如下:耗时52ms,占用内存13.8MB,属于当前最优效果。

2. 题目二

给出第二题的试题链接如下:

1. 解题思路

这道题我们实际来考察一下解法,就可以很快速地得到代码地实现思路。

在做这个问题时,我们只需要从末尾开始,每一次遇到一个不连续的字符,就做一次翻转,这样,做完全部的翻转之后,我们就能得到同样前后变化顺序的字符串,即他与原始字符串要么相同,要么相反。

然后,我们考虑第一个字符,如果是0,则我们无需再做额外的操作,反之,我们多做一次反转即可。

例:

代码语言:javascript
复制
src: 00000 -> tgt: 10111

step 01: 00000 -> 00111
step 02: 00111 -> 01000 
step 03: 01000 -> 10111

2. 代码实现

基于上述思路,我们即可快速地给出代码实现如下:

代码语言:javascript
复制
class Solution:
    def minFlips(self, target: str) -> int:
        count = 1 if target[0] == "1" else 0
        flag = target[0]
        for c in target:
            if c != flag:
                count += 1
                flag = c
        return count

提交代码得到评测结果如下:耗时60ms,占用内存14.3MB,属于当前最优效果。

3. 题目三

给出题目三的试题链接如下:

1. 解题思路

这一题的解题思路可以基于后续遍历进行改写。

对任意两个叶子节点,他们必定分立于某一个根节点的左右两子树,因此,他们的距离就是他们针对这一个根节点的深度之和。

故,整体的解题思路就可以写作如下:

  1. 对于任意一个根节点,找到其所有左子树下的叶子节点的深度以及右子树下叶子节点的深度;
  2. 两两计算左右子树中叶子节点的距离,如果不大于距离上限distance,则总计数加一;
  3. 将左右子树下的叶子节点深度全部加一并合并为一个集合进行返回,即可得到上一个根节点的左/右子树下的全部叶子数目及其对应的深度。

由于本人语文不太好,上述思路解释多少会有点晦涩。因此,下面我们直接给出代码实现,希望令上面的解释可以更好理解一点。。。

2. 代码实现

给出代码实现如下:

代码语言:javascript
复制
class Solution:
    def countPairs(self, root: TreeNode, distance: int) -> int:

        count = 0

        def dfs(root):
            nonlocal count
            if root is None:
                return []
            elif root.left is None and root.right is None:
                return [0]
            left_leaves = dfs(root.left)
            right_leaves = dfs(root.right)
            for lleaf in left_leaves:
                for rleaf in right_leaves:
                    if lleaf + rleaf + 2 <= distance:
                        count += 1
            return [dep + 1 for dep in left_leaves + right_leaves]
        
        dfs(root)
        return count

提交代码得到评测结果如下:耗时296ms,占用内存15.1MB。

当前的最优结果耗时240ms,但是思路为同样的思路,只是在实现细节上有所不同。

4. 题目四

给出题目四的试题链接如下:

1. 解题思路

这道题比赛的时候留了将近一个小时来做,最终做了半个多小时之后放弃了,因为实在想不到什么非常好的解题思路,甚至说连一个比较合理的暴力求解思路都没能想到。

其主要难点在于以下几点:

  1. 每一次删除操作都可以发生在字符串的任意位置;
  2. 每次删除操作之后都可能有以下几种情况发生:
    1. 删除之后压缩字符长度没有发生变化,如:a3 -> a2
    2. 删除操作之后本来不连贯的字符可以合并,如:a3b2a4 -> a7(删除了bb
    3. 删除操作之后,连续字符总长下降一个量级,如:a10 -> a9
    4. 进行删除后的连续字符串合并操作之后,连续字符总长增长一个量级,如:a5a6 -> a11

因此,直接按照字符串的子串簇的方式考虑每次最优先删除次序的方式就会很难考虑清楚每次操作究竟应该删除哪个子串,要删除多少长度。

比赛之后,研读了一下大佬的解法,发现大佬并没有考虑一次删除一个子串,而是每次删除一个字符,并基于此通过动态规划的方式对这个问题进行了解答

下面,我们给出大佬的解题思路:

  • 对于每个位置,我们都只可能保留或者删除该字符,我们只需要比较这两种情况下的得到的最优压缩子串长度,取较小值即可;

另外需要注意的是,在求解最优压缩子串长度的算法问题上,我们不能每次都暴力的将整个子串都传入进行求解,一来字符串的复制会消耗大量的时间,二来每次计算整个序列的压缩子串长度的时间复杂度是O(N),其两两之间会存在大量的重复计算内容。

参考大佬的解题方法,他是采用了增量地计算每一段连续子串的压缩字符长度的方式进行求解的。

下面,我们基于大佬的解答思路来进行自己的代码实现。

2. 代码实现

依照上述解题思路,我们仿写得到代码实现如下:

代码语言:javascript
复制
import math

class Solution:
    def getLengthOfOptimalCompression(self, s: str, k: int) -> int:
        def cal_compressed_consecutive_string_len(strlen):
            if strlen <= 1:
                return strlen
            else:
                return 1 + len(str(strlen))
            
        n = len(s)
        
        @lru_cache(None)
        def dp(idx, consecutive_len, pre_char, delete_num):
            if delete_num > k:
                return math.inf
            if idx == n:
                return cal_compressed_consecutive_string_len(consecutive_len)
            
            # delete s[idx]
            l1 = dp(idx+1, consecutive_len, pre_char, delete_num + 1)
            
            # keep s[idx]
            if s[idx] == pre_char:
                l2 = dp(idx+1, consecutive_len+1, pre_char, delete_num)
            else:
                l2 = dp(idx+1, 1, s[idx], delete_num) + cal_compressed_consecutive_string_len(consecutive_len)
                
            return min(l1, l2)
        
        return dp(0, 0, '', 0)

提交代码评测得到:耗时2764ms,占用内存372.8MB。

这个耗时在昨天的查看结果中属于第一梯队的,但是今天再次查看的时候最优耗时已经被刷到了500ms,2764ms这个成绩已经被甩到50%之后了。。。

看了一下大佬们的优化代码,发现对其中做了很多细节的优化。

但是,处于代码可读性的考虑(qi shi jiu shi lan),这里就不做过多的展开了,如果有兴趣的话可以自行查看大佬们的优化算法。

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 题目一
    • 1. 解题思路
      • 2. 代码实现
      • 2. 题目二
        • 1. 解题思路
          • 2. 代码实现
          • 3. 题目三
            • 1. 解题思路
              • 2. 代码实现
              • 4. 题目四
                • 1. 解题思路
                  • 2. 代码实现
                  相关产品与服务
                  文件存储
                  文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                  http://www.vxiaotou.com