移动应用开发实验室大一下考核题分析
力扣238除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请 不要使用除法,且在 O(n) 时间复杂度内完成此题。
示例 1:
输入: nums = [1,2,3,4]
输出: [24,12,8,6]
示例 2:
输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]
提示:
2 <= nums.length <= 105
-30 <= nums[i] <= 30
保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内
题目分析
输出一个数组,数组的第i位是除第i个数字的其他元素之积,不能使用除法
解题思路
利用前缀积和后缀积的思想,数组的每一位都等于它的前缀积×后缀积
注意:这里的前缀和后缀与正常不同,不能包含第i位
代码实现
1 | class Solution { |
力扣394字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例 1:
输入:s = “3[a]2[bc]
“
输出:”aaabcbc”
示例 2:
输入:s = “3[a2[c]]
“
输出:”accaccacc”
示例 3:
输入:s = “2[abc]3[cd]ef
“
输出:”abcabccdcdcdef”
示例 4:
输入:s = “abc3[cd]xyz
“
输出:”abccdcdcdxyz”
提示:
1 <= s.length <= 30
s 由小写英文字母、数字和方括号 ‘[]’ 组成
s 保证是一个 有效 的输入。
s 中所有整数的取值范围为 [1, 300]
题目分析
有关括号的匹配的字符串问题
解题思路
当我们遇到括号的匹配时,首先想到的就是用栈来解决
设置两个栈nums,strs,分别来存放字符串中的数字与字符串,定义一个字符串res用于输出1.遇到数字用num记录,遇到字符串用res记录
2.遇到左括号时,把数字和字符串分别压入栈,再重置num为0,res为空
3.遇到右括号时,开始解码,取num的栈顶作为字符串重复的次数,重复将res加入栈内后,若栈顶还是字母,就会直接加到res之后,因为它们是同一级的运算,若是左括号,res会被压入str,作为上一层的运算
代码实现
1 | class Solution { |
力扣23合并k个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
题目分析
与合并2个有序链表类似
解题思路
先合并前两个链表,再不断将新链表与下一个链表合并
代码实现
1 | class Solution { |
力扣232用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
输入:["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
提示:
1 <= x <= 9
最多调用 100 次 push、pop、peek 和 empty
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)
题目分析
用栈实现队列
解题思路
C语言
myQueueCreate
功能:创建一个新的队列,并初始化栈顶指针。
myQueuePush
功能:将一个元素推入队列。
myQueuePop
功能:从队列中弹出一个元素。
如果 stkOut 是空的,它会从 stkIn 中取出所有元素并放入 stkOut 中,然后弹出 stkOut 的顶部元素。这是为了确保弹出的元素是队列中最先进入的元素。
myQueuePeek
功能:查看队列的顶部元素但不弹出。
myQueueEmpty
功能:检查队列是否为空。
myQueueFree
功能:释放队列。
代码分析
1 | typedef struct { |
力扣61旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
示例 1:
输入:head = [1,2,3,4,5]
, k = 2
输出:[4,5,1,2,3]
示例 2:
输入:head = [0,1,2]
, k = 4
输出:[2,0,1]
提示:
链表中节点的数目在范围 [0, 500] 内
-100 <= Node.val <= 100
0 <= k <= 2 * 109
题目分析
将旋转后的链表重新排序
解题思路
将链表存到数组中,再用三个reverse反转数组,再存入数组中
三个反转:先全部反转,再反转前k个,最后反转后k个
代码实现
1 | /** |
力扣392判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,”ace”是”abcde”的一个子序列,而”aec”不是)。
进阶:
如果有大量输入的 S,称作 S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
致谢:
特别感谢 @pbrother 添加此问题并且创建所有测试用例。
示例 1:
输入:s = “abc”, t = “ahbgdc”
输出:true
示例 2:
输入:s = “axc”, t = “ahbgdc”
输出:false
提示:
0 <= s.length <= 100
0 <= t.length <= 10^4
两个字符串都只由小写字符组成
。
题目分析
判断s是否是t的子序列,其中可以有别的字符,但不能改变相对位置
解题思路
利用快慢指针,慢指针位于s,快指针位于t,只有快慢指针指向的字符相等时慢指针移动,快指针持续移动,当慢指针遍历完时(也就是快指针已经将慢指针指向的字符都匹配上)返回true
代码实现
1 | class Solution { |