算法练习-1
最近几天写算法写的挺开心的,为了以后保研面试啥的,继续准备算法学习工作,在家闲着也是闲着。
1.复杂链表的复制
1.1题目描述
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
来源:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof
1.2思路分析
采用深度优先搜索:
- 从头结点 head 开始拷贝;
- 由于一个结点可能被多个指针指到,因此如果该结点已被拷贝,则不需要重复拷贝;
- 如果还没拷贝该结点,则创建一个新的结点进行拷贝,并将拷贝过的结点保存在哈希表中;
- 使用递归拷贝所有的 next 结点,再递归拷贝所有的 random 结点。
1.3代码
1 |
|
1 |
|
2.对称二叉树
2.1题目描述
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1
/
2 2
/ \ /
3 4 4 3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
1
/
2 2
\
3 3
来源:https://leetcode-cn.com/problems/symmetric-tree
2.2思路分析
首先第一眼就反应到应该用递归操作比较简单,递归结束的条件是探索到叶子节点。
如果左右叶子都为NULL,证明该节点为叶节点
对称树要求左边叶子值等于右半部分对应叶子右边的值,于是递归条件就是判断相应的值是不是相等,是否有对应的节点。
2.3代码
1 |
|
3.寻找旋转排序数组中的最小值
3.1 题目描述
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。
你可以假设数组中不存在重复元素。
来源:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array
3.2思路分析
这个题就是最简单的排序,但是我们要想办法找一个时间复杂度小的算法。
最简单的直接排序就不说了,有个想法就是找出来旋转的那个点,特征就是前面的数字比后面的数字大,那么后面那个数字一定是最小的。但是要注意边界问题,下面的注释有说明。
3.3代码
1 |
|
4.二叉搜索树中第K小的元素
4.1题目描述
给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。
说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。
示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/
1 4
2
输出: 1
示例 2:
输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/
3 6
/
2 4
/
1
输出: 3
来源:https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst
4.2思路分析
最开始忘记了二叉搜索树的性质,所以还想着遍历之后再排序,后来发现二叉排序树是有性质的,采用中序遍历的结果就是从小到大排列的值。
于是我们可以递归采用中序遍历选出第k个值即可。
为了优化算法,我们在找到第k个值之后就结束,这样就可以减小搜索的时间复杂度。
4.3代码
1 |
|
4.4复习遍历算法
先序遍历
前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
若二叉树为空则结束返回,否则:
- 访问根节点
- 前序遍历左子树
- 前序遍历右子树
已知后序遍历和中序遍历,就能确定前序遍历。
中序遍历
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。若二叉树为空则结束返回,否则:
- 中序遍历左子树
- 访问根结点
- 中序遍历右子树
后序遍历
后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。
若二叉树为空则结束返回,否则:
- 后序遍历左子树
- 后序遍历右子树
- 访问根节点
三种遍历算法采用递归最容易实现。
5.UTF8编码验证
5.1题目描述
UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:
对于 1 字节的字符,字节的第一位设为0,后面7位为这个符号的unicode码。
对于 n 字节的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
这是 UTF-8 编码的工作方式:
Char. number range | UTF-8 octet sequence
(hexadecimal) | (binary)
——————————-+———————————————
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
给定一个表示数据的整数数组,返回它是否为有效的 utf-8 编码。
注意:
输入是整数数组。只有每个整数的最低 8 个有效位用来存储数据。这意味着每个整数只表示 1 字节的数据。
来源:https://leetcode-cn.com/problems/utf-8-validation
5.2思路分析
最简单的思路就是不做什么进制转换,直接按照不同条件分支判断即可,然后判断后面的字符是否符合标准,如果有一个不符合就直接返回false。中间踩了一个坑,就是忘记了数字位数不够的问题,导致数组访问溢出的情况。
5.3代码
1 |
|
6.二叉树的最小深度
6.1题目描述
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回它的最小深度 2.
来源:https://leetcode-cn.com/problems/minimum-depth-of-binary-tree
6.2思路分析
第一思路就是使用递归遍历,遍历整棵树后即可获得树的最小深度。
递归算法一定要注意,当时我将depth初始化为0的时候会出错,因为后面有个取最小值的步骤,如果深度初始化为0,每次取最小值都取0,最后结果肯定是错误的。因此我们需要取一个最大的值,保证不会出问题。
6.3代码
1 |
|