一起来刷leetcode——第一天 2020/10/28
刷题网站 :https://leetcode-cn.com/
github地址: https://github.com/zhe8300975/myleetcode
文章目录
整体总结
简单难度 383、387、389
中等难度 2
本次刷题 总结 以下4点
- ascii码 可以简化 char类型的运算复杂度
- 统计的次数的时候可以借助map 做到空间换时间
- char 加减法这种套路 有印象 以后说不定可以发散下
- 边界条件 要重视
总的来说 对应重新开始刷题的你我来说很合适的 长期的业务开发 会让我们基础数据类型的操作变得生疏 这几道题既可以熟悉基础语法 也可以熟悉基本数据类型 不错不错 哈哈
LeetCode 383
题目 —— 赎金信
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)
注意:
你可以假设两个字符串均只含有小写字母。
canConstruct(“a”, “b”) -> false
canConstruct(“aa”, “ab”) -> false
canConstruct(“aa”, “aab”) -> true
思路
首先题干中可以得到两个点:
- ransom里面的字符由magazine里面的字符组成
- magazine里面的字符只能用到一遍
所以可以得出
- magazine里面的字符需要被记录
- magazine里面的字符出现的次数需要被被记录
PS :看题可以猜的到 时间复杂度应该O(n)就够用 为什么是O(n)
正常我们应该遍历记录magazine (O(n) n是magazine的长度)
然后遍历ransom一遍对比magazine中的数据 (O(m) m是ransom长度)
整体时间复杂度 O(n+m) & m < n ----> O(2n) -> O(n)
综上 我很容易想到需要用一个Map记录magazine
key-出现的字符
value-字符出现的次数
解题
下面是就开始敲代码了
下面是第一版代码
通过 然而 平台提示的是运行速度和内存使用 都是下游水平的由此产生自我怀疑
首先想到的是的思路是不是不对的 ——看起来思路上应该没有问题
那就是代码上看能不能有所优化 —— 使用map的containKey 的话 会调用两次map 所以优化直接判断是不是为null可以做到一次
下面是代码
通过 然而 平台提示的是运行速度和内存使用 还是不行 比较是开始刷题 我觉得可以看看答案了
差异点 —— 官方答案中 利用字符的ascii编码 将hashmap退化成程度为26的数组 减少了hashmap 哈希的过程,内存上直接也限制了26 * int (int=4*8位)的数组大小长度
效率和 内存上 都有了显著的提高 代码如下
LeetCode 387
题目 —— 字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
示例:
s = “leetcode”
返回 0
s = “loveleetcode”
返回 2
提示:你可以假定该字符串只包含小写字母。
思路
这到题 瞬间 双重遍历每一字符遍历对比一遍 没有出现的其实就是想要的解 时间复杂度O( n^2 ) 然后瞬间推翻 提示不是没用的 猜测一定O(n)内可以解决
- O(n)内解决 肯定一两次循环就够
- 提示:你可以假定该字符串只包含小写字母。 那么根据上面的经验,char可以通过ascii转成int 最多26个
所以可以得出
- int[] 记录没有展示string中字符出现的次数 一次遍历
- 再遍历 找到第一个次数为1的
时间复杂度O(n);
解题
时间复杂度 和空间 复杂度 都在90%以上足够
复盘看下答案
- 官方解法一和我们思路基本一致
- 官方解法二 比我们方式要好 为什么 ?(具解法有兴趣的可以官网去看)
- 利用String 方法str.indexOf(ch) == str.lastIndexOf(ch) 判断是否有过重复 减少第一次循环次数
- 利用一共小写字母是26个 把我们第二个循环退化成了26次
LeetCode 389
题目 —— 找不同
给定两个字符串 s 和 t,它们只包含小写字母。
字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。
思路
- 延续上面套路 还是list记录 出现次数容易可以得出如下代码
解题
复盘看下答案
发现一个更好的解决方案 ,官方合理的利用了 随机位置添加一个字母 这个条件
利用减法 将两个字符串的ascii 做差 那么差值就是 差出来的那一个字符
代码如下
对比
虽然两次的运行时间差别不大 但是在内存上 差别还是挺明显的 毕竟数组直接退化成一个值了
LeetCode 2
题目 —— 两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
思路
抽离核心点
- 逆序链表
- 非负
- 一个节点一个数
综上所诉 其实最核心的就是逆序列表->链表头部是个位
题目很符合人类认知 两个链表同时后移相加 再一个变量记录进位就好了
解题
复盘看下答案
看了下答案 发现思路基本一致 不过在结题过程中 发现 这个题还有一个隐形的考察点 其实就是边界条件 结题的方式其实很简单 ,但是想要一次写出来也是不容易的