Skip to content

Oj 题目

本文章是收录有问题的Oj题目,

这里有问题是指做过了但是第二次做依然没有思路的题目

List

给定⼀个链表,判断链表中是否有环

使用快慢指针,一个速度为 2 另一个速度为 1,只要判断它们两是否相遇即可判断是否有环

问题:速度为什么一个是 2,一个是 1 ?一个是 3,一个是 4 行不行?

原因:它们之间的差为 1,只要满足这个条件,就一定可以追上,如果相差不是 1,就可能会跳过甚至永远不会相遇

Tree

⼆叉树的构建及遍历

使用递归的思路经行创建,通过外部 index 下标来获取字符

递归终止条件: index 获取到的字符是 # 递归过程: index 获取到的字符不是 #,创建根节点 root ,然后再通过 createTree 这个方法递归, 分别创建左子树与右子树,最后返回 root

就以 abc##de#g##f### 为例, a 就是根节点,左节点就是 bc##de#g##f##,右节点是 #

左节点的根节点是 b,它的左节点是 c## 它的右节点是 de#g##f##。以此类推……

二叉树的最近公共祖先

方法1:

  1. 获取到对应的节点到根节点的链表
  2. 然后通过寻找链表公共节点来获取到最近公共祖先(速度太慢了,于是看看视频是怎么写的)

方法2:

  1. p/q 是公共祖先
    1. root == q || root == p 那么就返回 root
    2. 不满足上诉条件时候,通过递归来获取
  2. p/qroot 两边
    1. 通过递归在左右两边同时找到相关的节点,直接返回 root
    2. 找不到直接递归即可

二叉树的前序遍历(非递归)

递归的方法很简单,这里就不说明了,这里主要说明的通过迭代的方法

迭代方法本质是把递归中系统自动开栈变成手动入栈的过程

把递归变成迭代需要明白 3 个要素

问题答案
什么时候入栈?等效于递归中进入方法的时候
为什么要入栈,入栈的目的主要是什么?为了可以恢复现场,记录下此时的状态,类似递归中的“归”的过程中,依然可以获取到当时的上下文
入栈怎么入递归是顺序来,而入栈的时候由于栈的性质,是需要反过来。比如前序遍历中,递归是先左再右,而迭代中入栈是先右再左

二叉树的中序遍历(非递归)

递归的方法很简单,这里就不说明了,这里主要说明的通过迭代的方法

  1. cur 来表示当前的节点
  2. cur 不为空,那么一直添加左子树,然后 cur = cur.left,将 cur 指向左子树
  3. cur 为空,说明左子树已经遍历完,就可以遍历右子树了,此时可以弹出根节点,并添加再 list 中,执行 cur = cur.right,把 cur 指向右子树
  4. 上诉为一次循环(遍历左子树),只需要再外层添加判断 stack 是否为空即可

二叉树的后序遍历(非递归)

大体的思路与 二叉树的中序遍历 一样,只是在左子树遍历完后处理的方式有所不同

  1. 是执行 stack.peek() 而不是 stack.pop(),因为不确定有没有遍历到右子树
  2. 如果右子树为空 或者 右子树已经遍历过,那么就直接 pop() 弹出,打印根节点,然后记录打印的节点
  3. 如果右子树不为空并且没有遍历过,那么将 cur 指向右子树,然后重新遍历

SetMap

随机链表的复制

通过 Map 这个数据结构来解决

  1. 遍历原数据,构建 MapMapkey 是旧节点下标, val 是新节点下标
  2. 此时 map.get(node) 可以获取到旧节点对应新节点的下标, 那么就可以通过 map.get(cur.next)map.get(cur.random) 获取到对应新节点的 nextrandom
  3. 最后返回新节点的头节点即可
步骤: 0 / 0

当前动作:等待输入...