第一次力扣参赛:第 174 场力扣周赛

第 174 场力扣周赛赛题:
https://leetcode-cn.com/circle/discuss/lEfEkb/view/OrAJAh/

第 174 场力扣周赛国内排名(点击小图标可查看选手代码):
https://leetcode-cn.com/contest/weekly-contest-174/ranking/1/

总体心得

使用python3,做成了第一道题,第二道题的解超时,便结束了第一次周赛。

下午看了排行榜靠前的参赛者代码,最快的在17分钟内就完赛了(使用python3),使用python3的和c++的数量几乎对半分。

先来说个问题:使用python算作弊吗?

我觉得不算,尽管python中有collections库这种强大的操作集,但是对不懂数据结构、或没有赛题解决思路的人来说,终究还是没有帮助的。python只是帮助我们把精力全部集中在算法的流程上,而非程序设计与具体实现上(python封装了太多常用操作,减少实现压力)。

况且,c++中也有vector<>()、java中也有hashtable<>()这种类似的可调用的数据结构对象,来简化操作。因此,python不算作弊。

我目前的编程,都是为了实现强化学习算法,没有涉及到底层系统或者企业级开发,因此选择用python3来刷力扣。

使用c/cpp来对每个指针进行操作,可能会在算法的时间空间复杂度上有一定优势,但是,实现起来会比较麻烦,而周赛比的是速度。况且,python3中封装的代码都是方法较优的。

这次最快的同学是 zerotrac2 ,看到了其领英上的简历,很强,高中就有极好的竞赛基础,在清华软工有9/74的排名:

这位同学的简历链接:https://www.linkedin.com/in/zerotrac/

看了他的代码,觉得“并不是我现在无法达到的水平”,收获了很多库的使用技巧与设计思想,下面对四道题一一分析。


[1341] 方阵中战斗力最弱的 K 行

很简单的排序问题,我的代码为:

class Solution(object):def kWeakestRows(self, mat, k):""":type mat: List[List[int]]:type k: int:rtype: List[int]"""fighter_dict = dict()r = -1for _ in mat:r += 1# key: row number, value: soldiers_countfighter_dict[r] = sum(mat[r])returns = list()while k > len(returns):current_min_row = fighter_dict.keys()[0]for row in fighter_dict:if fighter_dict[row] < fighter_dict[current_min_row]:current_min_row = rowreturns.append(current_min_row)del fighter_dict[current_min_row]return returns

高手的代码为:

class Solution:def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:c = [(sum(x), i) for i, x in enumerate(mat)]c.sort(key=lambda x: (x[0], x[1]))return [x[1] for x in c[:k]]

解决思路差不多,但是我没有很坚决地把问题抽象为一个二维排序问题,因此产生了犹豫,并且复杂化了代码实现过程,除此之外,上述代码值得学习的地方还有:

  • enumerate(list)返回(索引, 值)
  • 列表的方法sort(key=lambda x: expression)用法(升序);
  • list[:k]灵活运用切片。

我还存在一个问题,就是我的排序是我自己写的(在while里),我期望达到在线处理的效果,可是时间复杂度还是有O(k×n)O(k \times n)O(k×n)之多。以后遇到需要排序的问题,直接使用list.sort()算法,在网上查过,python3封装的排序算法应该是最优的(二分法),时间复杂度为O(n×log⁡2n)O(n \times \log_2 n)O(n×log2​n)。


[5329] 数组大小减半

我的算法超时了,看不到了,高手代码为:

class Solution:def minSetSize(self, arr: List[int]) -> int:c = collections.Counter(arr)s = 0ans = 0for k, v in c.most_common():s += vans += 1if s * 2 >= len(arr):return ansreturn -1

我学到了:

  • collection.Counter(arr)的使用,直接对个元素计数;
  • top-n 问题使用most_common()方法,也是基于collection.Counter对象的。

[5330] 分裂二叉树的最大乘积

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def maxProduct(self, root: TreeNode) -> int:def tot(node):if not node:return 0return tot(node.left) + tot(node.right) + node.valdef dfs(node, s):if not node:return 0, 0p1, q1 = dfs(node.left, s)p2, q2 = dfs(node.right, s)p = p1 + p2 + node.valreturn p, max(q1, q2, p * (s - p))s = tot(root)return dfs(root, s)[1] % 1000000007

看懂这个代码着实花了我一点时间,但是以后遇到类似代码不会再让我感到陌生了:

  • 就是一个深度优先搜索(bfs)而已;
  • 注意上述算法中的s值其实没有变过,作者之所以把其作为dfs()的参数,应该是因为:在一般的dfs()递归算法中,dfs()传入的都是(根结点, 参数),其中参数是参与递归过程的;
  • dfs()的两个返回值分别是:
    • 该子树的结点和;
    • (1)计算以该子树作为断点,独立成根,其产生的和与剩下部分产生的和的乘积的值,(2)与两个子树的该值比较,取最大的,保留,(3)子树的该值是子树与子树的子树的该值进行比较得到的。
  • 巧妙地运用递归进行了搜索,没有半行废话。

[5331] 跳跃游戏 V

惊了,大神前三题用的好好的 python3 ,第四题一下就换 cpp 了,是觉得太无聊了,想玩玩花样吗…

我觉得也有这种可能:

  • 大神们因为刷题太多,已经有了一个自己的轮子库;
  • 遇到新问题,马上抽象总结成一起遇到的问题;
  • 把以前的轮子稍加修改便可套用,这道题的兄弟题可能是大神以前使用从 cpp 做过的。

或者,此题使用 python3 可能超时。

class Solution {private:vector<bool> used;vector<int> f;public:void dfs(vector<int>& arr, int id, int d, int n) {// 传址调用 arrif (used[id]) {return;}used[id] = true;f[id] = 1;// 看着像二分法,实际上不是// 就是把小人投放到每个“柱子上”,然后递归跳跃for (int i = id - 1; i >= 0 && id - i <= d; --i) {// i可能等于-1,因此加入i>=0这个判断条件if (arr[id] > arr[i]) {dfs(arr, i, d, n);f[id] = max(f[id], f[i] + 1);}else {break;}}for (int i = id + 1; i < n && i - id <= d; ++i) {if (arr[id] > arr[i]) {dfs(arr, i, d, n);f[id] = max(f[id], f[i] + 1);}else {break;}}}int maxJumps(vector<int>& arr, int d) {int n = arr.size();// cpp 中的vertor.size() .resize() 方法库值得积累used.resize(n);f.resize(n);for (int i = 0; i < n; ++i) {dfs(arr, i, d, n);}return *max_element(f.begin(), f.end());// std 的 max_element() 返回指针,操作数也是指针// *max_element 中的星号是取 指针指的值// 而输入的操作数 f.begin() f.end() 表示查找区间范围}
};

我学到了:

  • dfs()实际上是一种“挖到最低层的状态结点,然后向上回溯”的过程。在本例中,小人只被投放到了各个结点一次,没有重复计算,当其被投放到最底层结点时,开始计算其步数,并累加至上一层。
  • for(,条件,)中增加条件,以保证迭代数在操作体内的可执行性;
  • cpp 中的vertor.size() .resize() 方法库值得积累;
  • *max_element()stdmax_element()返回指针,操作数也是指针,*max_element中的星号是取 指针指的值,而输入的操作数f.begin(), f.end()表示查找区间范围。

cpp 的结果为:

  • 127/127 cases passed (68 ms)
  • Your runtime beats 100 % of cpp submissions
  • Your memory usage beats 100 % of cpp submissions (10.5 MB)

而使用 python 的结果为:

  • 127/127 cases passed (1060 ms)
  • Your runtime beats 100 % of python3 submissions
  • Your memory usage beats 100 % of python3 submissions (14.2 MB)

(可见,同结构的数据与相同的算法下,python 比 cpp 慢很多)

python 的代码是我自己写的,如下:

class Solution:def maxJumps(self, arr: List[int], d: int) -> int:f = [0 for _ in range(len(arr))]def dfs(arr, index, d, n):if f[index]:return Nonef[index] = 1# left indexesi = index - 1while i >= 0 and index - i <= d:if arr[index] > arr[i]:dfs(arr, i, d, n)f[index] = max(f[index], f[i] + 1)else:breaki -= 1# right indexesi = index + 1while i < n and i - index <= d:if arr[index] > arr[i]:dfs(arr, i, d, n)f[index] = max(f[index], f[i] + 1)else:breaki += 1length = len(arr)for i in range(length):dfs(arr, i, d, length)return max(f)

后记心得

看完了这四道题的“高手”解法,认为明确易懂,且总结了不少规律。我对我自己的实力还是很有信心的。

我不知道我说的对不对:数据结构与算法的基础题,实际上就是一个字“找”,找什么?“解”。解都是找出来的。比的就是谁的方法又巧妙又易于实现(通常,易于实现的算法他人也一看就懂)。有什么好的办法来提升自己吗?刷题、总结、积累。所谓“找”之策,万变不离其宗(数据结构基础),能把问题抽象为已知的经典问题,就可快速解决。

今天周日,下周我想刷刷 LeetCode ,就当娱乐了。下周日的周赛再参加一次,我已经等不及了,说实话。

再后记: 步入“编程的正道”正好一年。去年这时跟着学长实现数学模型,要用到“孤立森林”(不是随机森林,是周志华等人提出的一种无监督离群点判断方法),matlab里没有封装好的孤立森林方法(2019年1月份前我只会用matlab),而python3sklearn库里有,于是入了python3,编辑器用的PyCharm,发现比matlab好用多了。从此,抛弃“伪代码”,钻入底层的世界,学习“配置环境”、“操作系统”、“数据结构”、“编译与字节码”到底是怎么一回事,javac/c++c#这种以前或许接触过的却根本不了解的编程语言也被我重新拾起。总之,读了很多很棒的文章,很重视学习编程的规范与底层知识的学习。

这一年里,我写了130+的博文,包括:操作系统&数据结构等等课程的笔记、python3的debug心得、编译器配置等等,我的CSDN:https://blog.csdn.net/weixin_42815609。

我还开了不少 GitHub repo,包括强化学习笔记、计算机核心课笔记:

  • GitHub 个人主页:https://github.com/PiperLiu
  • [更新中…]基于c/c++实现的计算机核心课笔记:https://github.com/PiperLiu/CS-courses-notes
  • [更新中…]强化学习笔记:https://github.com/PiperLiu/Reinforcement-Learning-practice-zh

对了,强烈推荐 VS Code 的插件 LeetCode for VS Code ,今天下午刚刚安装,简直神器。

链接:LeetCode for VS Code: 程序员 Offer 收割利器 - 知乎

PiperLiu
2020-2-2 21:18:04

第一次LeetCode周赛心得(力扣-cn周赛,使用python3)相关推荐

  1. C#实现力扣双周赛算法题:以组为单位订音乐会的门票订购

    目录: 前言: 一,算法题目描述 二,基本概念理解: 三,例子引入分析 四,代码解释 (1)安排座位函数 (2)查询函数 (2)求出1到RPS内的最小下标 (3)gather函数 (4)scatter ...

  2. 20200507:力扣151周赛下

    力扣151周赛下 题目 思路与算法 代码实现 题目 1. 从链表中删去总和值为零的连续节点 思路与算法 只做第三题了,第四题太耗费时间了,第三题对存在的链表进行一个判断就会发现,我们只需要去掉其中相加 ...

  3. 20200504:力扣187周赛下

    力扣187周赛下 题目 思路与算法 代码实现 题目 3.绝对差不超过限制的最长连续子数组 有序矩阵中的第 k 个最小数组和 思路与算法 第三题,本题没什么特殊的东西,滑动窗口即可,注意书写即可. 第四 ...

  4. 20200501:力扣185周赛上

    力扣185周赛上 题目 思路与算法 代码实现 题目 重新格式化字符串 点菜展示表 思路与算法 第一题,重新格式化字符串,没什么难度,直接遍历分类字符和数字,记得统计出数目,数目多1的那一类必须先拼接, ...

  5. leetcode|经典力扣第一题

    今天是 Kevin 的算法之路的第 20 天.为大家讲解 LeetCode 第 1 题,是一道简单但相当经典的题目. 每日一笑 玩游戏第一次坑朋友:对不起我不是故意的. 第二次坑朋友:emmm 第三次 ...

  6. Leetcode周赛复盘——第 71 场力扣双周赛与第 279 场力扣周赛

    双周赛: 5984. 拆分数位后四位数字的最小和 class Solution:def minimumSum(self, num: int) -> int:a, b, c, d = sorted ...

  7. LeetCode 第 69 场力扣双周赛

    5960. 将标题首字母大写 添加链接描述 给你一个字符串 title ,它由单个空格连接一个或多个单词组成,每个单词都只包含英文字母.请你按以下规则将每个单词的首字母 大写 : 如果单词的长度为 1 ...

  8. 第 338 场周赛 (力扣周赛)

    6354. K件物品的最大和 袋子中装有一些物品,每个物品上都标记着数字 1 .0 或 -1 . 给你四个非负整数 numOnes .numZeros .numNegOnes 和 k . 袋子最初包含 ...

  9. 力扣 双周赛补题 2086. 从房屋收集雨水需要的最少水桶数

    文章目录 题目 思路 AC代码 后记 题目 从房屋收集雨水需要的最少水桶数 思路 思路是贪心,因为我们需要从左向右找寻所有的水桶数,所以我们对于每一个房屋都优先判断右边是否能放水桶,右边不能放就看左边 ...

最新文章

  1. 【OpenCV3】OpenCV3.2.0在VS2013环境下Cmake编译与快速配置
  2. php ftp 大文件,php – 将文件复制到服务器与FTP之间的文件大小差异
  3. div设置宽度,实现不等比缩放,或设置最小宽度 min-width
  4. ExtJS入门(08)窗口,按钮,输入框,
  5. SAP Spartacus State
  6. 【Nginx】 Nginx实现端口转发
  7. c语言占用cpu的程序,Windows下用C语言获取进程cpu使用率,内存使用,IO情况
  8. O/R Mapping再乱弹
  9. springmvc请求返回一个字符_Spring MVC框架详解01
  10. 轻松学SQL Server数据库pdf
  11. 在VSCode中编辑HTML文档时,在Dom标签上写style属性时智能提示的问题
  12. 《ANSYS Workbench 14有限元分析自学手册》——1.3 ANSYS 14的界面
  13. Java 非小数BigDecimal转换为Integer
  14. 【SDOI 2009】学校食堂 Dining
  15. Mat 创建图像的理解
  16. SpringBoot房屋租赁系统
  17. Convert excel format exception.You can try specifying the ‘excelType‘ yourse-----EasyExcel导入
  18. Unity序列化——Assets序列化
  19. SpringMVC -- Restful风格的API
  20. 基于埋点日志数据的网络流量统计(网站独立访客数(UV)的统计)

热门文章

  1. 【SQL】结构化查询语言
  2. ubuntu命令行下中文乱码的解决方案
  3. 如何分组Windows窗体单选按钮?
  4. 什么是clearfix?
  5. 检索每个组中的最后一条记录-MySQL
  6. Linux技术进阶示意图
  7. aspx 判断字符串是否为decimal_C++编程技巧: 如何判断输入是否为整型
  8. python数据导出excel_【python Excel】如何使用python将大量数据导出到Excel中的小技巧之一...
  9. if/else双分支(JS)
  10. 实验4-2-8 输出整数各位数字 (15 分)