Long Luo's Life Notes

每一天都是奇迹

By Long Luo

The Solutions of LeetCode热题 100 | Top 100 Liked Questions:


No.ProblemsDifficultySource CodeSolution
001Two SumEasyJava2种方法:暴力 和 HashMap
002Add Two NumbersMediumJava2种方法:模拟 和 递归
003Longest Substring Without Repeating CharactersMediumJava
004Median of Two Sorted ArraysHardJava4种方法:合并数组,暴力法,二分搜索,划分数组
005Longest Palindromic SubstringMediumJava
010Regular Expression MatchingHardJava
011Container With Most WaterMediumJava2 Approaches: BF and Two Pointers with Image Explaination
0153SumMediumJava3种方法:暴力,Hash,双指针
017Letter Combinations of a Phone NumberMediumJava4 Approaches: BF 4 Loops, Backtracking, BFS, Queue with Image Explaination
019Remove Nth Node From End of ListEasyJava
020Valid ParenthesesEasyJava
021Merge Two Sorted ListsEasyJava
022Generate ParenthesesMediumJava2种方法:暴力法 和 回溯法
023Merge k Sorted ListsHardJava
024Swap Nodes in PairsMediumJava
025Reverse Nodes in k-GroupHardJava
031Next PermutationMediumJavaTwo Pointers Solution with Detailed Explanation and Code Commented
032Longest Valid ParenthesesHardJava
033Search in Rotated Sorted ArrayMediumJava
034Search for a RangeMediumJava
035Search Insert PositionMediumJava
039Combination SumMediumJava
042Trapping Rain WaterHardJava
045Jump Game IIMediumJava
046PermutationsMediumJava
048Rotate ImageMediumJava
049Group AnagramsMediumJava
053Maximum SubarrayMediumJava
055Jump GameMediumJava
056Merge IntervalsMediumJava
062Unique PathsMediumJava
064Minimum Path SumMediumJava
070Climbing StairsEasyJava
072Edit DistanceHardJava
075Sort ColorsMediumJava
076Minimum Window SubstringHardJava
078SubsetsMediumJava
079Word SearchMediumJava
084Largest Rectangle in HistogramHardJava
085Maximal RectangleHardJava
094Binary Tree Inorder TraversalMediumJava
096Unique Binary Search TreesMediumJava
098Validate Binary Search TreeMediumJava
101Symmetric TreeEasyJava
102Binary Tree Level Order TraversalEasyJava
104Maximum Depth of Binary TreeEasyJava
105Construct Binary Tree from Preorder and Inorder TraversalMediumJava
114Flatten Binary Tree to Linked ListMediumJava
121Best Time to Buy and Sell StockEasyJava
128Longest Consecutive SequenceHardJava
136Single NumberEasyJava
139Word BreakMediumJava
141Linked List CycleEasyJava
142Linked List Cycle IIMediumJava
146LRU CacheHardJava
148Sort ListMediumJava
152Maximum Product SubarrayMediumJava
155Min StackEasyJava3种方法:辅助栈,栈,链表
160Intersection of Two Linked ListsEasyJava
169Majority ElementEasyJava
198House RobberEasyJava
200Number of IslandsMediumJava
206Reverse Linked ListEasyJava
207Course ScheduleMediumJava
208Implement Trie (Prefix Tree)MediumJava
210Course Schedule IIMediumJava
215Kth Largest Element in an ArrayMediumJava
221Maximal SquareMediumJava
226Invert Binary TreeEasyJava
230Kth Smallest Element in a BSTMediumJava
234Palindrome Linked ListEasyJava
238Product of Array Except SelfMediumJava
239Sliding Window MaximumHardJava
240Search a 2D Matrix IIMediumJava
253Meeting Rooms IIMedium没权限
279Perfect SquaresMediumJava
283Move ZeroesEasyJava
287Find the Duplicate NumberMediumJava9 Approaches: Count, Hash, Sort, Binary Search, Bit, Fast Slow Pointers
297Serialize and Deserialize Binary TreeHardJava
300Longest Increasing SubsequenceMediumJava
301Remove Invalid ParenthesesHardJava
309Best Time to Buy and Sell Stock with CooldownMediumJava
312Burst BalloonsHardJava
322Coin ChangeMediumJava
328Odd Even Linked ListMediumJava
337House Robber IIIMediumJava
338Counting BitsMediumJava
347Top K Frequent ElementsMediumJava
394Decode StringMediumJava
399Evaluate DivisionMediumJava
406Queue Reconstruction by HeightMediumJava
416Partition Equal Subset SumMediumJava
437Path Sum IIIEasyJava
438Find All Anagrams in a StringEasyJava滑动窗口:从HashMap,数组,再到统计字母数量之差
448Find All Numbers Disappeared in an ArrayEasyJava
461Hamming DistanceEasyJava
494Target SumMediumJava
538Convert BST to Greater TreeEasyJava
543Diameter of Binary TreeEasyJava
560Subarray Sum Equals KMediumJava
572Subtree of Another TreeEasyJava
581Shortest Unsorted Continuous SubarrayEasyJava
617Merge Two Binary TreesEasyJava4 Approaches: Recursion, Iteration, BFS and DFS
621Task SchedulerMediumJava
647Palindromic SubstringsMediumJava
739Daily TemperaturesMediumJava
763Partition LabelsMediumJavaIllustration of the Max Position of the Char in the Partition with Easy Detailed Explanation

By Long Luo

Leetcode中 剑指Offer(专项突击版)


Leetcode题目难度解答Source Code
剑指Offer II 001. 整数除法EasyJava
剑指Offer II 002. 二进制加法EasyJava
剑指Offer II 003. 前 n 个数字二进制中 1 的个数EasyJava
剑指Offer II 004. 只出现一次的数字MediumJava
剑指Offer II 005. 单词长度的最大乘积MediumJava
剑指Offer II 006. 排序数组中两个数字之和EasyJava
剑指Offer II 007. 数组中和为 0 的三个数MediumJava
剑指Offer II 008. 和大于等于target的最短子数组MediumJava
剑指Offer II 011. 0 和 1 个数相同的子数组MediumJava
剑指Offer II 012. 左右两边子数组的和相等EasyJava
剑指Offer II 081. 允许重复选择元素的组合EasyJava
剑指Offer II 085. 生成匹配的括号MediumJava

By Long Luo

最近在做 Leetcode学习计划 中的 2021届秋季校招笔试真题 时,在这道题上 meituan-002. 小美的仓库整理 卡了一点时间,在此记录下自己从困惑到最终解决的全过程,吸取经验教训,提高自己知识水平。

题目

这是一道Medium难度的题目,如下所示:

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
27
28
29
30
31
32
33
34
35
36
37
meituan-002. 小美的仓库整理

小美是美团仓库的管理员,她会根据单据的要求按顺序取出仓库中的货物,每取出一件货物后会把剩余货物重新堆放,使得自己方便查找。已知货物入库的时候是按顺序堆放在一起的。如果小美取出其中一件货物,则会把货物所在的一堆物品以取出的货物为界分成两堆,这样可以保证货物局部的顺序不变。
已知货物最初是按1~n的顺序堆放的,每件货物的重量为w[i] ,小美会根据单据依次不放回的取出货物。请问根据上述操作,小美每取出一件货物之后,重量和最大的一堆货物重量是多少?

格式:

输入:
- 输入第一行包含一个正整数 n ,表示货物的数量。
- 输入第二行包含n个正整数,表示1~n号货物的重量w[i]。
- 输入第三行有n个数,表示小美按顺序取出的货物的编号,也就是一个1~n的全排列。

输出:
- 输出包含n行,每行一个整数,表示每取出一件货物以后,对于重量和最大的一堆货物,其重量和为多少。

示例:

输入:
5
3 2 4 4 5
4 3 5 2 1

输出:
9
5
5
3
0

解释:
原本的状态是{{3,2,4,4,5}},取出4号货物后,得到{{3,2,4},{5}},第一堆货物的和是9,然后取出3号货物得到{{3,2}{5}},此时第一堆和第二堆的和都是5,以此类推。

提示:
1 <= n <= 50000
1 <= w[i] <= 100

请注意,本题需要自行编写「标准输入」和「标准输出」逻辑,以及自行import/include需要的library。了解书写规则

从题意来看,这道题目并不难,所以当时看到题目之后,马上刷刷开始做题,觉得太简单了!

阅读全文 »

By Long Luo

之前虽然知道 KMP 算法,但是一直无法深入理解其原理,最近看了 2 篇文章:从头到尾彻底理解KMP(2014年8月22日版)KMP算法教程 ,然后再实际写代码,终于对 \(\textit{KMP}\) 算法有了一定了解了,下面写一写我个人的学习过程。

这篇文章主要从我个人学习过程来叙述:

为了解决什么问题?

\(\textit{KMP}\) 算法是一种字符串匹配算法,可以在 \(O(n+m)\) 的时间复杂度内实现两个字符串的匹配。

所谓字符串匹配,是这样一种问题:

  1. 字符串 \(\textit{P}\) 是否为字符串 \(\textit{S}\) 的子串?
  2. 如果是,\(\textit{P}\) 出现在 \(\textit{S}\) 的哪些位置?

其中 \(\textit{S}\) 称为主串\(\textit{P}\) 称为模式串

最常见的就是经常要用的搜索功能,比如要在一大段文字中找到某个句子或者找到出现的全部位置。在这种场景下,要找的句子就是给定的模式 \(\textit{P}\),而大段文字就是目标字符串 \(\textit{S}\)

从暴力法开始

我们先从最直观的地方开始:

  1. 两个字符串 \(\textit{A}\)\(\textit{B}\) 的比较?
  2. 如果 \(\textit{P}\)\(\textit{S}\) 的字串,第一个出现的位置在哪里?

所谓字符串比较,就是问两个字符串是否相等

最朴素的思想,就是从前往后逐字符比较,一旦遇到不相同的字符,就返回 \(\textit{False}\) ;如果两个字符串都结束了,仍然没有出现不对应的字符,则返回 \(\textit{True}\)

代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static int Search_BruteForce(String targetStr, String patternStr) {
int targetLen = targetStr.length();
int patLen = patternStr.length();

for (int i = 0; i < targetLen; i++) {
if (targetStr.charAt(i) == patternStr.charAt(i)) {
for (int j = 1; j < patLen; j++) {
if (targetStr.charAt(i + j) != patternStr.charAt(j)) {
break;
}

if (j == patLen - 1) {
return i;
}
}

}
}

return -1;
}

或者双指针版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static int ViolentMatch(String targetStr, String patternStr) {
int targetLen = targetStr.length();
int patLen = patternStr.length();

int i = 0;
int j = 0;
while (i < targetLen && j < patLen) {
if (targetStr.charAt(i) == patternStr.charAt(j)) {
i++;
j++;
} else {
i = i - j + 1;
j = 0;
}
}

if (j == patLen) {
return i - j;
} else {
return -1;
}
}

暴力解法复杂度分析

刚才我们成功实现了暴力算法,那么其时间复杂度如何?

\(n\) 为串 \(\textit{S}\) 的长度,\(m\) 为串 \(\textit{P}\) 的长度。

考虑“字符串比较”这个小任务的复杂度。最坏情况发生在:两个字符串唯一的差别在最后一个字符。这种情况下,字符串比较必须走完整个字符串,才能给出结果,因此复杂度是 \(O(len(str))\) 的。

由此,不难想到暴力算法所面对的最坏情况:

主串形如 “AAAAAAAAAAAAA…B” ,而模式串形如 “AAAAA…B” 。每次字符串比较都需要付出 \(O(m)\) 次字符比较的代价,总共需要比较 \(n\) 次,因此总时间复杂度是 \(O(nm)\)

那么如何改进呢?

信息熵冗余

我们很难降低字符串比较的复杂度(因为比较两个字符串,真的只能逐个比较字符)。因此,我们考虑降低比较的趟数。如果比较的趟数能降到足够低,那么总的复杂度也将会下降很多。

要优化一个算法,首先要回答的问题是“我手上有什么信息?” 我们手上的信息是否足够、是否有效,决定了我们能把算法优化到何种程度。请记住:尽可能利用残余的信息,是 \(\textit{KMP}\) 算法的思想所在。

很明显在暴力算法中,模式字符串每次都需要比较,非常复杂,那么这里面有没有优化的时间呢?

阅读全文 »

By Long Luo

之前开发 Android电子书阅读器App 时,需要支持 Pdf 文件的阅读和标记功能,经过分析和测试不同实现方案,最终选择 MuPdf 方案。

Pdf解决方案

目前手机上实现 Pdf 文件的支持,有很多解决方案:

  1. Andorid原生自带的Pdf解决方案,主要提供两个类 PdfRendererPdfDocument ,但是 Lollipop 才有的类,PdfRenderer 中核心代码是用的 native 方法,所以没办法将 PdfRenderer 从 SDK 中抽取出来用,局限性大,不采用。

  2. 开源 AndroidPdfViewer ,完全使用 Java 实现,但问题在于太大,性能不及原生,所以放弃。

  3. MuPdf,一款轻量级的 pdf 框架,支持前面两者功能,同时如果是文本的 pdf 文档还支持搜索、标注等功能,使用 native C 代码实现,快,编译好的so库也只有10M大小。

  4. 调起手机中第三方支持 Pdf 阅读的应用;

  5. 通过 pdf.js 实现在线预览,需要调用网页,性能不及原生,放弃。

MuPdf

MuPdf 是一个轻量级 PDF、XPS 和 E-book 阅读器,支持全部平台。

源码下载地址:https://mupdf.com/downloads/archive/

官网提供了一个例子:MuPDF Android Viewer,下面我们来编译并实现。

MuPdf编译

下载源码:

1
$ git clone --recursive git://git.ghostscript.com/mupdf-android-viewer.git

安装Cygwin或者直接在Linux下使用:

1
2
mupdf-android-viewer$cd jni
mupdf-android-viewer/jni$make generate

会调用 make -j4 -C libmupdf generate 命令编译字体文件,然后在 libmupdf 目录下生成 generated 文件夹,里面主要是一些字体文件。

阅读全文 »
0%