Long Luo's Life Notes

每一天都是奇迹

By Long Luo

之前的如何根据数组或者字符串创建链表? 详述了Leetcode链表 相关算法题的测试方法。在Leetcode中关于 的算法题中,很多树的题目,测试用例都是一个数组,比如102. 二叉树的层序遍历 中所示:

1
2
3
4
5
6
给定二叉树: [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7

那么问题来了,如何根据数组构造一颗树呢? 为了加快刷题,我们需要一个工具来实现构造树和打印树结构这2个问题。

树是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由 n(n>0)个有限节点组成一个具有层次关系的集合。

Tree

如上图所示,把它叫做「树」是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

树具有以下的特点: - 每个节点都只有有限个子节点或无子节点; - 没有父节点的节点称为根节点; - 每一个非根节点有且只有一个父节点; - 除了根节点外,每个子节点可以分为多个不相交的子树; - 树里面没有环路。

当我们完成一棵树的构建之后,虽然我们已经有树的前序、中序和后序遍历这种可以遍历树,但是如果我们如上图一样展示这棵树的结构,如何才能直观地打印出来呢?

如何打印一棵树?

这里我们借用Leetcode中二叉树的数据结构定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Definition for a binary tree node.
*/
public class TreeNode {
public int val;

public TreeNode left;
public TreeNode right;

public TreeNode(int x) {
this.val = x;
}

public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}

思路

树的展示方式有2种,水平展示和竖直展示。竖直展示比较直观,水平展示更适合用于节点元素大小长短不一致的情况,Linux下展示文件结构就是水平展示。

阅读全文 »

By Long Luo

https://leetcode.cn/problemset/lcof/

官方源码:https://github.com/zhedahht/CodingInterviewChinese2

题目难度解答Source Code
剑指Offer 03. 数组中重复的数字EasyJava
剑指Offer 06. 从尾到头打印链表EasyJava
剑指Offer 09. 用两个栈实现队列EasyJava
剑指Offer 12. 矩阵中的路径MediumJava
剑指Offer 15. 二进制中1的个数EasyJava

By Long Luo

Leetcode链表 相关的题时,给出的测试用例总是数组或者字符串形式,比如 61. 旋转链表 这道题,Testcase如下所示:

示例 1:

61. Rotate List TestCase 1

输入:head = [1,2,3,4,5], k = 2 输出:[4,5,1,2,3]

问题

如果在本地测试代码时,每次测试代码的时候,都需要自己创建测试用例,或者调用leetcode给的例子,都需要手动去创建一个链表的话,但这样效率太低!针对这种情况,写了几个工具函数用来处理链表的代码,可供大家参考。

测试代码

个人测试链表测试代码如下:

1
2
3
4
5
6
7
public static void main(String[] args) {
ListNode test1 = LinkedListUtils.constructListNode(new int[]{1, 2, 3, 4, 5});
System.out.println("[4,5,1,2,3] ?=" + LinkedListUtils.printLinkedList(rotateRight(test1, 2)));

ListNode test2 = LinkedListUtils.constructListNode(new int[]{0, 1, 2});
System.out.println("[2,0,1] ?=" + LinkedListUtils.printLinkedList(rotateRight(test2, 4)));
}

打印链表

Leetcode上链表最后输出形式:

输出:[4,5,1,2,3]

打印方法很简单,代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static String printLinkedList(ListNode head) {
if (head == null) {
return "[]";
} else if (head.next == null) {
return "[" + head.val + "]";
}

StringBuilder sb = new StringBuilder();
sb.append("[");
while (head.next != null) {
sb.append(head.val);
if (head != null) {
sb.append(",");
}
head = head.next;
}
sb.append(head.val).append("]");

return sb.toString();
}
阅读全文 »

By Long Luo

我的 Leetcode 的解题:


Chinese Solutions

Leetcode题目难度题解
1. 两数之和Easy2种方法:暴力 和 HashMap
2. 两数相加Medium2种方法:模拟 和 递归
4. 寻找两个正序数组的中位数Hard4种方法:合并数组,暴力法,二分搜索,划分数组
15. 三数之和Medium3种方法:暴力,Hash,双指针
18. 四数之和Medium4种方法:暴力,双指针,DFS,HashMap
22. 括号生成Medium2种方法:暴力法 和 回溯法
28. 实现 strStr()Easy理解KMP算法:从入门到推导
29. 两数相除Medium3种方法:暴力法,二分搜索,递归
42. 接雨水Hard5种解法:木桶原理,按行求,动态规划,双指针,单调栈
43. 字符串相乘Medium另辟蹊径,快速傅里叶变换(FFT)计算大数乘法
70. 爬楼梯Easy面试算法题:爬楼梯,N级楼梯有多少种走法?
148. 排序链表Medium4种方法:暴力,List,自顶向下归并排序,自底向上归并排序
155. 最小栈Easy3种方法:辅助栈,栈,链表
171. Excel 表列序号Easy仿照Excel的列编号,给定一个数字,输出该列编号字符串
209. 长度最小的子数组Medium5种方法:暴力,双指针,前缀和,前缀和 + 二分查找,二分查找
225. 用队列实现栈Easy如何改变队列元素顺序?
230. 二叉搜索树中第K小的元素Medium二叉搜索树中第K小的元素
232. 用栈实现队列Easy顺序翻转,使用两个栈:一个入队,一个出队
268. 丢失的数字Medium4种方法:排序,哈希表,异或,数学公式
299. 猜数字游戏Medium从遍历2次优化到遍历1次
318. 最大单词长度乘积Medium3种方法:从暴力状态压缩到位运算优化
384. 打乱数组Medium2种方法:暴力 和 洗牌算法
390. 消除游戏Medium经典算法:从约瑟夫问题说开去…
396. 旋转函数Medium3种方法:暴力法,动态规划,前缀和 + 滑动窗口
407. 接雨水 IIHard2种方法:优先队列存储每层围栏最低高度,BFS更新每个方块存水高度
超大数字的加减乘除 415. 字符串相加, 445. 两数相加 IIMedium超大数字的四则运算是如何实现的呢?
419. 甲板上的战舰Medium4种方法:一次遍历,DFS,统计战舰起点
423. 从英文中重建数字Medium找规律,依次确定数字的次数,逐步消元法
438. 找到字符串中所有字母异位词Medium滑动窗口:从HashMap,数组,再到统计字母数量之差
458. 可怜的小猪Hard从 经典面试问题 到 信息论
509. 斐波那契数Easy9种求斐波那契数(Fibonacci Numbers)的算法
519. 随机翻转矩阵Medium2种方法:暴力法 和 降维 + 哈希表
525. 连续数组Medium2种方法:暴力,前缀和 + 哈希表
559. N叉树的最大深度Easy3种方法:递归,DFS和BFS
594. 最长和谐子序列Easy4种方法:暴力枚举,排序 + 枚举,哈希表
598. 范围求和 IIEasy求所有操作的交集
686. 重复叠加字符串匹配Medium3种方法:暴力,字符串哈希,KMP
700. 二叉搜索树中的搜索Easy3种方法:递归,迭代,BFS
859. 亲密字符串Easy简单的字符串模拟
912. 排序数组Medium排序算法(Sorting Algorithms)
997. 找到小镇的法官Easy图论,计算各节点的入度和出度
1044. 最长重复子串Hard3种方法:从暴力到二分,二分搜索 + 字符串哈希,后缀数组
1218. 最长定差子序列Medium序列动态规划 + HashMap
1385. 两个数组间的距离值Easy2种方法:模拟 和 二分搜索
1705. 吃苹果的最大数目Medium贪心 + 优先队列:每天找最邻近过期的苹果吃
1816. 截断句子Easy3种方法:正则表达式,模拟和优化
meituan-002. 小美的仓库整理Medium记一道美团面试编程题的解题过程:从暴力到优化
阅读全文 »

By Long Luo

148. 排序链表

暴力 + ArrayList

思路与算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}

ListNode pNode = head;

List<Integer> nodeList = new ArrayList<>();
while (pNode != null) {
nodeList.add(pNode.val);
pNode = pNode.next;
}

Collections.sort(nodeList);

ListNode dummyNode = new ListNode(-1);
pNode = dummyNode;
for (int i = 0; i < nodeList.size(); i++) {
pNode.next = new ListNode(nodeList.get(i));
pNode = pNode.next;
}

return dummyNode.next;
}

123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}

ListNode pNode = head;

List<ListNode> nodeList = new ArrayList<>();
while (pNode != null) {
nodeList.add(pNode);
pNode = pNode.next;
}

nodeList.sort(Comparator.comparingInt(o -> o.val));

ListNode dummyNode = new ListNode(-1);
ListNode preNode = dummyNode;
for (int i = 0; i < nodeList.size(); i++) {
pNode = nodeList.get(i);
preNode.next = pNode;
pNode.next = null;
preNode = pNode;
}

return dummyNode.next;
}

复杂度分析

  • 时间复杂度:\(O(n \log n + n)\)
  • 空间复杂度:\(O(n)\)

归并排序

1
2
3



复杂度分析

  • 时间复杂度:\(O(n \log n + n)\)
  • 空间复杂度:\(O(n)\)

All suggestions are welcome. If you have any query or suggestion please comment below. Please upvote👍 if you like💗 it. Thank you:-)

Explore More Leetcode Solutions. 😉😃💗

0%