第一周LeetCode总结

3 篇文章 0 订阅
2 篇文章 0 订阅

写在前面

听说LeetCode已经很久了,这周下决心开刷,坚持下去,希望能有一些效果。第一周刷的都是一些简单的和栈相关的题目,因为有些中等难度和困难的想破头也想不出…那就先做一些简单的吧,回忆一下学过的知识。写代码时用的python,但是觉得python实在是太方便了,对单一的数据结构支持不是很好,所以下周准备换成C++。下面的解法有的是自己的思路,有的是当时做不出后来参考别人的,写的时候都是根据自己的理解来写。代码都放在我的github上。

题目(来源 https://leetcode-cn.com/problemset/all/)

1.两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解法:
1.暴力法。直接两次循环,时间复杂度o(n^2),空间复杂度为O(1)
2.用空间换时间。第一次遍历nums,将nums中的元素作为key,下标作为value放入HashMap中。第二次遍历nums,通过判断target-nums[i]是否在表中来确定当前元素是否满足条件。

2.两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解法:
遍历两个链表,对应位置相加,结果保存在新链表中,注意进位问题。
因为两个链表长度可能不同,所以可以将短的那个补0,直到两个链表长度相同。设置一个进位temp,初始等于0,如果进位则temp=1。每次都是对应位置相加再加temp。

3.无重复字符的最长子串

滑动窗口解法在这里

20.有效的括号

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false

解法:
用栈进行括号匹配。遇到 (,[,{进栈,遇到),],}出栈,检查弹出的元素是否和相应的括号匹配。

155.最小栈

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) – 将元素 x 推入栈中。
pop() – 删除栈顶的元素。
top() – 获取栈顶元素。
getMin() – 检索栈中的最小元素。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

解法:
要求在常数时间内检索到最小元素,所以应该想到用空间换时间。首先想到的是搞一个变量min,但是由于栈会有pop操作,所以单一的变量min操作会比较复杂。因此我们用一个辅助栈helper。helper是一个从栈顶到栈底递增有序的栈,也就是栈顶始终存放最小值。主栈stack进栈时,若helper为空或者当前元素小于栈顶的值则helper也进栈。stack出栈时,若出栈元素和helper栈顶元素相同,则helper也出栈。这样就可以保证helper栈顶元素始终是整个栈中的最小值,获取最小的时间复杂度为o(1)。

225.用队列实现栈

使用队列实现栈的下列操作:
push(x) – 元素 x 入栈
pop() – 移除栈顶元素
top() – 获取栈顶元素
empty() – 返回栈是否为空
注意:
你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。

解法:
本题很简单,注意队列的性质是先进先出,栈的性质是后进先出

232.用栈实现队列

使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。
示例:
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false

解法:
同上一题。

496.下一个更大的元素

给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。
示例 2:
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于num1中的数字2,第二个数组中的下一个较大数字是3。
对于num1中的数字4,第二个数组中没有下一个更大的数字,因此输出 -1。

解法:
1.暴力法。对nums1中每个数字,都遍历nums2,时间复杂度为o(n^2)。
2.稍微不那么暴力法。先将nums2中的数字都放在HashMap中,key为其中的元素,value为下标。遍历nums1,根据元素值在map中找到对应的下标i,从i+1开始向后找。执行速度可能会变快,最坏情况下依然要遍历整个nums2,因此时间复杂度为o(n^2)。
3.单调栈。类似这种题都适合单调栈的使用场景。单调栈,顾名思义就是单调递增或者单调递减的栈。对于本题,我们从后往前遍历nums2,单调栈中存放的是比当前元素大的元素的下标,从栈底到栈顶单调递减。对于每个数组元素nums2[i],如果栈不空,并且nums2[i]大于栈顶元素对应的数组元素,即 nums2[i] > nums2[stack.top],则出栈。(因为stack.top > i,在数组nums2中,nums[stac.top]在nums[i]右边,而栈是从栈底到栈顶单调递减,栈顶最小,如果stack.top不行,就弹出,继续往右找) 重复执行此操作,直到栈空或者nums2[i] < nums2[stack.top]。此时若栈空,则记录-1,否则记录nums2[stack.top]的值。然后再把i压入栈中,继续循环。

682.棒球比赛

你现在是棒球比赛记录员。
给定一个字符串列表,每个字符串可以是以下四种类型之一:
1.整数(一轮的得分):直接表示您在本轮中获得的积分数。
2. “+”(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
3. “D”(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
4. “C”(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。
每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。
你需要返回你在所有回合中得分的总和。
示例 1:
输入: [“5”,“2”,“C”,“D”,"+"]
输出: 30
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到2分。总和是:7。
操作1:第2轮的数据无效。总和是:5。
第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
第4轮:你可以得到5 + 10 = 15分。总数是:30。

解法:
本来想将这些字符压入栈中去处理,发现没法搞。。。。后来看了别人的思路才想到将每一轮的分数都放入栈中。。。而这些操作也刚好符合栈的操作

844.比较含退格的字符串

给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。
示例 1:
输入:S = “ab#c”, T = “ad#c”
输出:true
解释:S 和 T 都会变成 “ac”。
示例 2:
输入:S = “ab##”, T = “c#d#”
输出:true
解释:S 和 T 都会变成 “”。

解法:
没什么说的,两个栈,两次遍历,遇到 #且栈不空就出栈,否则什么也不做。最后判断栈中字符是否对应相等。

第一周刷力扣,DP,贪心算法什么的很多东西都忘了,而且很多题目一点也想不出。。。慢慢加油吧。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值