Showing preview only (370K chars total). Download the full file or copy to clipboard to get everything.
Repository: guokaide/algorithm
Branch: master
Commit: 9bee14b08b06
Files: 167
Total size: 284.7 KB
Directory structure:
gitextract_6zdwcmqq/
├── .gitignore
├── README.md
├── algorithms/
│ └── src/
│ ├── array/
│ │ ├── BinarySearch.java
│ │ ├── BinarySearchTest.java
│ │ ├── GenericArray.java
│ │ ├── MinNumberInRotatedArray.java
│ │ └── MinNumberInRotatedArrayTest.java
│ ├── joseph/
│ │ └── Joseph.java
│ ├── linkedlist/
│ │ ├── FindMidNode.java
│ │ ├── FindMidNodeTest.java
│ │ ├── SingleLinkedList.java
│ │ └── SingleLinkedListTest.java
│ ├── lru/
│ │ ├── LRU.java
│ │ └── LRUTest.java
│ ├── queue/
│ │ ├── ArrayQueue.java
│ │ ├── CircularQueue.java
│ │ ├── ListQueue.java
│ │ └── Queue.java
│ └── stack/
│ ├── ArrayStack.java
│ ├── DynamicArrayStack.java
│ ├── ListStack.java
│ ├── SampleBrowser.java
│ └── Stack.java
├── appendix/
│ ├── instructions.md
│ └── 刷题笔记.md
├── leetcode/
│ └── src/
│ ├── linkedlistcycle_141/
│ │ └── LinkedListCycle.java
│ ├── lrucache_146/
│ │ └── LRUCache.java
│ ├── mergetwosortedlist_21/
│ │ └── Merge2SortedLists.java
│ ├── middleofthelinkedlist_876/
│ │ └── MiddleNode.java
│ ├── palindromelinkedlist_234/
│ │ └── PalindromeLinkedList.java
│ ├── removenthnodefromendoflist_19/
│ │ └── RemoveNthNodeFromEndOfList.java
│ ├── reverselinkedlist_206/
│ │ └── ReverseList.java
│ ├── threesum_015/
│ │ └── ThreeSum.java
│ └── twosum_001/
│ └── TwoSum.java
├── offer/
│ └── src/
│ └── com/
│ └── ex/
│ ├── offer/
│ │ ├── Attention.txt
│ │ ├── Ex_03_FindDuplicatedNumInArray.java
│ │ ├── Ex_03_FindDuplicatedNumInWithoutChangeArray.java
│ │ ├── Ex_04_FindNumIn2VArray.java
│ │ ├── Ex_05_ReplaceSpace.java
│ │ ├── Ex_06_PrintListFromTailToHead.java
│ │ ├── Ex_07_ReConstructBT.java
│ │ ├── Ex_08_DescendantNode.java
│ │ ├── Ex_08_GetNextNodeInBT.java
│ │ ├── Ex_09_QueueWithTwoStack.java
│ │ ├── Ex_09_StackWithTwoQueue.java
│ │ ├── Ex_10_Fibonacci.java
│ │ ├── Ex_10_JumpFloor.java
│ │ ├── Ex_10_JumpFloorII.java
│ │ ├── Ex_10_RectCover.java
│ │ ├── Ex_11_MinNumOfRotatingArray.java
│ │ ├── Ex_11_SortAges.java
│ │ ├── Ex_12_HasPathInMatrix.java
│ │ ├── Ex_13_MovingCount.java
│ │ ├── Ex_14_MaxProductionAfterCutting.java
│ │ ├── Ex_15_Count1.java
│ │ ├── Ex_15_CountDifferInMN.java
│ │ ├── Ex_15_IsPowerOf2.java
│ │ ├── Ex_16_Power.java
│ │ ├── Ex_17_AddTwoBigNumber.java
│ │ ├── Ex_17_Print1ToMaxNDigits.java
│ │ ├── Ex_18_DeleteDuplicatedNode.java
│ │ ├── Ex_18_DeleteNodeInSList.java
│ │ ├── Ex_19_Match.java
│ │ ├── Ex_20_IsNumber.java
│ │ ├── Ex_21_ReOrderArray.java
│ │ ├── Ex_22_FindKthNodeToTail.java
│ │ ├── Ex_22_FindMedianNodeInList.java
│ │ ├── Ex_23_EntryNodeInList.java
│ │ ├── Ex_24_ReverseSList.java
│ │ ├── Ex_25_MergeList.java
│ │ ├── Ex_26_IsSubTree.java
│ │ ├── Ex_27_MirrorOfTree.java
│ │ ├── Ex_28_SymmetricalTree.java
│ │ ├── Ex_29_PrintMatrixWithClockWise.java
│ │ ├── Ex_30_StackWithMinFunction.java
│ │ ├── Ex_31_IsPopOrder.java
│ │ ├── Ex_32_PrintTreeByLayer.java
│ │ ├── Ex_32_PrintTreeWithZhi.java
│ │ ├── Ex_32_TraverseTreeByLayer.java
│ │ ├── Ex_33_VerifySequenceOfBST.java
│ │ ├── Ex_34_FindPathInBT.java
│ │ ├── Ex_34_FindPathInBT_1.java
│ │ ├── Ex_34_FindPathInBT_2.java
│ │ ├── Ex_35_CloneList.java
│ │ ├── Ex_36_ConvertBetweenBSTAndDList.java
│ │ ├── Ex_37_SerializeBT.java
│ │ ├── Ex_38_EightQueen.java
│ │ ├── Ex_38_StringCombination.java
│ │ ├── Ex_38_StringPermutation.java
│ │ ├── Ex_39_KthSmallestNumInArrayWithoutSort.java
│ │ ├── Ex_39_MoreThanHalfNum.java
│ │ ├── Ex_40_GetLeastKNumbers.java
│ │ ├── Ex_41_MedianInDataFlow.java
│ │ ├── Ex_42_MaxSumOfSubArray.java
│ │ ├── Ex_43_NumberOf1Between1AndN.java
│ │ ├── Ex_44_ANumInArray.java
│ │ ├── Ex_45_MinNumByConcatArray.java
│ │ ├── Ex_46_ConvertStringToIP.java
│ │ ├── Ex_46_TranslationFromIntToString.java
│ │ ├── Ex_47_MaxGiftValue.java
│ │ ├── Ex_48_LongestSubStringWithDuplication.java
│ │ ├── Ex_49_UglyNumber.java
│ │ ├── Ex_50_FirstNotRepeatedChar.java
│ │ ├── Ex_50_FirstNotRepeatedCharInDataFlow.java
│ │ ├── Ex_50_StringUtilsSolutions.java
│ │ ├── Ex_51_InversePairs.java
│ │ ├── Ex_51_InversePairs_BigData.java
│ │ ├── Ex_52_FirstCommonNode.java
│ │ ├── Ex_53_GetMissingNumber.java
│ │ ├── Ex_53_GetNumberOfK.java
│ │ ├── Ex_53_GetNumberSameAsIndex.java
│ │ ├── Ex_54_KthNodeInBST.java
│ │ ├── Ex_55_BalancedBT.java
│ │ ├── Ex_55_DepthOfBT.java
│ │ ├── Ex_56_AppearanceOnce.java
│ │ ├── Ex_56_AppearanceOnce_Continued.java
│ │ ├── Ex_57_FindContinuousSequence.java
│ │ ├── Ex_57_FindNumbersWithSum.java
│ │ ├── Ex_58_ROL.java
│ │ ├── Ex_58_ReverseSentence.java
│ │ ├── Ex_59_MaxNumOfSlidingWindow.java
│ │ ├── Ex_59_QueueWithMax.java
│ │ ├── Ex_60_ProbabilityOfS.java
│ │ ├── Ex_61_ContinuousSequence.java
│ │ ├── Ex_62_Josephus.java
│ │ ├── Ex_63_MaxProfits.java
│ │ ├── Ex_64_SumFrom1ToN.java
│ │ ├── Ex_65_AddWithoutCarry.java
│ │ ├── Ex_65_SwapNumWithoutTemp.java
│ │ ├── Ex_66_ConstructMultiplyArray.java
│ │ ├── Ex_67_StringToInt.java
│ │ ├── Ex_68_LowestCommonAncestor.java
│ │ ├── ListNode.java
│ │ ├── Node.java
│ │ ├── RandomListNode.java
│ │ ├── TestUtils.java
│ │ ├── TreeLinkNode.java
│ │ └── TreeNode.java
│ └── singleton/
│ ├── Singleton1.java
│ ├── Singleton2.java
│ ├── Singleton3.java
│ ├── Singleton4.java
│ ├── Singleton5.java
│ └── singleton.md
├── practice/
│ ├── Final.md
│ ├── README.md
│ └── src/
│ └── io/
│ └── gkd/
│ ├── ListNode.java
│ ├── Node.java
│ ├── TreeNode.java
│ ├── lectures/
│ │ ├── lecture04/
│ │ │ ├── Lc077_Combine.java
│ │ │ └── Lc078_SubSets.java
│ │ └── lecture05/
│ │ ├── Lc094_InOrderTraversal.java
│ │ ├── Lc105_BuildTree.java
│ │ ├── Lc236_LCA.java
│ │ ├── Lc297_Codec.java
│ │ ├── Lc429_LevelOrderNTree.java
│ │ └── Lc589_PreOrderNTree.java
│ ├── week01/
│ │ ├── Lc021_MergeTwoLists.java
│ │ └── Lc066_PlusOne.java
│ ├── week02/
│ │ ├── Lc146_LRUCache.java
│ │ └── Lc697_FindShortestSubArray.java
│ └── week03/
│ ├── Lc106_BuildTree.java
│ ├── Lc210_FindOrder2.java
│ └── NOTES.md
├── questions/
│ └── questions.md
├── solutions/
│ └── 剑指offer 题解.md
└── summary/
└── algorithm.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# idea
*.idea
*.iml
target/
*.mvn
*db
# others
*.extract
.DS_Store
================================================
FILE: README.md
================================================
# [算法练级计划](https://mp.weixin.qq.com/s/6vuaECCmrxrchr5Hc11S5w)
> **既然终要承受痛苦,那么尝试思考的痛总归比承受学习的苦更有意义。**
在正式开始之前,邀请你阅读「[The Key To Accelerating Your Coding Skills](http://blog.thefirehoseproject.com/posts/learn-to-code-and-be-self-reliant/)」,这篇文章将会告诉你如何快速有效地提高自己的编程能力。
## Introduction
**算法练级计划**以面试算法题目为线索,总结归纳面试涉及的算法知识点,整理LeetCode以及「剑指offer」出现的面试题目,在大量的LeetCode题目中梳理一个刷题脉络,让大家能够在有限的时间内,通过面试算法题目的练习,提高算法能力,更加有效地准备面试~
* 了解算法练级计划:[算法练级计划](https://mp.weixin.qq.com/s/6vuaECCmrxrchr5Hc11S5w)
* 在开启算法练级计划之前,需要同学们了解至少一门编程语言,我在这里推荐Java语言,Java学习参见:[Java练级攻略](https://mp.weixin.qq.com/s/i-j27vWXPS4kGmxO7i9p9w),Java学习资源参见:[Java练级资源包](https://mp.weixin.qq.com/s/BomvPTaoAV1rDI6X8yDs-w)
* 准备校招面试时,参见校招攻略:[2019秋招经验谈](https://mp.weixin.qq.com/s/iVHSbojhMSIL37K-UbM41A)
## *1*、 Data Structure and Algorithms
### 目录
[Data Structure and Algorithms](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md)
**数据结构与算法的要点总结**,包括数组、链表、栈、队列、二分查找、排序...不断更新中(每周至少更新一个知识点)...
### 正文
* [数组](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E6%95%B0%E7%BB%84)
* [链表](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E9%93%BE%E8%A1%A8)
* [栈](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E6%A0%88)
* [队列](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E9%98%9F%E5%88%97)
* [二分查找算法](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE)
* [排序算法](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E6%8E%92%E5%BA%8F)
* [设计思想](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E8%AE%BE%E8%AE%A1%E6%80%9D%E6%83%B3)
* [缓存](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md#%E7%BC%93%E5%AD%98)
## *2*、 Questions
### 目录
[Questions](https://github.com/guokaide/algorithm/blob/master/questions/questions.md)
> **Talk is cheap, show me the code.**
算法练级计划核心部分,通过coding,提高代码能力,掌握数据结构与算法。
所有问题均选自与校招面试真题,包括问答题,算法题,手撕代码题等。
大家可以点击更新列表中的**Title**列的题目,开始算法练级挑战,加油~
*ps.不断更新中(每周至少更新3个问题)*...
### 正文
#### [数组](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#%E6%95%B0%E7%BB%84)
|#|Title|Finished|
|:---:|:---|:---|
|001|[数组与泛型动态数组](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#1-%E6%95%B0%E7%BB%84%E4%B8%8E%E6%B3%9B%E5%9E%8B%E5%8A%A8%E6%80%81%E6%95%B0%E7%BB%84)|Yes|
|002|[1000万整数中查找某个数](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#2-1000%E4%B8%87%E6%95%B4%E6%95%B0%E4%B8%AD%E6%9F%A5%E6%89%BE%E6%9F%90%E4%B8%AA%E6%95%B0)|Yes|
|003|[约瑟夫问题](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#3-%E7%BA%A6%E7%91%9F%E5%A4%AB%E9%97%AE%E9%A2%98)|Yes|
#### [链表](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#%E9%93%BE%E8%A1%A8)
|#|Title|Finished|
|:---:|:---|:---|
|001|[链表与数组](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#1-%E9%93%BE%E8%A1%A8%E4%B8%8E%E6%95%B0%E7%BB%84)|Yes|
|002|[Reverse Linked List](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#2-reverse-linked-list)|Yes|
|003|[Middle of the Linked List](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#3-middle-of-the-linked-list)|Yes|
|004|[LRU Cache](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#4-lru-cache)|Yes|
|005|[Palindrome Linked List](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#5-palindrome-linked-list)|Yes|
|006|[Linked List Cycle](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#6-linked-list-cycle)|Yes|
|007|[Merge Two Sorted Lists](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#7-merge-two-sorted-lists)|Yes|
|008|[Remove Nth Node From End of List](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#8-remove-nth-node-from-end-of-list)|Yes|
#### [栈](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#%E6%A0%88)
|#|Title|Finished|
|:---:|:---|:---|
|001|[Implement Stack using Array](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#1-implement-stack-using-array)|Yes|
|002|[Implement Stack using Linked List](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#2-implement-stack-using-linked-list)|Yes|
|003|[Implement Stack using Queues](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#3-implement-stack-using-queues)|No|
|004|[Implement Queue using Stacks](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#4-implement-queue-using-stacks)|No|
|005|[Valid Parentheses](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#5-valid-parentheses)|No|
|006|[Min Stack](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#6-min-stack)|No|
|007|[Implement the Forward and Backward Functions of the Browser](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#7-implement-the-forward-and-backward-functions-of-the-browser)|No|
#### [队列](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#%E9%98%9F%E5%88%97)
|#|Title|Finished|
|:---:|:---|:---|
|001|[Implement Queue using Array](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#1-implement-queue-using-array)|Yes|
|002|[Implement Queue using Linked List](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#2-implement-queue-using-linked-list)|Yes|
|003|[Design Circular Queue](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#3-design-circular-queue)|No|
|004|[Design Circular Deque](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#4-design-circular-deque)|No|
#### [二分查找算法](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95)
|#|Title|Finished|
|:---:|:---|:---|
|001|[二分查找算法](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#1-%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95)|Yes|
|002|[二分查找算法变形问题](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#2-%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95%E5%8F%98%E5%BD%A2%E9%97%AE%E9%A2%98)|Yes|
|003|[旋转数组中的最小值](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#3-%E6%97%8B%E8%BD%AC%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E6%9C%80%E5%B0%8F%E5%80%BC)|Yes|
|004|[Sqrt(x)](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#4-sqrtx)|No|
#### [递归](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#%E9%80%92%E5%BD%92)
|#|Title|Finished|
|:---:|:---|:---|
|001|[Pow(x, n)](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#1-powx-n)|No|
## *3*、 leetcode
|#|Title|Difficulty|Solution|
|:---:|:---|:---|:---|
|876|[Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/)|Easy|[Java](https://github.com/guokaide/algorithm/tree/master/leetcode/src/middleofthelinkedlist_876)|
|234|[Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/)|Easy|[Java](https://github.com/guokaide/algorithm/tree/master/leetcode/src/palindromelinkedlist_234)|
|206|[Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/)|Easy|[Java](https://github.com/guokaide/algorithm/tree/master/leetcode/src/reverselinkedlist_206)|
|146|[LRU Cache](https://leetcode.com/problems/lru-cache/description/) |Hard|[Java](https://github.com/guokaide/algorithm/tree/master/leetcode/src/lrucache_146)|
|141|[Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/)|Easy|[Java](https://github.com/guokaide/algorithm/tree/master/leetcode/src/linkedlistcycle_141)|
|021|[Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/)|Easy|[Java](https://github.com/guokaide/algorithm/tree/master/leetcode/src/mergetwosortedlist_21)|
|019|[Remove Nth Node From End of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list/)|Medium|[Java](https://github.com/guokaide/algorithm/tree/master/leetcode/src/removenthnodefromendoflist_19)|
## *4*、 剑指offer
* [「剑指offer题解」(Java版)](https://github.com/guokaide/algorithm/blob/master/solutions/%E5%89%91%E6%8C%87offer%20%E9%A2%98%E8%A7%A3.md)
「剑指offer」的Java版本题解,不断更新中...
* 更新列表
|#|Title|Solution|
|:---:|:---|:---|
|002|[实现单例模式](https://github.com/guokaide/algorithm/blob/master/solutions/%E5%89%91%E6%8C%87offer%20%E9%A2%98%E8%A7%A3.md#2-%E5%AE%9E%E7%8E%B0%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F)|[Java](https://github.com/guokaide/algorithm/tree/master/offer/src/com/ex/singleton)|
|003|[数组中重复的数字](https://github.com/guokaide/algorithm/blob/master/solutions/%E5%89%91%E6%8C%87offer%20%E9%A2%98%E8%A7%A3.md#3-%E6%95%B0%E7%BB%84%E4%B8%AD%E9%87%8D%E5%A4%8D%E7%9A%84%E6%95%B0%E5%AD%97)|[Java](https://github.com/guokaide/algorithm/blob/master/offer/src/com/ex/offer/Ex_03_FindDuplicatedNumInArray.java)|
## Appendix
#### 1. 如何进行代码测试?
* [题目:二分查找算法](https://github.com/guokaide/algorithm/blob/master/questions/questions.md#1-%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95)
* [测试:二分查找算法测试示例](https://github.com/guokaide/algorithm/blob/master/algorithms/src/array/BinarySearchTest.java)
#### 2.刷题笔记
* [戳我](../master/appendix/刷题笔记.md)
## 欢迎大家关注我的公众号: 【算法修炼笔记】
主要分享校招笔试面试经验、数据结构与算法、计算机网络、操作系统、数据库以及法律知识等,完成从码农到工程师的进阶之路~

================================================
FILE: algorithms/src/array/BinarySearch.java
================================================
package array;
public class BinarySearch {
// 最简单的二分查找算法:针对有序无重复元素数组
// 迭代
public static int binarySearch(int[] array, int target) {
if (array == null) return -1;
int lo = 0;
int hi = array.length-1; // 始终在[lo, hi]范围内查找target
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1); // 这里若是 (lo + hi) / 2 有可能造成整型溢出
if (array[mid] > target) {
hi = mid - 1;
} else if (array[mid] < target) {
lo = mid + 1;
} else {
return mid;
}
}
return -1;
}
// 递归
public static int binarySearchRecur(int[] array, int target) {
if (array == null) return -1;
return bs(array, target, 0, array.length-1);
}
private static int bs(int[] array, int target, int lo, int hi) {
if (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
if (array[mid] > target) {
return bs(array, target, lo, mid-1);
} else if (array[mid] < target) {
return bs(array, target, mid+1, hi);
} else {
return mid;
}
}
return -1;
}
// 二分查找变形问题
// 1. 查找第一个值等于给定值的元素
public static int bsFirst(int[] array, int target) {
int lo = 0;
int hi = array.length - 1;
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
if (array[mid] > target) {
hi = mid - 1;
} else if (array[mid] < target) {
lo = mid + 1;
} else {
if (mid == lo || array[mid-1] != array[mid]) {
return mid;
} else {
hi = mid - 1;
}
}
}
return -1;
}
// 2. 查找最后一个值等于给定值的元素
public static int bsLast(int[] array, int target) {
int lo = 0;
int hi = array.length - 1;
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
if (array[mid] > target) {
hi = mid - 1;
} else if (array[mid] < target) {
lo = mid + 1;
} else {
if (mid == hi || array[mid] != array[mid+1]) {
return mid;
} else {
lo = mid + 1;
}
}
}
return -1;
}
// 3. 查找第一个大于等于给定值的元素
public static int bsFistGE(int[] array, int target) {
int lo = 0;
int hi = array.length - 1;
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
if (array[mid] >= target) {
if (mid == 0 || array[mid-1] < target) {
return mid;
} else {
hi = mid - 1;
}
} else {
lo = mid + 1;
}
}
return -1;
}
// 4. 查找最后一个小于等于给定值的元素
public static int bsLastLE(int[] array, int target) {
int lo = 0;
int hi = array.length - 1;
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
if (array[mid] <= target) {
if (mid == hi || array[mid+1] > target) {
return mid;
} else {
lo = mid + 1;
}
} else {
hi = mid - 1;
}
}
return -1;
}
}
================================================
FILE: algorithms/src/array/BinarySearchTest.java
================================================
package array;
import org.junit.Assert;
import org.junit.Test;
public class BinarySearchTest {
// 测试示例(完备)
@Test
public void testBinarySearch() {
int notFound = -1;
int target = 6;
// 测试数组为null
int[] arr = null;
Assert.assertEquals(notFound, BinarySearch.binarySearch(arr, target));
// 测试数组为空
int[] arr1 = new int[0];
Assert.assertEquals(notFound, BinarySearch.binarySearch(arr1, target));
// 功能测试
int[] arr2 = new int[] {3,4,5,6,8,9,12,20,25};
// 功能测试:not Found
int target1 = 30;
Assert.assertEquals(notFound, BinarySearch.binarySearch(arr2, target1));
// 功能测试:Found
int target2 = 5;
int expected = 2;
Assert.assertEquals(expected, BinarySearch.binarySearch(arr2, target2));
}
@Test
public void testBinarySearchRecur() {
int notFound = -1;
int target = 6;
// 测试数组为null
int[] arr = null;
Assert.assertEquals(notFound, BinarySearch.binarySearchRecur(arr, target));
// 测试数组为空
int[] arr1 = new int[0];
Assert.assertEquals(notFound, BinarySearch.binarySearchRecur(arr1, target));
// 功能测试
int[] arr2 = new int[] {3,4,5,6,8,9,12,20,25};
// 功能测试:not Found
int target1 = 30;
Assert.assertEquals(notFound, BinarySearch.binarySearchRecur(arr2, target1));
// 功能测试:Found
int target2 = 5;
int expected = 2;
Assert.assertEquals(expected, BinarySearch.binarySearchRecur(arr2, target2));
}
// 以下只进行功能测试
@Test
public void testBsFirst() {
int[] arr = new int[] {3,4,5,5,5,6,8,9,12,20,25};
int target = 5;
int expected = 2;
Assert.assertEquals(expected, BinarySearch.bsFirst(arr, target));
int target1 = 6;
int expected1 = 5;
Assert.assertEquals(expected1, BinarySearch.bsFirst(arr, target1));
int target2 = 30;
int expected2 = -1;
Assert.assertEquals(expected2, BinarySearch.bsFirst(arr, target2));
}
@Test
public void testBsLast() {
int[] arr = new int[] {3,4,5,5,5,6,8,9,12,20,25};
int target = 5;
int expected = 4;
Assert.assertEquals(expected, BinarySearch.bsLast(arr, target));
int target1 = 6;
int expected1 = 5;
Assert.assertEquals(expected1, BinarySearch.bsLast(arr, target1));
int target2 = 30;
int expected2 = -1;
Assert.assertEquals(expected2, BinarySearch.bsLast(arr, target2));
}
@Test
public void testBsFirstGE() {
int[] arr = new int[] {3,4,5,5,5,6,8,9,12,20,25};
int target = 5;
int expected = 2;
Assert.assertEquals(expected, BinarySearch.bsFistGE(arr, target));
int target1 = 7;
int expected1 = 6;
Assert.assertEquals(expected1, BinarySearch.bsFistGE(arr, target1));
int target2 = 30;
int expected2 = -1;
Assert.assertEquals(expected2, BinarySearch.bsFistGE(arr, target2));
}
@Test
public void testBsLastLE() {
int[] arr = new int[] {3,4,5,5,5,6,8,9,12,20,25};
int target = 5;
int expected = 4;
Assert.assertEquals(expected, BinarySearch.bsLastLE(arr, target));
int target1 = 7;
int expected1 = 5;
Assert.assertEquals(expected1, BinarySearch.bsLastLE(arr, target1));
int target2 = -2;
int expected2 = -1;
Assert.assertEquals(expected2, BinarySearch.bsLastLE(arr, target2));
}
}
================================================
FILE: algorithms/src/array/GenericArray.java
================================================
package array;
/**
* 泛型动态数组
*
* @param <T>
*
*/
public class GenericArray<T> {
private T[] data;
private int size; //数组当前元素个数,保证其可用范围为[0, size]
// 根据传入容量,构造Array
public GenericArray(int capacity) {
this.data = (T[]) new Object[capacity];
this.size = 0;
}
// 无参构造方法,默认数组容量为10
public GenericArray() {
this(10);
}
// 获取数组容量
public int getCapacity() {
return data.length;
}
// 获取当前数组元素个数
public int getSize() {
return size;
}
// 判断数组是否为空
public boolean isEmpty() {
return size == 0;
}
// 修改 index 位置的元素
public void set(int index, T e) {
checkIndex(index);
data[index] = e;
}
// 获取对应 index 位置的元素
public T get(int index) {
checkIndex(index);
return data[index];
}
// 查看数组是否包含元素e
public boolean contains(T e) {
for (int i = 0; i < size; i++) {
if (data[i].equals(e)) { // 注意这里
return true;
}
}
return false;
}
// 获取对应元素的下标, 未找到,返回 -1
public int find(T e) {
for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return i;
}
}
return -1;
}
// 在 index 位置,插入元素e, 时间复杂度 O(m+n)
public void add(int index, T e) {
checkIndex(index);
if (size == data.length) {
resize(2 * size);
}
for (int i = size - 1; i >= index; i++) {
data[i+1] = data[i];
}
data[index] = e;
size++;
}
// 向数组头插入元素
public void addFirst(T e) {
add(0, e);
}
// 向数组尾插入元素
public void addLast(T e) {
add(size, e);
}
// 删除 index 位置的元素,并返回
public T remove(int index) {
checkIndexForRemove(index);
T ret = data[index];
for (int i = index; i < size; i++) {
data[i] = data[i+1];
}
size--;
// 缩小容量
if (size == data.length / 4 && data.length / 2 != 0) {
resize(data.length / 2);
}
return ret;
}
// 删除第一个元素
public T removeFirst() {
return remove(0);
}
// 删除末尾元素
public T removeLast() {
return remove(size-1);
}
// 从数组中删除指定元素
public void removeElement(T e) {
int index = find(e);
if (index != -1) {
remove(index);
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(String.format("Array size = %d, capacity = %d \n", size, data.length));
builder.append('[');
for (int i = 0; i < size; i++) {
builder.append(data[i]);
if (i != size - 1) {
builder.append(", ");
}
}
builder.append(']');
return builder.toString();
}
// 扩容方法,时间复杂度 O(n)
private void resize(int capacity) {
T[] temp = (T[]) new Object[capacity];
for (int i = 0; i < data.length; i++) {
temp[i] = data[i];
}
data = temp;
}
private void checkIndex(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("Add failed! Require index >= 0 and index <= size.");
}
}
private void checkIndexForRemove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("Remove failed! Require index >= 0 and index < size.");
}
}
}
================================================
FILE: algorithms/src/array/MinNumberInRotatedArray.java
================================================
package array;
public class MinNumberInRotatedArray {
public static int getMinNumber(int[] arr) {
if (arr == null || arr.length < 1) {
throw new IllegalArgumentException("Invalid Array!");
}
// 循环不变条件 [左侧递增数组 | 右侧递增数组]
int l = 0; // l始终指向左侧递增数组
int r = arr.length-1; // r始终指向右侧递增数组
while (arr[l] >= arr[r]) {
if (r - l == 1) {
return arr[r];
}
int mid = l + ((r-l) >> 1);
// 若 arr[l] == arr[r] && arr[l] == arr[mid],
// arr[mid]无法判定属于左侧递增数组还是右侧递增数组,因此只能顺序查找
if (arr[l] == arr[r] && arr[l] == arr[mid]) {
return getMinInOrder(arr, l, r);
}
if (arr[mid] >= arr[l]) {
l = mid;
} else if (arr[mid] <= arr[r]) {
r = mid;
}
}
return arr[l]; // 若数组是已经排序的数组(从小到大),min = arr[l]。
}
private static int getMinInOrder(int[] arr, int l, int r) {
int min = arr[l];
for (int i = l+1 ; i <= r; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
}
================================================
FILE: algorithms/src/array/MinNumberInRotatedArrayTest.java
================================================
package array;
import org.junit.Assert;
import org.junit.Test;
public class MinNumberInRotatedArrayTest {
@Test
public void testGetMinNumber() {
int[] arr = new int[] {3,4,5,1,2};
int expected = 1;
Assert.assertEquals(expected, MinNumberInRotatedArray.getMinNumber(arr));
int[] arr1 = new int[] {1,2,3,4,5};
Assert.assertEquals(expected, MinNumberInRotatedArray.getMinNumber(arr1));
int[] arr2 = new int[] {1,0,1,1,1};
int expected1 = 0;
Assert.assertEquals(expected1, MinNumberInRotatedArray.getMinNumber(arr2));
int[] arr3 = new int[] {1,1,1,0,1};
Assert.assertEquals(expected1, MinNumberInRotatedArray.getMinNumber(arr3));
}
}
================================================
FILE: algorithms/src/joseph/Joseph.java
================================================
package joseph;
/**
* Joseph Question
*
* Solution: 圆圈长度为n时的解f(n,m)可以看成是圆圈长度为n-1时的解f(n-1,m)加m。
* 但是因为是循环的(圆圈),因此需要对相应的长度取余。
* f(n,m) = (f(n-1,m) + m) % n n > 1
* f(n,m) = 0 n = 1
*
* 如:要解决n = 5, m = 3的情形:
* n = 1: 0 0
* n = 2: 0,1 (0+3)%2 = 1;
* n = 3: 0,1,2 (1+3)%3 = 1;
* n = 4: 0,1,2,3 (1+3)%4 = 0;
* n = 5: 0,1,2,3,4 (0+3)%5 = 3;
*/
public class Joseph {
public int lastRemain(int n, int m) {
if (n < 1 || m < 1) {
return -1;
}
if (n == 1) {
return 0;
}
return (lastRemain(n-1, m) + m) % n;
}
public int lastRemainIter(int n, int m) {
if (n < 1 || m < 1) {
return -1;
}
int last = 0;
for (int i = 2; i <= n; i++) {
last = (last + m) % i;
}
return last;
}
}
================================================
FILE: algorithms/src/linkedlist/FindMidNode.java
================================================
package linkedlist;
public class FindMidNode {
// 1. T(n) = O(2*n) 遍历2次
public static Node findMidNode(Node head) {
if (head == null) {
return null;
}
int len = 0;
Node p = head;
while(p != null) {
len++;
p = p.next;
}
p = head;
for (int i = 0; i < len/2; i++) {
p = p.next;
}
return p;
}
// 2. T(n) = O(n) 遍历1次
// 快慢指针法
public static Node findMidNodeFast(Node head) {
if (head == null) {
return null;
}
Node fast = head;
Node slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
public static Node createNode(int value) {
return new Node(value, null);
}
public static class Node {
public int data;
public Node next;
public Node(int data, Node next) {
this.data = data;
this.next = next;
}
}
}
================================================
FILE: algorithms/src/linkedlist/FindMidNodeTest.java
================================================
package linkedlist;
import org.junit.Assert;
import org.junit.Test;
public class FindMidNodeTest {
@Test
public void testFindMidNode() {
FindMidNode.Node head = FindMidNode.createNode(0);
head.next = FindMidNode.createNode(1);
head.next.next = FindMidNode.createNode(2);
head.next.next.next = FindMidNode.createNode(3);
head.next.next.next.next = FindMidNode.createNode(4); //[0,1,2,3,4]
FindMidNode.Node node1 = FindMidNode.findMidNode(head);
head.next.next.next.next.next = FindMidNode.createNode(5); //[0,1,2,3,4,5]
FindMidNode.Node node2 = FindMidNode.findMidNode(head);
int expected1 = 2;
int expected2 = 3;
Assert.assertEquals(expected1, node1.data);
Assert.assertEquals(expected2, node2.data);
}
@Test
public void testFindMidNodeFast() {
FindMidNode.Node head = FindMidNode.createNode(0);
head.next = FindMidNode.createNode(1);
head.next.next = FindMidNode.createNode(2);
head.next.next.next = FindMidNode.createNode(3);
head.next.next.next.next = FindMidNode.createNode(4); //[0,1,2,3,4]
FindMidNode.Node node1 = FindMidNode.findMidNodeFast(head);
head.next.next.next.next.next = FindMidNode.createNode(5); //[0,1,2,3,4,5]
FindMidNode.Node node2 = FindMidNode.findMidNodeFast(head);
int expected1 = 2;
int expected2 = 3;
Assert.assertEquals(expected1, node1.data);
Assert.assertEquals(expected2, node2.data);
}
}
================================================
FILE: algorithms/src/linkedlist/SingleLinkedList.java
================================================
package linkedlist;
public class SingleLinkedList {
private Node head = null;
// 1. search
public Node findByValue(int value) {
if (head == null) {
return null;
}
for (Node p = head; p != null; p = p.next) {
if (p.data == value) return p;
}
return null;
}
public Node findByIndex(int index) {
if (head == null || index < 0) {
return null;
}
int temp = 0;
for (Node p = head; p != null; p = p.next) {
if (temp == index) return p;
temp++;
}
return null;
}
// 2. Insert
public void insertToHead(int value) {
Node newNode = createNode(value);
insertToHead(newNode);
}
public void insertToHead(Node newNode) {
if (newNode == null) {
return;
}
newNode.next = head;
head = newNode;
}
public void insertToTail(int value) {
Node newNode = createNode(value);
insertToTail(newNode);
}
public void insertToTail(Node newNode) {
if (newNode == null) {
return;
}
if (head == null) {
head = newNode;
return;
}
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
}
public void insertAfter(Node p, int value) {
Node newNode = createNode(value);
insertAfter(p, newNode);
}
public void insertAfter(Node p, Node newNode) {
if (p == null || newNode == null) {
return;
}
newNode.next = p.next;
p.next = newNode;
}
public void insertBefore(Node p, int value) {
Node newNode = createNode(value);
insertBefore(p, newNode);
}
public void insertBefore(Node p, Node newNode) {
if (p == null || newNode == null) {
return;
}
if (p == head) {
insertToHead(newNode);
return;
}
Node before = head;
while (before.next != p) {
before = before.next;
}
if (before == null) {
return;
} else {
newNode.next = p;
before.next = newNode;
}
}
// 3. delete
public void deleteByNode(Node p) {
if (head == null || p == null) {
return;
}
if (p == head) {
head = head.next;
return;
}
Node before = head;
while (before.next != p) {
before = before.next;
}
if (before == null) {
return;
} else {
before.next = p.next;
}
}
public void deleteByValue(int value) {
Node before = null;
for (Node p = head; p != null; p = p.next) {
if (p.getData() == value) {
if (p == head) {
head = head.next;
p = head;
} else {
before.next = p.next;
p = before;
}
}
before = p;
}
}
public void printAll() {
System.out.print("SingleLinkedList: [");
for (Node p = head; p != null; p = p.next) {
System.out.print(p.getData());
if (p.next != null) {
System.out.print(",");
}
}
System.out.print("]");
System.out.println();
}
public static Node createNode(int value) {
return new Node(value, null);
}
public static class Node {
private int data;
private Node next;
public Node(int data, Node next) {
this.data = data;
this.next = next;
}
public int getData() {
return data;
}
}
}
================================================
FILE: algorithms/src/linkedlist/SingleLinkedListTest.java
================================================
package linkedlist;
import org.junit.Test;
public class SingleLinkedListTest {
@Test
public void testSingleLinkedList() {
SingleLinkedList list = new SingleLinkedList(); //[]
list.insertToTail(2);
list.insertToTail(3);
list.insertToTail(4); // [2,3,4]
list.printAll();
list.insertToHead(1);
list.insertToHead(0); // [0,1,2,3,4]
list.printAll();
SingleLinkedList.Node node = list.findByIndex(2);
list.insertBefore(node, 10);
list.insertAfter(node, 10); // [0,1,10,2,10,3,4]
list.printAll();
list.deleteByValue(10);
list.printAll(); // [0,1,2,3,4]
SingleLinkedList.Node p = list.findByValue(2);
System.out.println(node.getData() == p.getData()); // true
}
}
================================================
FILE: algorithms/src/lru/LRU.java
================================================
package lru;
import java.util.HashMap;
import java.util.Iterator;
/**
* LRU Cache: 优先淘汰最久未使用的数据
* Solution: 双向链表+HashMap
* 1. 访问某个节点时,将其从原来的位置删除,并且重新插入到链表头部(保证链表尾部存储最近最久未使用的节点)。当节点数量大于缓存的
* 最大空间时,就淘汰链表尾部的节点。使用双端链表是为了保证删除操作时间复杂度为O(1)。
* 2. 为了使得删除操作的时间复杂度是O(1),就不能使用遍历的方式找到某个节点。HashMap存储的是Key到节点的映射,通过Key就能够以O(1)
* 的时间得到节点,然后再以O(1)的时间将其从双向队列中删除。
* 具体步骤:
* 1. get():
* 访问某个节点时,若这个节点不存在,返回null;
* 若这个节点存在,则将该节点从该位置删除,然后插入到链表头部,最后返回该节点的值。
* 2. put():
* 插入节点时,若这个节点存在,则将这个节点从原位置删除,然后插入到链表头部。
* 若这个节点不存在,则新建一个节点,然后将这个节点插入链表头部,然后将该节点插入到map中
* 此时,若map中节点的数量大于cache的容量,则将该链表尾部节点删除,同时在map中删除链表尾部节点。
*
* Example:
* head <-> 1,1 <-> 2,2 <-> 3,3 <-> tail;
* put(2,2): head <-> 2,2 <-> 1,1 <-> 3,3 <-> tail;
* get(3): head <-> 3,3 <-> 2,2 <-> 1,1 <-> tail;
*
* @param <K>
* @param <V>
*/
public class LRU<K,V> implements Iterable<K> {
private Node head;
private Node tail;
private HashMap<K, Node> map;
private int maxSize;
private class Node {
Node pre;
Node next;
K k;
V v;
public Node(K k, V v) {
this.k = k;
this.v = v;
}
}
public LRU(int maxSize) {
this.maxSize = maxSize;
this.map = new HashMap<>(maxSize * 4 / 3);
head = new Node(null, null);
tail = new Node(null, null);
head.next = tail;
tail.pre = head;
}
// O(1)
public V get(K key) {
if (!map.containsKey(key)) {
return null;
}
Node node = map.get(key);
unlink(node);
appendToHead(node);
return node.v;
}
// O(1)
public void put(K key, V value) {
if (map.containsKey(key)) {
Node node = map.get(key);
unlink(node);
}
Node node = new Node(key, value);
appendToHead(node);
map.put(key, node);
if (map.size() > maxSize) {
Node toRemove = removeTail();
map.remove(toRemove.k);
}
}
private Node removeTail() {
Node node = tail.pre;
Node pre = node.pre;
tail.pre = pre;
pre.next = tail;
node.next = null;
node.pre = null;
return node;
}
private void appendToHead(Node node) {
Node next = head.next;
node.next = next;
node.pre = head;
next.pre = node;
head.next = node;
}
private void unlink(Node node) {
Node pre = node.pre;
Node next = node.next;
pre.next = next;
next.pre = pre;
node.pre = null;
node.next = null;
}
@Override
public Iterator<K> iterator() {
return new LRUIterator<>();
}
private class LRUIterator<K> implements Iterator<K> {
private Node cur = head.next;
@Override
public boolean hasNext() {
return cur != tail;
}
@Override
public K next() {
Node node = cur;
cur = cur.next;
return (K) node.k;
}
}
}
================================================
FILE: algorithms/src/lru/LRUTest.java
================================================
package lru;
import org.junit.Assert;
import org.junit.Test;
public class LRUTest {
@Test
public void testLRU() {
LRU<Integer, Integer> lru = new LRU<>(5);
Assert.assertEquals(null, lru.get(1));
lru.put(1,1);
Assert.assertEquals(Integer.valueOf(1), lru.get(1));
lru.put(2,2);
lru.put(3,3);
lru.put(4,4);
lru.put(5,5);
for (Integer integer : lru) {
System.out.print(integer + " ");
}
System.out.println();
Assert.assertEquals(Integer.valueOf(2), lru.get(2));
for (Integer integer : lru) {
System.out.print(integer + " ");
}
System.out.println();
lru.put(6,6);
for (Integer integer : lru) {
System.out.print(integer + " ");
}
}
}
================================================
FILE: algorithms/src/queue/ArrayQueue.java
================================================
package queue;
public class ArrayQueue<T> implements Queue<T> {
private T[] items;
private int capacity;
private int head;
private int tail;
public ArrayQueue(int capacity) {
this.capacity = capacity;
this.items = (T[]) new Object[capacity];
this.head = 0;
this.tail = 0;
}
// T(N)=O(1)
@Override
public boolean enqueue(T item) {
if (tail == capacity) {
// head == 0 && tail == capacity, queue is full.
if (head == 0) {
return false;
}
// 数据搬移,空出位置
for (int i = head; i < tail; i++) {
items[i-head] = items[i];
}
// 搬移完之后,更新head和tail
tail -= head;
head = 0;
}
items[tail] = item;
tail++;
return true;
}
// T(N)=O(1)
@Override
public T dequeue() {
if (head == tail) {
return null;
}
T tmp = items[head];
head++;
return tmp;
}
// for test
public void printAll() {
System.out.print("[");
for (int i = head; i < tail; i++) {
System.out.print(items[i] + " ");
}
System.out.print("]");
System.out.println();
}
public static void main(String[] args) {
ArrayQueue<String> queue = new ArrayQueue<>(4);
queue.printAll();
queue.enqueue("A");
queue.printAll();
queue.enqueue("B");
queue.enqueue("C");
queue.enqueue("D");
queue.printAll();
queue.enqueue("E");
queue.printAll();
queue.dequeue();
queue.dequeue();
queue.dequeue();
queue.printAll();
}
}
================================================
FILE: algorithms/src/queue/CircularQueue.java
================================================
package queue;
public class CircularQueue<T> {
private T[] items;
private int capacity;
private int head;
private int tail;
public CircularQueue(int capacity) {
this.capacity = capacity;
this.items = (T[]) new Object[capacity];
this.head = 0;
this.tail = 0;
}
// T(N)=O(1)
public boolean enqueue(T item) {
// 队满条件
if ((tail + 1) % capacity == head) {
return false;
}
items[tail] = item;
tail = (tail + 1) % capacity;
return true;
}
// T(N)=O(1)
public T dequeue() {
// 队空条件
if (head == tail) {
return null;
}
T tmp = items[head];
items[head] = null; // 这里可以选择置为nulL,也可以不置为null.
head = (head + 1) % capacity;
return tmp;
}
// for test
public void printAll() {
System.out.print("[");
for (int i = 0; i < capacity; i++) {
System.out.print(items[i] + " ");
}
System.out.print("]");
System.out.println();
}
public static void main(String[] args) {
CircularQueue<java.lang.String> queue = new CircularQueue<>(4);
queue.printAll();
queue.enqueue("A");
queue.printAll();
queue.enqueue("B");
queue.enqueue("C");
queue.enqueue("D");
queue.printAll();
queue.enqueue("E");
queue.printAll();
queue.dequeue();
queue.dequeue();
queue.enqueue("E");
queue.printAll();
}
}
================================================
FILE: algorithms/src/queue/ListQueue.java
================================================
package queue;
public class ListQueue<T> implements Queue<T> {
Node head = null;
Node tail = null;
// T(N)=O(1)
@Override
public boolean enqueue(T item) {
Node newNode = new Node(item, null);
if (tail == null) {
tail = newNode;
head = newNode;
return true;
}
tail.next = newNode;
tail = tail.next;
return true;
}
// T(N)=O(1)
@Override
public T dequeue() {
if (head == null) {
return null;
}
Node tmp = head;
head = head.next;
tmp.next = null;
return (T) tmp.getData();
}
// for test
public void printAll() {
System.out.print("[");
for (Node p = head; p != null; p = p.next) {
System.out.print(p.getData() + " ");
}
System.out.print("]");
System.out.println();
}
private static class Node<T>{
private T data;
private Node next;
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
public T getData() {
return this.data;
}
}
public static void main(String[] args) {
ListQueue<String> queue = new ListQueue<>();
queue.printAll();
queue.enqueue("A");
queue.printAll();
queue.enqueue("B");
queue.enqueue("C");
queue.enqueue("D");
queue.printAll();
queue.enqueue("E");
queue.printAll();
queue.dequeue();
queue.dequeue();
queue.dequeue();
queue.printAll();
}
}
================================================
FILE: algorithms/src/queue/Queue.java
================================================
package queue;
public interface Queue<T> {
boolean enqueue(T item);
T dequeue();
}
================================================
FILE: algorithms/src/stack/ArrayStack.java
================================================
package stack;
public class ArrayStack<T> implements Stack<T> {
private T[] items; // 数组
private int top; // 栈中元素的个数(或者说是栈顶指针)
private int capacity; // 栈的容量
public ArrayStack(int capacity) {
this.capacity = capacity;
this.items = (T[]) new Object[capacity];
this.top = 0;
}
// T(N)=O(1)
@Override
public boolean push(T item) {
// 数组空间不足,无法push
if (top == capacity) {
return false;
}
// size为待push的位置
items[top] = item;
top++;
return true;
}
// T(N)=O(1)
@Override
public T pop() {
// 数组为空,无法pop
if (top == 0) {
return null;
}
T item = items[top -1];
top--;
return item;
}
// T(N)=O(1)
@Override
public T peek() {
if (top == 0) {
return null;
}
return items[top -1];
}
public static void main(String[] args) {
ArrayStack<String> stack = new ArrayStack<>(4);
stack.push("A");
stack.push("B");
stack.push("C");
stack.push("D");
System.out.println(stack.peek());
stack.pop();
System.out.println(stack.peek());
stack.pop();
stack.pop();
stack.pop();
stack.pop();
System.out.println(stack.peek());
}
}
================================================
FILE: algorithms/src/stack/DynamicArrayStack.java
================================================
package stack;
/**
* 支持动态扩容的栈
*
* @param <T>
*/
public class DynamicArrayStack<T> implements Stack<T> {
private T[] items;
private int top;
private int capacity;
public DynamicArrayStack(int capacity) {
this.capacity = capacity;
this.items = (T[]) new Object[capacity];
this.top = 0;
}
// T(N)=O(1): 思考一下,这里涉及到了数组的动态扩容,
// 那么时间复杂度为什么仍然是O(1)
@Override
public boolean push(T item) {
if (top == capacity) {
capacity = capacity * 2;
resize(capacity);
}
items[top] = item;
top++;
return false;
}
// T(N)=O(1)
@Override
public T pop() {
if (top == 0) {
return null;
}
T item = items[top -1];
top--;
return item;
}
// T(N)=O(1)
@Override
public T peek() {
if (top == 0) {
return null;
}
return items[top -1];
}
private void resize(int size) {
T[] tmp = (T[]) new Object[size];
for (int i = 0; i < items.length; i++) {
tmp[i] = this.items[i];
}
this.items = tmp;
}
public static void main(String[] args) {
DynamicArrayStack<String> stack = new DynamicArrayStack<>(4);
stack.push("A");
stack.push("B");
stack.push("C");
stack.push("D");
System.out.println(stack.peek());
stack.push("E");
System.out.println(stack.peek());
stack.pop();
System.out.println(stack.peek());
stack.pop();
stack.pop();
stack.pop();
stack.pop();
System.out.println(stack.peek());
}
}
================================================
FILE: algorithms/src/stack/ListStack.java
================================================
package stack;
public class ListStack<T> implements Stack<T> {
private Node top = null;
// T(N)=O(1)
@Override
public boolean push(T item) {
Node newNode = new Node(item, null);
// 需要判断栈是否为空
if (top == null) {
top = newNode;
} else {
newNode.next = top;
top = newNode;
}
return true;
}
// T(N)=O(1)
@Override
public T pop() {
if (top == null) {
return null;
}
Node tmp = top;
top = top.next;
tmp.next = null; // 释放删除的top
return (T) tmp.getData();
}
// T(N)=O(1)
@Override
public T peek() {
if (top == null) {
return null;
}
return (T) top.getData();
}
public static class Node<T> {
private T data;
private Node next;
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
public T getData() {
return this.data;
}
}
public static void main(String[] args) {
ListStack<String> stack = new ListStack<>();
stack.push("A");
stack.push("B");
stack.push("C");
stack.push("D");
System.out.println(stack.peek());
stack.pop();
System.out.println(stack.peek());
stack.pop();
stack.pop();
stack.pop();
stack.pop();
System.out.println(stack.peek());
}
}
================================================
FILE: algorithms/src/stack/SampleBrowser.java
================================================
package stack;
/**
* 浏览器页面的前进和后退功能
*/
public class SampleBrowser {
private String currentPage;
// private Stack backwardStack;
private Stac
}
================================================
FILE: algorithms/src/stack/Stack.java
================================================
package stack;
public interface Stack<T> {
boolean push(T item);
T pop();
T peek();
}
================================================
FILE: appendix/instructions.md
================================================
# 上传与更新本地代码到Github
1. 远程操作:
* Github上创建Repo
2. 本地操作:
* git clone https://github.com/guokaide/leetcode
* cd leetcode
* git init
* git add .
* git remote add origin https://github.com/guokaide/leetcode (将本地仓库与远程关联)
* git commit -m "update all files"
* git pull origin master (将remote所有的操作更新到本地,避免local与remote冲突)
* git push -u origin master
3. 注:核心更新操作
* git status
* git add *
* git commit -m "comments"
* git pull origin master
* git push origin master
================================================
FILE: appendix/刷题笔记.md
================================================
# 刷题笔记
> It does not matter how slowly you go as long as you do not stop.
## 如何有效学习数据结构与算法?
### 如何精通一个领域?
* Chunk it up 切碎知识点
将数据结构与算法的基本知识点分解开来,分解结果见:[数据结构与算法脑图]( http://naotu.baidu.com/file/cd094852bfc84ec5e1868867936451c3?token=ef906723267f2f9f )
* Deliberate Practicing 刻意练习
对分解之后的知识点进行分解训练和反复练习。
* 明白一个`原则`:基本功是区别业余和职业选手的根本,我们的目标是成为职业选手。
* 明白一个`误区`:**刷一道算法题,刷一遍是完全不够的,需要一遍遍刷题**。
* 明白一个`事实`:反复练习自己薄弱的地方,扩张舒适区,会让我们成长更快。
* Feedback 反馈
反馈对于学习的作用,主要是将揉碎的知识点再串联起来,形成体系结构,这样就建立了一个 `知识点-> 专项反复练习-> 建立知识体系`的学习闭环。
* 即时反馈
* 主动型反馈(自己去找)
* 高手代码,例如 Github,LeetCode(题解、Discussion)
* 第一视角直播
* 被动式反馈(高手指点)
* Code Review
* 教练看你打,然后给你反馈
### 如何精通数据结构与算法呢?
> 如何反复刷题呢?答案是:五步刷题法,我们称为***五毒神掌***。
1. 刷题第***1***遍
* 5分钟时间:读题+思考
* 若5分钟思考不出来,直接看解法,要注意:**对每一道题目,思考和比较这个题的多种解法,最好是全部解法**
* **背诵、默写好的解法**:这是积累代码能力的一个很好的办法。
2. 刷题第***2***遍
* 马上自己写 -> LeetCode提交
* **多种解法进行比较、体会 -> 优化**
3. 刷题第***3***遍
* **一天后**,再重复做题
* 针对不同解法的熟练程度 -> 对薄弱的地方进行专项练习
4. 刷题第***4***遍
* **一周后**,反复回来练习相同的题目
5. 刷题第***5***遍
* **面试前一周**进行恢复性训练。
> 如何刷一道题呢? 答案是:**切题四件套**。
1. Clarification: 多沟通,多思考,确保正确理解问题 ***(面试的时候,和面试官过一遍题目)***
2. Possible solutions: 思考关于这个题目的所有解法,比较其优劣,优化其性能
* compare(time/space)
* optimal(加强):例如空间换时间、升维(一维到二维) ***(提出多种解法,给出最优解法)***
3. Coding: 就是不停的写,多写,提高Coding能力的唯一法宝 ***(代码实现)***
4. Test cases ***(阐述测试样例)***
## 工具
### [visualgo](https://visualgo.net/zh)
### [bigocheatsheet](https://www.bigocheatsheet.com/)
## 代码模板
### 递归代码模板 Recursion
* Python
```python
def recursion(level, param1, param2, ...):
# recursion terminator
if (level > MAX_LEVEL):
# process result
return
# process logic in current level
process(level, data...)
# drill down
self.recursion(level + 1, p1, ...)
# restore current level status if needed
```
* Java
```java
public void recursion(int level, int param) {
// recursion terminator
if (level > MAX_LEVEL) {
// process result
return;
}
// process logic in current level
process(level, param);
// drill down
recursion( level: level + 1, newParam);
// restore current level status if needed
}
```
### 分治代码模板 Divide and Conquer
```python
def divide_conquer(problem, param1, param2, ...):
# recursion terminator
if problem is None:
print_result
return
# divide: prepare data
data = prepare_data(problem)
subproblems = split_problem(problem, data)
# conquer: conquer subproblems
subresult1 = self.divide_conquer(subproblems[0], p1, ...)
subresult2 = self.divide_conquer(subproblems[1], p1, ...)
subresult3 = self.divide_conquer(subproblems[2], p1, ...)
…
# merge: process and generate the final result
result = process_result(subresult1, subresult2, subresult3, …)
# restore current level states if needed
```
### 查找-搜索-遍历 模板
查找的特点是:
* 找到特定元素
搜索的特点是:
* 每个节点都要访问一次
* 每个节点仅仅访问一次
* 每个节点访问顺序不限
#### 二分查找(Binary Search)
```python
left, right = 0, len(array) - 1
while left <= right:
mid = (left + right) / 2
if array[mid] == target:
# find the target
break or return result
elif array[mid] < target:
left = mid + 1
else:
right = mid - 1
```
#### 深度优先搜索(DFS, Depth First Search)
```python
# 递归写法
visited = set()
def dfs(node, visited):
# terminator
if node in visited:
return # already visited
visited.add(node)
# process current node here
# ...
for next_node in node.children():
if next_node not in visited:
dfs(next_node, visited)
# 非递归写法
def DFS(self, tree):
if tree.root is None:
return []
visited, stack = [], [tree.root]
while stack:
node = stack.pop()
visited.add(node)
process(node)
nodes = generate_realted_nodes(node)
stack.push(nodes)
# other processing work
...
```
#### 广度优先遍历(BFS, Breadth First Search)
```python
def BFS(graph, start, end):
visited = set()
queue = []
queue.append([start])
while queue:
node = queue.pop()
visited.add(node)
process(node)
nodes = generate_related_nodes(node)
queue.push(nodes)
# other processing work
...
```
#### A*
```python
def AstarSearch(graph, start, end):
pq = collections.priority_queue() # 优先级 —> 估价函数
pq.append([start])
visited.add(start)
while pq:
node = pq.pop() # can we add more intelligence here ?
visited.add(node)
process(node)
nodes = generate_related_nodes(node)
unvisited = [node for node in nodes if node not in visited]
pq.push(unvisited)
```
### 归并排序
### Trie
#### 定义
Trie 树,也叫“字典树”。Trie 树也是一种树形结构。它是专门用来处理字符串匹配的数据结构,**用来解决一组字符串集合中快速查找某个字符串的问题**。
#### 本质
Trie 树的本质,就是利用字符串之间的公共前缀,将重复的前缀合并在一起,组成一颗多个字符串共用前缀的树。这种存储方式避免了重复存储一组字符串的相同前缀子串。
#### 实现
##### API
* void insert(char[] text) // 插入字符串
* boolean search(char[] pattern) // 查找字符串
* boolean startsWith(String prefix) // 查找前缀
##### 代码
假设字符串由a~z这26个小写字母构成,数组下标为0的位置存储指向子节点a的的指针,下标为1的位置存储指向子节点b的指针,以此类推,下标为25的位置存储指向子节点z的指针。如果某个子节点不存在,则对应下边位置处存储为null。
```java
public class TrieNode {
public char data;
public TrieNode[] children = new TrieNode[26];
public boolean isEndingChar = false;
public TrieNode(char data) {
this.data = data;
}
}
public class Triee {
// 根节点,存储无意义字符
private TrieNode root = new TrieNode('/');
// 插入字符串
public void insert(char[] text) {
TrieNode p = root;
for (int i = 0; i < text.length; ++i) {
int index = text[i] - 'a';
if (p.children[index] == null) {
TrieNode newNode = new TrieNode(text[i]);
p.children[index] = newNode;
}
p = p.children[index];
}
p.isEndingChar = true;
}
// 查找字符串
public boolean search(char[] pattern) {
TrieNode p = root;
for (int i = 0; i < pattern.length; ++i) {
int index = pattern[i] - 'a';
if (p.children[index] == null) {
return false;
}
p = p.children[index];
}
if (p.isEndingChar == false) {
return false; // pattern 仅仅是前缀, 无法完全匹配
} else {
return true; // 完全匹配
}
}
}
```
```python
class Trie(object):
def __init__(self):
self.root = {}
self.end_of_word = "#"
def insert(self, word):
node = self.root
for char in word:
node = node.setdefault(char, {})
node[self.end_of_word] = self.end_of_word
def search(self, word):
node = self.root
for char in word:
if char not in node:
return False
node = node[char]
return self.end_of_word in node
def startsWith(self, prefix):
node = self.root
for char in prefix:
if char not in node:
return False
node = node[char]
return True
```
[LeetCode 208. implement-trie-prefix-tree](https://leetcode-cn.com/problems/implement-trie-prefix-tree/)
```java
class Trie {
private TrieNode root;
/** Initialize your data structure here. */
public Trie() {
this.root = new TrieNode('/');
}
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode p = root;
for (int i = 0; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (p.children[index] == null) {
TrieNode newNode = new TrieNode(word.charAt(i));
p.children[index] = newNode;
}
p = p.children[index];
}
p.isEndingChar = true;
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
TrieNode p = root;
for (int i = 0; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (p.children[index] == null) {
return false;
}
p = p.children[index];
}
if (p.isEndingChar) return true;
else return false;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TrieNode p = root;
for (int i = 0; i < prefix.length(); i++) {
int index = prefix.charAt(i) - 'a';
if (p.children[index] == null) {
return false;
}
p = p.children[index];
}
return true;
}
class TrieNode {
public char data;
public TrieNode[] children = new TrieNode[26];
public boolean isEndingChar = false;
public TrieNode(char data) {
this.data = data;
}
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/
```
#### 性能
##### 时间复杂度
如果在一组字符串中,频繁地查询某些字符串,用 Trie 树会非常高效。
构建 Trie 树的过程,需要扫描所有的字符串,因此时间复杂度为 `O(N)`,其中`N` 为所有字符串长度之和。
构建 Trie 树的过程,时间复杂度较高,但是一旦构建成功,后续查询操作会非常高效。每次查询时,若查询的字符串长度为`k`,那么我们只需要对比大约 `k`个节点,就能完成查询操作,与原来的那组字符串长度和个数都没有关系。因此,构建 Trie 树之后,查询操作的时间复杂度为 `O(k)`, 其中 `k` 表示要查找的字符串的长度。
##### 空间复杂度
从前面的实现,可以看出,Trie 树的每个节点都需要维护一个长度为26的数组,如果字符串不仅包含小写字母,而且还包含大写字母,数字以及中文等,那需要的存储空间就更多了。Trie 树本质是为了避免重复存储相同的公共前缀,但是在重复的前缀不多的情况下,Trie 树不但不能节省内存,还有可能会浪费更多的内存。
Trie 树 是一种空间换时间的实现,尽管比较耗费空间,但是查找确实高效。
#### Trie 树的应用
Trie 树解决了在一组字符串集合中查找字符串的问题,相同的问题,我们其实还可以通过散列表或者红黑树解决。
事实上,Trie 树在一组字符串中查找字符串的表现并不是很好,它对要处理的字符串有极其严苛的要求。
1. 字符串中包含的字符集不能太大。字符集太大,将会浪费很多存储空间。
2. 要求多个字符串前缀重合比较多,不然将会浪费很多存储空间。
3. 通过指针穿起来的数据块是不连续的,而 Trie 树中用到了指针,所以对缓存不友好,性能上会打折扣。
事实上,Trie 树只是不适合精确匹配查找,而且不适合用来做动态数据的查找,这种问题更加适合用散列表或者红黑树解决。 `Trie 树更加适合查找前缀匹配的字符串`,例如Google时的关键词提示功能,自动补全等功能,或者是统计单词频次等问题。
### UnionFind
```java
class UnionFind {
private int count = 0;
private int[] parent;
/* 初始化为 n 个集合*/
public UnionFind(int n) {
count = n;
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
/* 确定 q 属于哪个子集合 */
public int find(int p) {
while (p != parent[p]) {
parent[p] = parent[parent[p]];
p = parent[p];
}
return p;
}
/* 合并 p 和 q 所在的集合*/
public void union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if (rooP == rootQ) return;
parent[rootP] = rootQ;
count--;
}
}
```
```python
def init(p):
p = [i for i in range(n)]
def union(self, p, i, j):
p1 = self.parent(p, i)
p2 = self.parent(p, j)
p[p1] = p2
def parent(self, p, i):
root = i;
while p[root] != root:
root = p[root]
while p[i] != i: # 路径压缩
x = i
i = p[i]
p[x] = root
return root
```
### 八皇后问题
https://shimo.im/docs/hV9GdhcrddcDJWwv
## Dynamic Programming
> Simplifying a complicated problem by breaking it down into simpler sub-problems in a recursive manner
### 动态规划基本理论
#### 一个模型:多阶段决策最优解模型
动态规划一般用于解决最优问题。多阶段决策最优解模型是指动态规划适合解决的问题的模型。解决问题的过程需要经历多个决策过程,每个决策过程都对应着一组状态。动态规划的目标在于寻找一组决策序列(每个决策过程的状态),通过这组决策序列产生最终期望的求解的最优值。
#### 三个特征
##### 最优子结构
最优子结构是指问题的最优解包含子问题的最优解。我们可以通过子问题的最优解得到问题的最优解,也就是说,后面的状态可以通过前面的状态推导出来。
##### 无后效性
无后效性有两层含义:
* 在推导后面状态的时候,我们只关心前面阶段的状态值,而不关心这个状态值的求解过程;
* 某个阶段的状态一旦确定,就不受之后阶段的决策影响,即状态定了就定了。
##### 重复子问题
不同的决策序列,到达某个相同的阶段的时候,可能会产生重复的状态。
##### 复杂度
1、状态存在更多的维度(二维、三维或者更多,甚至需要压缩)
2、状态方程更加复杂
#### 实例
> 问题:给定一个`n * n`的矩阵` w[n][n]`,矩阵存储的均为正整数。棋子从矩阵的左上角出发去右下角,每次只能向右或者是向下移动1位。从左上角到右下角有很多不同的路径可以走。规定每条路径经过的数字之和就是这条路径的长度。求从左上角到右下角的最短路径。
##### 分析:
***这个问题是否满足`一个模型`呢?***
从 `(0, 0)` 出发到 `(n-1, n-1)`,总计`2*(n-1)`步,对应着`2*(n-1)`个阶段,每个阶段都有向右或者向下2种决策,因此每个阶段都会对应一个状态集合。问题的目标在于找到一个状态序列,从而确定 `(0, 0)` 出发到 `(n-1, n-1)`的最短距离。因此整个问题是一个`多阶段决策最优解`问题。
***这个问题是否满足`三大特征`呢?***
对于任意一个节点`(i, j)`来说,从 `(0, 0)` 出发到 `(i, j)`存在多种路线,因此可能存在`重复子问题`。
对于任意一个节点`(i, j)`来说,`(i, j)`这个位置的状态需要通过 `(i-1, j)`以及 `(i, j-1)`两个位置的状态来确定,但是并不需要关心这2个位置的状态的求解过程。而且,由于仅仅允许向右或者向下运动,因此前面阶段的状态确定了之后,不会被后面的状态所改变,因此满足`无后效性`的特征。
定义状态为:`min_dist(i, j)`,表示从 `(0, 0)` 出发到 `(i, j)`的最短距离。那么到达`(i, j)`的最短路径必然经过`(i-1, j)`或 `(i, j-1)`,因此,到达`(i, j)`的最短路径必然包含到达这2个位置的最短路径之一。因此满足 `最优子结构` 的特征。
综上所述,`min_dist(i, j) = w[i][j] + min(min_dist(i, j-1), min_dist(i-1, j))`。
##### 求解:
```java
// 回溯算法
private int min = Integer.MAX_VALUE;
public void minDist(int i, int j, int dist, int[][] w, int n) {
// terminator
if (i == n && j == n) {
if (dist < min) min = dist;
return;
}
// drill down
if (i < n) {
minDist(i + 1, j, dist + w[i][j], w, n);
}
if (j < n) {
minDist(i, j + 1, dist + w[i][j], w, n);
}
}
```
```java
// 递归+备忘录(缓存)减少重复计算
private int[][] mem = new int[n][n];
public int minDist(int i, int j, int[][] w) {
if (i == 0 && j == 0) {
return w[0][0];
}
if (mem[i][j] > 0) {
return mem[i][j];
}
int minLeft = Integer.MAX_VALUE;
if (j-1>=0 ) {
minLeft = minDist(i, j-1);
}
int minUp = Integer.MAX_VALUE;
if (i-1>= 0) {
minUp = minDist(i-1, j);
}
int curMinDist = w[i][j] + Math.min(minLeft, minUp);
mem[i][j] = curMinDist;
return curMinDist;
}
```
```java
// 动态规划
public int minDist(int[][] w, int n) {
int[][] states = new int[n][n];
int sum = 0;
for (int j = 0; j < n; j++) {
sum += w[0][j];
states[0][j] = sum;
}
sum = 0;
for (int i = 0; i < n; i++) {
sum += w[i][0];
states[i][0] = sum;
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < n; j++) {
states[i][j] = w[i][j] + Math.min(states[i][j-1], states[i-1][j]);
}
}
return states[n-1][n-1];
}
```
### 一维动态规划:Fibnacci
```java
# 递归:自顶向下 O(2^N)
int fib(int n) {
if (n <= 1) {
return n;
}
return fib(n - 1) + fib(n - 2); // 改进:return n <= 1 ? n : fib(n-1) + fib(n-2);
}
# 递归 + 备忘录 (记忆化搜索) O(N)
int fib(int n, int[] memo) {
if (n <= 1) {
return n;
}
if (memo[n] == 0) {
memo[n] = fib(n-1, memo) + fib(n-2, memo);
}
return memo[n];
}
# 动态规划:自底向上 O(N)
int fib(int n) {
int[] dp = new int[n];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
# 一维的Equation: f(n) = f(n-1) + f(n-2)
```
### 二维动态规划:Count the paths
```java
// 递归
int countPaths(boolean[][] grid, int row, int col) {
if (!validSqure(grid, row, col)) return 0;
if (isAtEnd(grid, row, col)) return 1;
return countPaths(grid, row + 1, col) + countPaths(grid, row, col+1);
}
opt[i, j] = opt[i+1, j] + opt[i, j+1];
if a[i, j] == '空地':
opt[i, j] = opt[i+1, j] + opt[i, j+1];
else:
opt[i, j] = 0;
对比:
# 一维的Equation: f(n) = f(n-1) + f(n-2)
# 二维的Equation: opt[i, j] = opt[i+1, j] + opt[i, j+1];
```
## 总结代码库(示例)
* Valid anagram
```python
# 思路:手动模拟hashtable,将字符串”a-z“的ASCII码作key,计数求差异
def isAnagram(self, s: str, t: str) -> bool:
arr1, arr2 = [0]*26, [0]*26
for i in s:
arr1[ord(i) - ord('a')] += 1
for i in t:
arr2[ord(i) - ord('a')] += 1
return arr1 == arr2
# 思路:map计数,对比计数差异
def isAnagram(self, s: str, t: str) -> bool:
dict1, dict2 = {}, {}
for item in s:
dict1[item] = dict1.get(item,0) + 1
for item in t:
dict2[item] = dict2.get(item,0) + 1
return dict1 == dict2
# 思路:数组排序后比较差异
def isAnagram(self, s: str, t: str) -> bool:
return sorted(s) == sorted(t)
```
```java
public class Solution {
public boolean isAnagram(String s, String t) {
if(s.length() != t.length()) return false;
int [] a = new int [26];
for(Character c : s.toCharArray()) a[c - 'a']++;
for(Character c : t.toCharArray()) {
if(a[c -'a'] == 0) return false;
a[c - 'a']--;
}
return true;
}
public boolean isAnagram(String s1, String s2) {
int[] freq = new int[256];
for(int i = 0; i < s1.length(); i++) freq[s1.charAt(i)]++;
for(int i = 0; i < s2.length(); i++) if(--freq[s2.charAt(i)] < 0) return false;
return s1.length() == s2.length();
}
public boolean isAnagram(String s, String t) {
char[] sChar = s.toCharArray();
char[] tChar = t.toCharArray();
Arrays.sort(sChar);
Arrays.sort(tChar);
return Arrays.equals(sChar, tChar);
}
}
```
* Group Anagrams
```python
def groupAnagrams(self, strs):
d = {}
for w in sorted(strs):
key = tuple(sorted(w))
d[key] = d.get(key, []) + [w]
return d.values()
def groupAnagrams(self, strs):
dic = {}
for item in sorted(strs):
sortedItem = ''.join(sorted(item))
dic[sortedItem] = dic.get(sortedItem, []) + [item]
return dic.values()
```
```java
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<>();
HashMap<String, List<String>> map = new HashMap<>();
Arrays.sort(strs);
for (int i = 0; i < strs.length; i++) {
String temp = strs[i];
char[] ch = temp.toCharArray();
Arrays.sort(ch);
if (map.containsKey(String.valueOf(ch))) {
map.get(String.valueOf(ch)).add(strs[i]);
} else {
List<String> each = new ArrayList<>();
each.add(strs[i]);
map.put(String.valueOf(ch), each);
}
}
for (List<String> item: map.values()) {
res.add(item);
}
return res;
}
```
* Two sum
```python
def twoSum(self, nums, target):
d = dict()
for index,num in enumerate(nums):
if d.get(num) == None:
d[target - num] = index
else:
return [d.get(num), index
```
```java
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> tracker = new HashMap<Integer, Integer>();
int len = nums.length;
for (int i = 0; i < len; i++){
if (tracker.containsKey(nums[i])){
int left = tracker.get(nums[i]);
return new int[]{left+1, i+1};
} else {
tracker.put(target - nums[i], i);
}
}
return new int[2];
}
```
## 刷题开始
### Array
#### 283. [move zeros]( https://leetcode-cn.com/problems/move-zeroes/ )
> 方法1:将所有的非零元素都填充到数组前侧,然后将0填充到数组后侧 `#双指针法`
```java
class Solution {
public void moveZeroes(int[] nums) {
int lastNotZeroIndex = 0;
for (int i = 0; i < nums.length; ++i) {
if (nums[i] != 0) {
nums[lastNotZeroIndex++] = nums[i];
}
}
for (int i = lastNotZeroIndex; i < nums.length; ++i) {
nums[i] = 0;
}
}
}
```
> 方法2:一维数组的坐标转换 i, j `#双指针法`
>
> 用 j 记录上一个可能为0的值的索引,用 i 遍历数组,当遇到不为0的值的时候,将该元素 num[i] 与 nums[j] 交换,保证 j 前面的元素均为非0值。
```java
class Solution {
public void moveZeroes(int[] nums) {
int lastZeroIndex = 0;
for (int i = 0; i < nums.length; ++i) {
if (nums[i] != 0) {
int temp = nums[i];
nums[i] = nums[lastZeroIndex];
nums[lastZeroIndex] = temp;
lastZeroIndex++;
}
}
}
}
```
#### 11. [container with most water]( https://leetcode-cn.com/problems/container-with-most-water/ )
> 思路:
>
> 1.`枚举`: left bar x, right bar y, (y - x) * min_height O(n^2) `#枚举`
```java
// 遍历数组的一个常见的办法:遍历左右边界,且左右边界不能重复
class Solution {
public int maxArea(int[] a) {
int max = 0
for (int i = 0; < a.length - 1; ++i) {
for (int j = i + 1; j < a.length; ++j) {
int area = (j - i) * Math.min(a[i], a[j]);
max = Math.max(max, area);
}
}
return max;
}
}
```
> 2.`左右夹逼/双指针法`:左右边界 i, j, 向中间收敛 `#双指针法:左右夹中间,中间到两边`
```java
// 遍历数组的一个常见的办法:遍历左右边界,且左右边界不能重复
class Solution {
public int maxArea(int[] a) {
int max = 0
for (int i = 0, j = a.length - 1; i < j; ) {
int minHeight = a[i] < a[j] ? a[i++] : a[j--];
max = Math.max(max, (j - i + 1) * minHeight);
}
return max;
}
}
```
#### 70. [climbing stairs](https://leetcode-cn.com/problems/climbing-stairs/)
```java
class Solution {
public int climbStairs(int n) {
if (n <= 2) return n;
int f1 = 1;
int f2 = 2;
int f3 = 3;
for (int i = 3; i <= n; i++) {
f3 = f1 + f2;
f1 = f2;
f2 = f1;
}
return f3;
}
}
```
#### 1. [2sum](https://leetcode-cn.com/problems/two-sum/)
> 方法1:暴力解法 O(n^2)
```java
// 遍历数组的一个常见的办法:遍历左右边界,且左右边界不能重复
class Solution {
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length - 1; ++i) {
for (int j = i + 1; j < nums.length; ++j) {
if (nums[i] + nums[j] == target) {
return new int[] {i, j};
}
}
}
return new int[2];
}
}
```
> 方法2:两遍哈希表
>
> 思想:空间换时间
>
> ***保持数组中的每个元素与其索引相互对应的最好方式是什么? 哈希表。***
>
> 哈希表查找的时间复杂度为 O(1)。
```java
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; ++i) {
map.put(target - nums[i], i);
}
for (int i = 0; i < nums.length; ++i) {
if (map.containsKey(nums[i]) && i != map.get(nums[i])) {
return new int[] {i, map.get(nums[i])};
}
}
return new int[2];
}
}
```
> 方法3:一遍哈希表
>
> 由于在遍历数组的过程中,可以回过头来查找哈希表中是否存储了目标元素的值,因此,没有必要遍历完整的数组将目标元素的值存储到哈希表中,可以边遍历边存储。
```java
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; ++i) {
int component = target - nums[i];
if (map.containsKey(component)) {
return new int[] {map.get(component), i};
}
map.put(nums[i], i);
}
return new int[2];
}
}
```
#### 15. [3sum](https://leetcode-cn.com/problems/3sum/)
> 思路:转化 a + b = -c
>
> 1.暴力解法:三重循环
>
> 2.HashMap
>
> 3.`左右夹逼/双指针法`,这种办法有时候需要排序。
### Linked List
#### 141. [linked-list-cycle](https://leetcode.com/problems/linked-list-cycle)
> 1.暴力解法:遍历链表,hash/set
>
> 2.`快慢指针 ` `#快慢指针法`
### Stack
#### 20. [valid parentheses](https://leetcode-cn.com/problems/valid-parentheses/description/)
> 为啥这个题目可以用栈解决? 具有最近相关性
>
> 1.暴力解法:不断replace匹配的括号 -> "" O(n^2)
>
> a. (){}[]
>
> b.((({[]})))
>
> 2.Stack
#### 155. [min Stack](https://leetcode-cn.com/problems/min-stack/)
> `两个队列实现栈`
>
> `两个栈实现队列`
#### 84. [largest rectangle in histogram](https://leetcode-cn.com/problems/largest-rectangle-in-histogram/)
> 思考一下这个题目和 [container with most water]( https://leetcode-cn.com/problems/container-with-most-water/ ) 有何差别?
>
> 差别在于这个题目的高度是指所有柱子中最低的高度,而 [container with most water]( https://leetcode-cn.com/problems/container-with-most-water/ ) 则是左右两边最小的高度。
>
> 1.暴力解法 O(n^3)
>
> ```java
> for i -> 0, n-2
> for j -> i+1, n-1
> (i, j) -> 最小高度, area
> update max-area
> ```
>
> 2.`暴力加速`
>
> ```java
> for i -> 0, n-1
> 找到 left bound, right bound // 固定中间一个高度,找到左右两边比他小的最小值
> area = height[i] * (right - left)
> update max-area
> ```
>
> 3.`Stack:有序栈(单调栈)找左右边界` `#单调栈`
>
> 维护一个从小到大的有序栈
>
> 那么左边界left bound在栈里,而右边界则是比栈顶元素小的新元素
>
> 如果新元素的值大于栈顶元素,说明栈顶元素的右边界没有找到。
>
> 构造这个有序栈的过程,其实就是不断找到栈顶元素的右边界的过程(左边界在栈里)。
### Queue
#### 239. [sliding window maximum](https://leetcode-cn.com/problems/sliding-window-maximum/)
> 1.暴力 O(n*k)
>
> 2.`deque O(n)` 滑动窗口 -> 队列 `#单调队列`
### Hash Table
#### [242. valid anagram](https://leetcode-cn.com/problems/valid-anagram/description/)
> `#切题四件套`
>
> clarification
>
> -确定异位词是什么意思?
>
> -确定大小写是否敏感?
>
> 方法1:
>
> 暴力 sort -> sorted_str 是否相等? O(NlogN)
>
> 方法2:哈希表
>
> 统计每个字符出现的频次
>
> (1)第一个string,碰到字母加1,第二个string,碰到同样的字母减1,最后看map是否为空
>
> (2)int[256] 的数组,ascii -> index
#### [49.group anagrams](https://leetcode-cn.com/problems/group-anagrams/)
### Tree
#### [94. binary tree inorder traversal](https://leetcode-cn.com/problems/binary-tree-inorder-traversal/)
#### [98. validate binary search tree](https://leetcode-cn.com/problems/validate-binary-search-tree/)
> 中序遍历是递增的。
### Recursion
#### [70. climbing stairs](https://leetcode-cn.com/problems/climbing-stairs/)
> 找 `最近重复性`
>
> 1: 1
>
> 2: 2
>
> 3: f(1) + f(2) 1的总的走法,跨2步走上3 + 2的总的走法,跨1步走上3 mutual exclusive, complete exhaustive
>
> 4: f(2) + f(3)
>
> ...
>
> n: f(n) = f(n-1) + f(n-2) Fibonacci
```java
class Solution {
public int climbStairs(int n) {
if(n <= 2) return n;
return climbStairs(n-1) + climbStairs(n-2);
}
}
```
#### [22. generate parenthess * ](https://leetcode-cn.com/problems/generate-parentheses/)
```java
// 递归模板
class Solution {
public void generateParenthesis(int n) {
generate(0, 2 * n, "");
}
private void generate(int level, int max, String s) {
// terminator
if (level >= max) {
System.out.println(s);
return;
}
// process current logic
String s1 = s + "(";
String s2 = s + ")";
// drill down
generate(level + 1, max, s1);
generate(level + 1, max, s2);
// reverse states
}
}
// 检查括号合法性
// left 随时加,只要不超标 n
// right 左括号个数 > 右括号个数
class Solution {
List<String> result;
public List<String> generateParenthesis(int n) {
result = new ArrayList<>();
generate(0, 0, n, "");
}
private void generate(int left, int right, int n, String s) {
// terminator
if (left == n && right == n) {
result.add(s);
return;
}
// process current logic
String s1 = s + "(";
String s2 = s + ")";
// drill down
if (left < n) {
generate(left + 1, right, n, s1);
}
if (left > right) {
generate(left, right + 1, n, s2);
}
generate(level + 1, max, s1);
generate(level + 1, max, s2);
// reverse states
}
}
// 本质就是DFS
```
### Divide and conquer
#### [50. Pow(x, n)](https://leetcode-cn.com/problems/powx-n/)
> 1.暴力 O(n)
>
> ```java
> result = 1;
> for (int i = 0; i < n; i++) {
> result *= x;
> }
> ```
>
> 2.分治 O(logn)
>
> `template`: 1. terminator 2. process (`divide` your big problem) 3. drill down (`conquer` your subproblems ) 4. `merge` sub result 5. reverse states.
>
> ```java
> pow(x, n):
> subproblem: subresult = pow(x, n/2);
> mege:
> if (n % 2 == 1) {
> result = subresult * subresult * x;
> } else {
> result = subresult * subresult;
> }
> ```
#### [78. subsets](https://leetcode-cn.com/problems/subsets/) *
```java
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
if (nums == null) return ans;
dfs(ans, nums, new ArrayList<Integer>(), 0);
return ans;
}
private void dfs(List<List<Integer>> ans, int[] nums, List<Integer> list, int index) {
// terminator
if (index == nums.length) {
ans.add(new ArrayList<Integer>(list));
return;
}
// not pick the number at this index
dfs(ans, nums, list, index + 1);
// pick the number at this index
list.add(num[index]);
dfs(ans, nums, list, index + 1);
// reverse the current state
list.remove(list.size() - 1);
}
// or
private void dfs(List<List<Integer>> ans, int[] nums, List<Integer> list, int index) {
// terminator
if (index == nums.length) {
ans.add(new ArrayList<Integer>(list));
return;
}
// not pick the number at this index
dfs(ans, nums, list.clone, index + 1);
// pick the number at this index
list.add(num[index]);
dfs(ans, nums, list.clone, index + 1);
// reverse the current state
}
```
```python
class Solution(object):
def subsets(self, nums):
result =[[]]
for num in nums:
newsets = []
for subset in result:
new_subset = subset + [num]
newsets.append(new_subset)
result.extend(newsets)
return result
```
#### [169. majority element](https://leetcode-cn.com/problems/majority-element/description/)
#### [17. letter combinations of a phone number](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/) *
```java
public List<String> letterCombination(String digits) {
if (digits == null || digits.length() == 0) {
return new ArrayList();
}
Map<Character, String> map = new HashMap<>();
map.put('2', "abc");
map.put('3', "def");
map.put('4', "ghi");
map.put('5', "jkl");
map.put('6', "mno");
map.put('7', "pqrs");
map.put('8', "tuv");
map.put('9', "wxyz");
List<String> res = new ArrayList<>();
search("", digits, 0, res, map);
return res;
}
private void search(String s,
String digits,
int i, // level
List<String> res,
Map<Character, String> map) {
// terminator
if (i == digits.length) {
res.add(s);
return;
}
// process
String letters = map.get(digits.charAt(i));
for (int j = 0; j < letters.length(); j++) {
// drill down
search(s+letters.charAt(j), digits, i+1, res, map);
}
}
```
#### [51. n queens](https://leetcode-cn.com/problems/n-queens/)
```python
def sovleNQueen(self, n):
if n < 1: return []
self.result = []
# 之前的皇后所攻击的位置(列,pie, na)
self.cols = set();
self.pie = set();
self.na = set();
self.DFS(n, 0, [])
return self._generate_result(n)
def DFS(self, n, row, cur_state):
# ternimator
if row >= n:
self.result.append(cur_state)
return
# current level! Do it!
for col in range(n): # 遍历列 column
if col in self.cols or row + col in self.pie or row - col in self.na:
# go die
continue
# update the flags
self.cols.add(col)
self.pie.add(row+col)
self.na.add(row-col)
self.DFS(n, row + 1, cur_state + [col])
# reverse state
self.cols.remove(col)
self.pie.remove(row+col)
self.na.remove(row-col)
def _generate_result(self, n):
board = []
for res in self.result:
for i in res:
board.append("." * i + "Q" + "." * (n - i - 1))
return [board[i: i + n] for i in range(0, len(board), n)]
```
### Binary Search
#### [69. sqrtx](https://leetcode-cn.com/problems/sqrtx/)
```java
class Solution {
public int mySqrt(int x) {
if (x == 0 || x == 1) {
return x;
}
long left = 1;
long right = x / 2; // (x/2)^2 >= x
while (left < right) {
long mid = left + (right - left + 1) / 2;
if (mid * mid > x) {
right = mid - 1;
} else {
left = mid;
}
}
return (int)left;
}
}
```
* 扩展阅读:[牛顿迭代法](https://www.beyond3d.com/content/articles/8/)
#### [33. search in rotated sorted array](https://leetcode-cn.com/problems/search-in-rotated-sorted-array/)
> 1.暴力遍历 O(N)
>
> 2.还原O(log N) -> 升序 -> 二分查找O(log N)
>
> 3.二分查找O(log N)
```java
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[0] <= nums[mid] && (target > nums[mid] || target < nums[0])) {
left = mid + 1;
} else if (target > nums[mid] && target < nums[0]) {
left = mid + 1;
} else {
right = mid;
}
}
return left == right && nums[left] == target ? left : -1;
}
}
```
### BFS & DFS
#### [102. binary tree level order traversal](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/#/description)
> 1.BFS
>
> 2.DFS
#### [22. generate parenthess * ](https://leetcode-cn.com/problems/generate-parentheses/)
> DFS
#### [200. number of islands](https://leetcode-cn.com/problems/number-of-islands/)
> floodfill
```java
class Solution {
int[] dx = new int[]{-1, 1, 0, 0};
int[] dy = new int[]{0, 0, -1, 1};
char[][] g;
public int numIslands(char[][] grid) {
int islands = 0;
g = grid;
for (int i = 0; i < g.length; i++) {
for (int j = 0; j < g[i].length; j++) {
if (g[i][j] == '0') continue;
islands += sink(i, j);
}
}
return islands;
}
private int sink(int i, int j) {
if (g[i][j] == '0') {
return 0;
}
g[i][j] = '0';
for (int k = 0; k < dx.length; k++) {
int x = i + dx[k];
int y = j + dy[k];
if (x >= 0 && x < g.length && y >= 0 && y < g[x].length) {
if (g[x][y] == '0') continue;
sink(x, y);
}
}
return 1;
}
}
```
#### [79. word search](https://leetcode-cn.com/problems/word-search/) 与212一起看
### Greedy
> 从后往前
>
> 从前往后
>
> 从某个点切入往某一边
#### [455. assign cookies]( https://leetcode-cn.com/problems/assign-cookies/ )
#### [122. best time to buy and sell stock ii](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/description/)
#### [55. jump game](https://leetcode-cn.com/problems/jump-game/)
```java
class Solution {
public boolean canJump(int[] nums) {
if (nums == null) {
return false;
}
int endReachable = nums.length - 1;
for (int i = nums.length - 1; i >= 0; i--) {
if (nums[i] + i >= endReachable) {
endReachable = i;
}
}
return endReachable == 0;
}
}
```
### Dynamic Programming
#### [70. climbing stairs](https://leetcode-cn.com/problems/climbing-stairs/)
> 找 `最近重复性`
>
> 1: 1
>
> 2: 2
>
> 3: f(1) + f(2) 1的总的走法,跨2步走上3 + 2的总的走法,跨1步走上3 mutual exclusive, complete exhaustive
>
> 4: f(2) + f(3)
>
> ...
>
> n: f(n) = f(n-1) + f(n-2) Fibonacci
>
```java
class Solution {
public int climbStairs(int n) {
if(n <= 2) return n;
return climbStairs(n-1) + climbStairs(n-2);
}
}
class Solution {
public int climbStairs(int n) {
if (n <= 2) return n;
int f1 = 1;
int f2 = 2;
int f3 = 3;
for (int i = 3; i <= n; i++) {
f3 = f1 + f2;
f1 = f2;
f2 = f1;
}
return f3;
}
}
class Solution {
public int climbStairs(int n) {
if (n <= 2) return n;
int[] dp = new int[n];
dp[0] = 1;
dp[1] = 2;
for (int i = 2; i < n; i++) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n-1];
}
}
```
> 进阶:
>
> (1)可以走1, 2,3步,如何解决?easy -> f(n) = f(n-1) + f(n-2) + f(n-3)
>
> (2)给定一个数组[x1, x2, ..., xn ] 表示可以走 x1,x2, ..., xn步, 如何解决?
>
> (2)相邻2步的步伐不同,如何解决? medium
##### 小结:一维动态规划:Fibnacci
```java
# 递归:自顶向下 O(2^N)
int fib(int n) {
if (n <= 1) {
return n;
}
return fib(n - 1) + fib(n - 2); // 改进:return n <= 1 ? n : fib(n-1) + fib(n-2);
}
# 递归 + 备忘录 (记忆化搜索) O(N)
int fib(int n, int[] memo) {
if (n <= 1) {
return n;
}
if (memo[n] == 0) {
memo[n] = fib(n-1, memo) + fib(n-2, memo);
}
return memo[n];
}
# 动态规划:自底向上 O(N)
int fib(int n) {
int[] dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
# 一维的Equation: f(n) = f(n-1) + f(n-2)
```
#### [62. unique paths](https://leetcode-cn.com/problems/unique-paths/)
> ```
> opt[i, j] = opt[i+1, j] + opt[i, j+1];
> if a[i, j] == '空地':
> opt[i, j] = opt[i+1, j] + opt[i, j+1];
> else:
> opt[i, j] = 0;
> ```
```java
int countPaths(boolean[][] grid, int row, int col) {
if (!validSqure(grid, row, col)) return 0;
if (isAtEnd(grid, row, col)) return 1;
return countPaths(grid, row + 1, col) + countPaths(grid, row, col+1);
}
class Solution {
// 二维DP数组
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}
for (int j = 0; j < n; j++) {
dp[0][j] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
// 一维DP数组:将每一行都压缩在固定的一行更新,更新m次
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
Arrays.fill(dp, 1);
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[j] += dp[j-1];
}
}
return dp[n-1];
}
}
```
#### [65. unique paths ii](https://leetcode-cn.com/problems/unique-paths-ii/submissions/)
```java
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int n = obstacleGrid[0].length;
int[] dp = new int[n];
dp[0] = 1;
for (int[] row : obstacleGrid) { // 注意这种写法
for (int j = 0; j < n; j++) { // 这里j一定要从0开始,因为row[0]可能是障碍物
if (row[j] == 1) {
dp[j] = 0;
} else if (j > 0){
dp[j] += dp[j-1];
}
}
}
return dp[n-1];
}
}
```
#### [64. minimum path sum](https://leetcode-cn.com/problems/minimum-path-sum/submissions/)
```java
// 暴力解法
class Solution {
public int minPathSum(int[][] grid) {
return minPathSum(0, 0, grid);
}
private int minPathSum(int i, int j, int[][] grid) {
if (i == grid.length || j == grid[0].length) return Integer.MAX_VALUE;
if (i == grid.length - 1 && j == grid[0].length - 1) {
return grid[i][j];
}
return grid[i][j] + Math.min(minPathSum(i+1, j, grid), minPathSum(i, j+1, grid));
}
}
// 动态规划
class Solution {
public int minPathSum(int[][] grid) {
if (grid == null || grid.length <= 0 || grid[0].length <= 0) {
return 0;
}
int m = grid.length;
int n = grid[0].length;
int[][] states = new int[m][n];
int sum = 0;
for (int j = 0; j < n; j++) {
sum += grid[0][j];
states[0][j] = sum;
}
sum = 0;
for (int i = 0; i < m; i++) {
sum += grid[i][0];
states[i][0] = sum;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
states[i][j] = grid[i][j] + Math.min(states[i][j-1], states[i-1][j]);
}
}
return states[m-1][n-1];
}
}
```
##### 小结:二维动态规划:Count the paths
```java
// 递归
int countPaths(boolean[][] grid, int row, int col) {
if (!validSqure(grid, row, col)) return 0;
if (isAtEnd(grid, row, col)) return 1;
return countPaths(grid, row + 1, col) + countPaths(grid, row, col+1);
}
opt[i, j] = opt[i+1, j] + opt[i, j+1];
if a[i, j] == '空地':
opt[i, j] = opt[i+1, j] + opt[i, j+1];
else:
opt[i, j] = 0;
对比:
# 一维的Equation: f(n) = f(n-1) + f(n-2)
# 二维的Equation: opt[i, j] = opt[i+1, j] + opt[i, j+1];
```
#### [120. triangle](https://leetcode-cn.com/problems/triangle/description/) ([一个不错的分析过程](https://leetcode.com/problems/triangle/discuss/38735/Python-easy-to-understand-solutions-(top-down-bottom-up).))
> 1、brute-force 递归, n层: left or right: O(2^N)
>
> 2、DP
>
> a. 重复性 `problem(i, j) = min(sub(i+1, j) , sub(i+1, j+1)) + a[i][j]`
>
> b. 状态数组 `f(i, j) `
>
> c. DP方程 `f(i, j) = min(f(i+1, j) , f(i+1, j+1)) + a[i][j]`
>
```python
class Solution:
def minimumTotal(self, triangle):
"""
:type triangle: List[List[int]]
:rtype: int
"""
dp = triangle
for i in range(len(triangle) - 2, -1, -1):
for j in range(len(triangle[i])):
dp[i][j] += min(dp[i+1][j], dp[i+1][j+1])
print(triangle[0][0])
return dp[0][0]
```
```java
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int[] dp = new int[triangle.size() + 1];
for (int i = triangle.size() - 1; i >= 0; i--) {
for (int j = 0; j < triangle.get(i).size(); j++) {
dp[j] = Math.min(dp[j], dp[j+1]) + triangle.get(i).get(j);
}
}
return dp[0];
}
}
```
```java
class Solution {
int maxRow;
public int minimumTotal(List<List<Integer>> triangle) {
maxRow = triange.size();
return helper(0, 0, triangle);
}
private int helper(int row, int col, List<List<Integer>> triangle) {
if (row == maxRow-1) {
return triangle.get(row).get(col);
}
int left = helper(row+1, col, triangle);
int right = helper(row+1, col+1, triangle);
return Math.min(left, right) + triangle.get(row).get(col);
}
}
```
```java
class Solution {
int maxRow;
Integer[][] memo;
public int minimumTotal(List<List<Integer>> triangle) {
maxRow = triange.size();
memo = new Integer[row][row];
return helper(0, 0, triangle);
}
private int helper(int row, int col, List<List<Integer>> triangle) {
if (memo[row][col] != null) {
return memo[row][col];
}
if (row == maxRow-1) {
return memo[row][col] = triangle.get(row).get(col);
}
int left = helper(row+1, col, triangle);
int right = helper(row+1, col+1, triangle);
return memo[row][col] = Math.min(left, right) + triangle.get(row).get(col);
}
}
```
#### [53. maximum sum subarray](https://leetcode-cn.com/problems/maximum-subarray/)
> 1、暴力 O(N^2)
>
> 2、DP
>
> a. 重复性 max_sum(i) = Max(max_sum(i-1) , 0) + a[i] max_sum(i) : 表示以第i个元素结尾(包含)的连续子数组最大和
>
> b. 状态数组 f(i)
>
> c. DP方程 f(i) = max(f(i-1), 0) + a[i]
```python
class Solution(object):
def maxSubArray(self, nums):
"""
1. dp[i] = max(nums[i], nums[i] + dp[i-1])
2. 最大子序列和 = 当前元素最大(之前元素和为负) 或者 包含之前+当前之后最大
"""
dp = nums
for i in range(1, len(nums)):
dp[i] = max(0, dp[i-1]) + nums[i]
return max(dp)
```
#### [152. maximum product subarray](https://leetcode-cn.com/problems/maximum-product-subarray/description/)
#### [322. coin change]( https://leetcode-cn.com/problems/coin-change/description/ ) ([推荐题解](https://leetcode-cn.com/problems/coin-change/solution/ling-qian-dui-huan-by-leetcode/))
> 1、暴力递归
>
> 2、BFS
>
> 3、DP
>
> a. 重复性
>
> b. DP array
>
> c. DP equation: f(n) = min{f(n-k), for k in [1, 2, 5]} + 1
>
>
>
> 变形:若问`共有多少种组合方式`?
>
> 分析:这个问题就类似于爬楼梯问题,爬楼梯每次可以爬1阶,每次可以爬2阶,每次也可以爬5阶,问爬到11阶有多少种方式?(不同之处在于硬币[1,2,1]和[1,1,2]是一种情况,而爬楼梯则不是)
```java
public class Solution {
public int coinChange(int[] coins, int amount) {
return coinChange(0, coins, amount);
}
private int coinChange(int index, int[] coins, int amount) {
if (amount == 0) {
return 0;
}
if (index < coins.length && amount > 0) {
int maxVal = amount / coins[index];
int minCost = Integer.MAX_VALUE;
for (int x = 0; x <= maxVal; x++) {
if (amount >= x * coins[index]) {
int res = coinChange(index+1, coins, amount - x * coins[index]);
if (res != -1) {
minCost = Math.min(minCost, res + x);
}
}
}
return minCost == Integer.MAX_VALUE ? -1 : minCost;
}
return -1;
}
}
```
```java
public class Solution {
public int coinChange(int[] coins, int amount) {
if (amount <=0) return 0;
return coinChange(coins, amount, new int[amount]);
}
private int coinChange(int[] coins, int remain, int[] count) {
if (remain < 0) {
return -1;
}
if (remain == 0) {
return 0;
}
if (count[remain-1] != 0) {
return count[remain-1];
}
int min = Integer.MAX_VALUE;
for (int coin : coins) {
int res = coinChange(coins, remain - coin, count);
if (res >= 0 && res < min) {
min = res + 1;
}
}
count[remain - 1] = min == Integer.MAX_VALUE ? -1 : min;
return count[remain - 1];
}
}
```
```java
class Solution {
public int coinChange(int[] coins, int amount) {
int max = amount + 1;
int[] dp = new int[amount + 1];
Arrays.fill(dp, max);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i-coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
```
#### [1143. longest common subsequence](https://leetcode-cn.com/problems/longest-common-subsequence/)
> `# 经验`
>
> 1.对于2个字符串的比较,很多时候,我们会从字符串的尾部向前看。
>
> 2.对于2个字符串的变化问题,很多时候会表示成一个二维数组,行和列的元素分别是2个字符串的字符
```java
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
if (text1 == null || text2 == null) {
return 0;
}
int n = text1.length();
int m = text2.length();
int[][] dp = new int[n+1][m+1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (text1.charAt(i-1) == text2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[n][m];
}
public int longestCommonSubsequence(String text1, String text2) {
if (text1 == null || text2 == null) {
return 0;
}
int n = text1.length();
int m = text2.length();
int[] dp = new int[m+1];
for (int i = 1; i <= n; i++) {
int temp = 0;
for (int j = 1; j <= m; j++) {
int prev = temp;
temp = dp[j];
if (text1.charAt(i-1) == text2.charAt(j-1)) {
dp[j] = prev + 1;
} else {
dp[j] = Math.max(dp[j], dp[j-1]) ;
}
}
}
return dp[m];
}
}
```
#### [72. edit distance (莱文斯坦距离)](https://leetcode-cn.com/problems/edit-distance/)
> 1、BFS, two-ended BFS
>
> 2、DP
>
> `dp[i][j] // word1.substr(0, i) 与 word2.substr(0, j)的编辑距离`
>
> (1) if w1[i] == w2[j]
>
> w1: ............x (i)
>
> w2: .............x (j)
>
> edit_dist(i, j) = edit_dist(i-1, j-1)
>
> (2) if w1[i] != w2[j]
>
> w1: ............x (i)
>
> w2: .............y (j)
>
> edit_dist(i, j) =
>
> min(
>
> edit_dist(i-1, j-1) + 1 // x -> y (w1) or y -> x (w2)
>
> edit_dist(i - 1, j) + 1 // 删除 x
>
> edit_dist(i, j - 1) + 1 // 删除 y
>
> )
```java
class Solution {
// 单独处理空字符串的dp
public int minDistance(String word1, String word2) {
if (word1 == null || word2 == null) {
return 0;
}
int n = word1.length();
int m = word2.length();
if (n == 0) {
return m;
} else if (m == 0) {
return n;
}
int[][] dp = new int[n][m];
for (int j = 0; j < m; j++) {
if (word1.charAt(0) == word2.charAt(j)) dp[0][j] = j;
else if (j != 0) dp[0][j] = dp[0][j-1] + 1;
else dp[0][j] = 1;
}
for (int i = 0; i < n; i++) {
if (word1.charAt(i) == word2.charAt(0)) dp[i][0] = i;
else if (i != 0) dp[i][0] = dp[i-1][0] + 1;
else dp[i][0] = 1;
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
if (word1.charAt(i) == word2.charAt(j)) {
dp[i][j] = min(dp[i-1][j] + 1, dp[i][j-1] + 1, dp[i-1][j-1]);
} else {
dp[i][j] = min( dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1;
}
}
}
return dp[n-1][m-1];
}
// 统一处理空字符串的dp
public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
int[][] dp = new int[n+1][m+1];
for (int j = 0; j <= m; j++) {
dp[0][j] = j;
}
for (int i = 0; i <= n; i++) {
dp[i][0] = i;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (word1.charAt(i-1) == word2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1;
}
}
}
return dp[n][m];
}
private int min(int x, int y, int z) {
return Math.min(x, Math.min(y, z));
}
}
```
#### [198. house robber](https://leetcode-cn.com/problems/house-robber/)
> `a[i] `: 0...i 能偷到的 max value : a[n-1]
>
> `a[i][0,1]`: 0: 表示第 i 个房子不偷,1:偷
>
>
>
> `a[i][0] = max(a[i-1][0], a[i-1][1]) `
>
> `a[i][1] = a[i-1][0] + nums[i]`
```java
class Solution {
public int rob(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int n = nums.length;
int[][] dp = new int[n][2];
dp[0][0] = 0;
dp[0][1] = nums[0];
for(int i = 1; i < n; i++) {
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]);
dp[i][1] = dp[i-1][0] + nums[i];
}
return Math.max(dp[n-1][0], dp[n-1][1]);
}
}
```
> `a[i] `: 0...i ,且包含了 `nums[i]` 必偷的情形,max value: max(a)
>
> `a[i] = max(a[i-1], a[i-2] + nums[i])`
```java
class Solution {
public int rob(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
if (nums.length == 1) return nums[0];
int n = nums.length;
int[] dp = new int[n];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
int res = Math.max(dp[0], dp[1]);
for(int i = 2; i < n; i++) {
dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]);
res = Math.max(res, dp[i]);
}
return res;
}
}
```
#### 股票问题 [分析](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/yi-ge-fang-fa-tuan-mie-6-dao-gu-piao-wen-ti-by-l-3/)
### Trie
#### [208. implement trie prefix tree](https://leetcode-cn.com/problems/implement-trie-prefix-tree/)
```java
class Trie {
private TrieNode root;
/** Initialize your data structure here. */
public Trie() {
this.root = new TrieNode('/');
}
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode p = root;
for (int i = 0; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (p.children[index] == null) {
TrieNode newNode = new TrieNode(word.charAt(i));
p.children[index] = newNode;
}
p = p.children[index];
}
p.isEndingChar = true;
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
TrieNode p = root;
for (int i = 0; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (p.children[index] == null) {
return false;
}
p = p.children[index];
}
if (p.isEndingChar) return true;
else return false;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TrieNode p = root;
for (int i = 0; i < prefix.length(); i++) {
int index = prefix.charAt(i) - 'a';
if (p.children[index] == null) {
return false;
}
p = p.children[index];
}
return true;
}
class TrieNode {
public char data;
public TrieNode[] children = new TrieNode[26];
public boolean isEndingChar = false;
public TrieNode(char data) {
this.data = data;
}
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/
```
#### [212. word search ii](https://leetcode-cn.com/problems/word-search-ii/)
> 1、words 遍历 --> board 中 search
>
> 2、Trie
>
> a. all words --> Trie
>
> b. board --> DFS
```python
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
END_OF_WORD = "#"
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
if not board or not board[0]: return []
if not words: return []
self.result = set()
# 根据words构建Trie
root = {}
for word in words:
node = root
for char in word:
node = node.setdefault(char, {})
node[END_OF_WORD] = END_OF_WORD
self.m, self.n = len(board), len(board[0])
for i in range(self.m):
for j in range(self.n):
if board[i][j] in root: # 剪枝
self._dfs(board, i, j, "", root)
return list(self.result)
def _dfs(self, board, i, j, cur_word, cur_dict):
# terminator
cur_word += board[i][j]
cur_dict = cur_dict[board[i][j]]
if END_OF_WORD in cur_dict:
self.result.add(cur_word)
# process current logic
tmp, board[i][j] = board[i][j], '@' # @表示 board[i][j]用过了,就不再用了
# drill down
for k in range(4):
x, y = i + dx[k], j + dy[k]
if 0 <= x < self.m and 0 <= y < self.n and board[x][y] != '@' and board[x][y] in cur_dict:
self._dfs(board, x, y, cur_word, cur_dict)
# 恢复 board
board[i][j] = tmp
```
### Sort
#### [242. valid anagram](https://leetcode-cn.com/problems/valid-anagram/)
```java
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) return false;
char[] sArray = s.toCharArray();
char[] tArray = t.toCharArray();
Arrays.sort(sArray);
Arrays.sort(tArray);
return Arrays.equals(sArray, tArray);
}
}
```
### 位运算
#### [231. power of two](https://leetcode-cn.com/problems/power-of-two/)
================================================
FILE: leetcode/src/linkedlistcycle_141/LinkedListCycle.java
================================================
package linkedlistcycle_141;
/**
* 141. Linked List Cycle
* https://leetcode.com/problems/linked-list-cycle/
*/
public class LinkedListCycle {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) return true;
}
return false;
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x;}
}
}
================================================
FILE: leetcode/src/lrucache_146/LRUCache.java
================================================
package lrucache_146;
import java.util.HashMap;
/**
* 146. LRU Cache
* https://leetcode.com/problems/lru-cache/description/
*/
public class LRUCache {
private Node head;
private Node tail;
private HashMap<Integer, Node> map;
private int capacity;
public LRUCache(int capacity) {
this.capacity = capacity;
this.map = new HashMap<>(capacity * 4 / 3);
head = new Node(-1,-1);
tail = new Node(-1,-1);
head.next = tail;
tail.pre = head;
}
public int get(int key) {
// key 不存在
if (!map.containsKey(key)) {
return -1;
}
// key 存在
Node node = map.get(key);
delete(node);
insertToHead(node);
return node.value;
}
public void put(int key, int value) {
// key 存在
if (map.containsKey(key)) {
Node node = map.get(key);
delete(node);
}
// key 不存在
Node node = new Node(key, value);
insertToHead(node);
map.put(key, node);
if (map.size() > capacity) {
Node remove = deleteTail();
map.remove(remove.key);
}
}
private void delete(Node node) {
Node next = node.next;
Node pre = node.pre;
pre.next = next;
next.pre = pre;
node.next = null;
node.pre = null;
}
private void insertToHead(Node node) {
Node next = head.next;
node.next = next;
node.pre = head;
next.pre = node;
head.next = node;
}
private Node deleteTail() {
Node node = tail.pre;
Node pre = node.pre;
tail.pre = pre;
pre.next = tail;
node.next = null;
node.pre = null;
return node;
}
private class Node {
int key;
int value;
Node pre;
Node next;
public Node (int key, int value) {
this.key = key;
this.value = value;
}
}
}
================================================
FILE: leetcode/src/mergetwosortedlist_21/Merge2SortedLists.java
================================================
package mergetwosortedlist_21;
/**
* 21. Merge Two Sorted Lists
* https://leetcode.com/problems/merge-two-sorted-lists/
*/
public class Merge2SortedLists {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
// 利用哨兵(前哨节点)简化实现难度
ListNode outpost = new ListNode(-1);
ListNode temp = outpost;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
temp.next = l1;
l1 = l1.next;
} else {
temp.next = l2;
l2 = l2.next;
}
temp = temp.next;
}
if (l1 == null) {
temp.next = l2;
}
if (l2 == null) {
temp.next = l1;
}
return outpost.next;
}
public ListNode mergeTwoListsRecur(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoListsRecur(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoListsRecur(l1, l2.next);
return l2;
}
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x;}
}
}
================================================
FILE: leetcode/src/middleofthelinkedlist_876/MiddleNode.java
================================================
package middleofthelinkedlist_876;
/**
* 876. Middle of the Linked List
* https://leetcode.com/problems/middle-of-the-linked-list/
*/
public class MiddleNode {
public ListNode middleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x;}
}
}
================================================
FILE: leetcode/src/palindromelinkedlist_234/PalindromeLinkedList.java
================================================
package palindromelinkedlist_234;
/**
* 234. Palindrome Linked List
* https://leetcode.com/problems/palindrome-linked-list/
* Solution:
* 1. 找到中间节点,将单链表后半段逆置
* 2. 左半段从左到右,右半段从右到左,比较2段链表是否对应相等
* 3. 对比完之后,最好能将右半段逆置,还原链表
* 示例:
* 1->2->2->1
* 1->2->2<-1 (第2个2指向null)
*/
public class PalindromeLinkedList {
public boolean isPalindrome(ListNode head) {
// 1. 找到单链表的中间节点
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next; // 此时slow就是中间节点
}
// 2. 从中间节点开始,将右半段链表逆置
ListNode pre = null;
ListNode next = null;
while (slow != null) {
next = slow.next;
slow.next = pre;
pre = slow;
slow = next;
}
// 3. 左半段从左到右,右半段从右到左,比较2段链表是否对应相等
fast = head;
slow = pre;
while (slow != null) {
if (fast.val != slow.val) {
return false;
}
fast = fast.next;
slow = slow.next;
}
// 4. 对比完之后,最好能将右半段逆置,还原链表
return true;
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) {
this.val = val;
}
}
}
================================================
FILE: leetcode/src/removenthnodefromendoflist_19/RemoveNthNodeFromEndOfList.java
================================================
package removenthnodefromendoflist_19;
/**
* 19. Remove Nth Node From End of List
* https://leetcode.com/problems/remove-nth-node-from-end-of-list/
*/
public class RemoveNthNodeFromEndOfList {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p1 = head;
for (int i = 0; i < n; i++) {
p1 = p1.next;
}
ListNode p2 = head; // 要删除的节点
ListNode pre = null;
while (p1 != null) {
p1 = p1.next;
pre = p2;
p2 = p2.next;
}
if (p2 == head) { // 要删除的节点为head,特殊处理
head = head.next;
} else {
pre.next = p2.next;
p2.next = null;
}
return head;
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) {
this.val = val;
}
}
}
================================================
FILE: leetcode/src/reverselinkedlist_206/ReverseList.java
================================================
package reverselinkedlist_206;
/**
* 206. Reverse Linked List
* https://leetcode.com/problems/reverse-linked-list/
*/
public class ReverseList {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode pre = null;
ListNode next = null;
while (head != null) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) {
this.val = val;
}
}
}
================================================
FILE: leetcode/src/threesum_015/ThreeSum.java
================================================
package threesum_015;
public class ThreeSum {
}
================================================
FILE: leetcode/src/twosum_001/TwoSum.java
================================================
package twosum_001;
public class TwoSum {
public static void main(String[] args) {
}
}
================================================
FILE: offer/src/com/ex/offer/Attention.txt
================================================
- 面试沟通
(1)面试时,要经常和面试官沟通。沟通好题目条件、问题的意图之后再动手coding或者回答问题。
(2)面试中,若面试官提出新的概念,面试者需要和面试官积极沟通,多问几个问题,把概念搞清楚。
(3)面试中,若有多种解法,且多种解法各有优缺点,则需要和面试官沟通,确定问题需要的最合适的解法。
(4)考虑性能的时候,是关注时间还是空间?其复杂度要求是多少?
考虑实现的时候,是否可以修改原来的结构?是否可以在新的结构中操作?
- 排序和查找
--查找:顺序查找 二分查找 哈希表查找 二叉排序树(其实就是二叉搜索树)查找
(1) 二分查找:要求在排序或者是部分排序的数组中查找一个数字或者统计某个数字出现的次数,可以尝试二分查找。
(2) 哈希表&二叉排序树:重点在于考察数据结构本身,不在于算法
(3) 哈希表:优点是能够在O(1)内找到某一个元素,是效率最高的查找方式。缺点是需要额外空间实现哈希表。
-- 排序:插入排序 冒泡排序 归并排序 快速排序
关注其实现,性能,场景等
- 回溯法:
(1)类似于暴力解答
(2)常常使用递归,回溯法很适合递归实现。递归可以用栈来模拟。
注:二维数组或者迷宫问题,可以尝试回溯法。
- 递归与循环:
(1)递归:由于递归实现更加简洁,若没有特殊要求,可以优先选用递归实现。
效率问题:递归可能存在大量的重复运算,因此性能可能弱于循环。如:Ex_10_Fibonacci
栈溢出问题:递归还可能引起调用栈溢出的问题。
(2)思考:一般用递归的方式思考答案,用循环的方式实现代码。
- 动态规划
(1)动态规划多可以用递归解决;
(2)但是递归中有很多需要重复计算的项,如Ex_10_Fibonacci
(3)动态规划从下到上,将重复的子问题的答案存储起来,减少了重复计算的时间浪费,但是增加了空间的消耗。
- 贪心算法
- 说明
(1) 若求某个问题的最优解,且该问题可以分解为多个子问题,则可以尝试动态规划。
递归操作是自上而下,动态规划则是自下而上,避免不必要的重复计算。
若是某个问题有特殊的选择,那么这个问题的最优解可能就是贪婪算法得出的。
(2) 思考路线:递归->动态规划->贪婪算法
- 位运算
(1) 基本运算:与、或、异或、左移、右移
(2) 把一个整数减1之后再和原来的整数做位与运算,相当于将整数的二进制表示中的最右边的1变成0:
x = (x - 1) & x : 将x的二进制最右边的1变成了0
- 高质量的代码
-- 代码的规范性
(1)书写清晰
(2)布局清晰
(3)命名合理
-- 代码的完整性
(1)功能测试:基本功能
(2)边界测试:边界值
(3)负面测试:非法值
-- 代码的鲁棒性:程序对输入的合法性判断以及对非法输入的处理
--- 容错性
--- 防御性编程
--注:在处理链表问题时,当我们用一个指针遍历链表无法解决问题时,可以尝试用2个指针解决问题。
可以让一个指针遍历的速度快一点(一次走2步,或者先走若干步),让另外一个指针遍历的速度慢一点
--注:
(1)若面试题是关于n位的整数且没有限定n的取值范围,或者输入任意大小的整数,则此题目可能需要考虑大数问题。
(2)大数问题如何处理?字符串是一种有效的地表示大数地方法。
(3)例:Ex_17_AddTwoBigNumber
- 解决面试题的思路
-- 在解决笔试或者面试题目之前,应该思考清楚题目的解决思路,然后再进行编码。
-- 画图
-- 举例
-- 分解
-- 注:
1. 二叉树遍历
-- 先序 Stack T26:树的子结构; T7:重建二叉树 T37:树的序列化和反序列化
-- 中序 Stack T7:重建二叉树
-- 后序 Stack T33:判断一个序列是否是BST的后序(先序)遍历序列;
-- Morris遍历 Stack
-- 宽度优先遍历:层遍历(也叫广度优先遍历)T32:从上到下打印二叉树
-- 不分行 Queue
-- 分行 Queue + 记录节点
-- 之字形 Stack * 2
-- 深度优先遍历:先序遍历 T34:二叉树中和为某一个值的路径
2. 二叉树分类
-- 二叉搜索树
-- 红黑树
-- 二叉堆
3. 技巧:
-- 若要求处理二叉树的遍历序列,则可以先找到二叉树的根节点,
然后基于根节点将二叉树的遍历序列分成左子树和右子树对应的子序列 分界:i
然后递归处理这2个子序列.模式如下
process(sequence, start, end)
-> process(sequence, start, i-1)
-> process(sequence, i, end)
--- 例如:面试题33:判断一个序列是否是BST的后序(先序)遍历序列;
面试题7:重建二叉树
- 优化时间和空间效率
-- 注:若需要判断多个字符是否在某个字符串中出现过或者统计其出现的次数,考虑哈希表,或者考虑基于数组创建一个简单的哈希表,
这样可以用很小得空间消耗换来时间效率的提升。
-- 如何降低时间复杂度?
1. 改用更高效的算法
2. 空间换时间
-- 递归与动态规划
- 面试考察能力
--编程能力
--学习能力
--抽象建模能力
--发散思维能力
--知识迁移能力
--沟通能力
*******************************************************
- 编写程序时需要考虑的一些问题:
-- 关注鲁棒性:边界条件 特殊输入 错误处理等
-- 编写过程:
测试用例
-> 找出规律
-> 编程
-> 检验 (基本功能、边界条件、错误处理)
-> 优化
================================================
FILE: offer/src/com/ex/offer/Ex_03_FindDuplicatedNumInArray.java
================================================
package com.ex.offer;
import java.util.HashMap;
/**
* problem 3: 数组中重复的数字
* 在一个长度为n的数组里的所有数字都在0到n-1的范围内。
* 数组中某些数字是重复的,但不知道有几个数字是重复的。
* 也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
* 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
*/
public class Ex_03_FindDuplicatedNumInArray {
public boolean duplicate(int numbers[], int [] duplication) {
if (numbers == null || numbers.length < 2) {
return false;
}
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < numbers.length; i++) {
if (!map.containsKey(numbers[i])) {
map.put(numbers[i], 1);
} else {
duplication[0] = numbers[i];
return true;
}
}
return false;
}
/**
* 由于numbers数组中的元素[0,n-1]
* 若没有重复元素,排序之后i位置为i
* 若有重复元素,则i位置为i,但是其他位置也可能有i
* 思路:
* 遍历数组
* 若i位置为i,i++
* 若i位置不是i
* (1)m = numbers[i], 则m的正确位置为numbers[m], 若numbers[m] = m,则重复元素就是m,否则
* (2) 交换m到正确的位置上。
* @param numbers
* @param duplication
* @return
*/
public boolean duplicateImprove(int numbers[], int [] duplication) {
if (numbers == null || numbers.length < 2) {
return false;
}
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == i) {
i++;
} else {
int m = numbers[i];
if (numbers[m] == m) {
duplication[0] = m;
return true;
} else {
swap(numbers, i, m);
}
}
}
return false;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_03_FindDuplicatedNumInWithoutChangeArray.java
================================================
package com.ex.offer;
/**
* problem 3: 不修改数组找出重复的数字。 [binary search]
*
* 特性:若数组中没有重复元素,则[x,y]范围内的数字个数为y-x+1,若超出这个个数,则说明有重复的数字。
*/
public class Ex_03_FindDuplicatedNumInWithoutChangeArray {
public static int duplicate(int numbers[]) {
if (numbers == null || numbers.length < 2) {
return -1;
}
int start = 1;
int end = numbers.length - 1;
while(start <= end) {
int mid = start + ((end - start) >> 1); // 这里 >> 一定要放在括号内
int count = countRange(numbers, start, mid);
if (start == end) {
if (count > 1) {
return start;
} else {
break;
}
}
if (count > (mid - start + 1)) {
end = mid;
} else {
start = mid + 1;
}
}
return -1;
}
private static int countRange(int[] numbers, int start, int end) {
if (numbers == null) {
return 0;
}
int count = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] <= end && numbers[i] >= start) {
count++;
}
}
return count;
}
public static void main(String[] args) {
int[] numbers = new int[]{2, 3, 5, 4, 3, 2, 6, 7};
int duplicate = duplicate(numbers);
System.out.println(duplicate);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_04_FindNumIn2VArray.java
================================================
package com.ex.offer;
/**
* 1.在一个二维数组中,每一行都按照从左到右递增的顺序排序,
* 每一列都按照从上到下递增的顺序排序。请完成一个函数,
* 输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
*/
public class Ex_04_FindNumIn2VArray {
public static boolean Find(int target, int[][] array) {
if (array == null || array.length == 0) {
return false;
}
//从右上角向左下遍历
int row = 0;
int col = array[0].length - 1;
while (row < array.length && col > -1) {
if (array[row][col] == target) {
return true;
} else if (array[row][col] < target) {
row++;
} else {
col--;
}
}
return false;
}
public static void main(String[] args) {
int[][] array = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0
{ 10, 12, 13, 15, 16, 17, 18 },// 1
{ 23, 24, 25, 26, 27, 28, 29 },// 2
{ 44, 45, 46, 47, 48, 49, 50 },// 3
{ 65, 66, 67, 68, 69, 70, 71 },// 4
{ 96, 97, 98, 99, 100, 111, 122 },// 5
{ 166, 176, 186, 187, 190, 195, 200 },// 6
{ 233, 243, 321, 341, 356, 370, 380 } // 7
};
int target = 233;
System.out.println(Find(target, array));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_05_ReplaceSpace.java
================================================
package com.ex.offer;
/**
* 2.请实现一个函数,将一个字符串中的空格替换成“%20”。
* 例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
*/
public class Ex_05_ReplaceSpace {
public static String replaceSpace(StringBuffer str) {
String s = str.toString();
String res = s.replaceAll(" ", "%20");
return res;
}
/**
* 问题1:替换字符串,是在原来的字符串上做替换,还是新开辟一个字符串做替换!
* 问题2:在当前字符串替换,怎么替换才更有效率(不考虑java里现有的replace方法)。
* 从前往后替换,后面的字符要不断往后移动,要多次移动,所以效率低下
* 从后往前,先计算需要多少空间,然后从后往前移动,则每个字符只移动一次,这样效率更高。
*
* @param str
* @return
*/
public static String replaceBlank(StringBuffer str) {
if (str == null) {
return null;
}
int spaceNum = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == ' ') {
spaceNum++;
}
}
int len = str.length() + 2 * spaceNum;
int indexOld = str.length() - 1;
int indexNew = len - 1;
str.setLength(len);
while (indexOld >= 0) {
if (str.charAt(indexOld) == ' ') {
str.setCharAt(indexNew--, '0');
str.setCharAt(indexNew--, '2');
str.setCharAt(indexNew--, '%');
} else {
str.setCharAt(indexNew--, str.charAt(indexOld));
}
indexOld--;
}
return str.toString();
}
public static void main(String[] args) {
StringBuffer str = new StringBuffer();
str.append("We Are Happy");
String s = replaceBlank(str);
System.out.print(s);
System.out.println();
StringBuffer str1 = new StringBuffer();
str1.append("");
String s1 = replaceBlank(str1);
System.out.print(s1);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_06_PrintListFromTailToHead.java
================================================
package com.ex.offer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
public class Ex_06_PrintListFromTailToHead {
public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if (listNode == null) {
return new ArrayList<>();
}
Stack<Integer> stack = new Stack<>();
ArrayList<Integer> list = new ArrayList<>();
for (ListNode node = listNode; node != null; node = node.next) {
stack.push(node.val);
}
while(!stack.isEmpty()) {
list.add(stack.pop());
}
return list;
}
public static ArrayList<Integer> printListFromTailToHeadRecur(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<>();
if (listNode != null) {
if (listNode.next != null) {
ArrayList<Integer> temp = new ArrayList<>();
temp = printListFromTailToHeadRecur(listNode.next);
for (Integer i : temp) {
list.add(i);
}
}
list.add(listNode.val);
}
return list;
}
public static ArrayList<Integer> printListFromTailToHeadWithCollections(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<>();
for (ListNode p = listNode; p != null; p = p.next) {
list.add(p.val);
}
Collections.reverse(list);
return list;
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
ArrayList<Integer> list = new ArrayList<>();
list = printListFromTailToHeadRecur(head);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_07_ReConstructBT.java
================================================
package com.ex.offer;
/**
* 4.输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
* 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
* 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
* 则重建二叉树并返回。
*
* 思路:
* 1.pre负责确定树的root;
* 2.in负责确定树的root.left,root.right,即左右子树;
* 3.递归1,2
*/
public class Ex_07_ReConstructBT {
public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
if (pre == null || in == null || pre.length == 0 || in.length == 0) {
return null;
}
TreeNode root = reConstructBinaryTree(pre, 0, pre.length-1, in, 0, in.length-1);
return root;
}
private static TreeNode reConstructBinaryTree(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd) {
return null;
}
TreeNode root = new TreeNode(pre[preStart]);
for (int i = inStart; i <= inEnd; i++) {
if (in[i] == pre[preStart]) {
root.left = reConstructBinaryTree(pre, preStart+1, preStart+(i-inStart), in, inStart, i-1);
root.right = reConstructBinaryTree(pre, preStart + 1 + (i-inStart), preEnd, in, i+1, inEnd);
break;
}
}
return root;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_08_DescendantNode.java
================================================
package com.ex.offer;
public class Ex_08_DescendantNode {
public static class Node {
public int value;
public Node left;
public Node right;
public Node parent;
public Node(int data) {
this.value = data;
}
}
public static Node getNextNode(Node node) {
if (node == null) {
return node;
}
if (node.right != null) {
return getLeftMost(node.right);
} else {
Node parent = node.parent;
while (parent != null && parent.left != node) {
node = parent;
parent = node.parent;
}
return parent;
}
}
public static Node getLeftMost(Node node) {
if (node == null) {
return node;
}
while (node.left != null) {
node = node.left;
}
return node;
}
public static void main(String[] args) {
Node head = new Node(6);
head.parent = null;
head.left = new Node(3);
head.left.parent = head;
head.left.left = new Node(1);
head.left.left.parent = head.left;
head.left.left.right = new Node(2);
head.left.left.right.parent = head.left.left;
head.left.right = new Node(4);
head.left.right.parent = head.left;
head.left.right.right = new Node(5);
head.left.right.right.parent = head.left.right;
head.right = new Node(9);
head.right.parent = head;
head.right.left = new Node(8);
head.right.left.parent = head.right;
head.right.left.left = new Node(7);
head.right.left.left.parent = head.right.left;
head.right.right = new Node(10);
head.right.right.parent = head.right;
Node test = head.left.left;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.left.left.right;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.left;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.left.right;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.left.right.right;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.right.left.left;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.right.left;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.right;
System.out.println(test.value + " next: " + getNextNode(test).value);
test = head.right.right; // 10's next is null
System.out.println(test.value + " next: " + getNextNode(test));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_08_GetNextNodeInBT.java
================================================
package com.ex.offer;
/**
* 后继节点
*/
public class Ex_08_GetNextNodeInBT {
public TreeLinkNode GetNext(TreeLinkNode pNode) {
if (pNode == null) {
return null;
}
if (pNode.right != null) {
return getMostLeft(pNode.right);
} else {
TreeLinkNode parent = pNode.parent;
while (parent != null && parent.left != pNode) {
pNode = parent;
parent = parent.parent;
}
return parent;
}
}
private TreeLinkNode getMostLeft(TreeLinkNode node) {
while (node.left != null) {
node = node.left;
}
return node;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_09_QueueWithTwoStack.java
================================================
package com.ex.offer;
import java.util.Stack;
/**
* problem 9: 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
*/
public class Ex_09_QueueWithTwoStack {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
int res = 0;
while (!stack1.isEmpty()) {
res = stack1.pop();
if (!stack1.isEmpty()) {
stack2.push(res);
}
}
while (!stack2.isEmpty()) {
stack1.push(stack2.pop());
}
return res;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_09_StackWithTwoQueue.java
================================================
package com.ex.offer;
import java.util.LinkedList;
import java.util.Queue;
public class Ex_09_StackWithTwoQueue {
Queue<Integer> queue1 = new LinkedList<>();
Queue<Integer> queue2 = new LinkedList<>();
public void push(int node) {
queue1.add(node);
}
public int pop() {
int res = 0;
while (!queue1.isEmpty()) {
res = queue1.poll();
if (!queue1.isEmpty()) {
queue2.add(res);
}
}
while (!queue2.isEmpty()) {
queue1.add(queue2.poll());
}
return res;
}
public static void main(String[] args) {
Ex_09_StackWithTwoQueue stack = new Ex_09_StackWithTwoQueue();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_10_Fibonacci.java
================================================
package com.ex.offer;
public class Ex_10_Fibonacci {
public static int fib1(int n) {
if (n <= 0) {
return 0;
}
if (n == 1) {
return 1;
}
return fib1(n-1) + fib1(n-2);
}
/**
* |Fn+1 Fn | |1 1|^n
* |Fn Fn-1 | |1 0|
* @param n
* @return
*/
public static int fib2(int n) {
return -1;
}
public static int Fibonacci(int n) {
if (n <= 0) {
return 0;
}
if (n == 1) {
return 1;
}
int fib1 = 0;
int fib2 = 1;
int fibN = 0;
for (int i = 2; i <= n; i++) {
fibN = fib1 + fib2;
fib1 = fib2;
fib2 = fibN;
}
return fibN;
}
public static void main(String[] args) {
int n = 5;
System.out.println(fib1(n));
System.out.println(Fibonacci(n));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_10_JumpFloor.java
================================================
package com.ex.offer;
public class Ex_10_JumpFloor {
public int jumpFloor(int target) {
if (target == 1 || target == 2) {
return target;
}
return jumpFloor(target - 1) + jumpFloor(target - 2);
}
public int JumpFloor(int target) {
if (target == 1 || target == 2) {
return target;
}
int jump1 = 1;
int jump2 = 2;
int jumpN = 0;
for (int i = 3; i <= target; i++) {
jumpN = jump1 + jump2;
jump1 = jump2;
jump2 = jumpN;
}
return jumpN;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_10_JumpFloorII.java
================================================
package com.ex.offer;
/**
* f(n)
* f(1) = 1;
* f(2) = f(2-1) + f(2-2) = 1 + 1 = 2;
* f(3) = f(3-1) + f(3-2) + f(3-2)
* = f(0) + f(1) + f(2)
* f(n-1) = f(0) + f(1) + f(2) + ... + f(n-2)
* f(n) = f(0) + f(1) + f(2) + ... + f(n-2) + f(n-1)
* = f(n-1) + f(n-1)
* = 2 * f(n-1)
* = 2 ^ 2 * f(n-2)
* = ...
* = 2 ^ (n-1) * f(1)
* = 2 ^ (n-1)
*
* f(n) = 2 ^ (n-1)
*/
public class Ex_10_JumpFloorII {
public static int JumpFloorII(int target) {
if (target == 1) {
return 1;
}
int res = 1;
for (int i = 1; i < target; i++) {
res *= 2;
}
return res;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_10_RectCover.java
================================================
package com.ex.offer;
public class Ex_10_RectCover {
public int RectCover(int target) {
if (target == 1 || target == 2) {
return target;
}
int rect1 = 1;
int rect2 = 2;
int rectN = 0;
for (int i = 3; i <= target; i++) {
rectN = rect1 + rect2;
rect1 = rect2;
rect2 = rectN;
}
return rectN;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_11_MinNumOfRotatingArray.java
================================================
package com.ex.offer;
/**
* 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
* 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
* 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
* NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
*/
public class Ex_11_MinNumOfRotatingArray {
public static int minNumberInRotateArray(int [] array) {
if (array == null || array.length <= 0) {
return 0;
}
int low = 0;
int high = array.length - 1;
int mid = low; // 若是旋转数组本身,则第一个元素是最小值,直接不进入循环
// 在这里,假设前面的递增数组第一个元素 > 后面的递增数组最后一个元素
while (array[low] >= array[high]) {
if (high - low == 1) {
mid = high;
break;
}
mid = low + (high - low) / 2;
// 如果arr[low] == array[mid] == array[high],
// 则无法用中间和两边比较的方式判断mid属于左边的递增序列还是右边的递增序列
if (array[low] == array[high] && array[low] == array[mid]) {
return minInOrder(array, low, high);
}
if (array[mid] >= array[low]) { // 此时,mid位于第一个递增数组中,因此min位于第二个递增数组中
low = mid;
} else if (array[mid] <= array[high]){
high = mid;
}
}
return array[mid];
}
private static int minInOrder(int[] array, int low, int high) {
int min = array[low];
for (int i = low + 1; i <= high; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
public static void main(String[] args) {
int[] array = new int[]{3,4,5,1,2};
int[] array1 = new int[]{1,2,3,4,5};
System.out.println(minNumberInRotateArray(array));
System.out.println(minNumberInRotateArray(array1));
int[] array2 = new int[]{1, 0, 1, 1, 1};
int[] array3 = new int[]{1, 1, 1, 0, 1};
System.out.println(minNumberInRotateArray(array2));
System.out.println(minNumberInRotateArray(array3));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_11_SortAges.java
================================================
package com.ex.offer;
public class Ex_11_SortAges {
// counting sort
public static void sortAges(int[] ages) {
if (ages == null || ages.length <= 0) {
return;
}
int maxAge = 99;
int[] countAge = new int[maxAge + 1]; // 0~99
for (int i = 0; i < ages.length; i++) {
countAge[ages[i]]++;
}
int index = 0;
for (int i = 0; i <= maxAge; i++) { // i:年龄
for (int j = 0; j < countAge[i]; j++) { // j:年龄的个数
ages[index++] = i;
}
}
}
public static void printArray(int[] arr) {
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
}
public static void main(String[] args) {
int[] ages = new int[]{2, 8, 99, 6, 20, 99, 88, 77 ,99, 44, 55, 55, 77, 23, 18};
printArray(ages);
sortAges(ages);
printArray(ages);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_12_HasPathInMatrix.java
================================================
package com.ex.offer;
public class Ex_12_HasPathInMatrix {
public static boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
if (matrix == null || matrix.length <= 0 || str == null || str.length <= 0 ||
rows <= 0 || cols <= 0 || matrix.length != rows * cols || matrix.length < str.length) {
return false;
}
boolean[] visited = new boolean[rows * cols];
int pathLength = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (hasPathCore(matrix, rows, cols,str, i, j, visited, pathLength)) {
return true;
}
}
}
return false;
}
public static boolean hasPathCore(char[] matrix, int rows, int cols, char[] str, int rowStart, int colStart,
boolean[] visited, int pathLength) {
boolean flag = false;
if (rowStart >= 0 && rowStart < rows && colStart >= 0 && colStart < cols &&
!visited[rowStart*cols+colStart] && matrix[rowStart*cols+colStart] == str[pathLength]) {
pathLength++;
visited[rowStart*cols+colStart] = true;
if (pathLength == str.length) {
return true;
}
flag = hasPathCore(matrix, rows, cols, str, rowStart, colStart+1, visited, pathLength) ||
hasPathCore(matrix, rows, cols, str, rowStart+1, colStart, visited, pathLength) ||
hasPathCore(matrix, rows, cols, str, rowStart, colStart-1, visited, pathLength) ||
hasPathCore(matrix, rows, cols, str, rowStart-1, colStart, visited, pathLength);
if (!flag) {
pathLength--;
visited[rowStart*cols+colStart] = false;
}
}
return flag;
}
public static void main(String[] args) {
String m = "ABCESFCSADEE";
String s = "ABCCED";
char[] matrix = m.toCharArray();
char[] str = s.toCharArray();
System.out.println(hasPath(matrix, 3, 4, str));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_13_MovingCount.java
================================================
package com.ex.offer;
public class Ex_13_MovingCount {
public int movingCount(int threshold, int rows, int cols) {
if (threshold < 0 || rows <= 0 || cols <= 0) {
return 0;
}
boolean[] visited = new boolean[rows * cols];
int count = helper(threshold, rows, cols, 0, 0, visited);
return count;
}
public int helper(int threshold, int rows, int cols, int row, int col, boolean[] visited) {
int count = 0;
if (check(threshold, rows, cols, row, col, visited)) {
visited[row * cols + col] = true;
count = 1 + helper(threshold, rows, cols, row, col+1, visited)
+ helper(threshold, rows, cols, row+1, col, visited)
+ helper(threshold, rows, cols, row, col-1, visited)
+ helper(threshold, rows, cols, row-1, col, visited);
}
return count;
}
public boolean check(int threshold, int rows, int cols, int row, int col, boolean[] visited) {
if (row >= 0 && row < rows && col >= 0 && col < cols
&& !visited[row * cols + col]
&& getDigitSum(row) + getDigitSum(col) <= threshold) {
return true;
}
return false;
}
public int getDigitSum(int x) {
int sum = 0;
while (x > 0) {
sum += x % 10;
x = x / 10;
}
return sum;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_14_MaxProductionAfterCutting.java
================================================
package com.ex.offer;
public class Ex_14_MaxProductionAfterCutting {
public static int maxProduction(int n) {
if (n == 1) {
return 0;
}
if (n == 2) {
return 1;
}
if (n == 3) {
return 2;
}
int[] products = new int[n+1];
products[0] = 0;
products[1] = 1;
products[2] = 2;
products[3] = 3;
int max = 0;
for (int i = 4; i <= n; i++) {
max = 0;
for (int j = 0; j <= i/2; j++) {
int product = products[j] * products[i-j];
if (product > max) {
max = product;
}
products[i] = max;
}
}
max = products[n];
return max;
}
public static int maxProductionWithGreedy(int n) {
if (n == 1) {
return 0;
}
if (n == 2) {
return 1;
}
if (n == 3) {
return 2;
}
int timesOf3 = n/3; // 此时 n < 3
if (n - timesOf3 * 3 == 1) {
timesOf3--; // 此时 n > 5
}
int timesOf2 = (n - timesOf3 * 3) / 2; // 此时 n < 2
return (int) (Math.pow(2, timesOf2) * Math.pow(3, timesOf3));
}
public static void main(String[] args) {
int n = 8;
System.out.println(maxProduction(n));
System.out.println(maxProductionWithGreedy(n));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_15_Count1.java
================================================
package com.ex.offer;
public class Ex_15_Count1 {
public static int NumberOf1(int n) {
int count = 0;
int flag = 1;
while (flag != 0) {
if ((n & flag) != 0) {
count++;
}
flag = flag << 1;
}
return count;
}
public static int NumberOf1Optimal(int n) {
int count = 0;
while (n != 0) {
count++;
n = (n-1) & n;
}
return count;
}
public static void main(String[] args) {
System.out.println(NumberOf1(10));
System.out.println(NumberOf1Optimal(10));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_15_CountDifferInMN.java
================================================
package com.ex.offer;
public class Ex_15_CountDifferInMN {
/**
* 计算需要改变m的二进制表示中的多少位才能得到n.
* @param m
* @param n
* @return
*/
public static int countDiffBetweenMN(int m, int n) {
int x = m ^ n; // 1. m ^ n : x中1的个数表示m和n中不同的位数个数
int count = 0;
while (x != 0) {
count++;
x = (x-1) & x;
}
return count;
}
public static void main(String[] args) {
int m = 10;
int n = 13;
System.out.println(countDiffBetweenMN(10, 13));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_15_IsPowerOf2.java
================================================
package com.ex.offer;
public class Ex_15_IsPowerOf2 {
/**
* 判断1个数是否是2的整数次幂,例如2 4 8 ...
* 特点:若一个数是2的整数此幂,则这个数的二进制只有一个1
* (n-1) & n 将n中最右边的一个1变成了0
* @param n
* @return
*/
public static boolean isPowerOf2(int n) {
if (n < 2) {
return false;
}
n = (n - 1) & n;
if (n == 0) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
int n = 100;
for (int i = 0; i <= n; i++) {
if (isPowerOf2(i))
System.out.println(i);
}
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_16_Power.java
================================================
package com.ex.offer;
public class Ex_16_Power {
/**
* f(n) = a ^ n
* 1. a != 0
* 2. n < 0 时, f(n) = 1 / a ^ abs(-n)
* 3. n > 0 时, f(n) = a ^ n
* @param base
* @param exponent
* @return
*/
public static double Power(double base, int exponent) {
boolean InvalidInput_flag = false; // 全局变量标识是否为非法输入
if (base == 0) {
InvalidInput_flag = true;
return 0.0;
}
int absExp = Math.abs(exponent);
double result = PowerWithUnsignedExponent(base, absExp);
if (exponent < 0) {
return 1 / result;
} else {
return result;
}
}
public static double PowerWithUnsignedExponent(double base, int exponent) {
double result = 1.0;
for (int i = 1; i <= exponent; i++) {
result *= base;
}
return result;
}
public static double PowerWithUnsignedExponentOptimal(double base, int exponent) {
if (exponent == 0) {
return 1;
}
if (exponent == 1) {
return base;
}
double result = PowerWithUnsignedExponentOptimal(base, exponent >> 1);
result *= result;
if ((exponent & 0x1) == 1) {
result *= base;
}
return result;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_17_AddTwoBigNumber.java
================================================
package com.ex.offer;
public class Ex_17_AddTwoBigNumber {
/**
* 大数相加问题:
* 大数相加不能直接使用基本的int类型,因为int可以表示的整数有限,不能满足大数的要求。
* 可以使用字符串来表示大数,模拟大数相加的过程。
*
* 思路:
* 1. 反转字符串,便于从低位到高位的相加;
* 2. 对齐字符串,短字符串的高位用 ‘0’ 补齐,便于相加;
* 3. 相加。
* @param n1
* @param n2
* @return
*/
public static String add(StringBuffer n1, StringBuffer n2) {
StringBuffer result = new StringBuffer();
n1.reverse();
n2.reverse();
int len1 = n1.length();
int len2 = n2.length();
int len = len1 > len2 ? len1 : len2;
boolean nOverFlow = false;
int nTakeOver = 0;
if (len1 < len2) {
for (int i = len1; i < len2; i++) {
n1.append('0');
}
} else {
for (int i = len2; i < len1; i++) {
n2.append('0');
}
}
for (int i = 0; i < len; i++) {
int nSum = Integer.parseInt(n1.charAt(i)+"") + (n2.charAt(i) - '0');
nSum += nTakeOver;
if (nSum >= 10) {
if (i == len - 1) {
nOverFlow = true;
}
nTakeOver = 1;
result.append(nSum - 10);
} else {
nTakeOver = 0;
result.append(nSum);
}
}
if (nOverFlow) {
result.append(nTakeOver);
}
return result.reverse().toString();
}
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("-999");
StringBuffer s2 = new StringBuffer("99");
System.out.println(add(s1, s2));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_17_Print1ToMaxNDigits.java
================================================
package com.ex.offer;
public class Ex_17_Print1ToMaxNDigits {
/**
* 1. 实现基本功能,但是当n很大时,count会出现int范围不够的问题,改成long,仍然会有相同的问题
* @param n
*/
public static void print1ToMaxNDigits_1 (int n) {
int count = 1;
int i = 0;
while (i < n) {
count *= 10;
i++;
}
for (int k = 1; k < count; k++) {
System.out.print(k + " ");
if (k % 10 == 0) {
System.out.println();
}
}
}
/**
* 2. 字符串存储数字
*
* @param n
*/
public static void print1ToMaxNDigits_2 (int n) {
if (n <= 0) {
return;
}
StringBuffer number = new StringBuffer();
for (int i = 0; i < n; i++) {
number.append('0');
}
while (!Increment(number)) {
printNumber(number);
}
}
/**
* n位所有的十进制数:n个0~9的全排列
* @param n
*/
public static void print1ToMaxNDigits_3 (int n) {
if (n <= 0) {
return;
}
StringBuffer s = new StringBuffer();
for (int i = 0; i < n; i++) {
s.append('0');
}
for (int i = 0; i < 10; i++) {
s.setCharAt(0, (char)(i+'0')); //“xx” x:0~9
print1ToMaxNDigits_3_Recur(s, n, 0);
}
}
/**
* index 数字已经确定,要确定index + 1位的数字 可选范围[0,9]
* @param s
* @param n
* @param index
*/
public static void print1ToMaxNDigits_3_Recur(StringBuffer s, int n, int index) {
if (index == n-1) {
printNumber(s);
return;
}
for (int i = 0; i < 10; i++) {
s.setCharAt(index + 1, (char)(i+'0'));
print1ToMaxNDigits_3_Recur(s, n, index + 1);
}
}
public static boolean Increment(StringBuffer s) {
boolean isOverflow = false;
int nTakeOver = 0; //进位
int len = s.length();
for (int i = len-1; i >= 0; i--) {
int nSum = s.charAt(i) - '0' + nTakeOver;
// 若是最后1位,加1
if (i == len-1) {
nSum++;
}
// 若高位第一位之后的某位nSum >= 10, 则需要执行进位操作
// 若高位第一位nSum >= 10, 则直接返回true,说明已经执行到了最高位,且最高位进位了
if (nSum >= 10) {
if (i == 0) {
isOverflow = true;
} else {
nSum -= 10;
nTakeOver = 1;
s.setCharAt(i, (char)(nSum + '0'));
}
} else { // 若高位第一位之后的任何一位的nSum < 10, 则直接退出
s.setCharAt(i, (char)(nSum + '0'));
break;
}
}
return isOverflow;
}
// 有效位前面的0不打印
public static void printNumber(StringBuffer s) {
boolean isBeginWith0 = true;
for (int i = 0; i < s.length(); i++) {
if (isBeginWith0 && s.charAt(i) != '0') {
isBeginWith0 = false;
}
if (!isBeginWith0) {
System.out.print(s.charAt(i));
}
}
System.out.println();
}
public static void main(String[] args) {
// print1ToMaxNDigits_1(2);
// System.out.println();
// print1ToMaxNDigits_2(2);
// System.out.println();
print1ToMaxNDigits_3(2);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_18_DeleteDuplicatedNode.java
================================================
package com.ex.offer;
public class Ex_18_DeleteDuplicatedNode {
public static ListNode deleteDuplication (ListNode pHead) {
ListNode first = new ListNode(-1); // 设置一个前哨节点,不用考虑pre为空的情况
first.next = pHead;
ListNode last = first;
ListNode p = pHead;
while (p != null && p.next != null) {
if (p.val == p.next.val) {
int val = p.val;
while (p != null && p.val == val) {
p = p.next;
}
last.next = p;
} else {
last = p;
p = p.next;
}
}
return first.next;
}
public static ListNode deleteDuplication1 (ListNode pHead) {
if (pHead == null || pHead.next == null) {
return pHead;
}
ListNode pre = null;
ListNode cur = pHead;
while (cur != null) {
ListNode next = cur.next;
boolean needDelete = false;
if (next != null && cur.val == next.val) {
needDelete = true;
}
if (!needDelete) {
pre = cur;
cur = next;
} else {
int val = cur.val;
while (cur != null && cur.val == val) {
cur = cur.next;
}
if (pre == null) {
pHead = cur;
} else {
pre.next = cur;
}
}
}
return pHead;
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(3);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(4);
ListNode node6 = new ListNode(5);
head.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
ListNode h1 = deleteDuplication1(head);
TestUtils.printList_ListNode(h1);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_18_DeleteNodeInSList.java
================================================
package com.ex.offer;
public class Ex_18_DeleteNodeInSList {
public static Node deleteNode(Node head, Node toBeDeleted) {
if (head == null || toBeDeleted == null) {
return head;
}
// toBeDeleted is not tail
if (toBeDeleted.next != null) {
Node temp = toBeDeleted.next;
toBeDeleted.val = temp.val;
toBeDeleted.next = temp.next;
temp = null;
} else if (head == toBeDeleted){ // toBeDeleted is tail and list length = 1
toBeDeleted = null;
head = null;
} else { // // toBeDeleted is tail and list length != 1
Node pNode = head;
while (pNode.next != toBeDeleted) {
pNode = pNode.next;
}
pNode.next = null;
}
return head;
}
public static void main(String[] args) {
Node node1 = new Node(1);
node1.next = null;
Node head1 = deleteNode(node1, node1); // case 2:注意 Java中是值传递
TestUtils.printList(head1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = null;
Node head2 = deleteNode(node2, node2); // case 1
TestUtils.printList(head2);
Node head3 = deleteNode(head2, node5); // case 3
TestUtils.printList(head3);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_19_Match.java
================================================
package com.ex.offer;
/**
* 当模式中的第二个字符不是“*”时:
* 1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。
* 2、如果 字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。
*
* 而当模式中的第二个字符是“*”时:
* 如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:
* 1、模式后移2字符,相当于x*被忽略;
* 2、字符串后移1字符,模式后移2字符;
* 3、字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位;
*/
public class Ex_19_Match {
public boolean match(char[] str, char[] pattern) {
if (str == null || pattern == null) {
return false;
}
return matchCore(str, 0, pattern, 0);
}
private boolean matchCore(char[] str, int strIndex, char[] pattern, int patIndex) {
// 有效性检验: str 和 pattern都到尾,则匹配成功
if (strIndex == str.length && patIndex == pattern.length) {
return true;
}
// pattern 先到尾,则匹配失败
if (strIndex != str.length && patIndex == pattern.length) {
return false;
}
// pattern第2个是*,且str第1个和pattern第1个匹配,分3种情况;若不匹配,则pattern后移2位
if (patIndex + 1 < pattern.length && pattern[patIndex + 1] == '*') {
if (strIndex != str.length && (pattern[patIndex] == str[strIndex] || pattern[patIndex] == '.')) {
return matchCore(str, strIndex, pattern, patIndex+2) // 模式串后移2位,相当于忽略x*
|| matchCore(str, strIndex+1, pattern, patIndex+2) // 字符串,模式串都后移1位,相当于忽略*
|| matchCore(str, strIndex+1, pattern, patIndex); // 字符串后移1位,相当于*之前扩展了。
} else {
return matchCore(str, strIndex, pattern, patIndex+2);
}
}
// pattern第2个不是* ,且str 第1个和pattern第1个匹配,则后移一位,否则直接返回false
if (strIndex != str.length && (pattern[patIndex] == str[strIndex] || pattern[patIndex] == '.')) {
return matchCore(str, strIndex+1, pattern, patIndex+1);
}
return false;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_20_IsNumber.java
================================================
package com.ex.offer;
import org.junit.Test;
public class Ex_20_IsNumber {
/**
* A.B[E|e]C
* A.B: A B任意有其一即可
* XEC: X C 缺一不可
*/
private int index = 0;
public boolean isNumeric(char[] str) {
if (str == null || str.length == 0) {
return false;
}
boolean flag = scanInteger(str);
if (index < str.length && str[index] == '.') {
index++;
flag = scanUnsignedInteger(str) || flag; //若是||的话,必须先执行scan函数,否则index无法更新
}
if (index < str.length && (str[index] == 'E' || str[index] == 'e')) {
index++;
flag = flag && scanInteger(str);
}
return flag && index == str.length;
}
private boolean scanInteger(char[] str) {
if (index < str.length && (str[index] == '+' || str[index] == '-')) {
index++;
}
return scanUnsignedInteger(str);
}
private boolean scanUnsignedInteger(char[] str) {
int start = index;
while (index < str.length && str[index] >= '0' && str[index] <= '9') {
index++;
}
return start < index;
}
/**
以下对正则进行解释:
[\\+\\-]? -> 正或负符号出现与否
\\d* -> 整数部分是否出现,如-.34 或 +3.34均符合
(\\.\\d+)? -> 如果出现小数点,那么小数点后面必须有数字,否则一起不出现
([eE][\\+\\-]?\\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现,
紧接着必须跟着整数;或者整个部分都不出现
*/
public boolean isNumberic1(char[] str) {
String string = String.valueOf(str);
return string.matches("[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?");
}
@Test
public void test() {
String str = "123.45e+6";
char[] chars = str.toCharArray();
System.out.println(isNumeric(chars));
System.out.println(isNumberic1(chars));
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_21_ReOrderArray.java
================================================
package com.ex.offer;
import org.junit.Test;
public class Ex_21_ReOrderArray {
public void reOrderArray(int [] array) {
if (array == null || array.length == 0) {
return;
}
int i = 0;
while (i < array.length) {
while (i < array.length && (array[i] & 1) == 1) {
i++;
}
int j = i+1;
while (j < array.length && (array[j] & 1) != 1) {
j++;
}
if (j < array.length) {
int tmp = array[j];
for (int k = j-1; k >= i; k--) {
array[k+1] = array[k];
}
array[i] = tmp;
i++;
} else {
break;
}
}
}
public void reOrderArray1(int [] array) {
if (array == null || array.length == 0) {
return;
}
int i = 0;
int j = array.length-1;
while (i < j) {
while ((array[i] & 1) != 0) {
i++;
}
while ((array[j] & 1) == 0) {
j--;
}
if (i > j) break;
swap(array, i, j);
}
}
public void reOrderArray2(int [] array) {
if(array == null || array.length == 0) {
return;
}
for (int i = 0; i < array.length-1; i++) {
for (int j = 0; j < array.length-1-i; j++) {
if (array[j] % 2 == 0 && array[j+1] % 2 == 1) {
swap(array, j, j+1);
}
}
}
}
private void swap(int[] array, int i, int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
@Test
public void test() {
int[] array = new int[] {1,2,3,4,5,6,7};
reOrderArray1(array);
TestUtils.printArray(array);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_22_FindKthNodeToTail.java
================================================
package com.ex.offer;
import org.junit.Test;
public class Ex_22_FindKthNodeToTail {
/**
* 1. 空链表
* 2. k <= 0
* 3. k > len
* @param head
* @param k
* @return
*/
public ListNode FindKthToTail(ListNode head, int k) {
// 1. 边界条件: head == null k <= 0
if (head == null || k <= 0) return null;
ListNode before = head;
ListNode after = head;
for (int i = 0; i < k-1; i++) {
before = before.next;
}
// 2. n < k: 第k个元素before已经到null,则k > n
if (before == null) return null;
while (before.next != null) {
before = before.next;
after = after.next;
}
return after;
}
@Test
public void test() {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
FindKthToTail(head, 5);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_22_FindMedianNodeInList.java
================================================
package com.ex.offer;
import org.junit.Test;
public class Ex_22_FindMedianNodeInList {
public ListNode findMedian(ListNode head) {
if (head == null) return null;
ListNode before = head;
ListNode after = head;
while (before.next != null && before.next.next != null) {
before = before.next.next;
after = after.next;
}
return after;
}
@Test
public void test() {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
//head.next.next.next.next = new ListNode(5);
System.out.println(findMedian(head).val);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_23_EntryNodeInList.java
================================================
package com.ex.offer;
public class Ex_23_EntryNodeInList {
public ListNode EntryNodeOfLoop(ListNode pHead) {
if (pHead == null) {
return null;
}
ListNode fast = pHead;
ListNode slow = pHead;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
break;
}
}
if (fast.next == null || fast.next.next == null) return null;
fast = pHead;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_24_ReverseSList.java
================================================
package com.ex.offer;
public class Ex_24_ReverseSList {
public ListNode ReverseList(ListNode head) {
if (head == null) return null;
ListNode pre = null;
ListNode cur = head;
ListNode next = null; // 指向剩余的需要被reverse的链表
while (cur != null) {
next = cur.next; // 记录:剩余的需要被reverse的链表
cur.next = pre; // 核心:cur -> pre
pre = cur; // 更新pre
cur = next; // 更新cur
}
head = pre;
return head;
}
public ListNode reverseList(ListNode head) {
//若是空链表或者tail节点
if (head == null || head.next == null) return head;
//先反转 head.next -> ... 例如: 1->2->3->4->null 1-> |2<-3<-4|
ListNode reverseHead = reverseList(head.next);
//修改head指向 null <- 1 <- |2<-3<-4|
head.next.next = head;
head.next = null;
return reverseHead;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_25_MergeList.java
================================================
package com.ex.offer;
import org.junit.Test;
public class Ex_25_MergeList {
public ListNode Merge(ListNode list1, ListNode list2) {
if (list1 == null) return list2;
if (list2 == null) return list1;
ListNode head = null;
if (list1.val < list2.val) {
head = list1;
head.next = Merge(list1.next, list2);
} else {
head = list2;
head.next = Merge(list1, list2.next);
}
return head;
}
public ListNode Merge1(ListNode list1, ListNode list2) {
if (list1 == null) return list2;
if (list2 == null) return list1;
ListNode pre = new ListNode(-1);
ListNode node = pre;
ListNode p1 = list1;
ListNode p2 = list2;
while (p1 != null && p2 != null) {
while (p1 != null && p1.val < p2.val) {
node.next = new ListNode(p1.val);
node = node.next;
p1 = p1.next;
}
if (p1 == null) {
while (p2 != null) {
node.next = new ListNode(p2.val);
node = node.next;
p2 = p2.next;
}
}
while (p2 != null && p2.val < p1.val) {
node.next = new ListNode(p2.val);
node = node.next;
p2 = p2.next;
}
if (p2 == null) {
while (p1 != null) {
node.next = new ListNode(p1.val);
node = node.next;
p1 = p1.next;
}
}
}
return pre.next;
}
@Test
public void test() {
ListNode head = new ListNode(1);
head.next = new ListNode(3);
head.next.next = new ListNode(5);
ListNode head1 = new ListNode(2);
head1.next = new ListNode(4);
head1.next.next = new ListNode(6);
ListNode h = Merge(head, head1);
TestUtils.printList_ListNode(h);
}
@Test
public void test1() {
ListNode head = new ListNode(1);
head.next = new ListNode(3);
head.next.next = new ListNode(5);
ListNode head1 = new ListNode(2);
head1.next = new ListNode(4);
head1.next.next = new ListNode(6);
ListNode h1 = Merge1(head, head1);
TestUtils.printList_ListNode(h1);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_26_IsSubTree.java
================================================
package com.ex.offer;
// 此题目还可以将Tree A B 序列化,然后看B字符串是否在A字符串中,KMP算法
public class Ex_26_IsSubTree {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root1 == null || root2 == null) return false;
return doesTree1HasTree2(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
public boolean doesTree1HasTree2(TreeNode root1, TreeNode root2) {
if (root2 == null) {
return true;
}
if (root1 == null) {
return false;
}
if (root1.val != root2.val) {
return false;
}
return doesTree1HasTree2(root1.left, root2.left) && doesTree1HasTree2(root1.right, root2.right);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_27_MirrorOfTree.java
================================================
package com.ex.offer;
public class Ex_27_MirrorOfTree {
public void Mirror(TreeNode root) {
if (root == null) return;
if (root.left == null && root.right == null) return;
swapLeftAndRight(root);
Mirror(root.left);
Mirror(root.right);
}
public void swapLeftAndRight(TreeNode root) {
if (root == null) return;
TreeNode tmp = root.left;
root.left = root.right;
root.right =tmp;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_28_SymmetricalTree.java
================================================
package com.ex.offer;
public class Ex_28_SymmetricalTree {
boolean isSymmetrical(TreeNode pRoot) {
if (pRoot == null) return true;
return isSymmetrical(pRoot, pRoot);
}
// 树的前序遍历和对称前序遍历
boolean isSymmetrical(TreeNode pRoot1, TreeNode pRoot2) {
// 递归结束条件
if (pRoot1 == null && pRoot2 == null) return true;
if (pRoot1 == null || pRoot2 == null) return false;
if (pRoot1.val != pRoot2.val) {
return false;
}
return isSymmetrical(pRoot1.left, pRoot2.right) && isSymmetrical(pRoot1.right, pRoot2.left);
}
// 树的前序遍历
public boolean doesTree1HasTree2(TreeNode root1, TreeNode root2) {
// 递归结束条件
if (root2 == null) {
return true;
}
if (root1 == null) {
return false;
}
if (root1.val != root2.val) {
return false;
}
return doesTree1HasTree2(root1.left, root2.left) && doesTree1HasTree2(root1.right, root2.right);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_29_PrintMatrixWithClockWise.java
================================================
package com.ex.offer;
import java.util.ArrayList;
public class Ex_29_PrintMatrixWithClockWise {
public ArrayList<Integer> printMatrix(int [][] matrix) {
if (matrix == null || matrix.length <= 0) {
return new ArrayList<>();
}
ArrayList<Integer> result = new ArrayList<>();
ArrayList<Integer> temp = new ArrayList<>();
int r1 = 0;
int c1 = 0;
int r2 = matrix.length-1;
int c2 = matrix[r2].length-1;
while (r1 <= r2 && c1 <= c2) {
temp = printMatrixWithCircle(matrix, r1++, c1++, r2--, c2--);
for (Integer i : temp) {
result.add(i);
}
}
return result;
}
public ArrayList<Integer> printMatrixWithCircle(int[][] matrix, int r1, int c1, int r2, int c2) {
ArrayList<Integer> result = new ArrayList<>();
if (r1 == r2) {
for (int i = c1; i <= c2; i++) {
result.add(matrix[r1][i]);
}
return result;
}
if (c1 == c2) {
for (int i = r1; i <= r2; i++) {
result.add(matrix[i][c1]);
}
return result;
}
for (int i = c1; i < c2; i++) {
result.add(matrix[r1][i]);
}
for (int i = r1; i < r2; i++) {
result.add(matrix[i][c2]);
}
for (int i = c2; i > c1; i--) {
result.add(matrix[r2][i]);
}
for (int i = r2; i > r1; i--) {
result.add(matrix[i][c1]);
}
return result;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_30_StackWithMinFunction.java
================================================
package com.ex.offer;
import java.util.Stack;
public class Ex_30_StackWithMinFunction {
Stack<Integer> stack = new Stack<>();
Stack<Integer> help = new Stack<>();
public void push(int node) {
stack.push(node);
if (help.isEmpty()) {
help.push(node);
}
if (help.peek() >= node) {
help.push(node);
} else {
help.push(help.peek());
}
}
public void pop() {
if (!stack.isEmpty()) {
stack.pop();
help.pop();
}
}
public int top() {
if (!stack.isEmpty()) {
return stack.peek();
}
return -1;
}
public int min() {
if (!help.isEmpty()) {
return help.peek();
}
return -1;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_31_IsPopOrder.java
================================================
package com.ex.offer;
import java.util.Stack;
public class Ex_31_IsPopOrder {
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> stack = new Stack<>();
int index = 0;
// push: 1 2 3 4 5
// pop : 4 5 3 2 1
// stack : 1 2 3 -4- | <- 5 push: empty pop: 4 5 3 2 1
// stack : 1 2 3 5 | push: empty pop: 5 3 2 1
for (int i = 0; i < pushA.length; i++) {
while (!stack.isEmpty() && popA[index] == stack.peek()) {
stack.pop(); // 遍历完push之前pop出去的
index++;
}
stack.push(pushA[i]);
}
// 遍历完push之后pop出去的
while (!stack.isEmpty() && popA[index] == stack.peek()) {
stack.pop();
index++;
}
return stack.isEmpty();
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_32_PrintTreeByLayer.java
================================================
package com.ex.offer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class Ex_32_PrintTreeByLayer {
ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
ArrayList<Integer> nodes = new ArrayList<>();
int countOfNextLevel = 0; // 统计下一层的节点数
int left = 1; // 统计本层剩余的打印数
if (pRoot == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(pRoot);
while (!queue.isEmpty()) {
TreeNode x = queue.poll();
left--;
nodes.add(x.val);
if (x.left != null) {
queue.add(x.left);
countOfNextLevel++;
}
if (x.right != null) {
queue.add(x.right);
countOfNextLevel++;
}
if (left == 0) {
result.add(new ArrayList<>(nodes)); // 一定要注意这里,拷贝构造,而不能直接将nodes(这只是个引用)扔进去
nodes.clear();
left = countOfNextLevel;
countOfNextLevel = 0;
}
}
return result;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_32_PrintTreeWithZhi.java
================================================
package com.ex.offer;
import java.util.ArrayList;
import java.util.Stack;
public class Ex_32_PrintTreeWithZhi {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
ArrayList<Integer> nodes = new ArrayList<>();
if (pRoot == null) return result;
Stack<TreeNode> s1 = new Stack<>(); // 奇数层 1
Stack<TreeNode> s2 = new Stack<>(); // 偶数层 0
int cur = 1;
int next = 0;
s1.add(pRoot);
while (!s1.isEmpty() || !s2.isEmpty()) {
TreeNode x = null;
if (cur == 1) {
x = s1.pop();
} else {
x = s2.pop();
}
nodes.add(x.val);
if (cur == 1) {
if (x.left != null) {
s2.push(x.left);
}
if (x.right != null) {
s2.push(x.right);
}
} else {
if (x.right != null) {
s1.push(x.right);
}
if (x.left != null) {
s1.push(x.left);
}
}
if (cur == 1 && s1.isEmpty() && !nodes.isEmpty()) {
result.add(new ArrayList<>(nodes));
nodes.clear();
next = 1-next;
cur = 1-cur;
}
if (cur == 0 && s2.isEmpty() && !nodes.isEmpty() ) {
result.add(new ArrayList<>(nodes));
nodes.clear();
next = 1-next;
cur = 1-cur;
}
}
return result;
}
// 此答案有错
public ArrayList<ArrayList<Integer>> Print1(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
ArrayList<Integer> nodes = new ArrayList<>();
if (pRoot == null) return result;
Stack<TreeNode>[] stacks = new Stack[2];
int current = 0; //奇数层
int next = 1; //偶数层
stacks[current].push(pRoot);
while (!stacks[0].isEmpty() || !stacks[1].isEmpty()) {
TreeNode x = stacks[current].pop();
nodes.add(x.val);
if (current == 0) {
if (x.left != null) {
stacks[next].push(x.left);
}
if (x.right != null) {
stacks[next].push(x.right);
}
} else {
if (x.right != null) {
stacks[next].push(x.right);
}
if (x.left != null) {
stacks[next].push(x.left);
}
}
if (stacks[current].isEmpty()) {
result.add(new ArrayList<>(nodes));
nodes.clear();
current = 1 - current;
next = 1- next;
}
}
return result;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_32_TraverseTreeByLayer.java
================================================
package com.ex.offer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
/**
* 注1:
* 树的按层遍历借助于 队列
* 树的先中后序遍历借助于 栈
*
* 注2:
* 树的按层遍历本质上说就是广度优先遍历二叉树(树是图的一种特殊退化形式)
* 那么如何广度优先遍历有向图呢?
*
* A:无论是广度优先遍历有向图还是二叉树,都需要用到队列。
* 首先把起始节点(或者根节点(对树而言))放入队列
* 然后每次从队列的头部取出一个节点,遍历这个节点之后把它能够到达的节点(或者子节点(对树而言))都一次放入队列中
* 重复以上遍历过程,知道队列中所有的节点全部被遍历完。
*
*/
public class Ex_32_TraverseTreeByLayer {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode temp = queue.poll();
result.add(temp.val);
if (temp.left != null) queue.add(temp.left);
if (temp.right != null) queue.add(temp.right);
}
return result;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_33_VerifySequenceOfBST.java
================================================
package com.ex.offer;
import org.junit.Test;
public class Ex_33_VerifySequenceOfBST {
public boolean VerifySequenceOfBST(int [] sequence) {
if (sequence == null || sequence.length <= 0) {
return false;
}
return verifySequence(sequence, 0, sequence.length-1);
}
public boolean verifySequence(int[] sequence, int start, int end) {
if (sequence == null || start > end) {
return false;
}
// 若数组区间[start, end]元素为0则停止递归,其实可以去掉这个判断
if (start == end) {
return true;
}
int root = sequence[end];
// 找到左右子树的分界点[i-1,i]
// 小于root: [start, i-1]
int i = start;
for ( ; i < end; i++) {
if (sequence[i] > root) {
break;
}
}
// 大于root: [i, end-1]
int j = i;
for ( ; j < end; j++) {
if (sequence[j] < root) {
return false;
}
}
// 判断左子树
boolean left = true; // 若左子树为空,则左子树为后序遍历序列
if (i > start) {
left = verifySequence(sequence, start, i-1);
}
// 判断右子树
boolean right = true; // 若右子树为空,则右子树为后序遍历序列
if (i < end) {
right = verifySequence(sequence, i, end-1);
}
return left && right;
}
@Test
public void test() {
int[] arr = new int[] {5, 7, 6, 9, 11, 10, 8};
boolean result = VerifySequenceOfBST(arr);
System.out.println(result);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_34_FindPathInBT.java
================================================
package com.ex.offer;
import org.junit.Test;
import java.util.ArrayList;
public class Ex_34_FindPathInBT {
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
ArrayList<ArrayList<Integer>> pathList = new ArrayList<>();
if (root == null) {
return pathList;
}
ArrayList<Integer> path = new ArrayList<>();
findPath(root, target, path, pathList);
return pathList;
}
private void findPath(TreeNode root,
int target,
ArrayList<Integer> path,
ArrayList<ArrayList<Integer>> pathList) {
if (root == null) return;
if (root.left == null && root.right == null) {
if (root.val == target) {
path.add(root.val);
pathList.add(path);
}
return;
}
path.add(root.val);
ArrayList<Integer> pathCopy = new ArrayList<>(path);
findPath(root.left, target - root.val, path, pathList);
findPath(root.right, target - root.val, pathCopy, pathList);
return;
}
@Test
public void test() {
TreeNode node1 = new TreeNode(10);
TreeNode node2 = new TreeNode(5);
TreeNode node3 = new TreeNode(12);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(7);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
ArrayList<ArrayList<Integer>> list = FindPath(node1, 22);
int a = 5;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_34_FindPathInBT_1.java
================================================
package com.ex.offer;
import org.junit.Test;
import java.util.ArrayList;
public class Ex_34_FindPathInBT_1 {
ArrayList<ArrayList<Integer>> pathList = new ArrayList<>();
ArrayList<Integer> path = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
if (root == null) return pathList;
findPath(root, target);
return pathList;
}
private void findPath(TreeNode root, int target) {
path.add(root.val);
if (root.val == target && root.left == null && root.right == null) {
pathList.add(new ArrayList<>(path));
}
if (root.left != null) {
findPath(root.left, target - root.val);
}
if (root.right != null) {
findPath(root.right, target - root.val);
}
path.remove(path.size()-1);
return;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_34_FindPathInBT_2.java
================================================
package com.ex.offer;
import java.util.ArrayList;
public class Ex_34_FindPathInBT_2 {
ArrayList<ArrayList<Integer>> pathList = new ArrayList<>();
ArrayList<Integer> path = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
if (root == null) return pathList;
findPath(root, target, 0);
return pathList;
}
private void findPath(TreeNode root, int target, int sum) {
path.add(root.val);
sum += root.val;
if (sum == target && root.left == null && root.right == null) {
pathList.add(new ArrayList<>(path));
}
if (root.left != null) {
findPath(root.left, target, sum);
}
if (root.right != null) {
findPath(root.right, target, sum);
}
path.remove(path.size()-1);
return;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_35_CloneList.java
================================================
package com.ex.offer;
import java.util.HashMap;
import java.util.Map;
public class Ex_35_CloneList {
public RandomListNode Clone(RandomListNode pHead)
{
if (pHead == null) return pHead;
RandomListNode node = pHead;
// A - A' - B - B' - C - C' - null
while (node != null) {
RandomListNode cloneNode = new RandomListNode(node.label);
cloneNode.next = node.next;
node.next = cloneNode;
node = cloneNode.next;
}
// 设置Random
node = pHead;
while (node != null) {
RandomListNode cloneNode = node.next;
if (node.random != null) cloneNode.random = node.random.next;
node = cloneNode.next;
}
RandomListNode head = pHead.next;
// 拆分链表
node = pHead;
RandomListNode node1 = head;
while (node != null) {
node.next = node1.next;
node = node.next;
if (node == null) break;
node1.next = node.next;
node1 = node1.next;
}
return head;
}
public RandomListNode Clone1(RandomListNode pHead)
{
if (pHead == null) return pHead;
Map<RandomListNode, RandomListNode> map = new HashMap<>();
RandomListNode node = pHead;
while (node != null) {
map.put(node, new RandomListNode(node.label));
}
for (RandomListNode key : map.keySet()) {
map.get(key).next = map.get(key.next);
map.get(key).random = map.get(key.random);
}
return map.get(0);
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_36_ConvertBetweenBSTAndDList.java
================================================
package com.ex.offer;
import java.util.Stack;
public class Ex_36_ConvertBetweenBSTAndDList {
TreeNode head = null;
TreeNode tail = null;
public TreeNode Convert(TreeNode pRootOfTree) {
convert(pRootOfTree);
return head;
}
public void convert(TreeNode pRootOfTree) {
if (pRootOfTree == null) return;
convert(pRootOfTree.left);
if (head == null) { // 第一次,标记head节点
head = pRootOfTree;
tail = pRootOfTree;
} else {
tail.right = pRootOfTree;
pRootOfTree.left = tail;
tail = pRootOfTree;
}
convert(pRootOfTree.right);
}
public TreeNode ConvertIterative(TreeNode pRootOfTree) {
if (pRootOfTree == null) return null;
Stack<TreeNode> stack = new Stack<>();
TreeNode node = pRootOfTree;
TreeNode pre = null;
TreeNode head = null;
boolean isFirst = true;
while (node != null || !stack.isEmpty()) {
while (node != null) {
stack.push(node);
node = node.left;
}
node = stack.pop();
if (isFirst) {
head = node;
pre = head;
isFirst = false;
} else {
pre.right = node;
node.left = pre;
pre = node;
}
node = node.right;
}
return head;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_37_SerializeBT.java
================================================
package com.ex.offer;
public class Ex_37_SerializeBT {
String Serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
if (root == null) {
return sb.toString();
}
serialize(root, sb);
return sb.toString();
}
void serialize(TreeNode root, StringBuilder sb) {
if (root == null) {
sb.append("#,");
return;
}
sb.append(root.val + ",");
serialize(root.left, sb);
serialize(root.right, sb);
}
int index = -1;
TreeNode Deserialize(String str) {
if (str.length() == 0) return null;
String[] strs = str.split(",");
return Deserialize(strs);
}
TreeNode Deserialize(String[] strs) {
index++; // 遍历strs,待返回root时,遍历结束
TreeNode node = null;
if (!strs[index].equals("#")) {
node = new TreeNode(Integer.parseInt(strs[index]));
node.left = Deserialize(strs);
node.right = Deserialize(strs);
}
return node;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_38_EightQueen.java
================================================
package com.ex.offer;
import org.junit.Test;
// 8皇后问题与回溯法:https://www.cnblogs.com/bigmoyan/p/4521683.html
//
// 回溯法
// 引例:设想将你放在迷宫之中,要想走出迷宫,最直接的办法是什么?试!先选择一条路开始走,
// 走不通就退回去尝试别的路,走不通接着回退,直到走通为止。
// 本质: 暴力破解。只不过是在暴力破解之前,利用了一些条件减少了暴力破解的一些步骤。
public class Ex_38_EightQueen {
private static final int QUEEN_NUMBER = 8; // 皇后个数
private int[] columns = new int[QUEEN_NUMBER]; // 每个皇后存储的列 (row, col), row天然不相等
private int total = 0;
public int solution() {
queen(0);
return total;
}
private void queen(int row) {
if (row == QUEEN_NUMBER) {
total++;
} else {
for (int col = 0; col != QUEEN_NUMBER; col++) {
columns[row] = col;
if (isPut(row)) {
queen(row+1);
}
}
}
}
private boolean isPut(int row) {
for (int i = 0; i != row; i++) {
if (columns[row] == columns[i] || row - i == Math.abs(columns[row]-columns[i])) {
return false;
}
}
return true;
}
@Test
public void test() {
System.out.println(solution()); //92
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_38_StringCombination.java
================================================
package com.ex.offer;
import org.junit.Test;
import java.util.ArrayList;
public class Ex_38_StringCombination {
public ArrayList<String> Combination(String str) {
ArrayList<String> res = new ArrayList<>();
if (str == null || str.length() <= 0) return res;
combination(str.toCharArray(), 0, res);
return res;
}
private void combination(char[] chars, int startIndex, ArrayList<String> res) {
if (startIndex == chars.length) {
StringBuilder sb = new StringBuilder();
for (char c : chars) {
if (c != 0) sb.append(c);
}
res.add(sb.toString());
return;
}
combination(chars, startIndex+1, res);
char temp = chars[startIndex];
chars[startIndex] = 0;
combination(chars, startIndex+1, res);
chars[startIndex] = temp;
}
@Test
public void test() {
ArrayList<String> res = Combination(new String("abc"));
for (String str : res) {
System.out.println(str);
}
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_38_StringPermutation.java
================================================
package com.ex.offer;
import java.util.ArrayList;
import java.util.Collections;
public class Ex_38_StringPermutation {
public ArrayList<String> Permutation(String str) {
ArrayList<String> res = new ArrayList<>();
if (str == null || str.length() <= 0) return res;
permutation(str.toCharArray(), 0, res);
Collections.sort(res);
return res;
}
private void permutation(char[] chars, int startIndex, ArrayList<String> res) {
if (startIndex == chars.length-1) {
String str = String.valueOf(chars);
if (!res.contains(str)) {
res.add(str);
}
} else {
// 第一个字符与后面所有字符逐个交换:a|bcde b|acde c|bade d|bcae e|bcda
// 第一个字符固定,第二个字符和后面所有字符逐个交换:a || b|cde c|bde d|cbe e|cdb
for (int i = startIndex; i < chars.length; i++) {
swap(chars, startIndex, i);
permutation(chars, startIndex + 1, res); // a || b|cde c|bde d|cbe e|cdb
swap(chars, startIndex, i);
}
}
}
private void swap(char[] chars, int i, int j) {
char tmp = chars[i];
chars[i] = chars[j];
chars[j] = tmp;
}
}
================================================
FILE: offer/src/com/ex/offer/Ex_39_KthSmallestNumInArrayWithoutSort.java
================================================
package com.ex.offer;
public class Ex_39_KthSmallestNumInArrayWithoutSort {
/**
* 找到第K个最小的数字,同时RAND-PARTITION之后,K个数(包含第K个数)左侧为最小的K个数
* @param arr
* @param K
* @return
*/
public static int kthNumIte(int[] arr, int K) {
if (arr == null || arr.length < K || K <= 0 || arr.length <= 0) {
return -1;
}
int low = 0;
int high = arr.length - 1;
int p = partition(arr, low, high);
while (p != K-1) {
if (p > K - 1) {
p = partition(arr, low, p-1);
} else {
p = partition(arr, p+1, high);
}
}
return arr[p];
}
public static int kthNum(int[] arr, int K) {
if (arr == null || arr.length < K || K <= 0 || arr.length <= 0) {
return -1;
}
return kthNum(arr, K, 0, arr.length-1);
}
/**
* RAND-SELECT(array, K, low, high)
* 1. if low == high, RETURN array[low] // 递归结束的条件
* 2. p = RAND-PARTITION(arr, low, high) // [low, high]中,pivot元素在数组中的index
* 3. count = p - low + 1; // [low, high]中, pivot元素是第几个元素
* 4. if count > k RETURN RAND-SELECT(array, K, low, p-1)
* else if count < K RETURN RAND-SELECT(array, K-count, p+1, high)
* else RETURN arr[p];
*
* @param arr
* @param K
* @param low
* @param high
* @return
*/
public static int kthNum(int[] arr, int K, int low, int high) {
if (low == high) {
return arr[low];
} else{
int p = partition(arr, low, high);
int count = p - low + 1; // count:从low开始第count个值
if (count > K) {
return kthNum(arr, K, low, p-1);
} else if (count < K) {
return kthNum(arr, K-count, p+1, high);
} else {
return arr[p];
}
}
}
/**
* RAND-PARTITION(array, low, high)
*
* 1. 随机挑选一个元素作为主元pivot,将该元素换到low位置;
* 2. 指定2个指针:
* 2.1 i:指向low,若arr[i] < pivot,则i++;
* 2.2 j:指向high,若arr[j] > pivot, 则j--;
* 不断重复2.1 2.2,此时,arr[i] >= pivot, arr[j] <= pivot, 交换arr[i], arr[j]
* 3. 重复步骤2,直到 i < j条件不满足
* 4. 交换 arr[low] 和 arr[j]
* low i j
* [pivot, <= x, >= x]
*
* @param arr
* @param low
* @param high
* @return
*/
public static int partition(int[] arr, int low, int high) {
if (low == high) {
return low;
}
int pIndex = low + (int)(Math.random() * (high - low));
swap(arr, pIndex, low);
int pivot = arr[low]; // pivot始终选择第一个元素
int i = low;
int j = high + 1;
while (i < j) {
while (arr[++i] < pivot) {
if (i == high) {
break;
}
}
while (arr[--j] > pivot) {
if (j == low) {
break;
}
}
if (i > j) {
break;
}
swap(arr, i, j);
}
swap(arr, j, low);
return j;
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] arr = new int[] {6, 4, 7, -2, 9, 6, 8, 2, -5, 5};
// ArrayUtils.printArray(arr);
// int p = partition(arr, 0, arr.length-1);
// System.out.println(p + " : " + arr[p]);
// ArrayUtils.printArray(arr);
System.out.println("======================================");
TestUtils.printArray(arr);
for (int K = 1; K <= arr.length; K++) {
int kth = kthNum(arr, K);
System.out.print(kth + " ");
}
int kth = kthNum(arr, 0);
System.out.print(kth + " ");
System.out.println();
System.out.println("=============================
gitextract_6zdwcmqq/
├── .gitignore
├── README.md
├── algorithms/
│ └── src/
│ ├── array/
│ │ ├── BinarySearch.java
│ │ ├── BinarySearchTest.java
│ │ ├── GenericArray.java
│ │ ├── MinNumberInRotatedArray.java
│ │ └── MinNumberInRotatedArrayTest.java
│ ├── joseph/
│ │ └── Joseph.java
│ ├── linkedlist/
│ │ ├── FindMidNode.java
│ │ ├── FindMidNodeTest.java
│ │ ├── SingleLinkedList.java
│ │ └── SingleLinkedListTest.java
│ ├── lru/
│ │ ├── LRU.java
│ │ └── LRUTest.java
│ ├── queue/
│ │ ├── ArrayQueue.java
│ │ ├── CircularQueue.java
│ │ ├── ListQueue.java
│ │ └── Queue.java
│ └── stack/
│ ├── ArrayStack.java
│ ├── DynamicArrayStack.java
│ ├── ListStack.java
│ ├── SampleBrowser.java
│ └── Stack.java
├── appendix/
│ ├── instructions.md
│ └── 刷题笔记.md
├── leetcode/
│ └── src/
│ ├── linkedlistcycle_141/
│ │ └── LinkedListCycle.java
│ ├── lrucache_146/
│ │ └── LRUCache.java
│ ├── mergetwosortedlist_21/
│ │ └── Merge2SortedLists.java
│ ├── middleofthelinkedlist_876/
│ │ └── MiddleNode.java
│ ├── palindromelinkedlist_234/
│ │ └── PalindromeLinkedList.java
│ ├── removenthnodefromendoflist_19/
│ │ └── RemoveNthNodeFromEndOfList.java
│ ├── reverselinkedlist_206/
│ │ └── ReverseList.java
│ ├── threesum_015/
│ │ └── ThreeSum.java
│ └── twosum_001/
│ └── TwoSum.java
├── offer/
│ └── src/
│ └── com/
│ └── ex/
│ ├── offer/
│ │ ├── Attention.txt
│ │ ├── Ex_03_FindDuplicatedNumInArray.java
│ │ ├── Ex_03_FindDuplicatedNumInWithoutChangeArray.java
│ │ ├── Ex_04_FindNumIn2VArray.java
│ │ ├── Ex_05_ReplaceSpace.java
│ │ ├── Ex_06_PrintListFromTailToHead.java
│ │ ├── Ex_07_ReConstructBT.java
│ │ ├── Ex_08_DescendantNode.java
│ │ ├── Ex_08_GetNextNodeInBT.java
│ │ ├── Ex_09_QueueWithTwoStack.java
│ │ ├── Ex_09_StackWithTwoQueue.java
│ │ ├── Ex_10_Fibonacci.java
│ │ ├── Ex_10_JumpFloor.java
│ │ ├── Ex_10_JumpFloorII.java
│ │ ├── Ex_10_RectCover.java
│ │ ├── Ex_11_MinNumOfRotatingArray.java
│ │ ├── Ex_11_SortAges.java
│ │ ├── Ex_12_HasPathInMatrix.java
│ │ ├── Ex_13_MovingCount.java
│ │ ├── Ex_14_MaxProductionAfterCutting.java
│ │ ├── Ex_15_Count1.java
│ │ ├── Ex_15_CountDifferInMN.java
│ │ ├── Ex_15_IsPowerOf2.java
│ │ ├── Ex_16_Power.java
│ │ ├── Ex_17_AddTwoBigNumber.java
│ │ ├── Ex_17_Print1ToMaxNDigits.java
│ │ ├── Ex_18_DeleteDuplicatedNode.java
│ │ ├── Ex_18_DeleteNodeInSList.java
│ │ ├── Ex_19_Match.java
│ │ ├── Ex_20_IsNumber.java
│ │ ├── Ex_21_ReOrderArray.java
│ │ ├── Ex_22_FindKthNodeToTail.java
│ │ ├── Ex_22_FindMedianNodeInList.java
│ │ ├── Ex_23_EntryNodeInList.java
│ │ ├── Ex_24_ReverseSList.java
│ │ ├── Ex_25_MergeList.java
│ │ ├── Ex_26_IsSubTree.java
│ │ ├── Ex_27_MirrorOfTree.java
│ │ ├── Ex_28_SymmetricalTree.java
│ │ ├── Ex_29_PrintMatrixWithClockWise.java
│ │ ├── Ex_30_StackWithMinFunction.java
│ │ ├── Ex_31_IsPopOrder.java
│ │ ├── Ex_32_PrintTreeByLayer.java
│ │ ├── Ex_32_PrintTreeWithZhi.java
│ │ ├── Ex_32_TraverseTreeByLayer.java
│ │ ├── Ex_33_VerifySequenceOfBST.java
│ │ ├── Ex_34_FindPathInBT.java
│ │ ├── Ex_34_FindPathInBT_1.java
│ │ ├── Ex_34_FindPathInBT_2.java
│ │ ├── Ex_35_CloneList.java
│ │ ├── Ex_36_ConvertBetweenBSTAndDList.java
│ │ ├── Ex_37_SerializeBT.java
│ │ ├── Ex_38_EightQueen.java
│ │ ├── Ex_38_StringCombination.java
│ │ ├── Ex_38_StringPermutation.java
│ │ ├── Ex_39_KthSmallestNumInArrayWithoutSort.java
│ │ ├── Ex_39_MoreThanHalfNum.java
│ │ ├── Ex_40_GetLeastKNumbers.java
│ │ ├── Ex_41_MedianInDataFlow.java
│ │ ├── Ex_42_MaxSumOfSubArray.java
│ │ ├── Ex_43_NumberOf1Between1AndN.java
│ │ ├── Ex_44_ANumInArray.java
│ │ ├── Ex_45_MinNumByConcatArray.java
│ │ ├── Ex_46_ConvertStringToIP.java
│ │ ├── Ex_46_TranslationFromIntToString.java
│ │ ├── Ex_47_MaxGiftValue.java
│ │ ├── Ex_48_LongestSubStringWithDuplication.java
│ │ ├── Ex_49_UglyNumber.java
│ │ ├── Ex_50_FirstNotRepeatedChar.java
│ │ ├── Ex_50_FirstNotRepeatedCharInDataFlow.java
│ │ ├── Ex_50_StringUtilsSolutions.java
│ │ ├── Ex_51_InversePairs.java
│ │ ├── Ex_51_InversePairs_BigData.java
│ │ ├── Ex_52_FirstCommonNode.java
│ │ ├── Ex_53_GetMissingNumber.java
│ │ ├── Ex_53_GetNumberOfK.java
│ │ ├── Ex_53_GetNumberSameAsIndex.java
│ │ ├── Ex_54_KthNodeInBST.java
│ │ ├── Ex_55_BalancedBT.java
│ │ ├── Ex_55_DepthOfBT.java
│ │ ├── Ex_56_AppearanceOnce.java
│ │ ├── Ex_56_AppearanceOnce_Continued.java
│ │ ├── Ex_57_FindContinuousSequence.java
│ │ ├── Ex_57_FindNumbersWithSum.java
│ │ ├── Ex_58_ROL.java
│ │ ├── Ex_58_ReverseSentence.java
│ │ ├── Ex_59_MaxNumOfSlidingWindow.java
│ │ ├── Ex_59_QueueWithMax.java
│ │ ├── Ex_60_ProbabilityOfS.java
│ │ ├── Ex_61_ContinuousSequence.java
│ │ ├── Ex_62_Josephus.java
│ │ ├── Ex_63_MaxProfits.java
│ │ ├── Ex_64_SumFrom1ToN.java
│ │ ├── Ex_65_AddWithoutCarry.java
│ │ ├── Ex_65_SwapNumWithoutTemp.java
│ │ ├── Ex_66_ConstructMultiplyArray.java
│ │ ├── Ex_67_StringToInt.java
│ │ ├── Ex_68_LowestCommonAncestor.java
│ │ ├── ListNode.java
│ │ ├── Node.java
│ │ ├── RandomListNode.java
│ │ ├── TestUtils.java
│ │ ├── TreeLinkNode.java
│ │ └── TreeNode.java
│ └── singleton/
│ ├── Singleton1.java
│ ├── Singleton2.java
│ ├── Singleton3.java
│ ├── Singleton4.java
│ ├── Singleton5.java
│ └── singleton.md
├── practice/
│ ├── Final.md
│ ├── README.md
│ └── src/
│ └── io/
│ └── gkd/
│ ├── ListNode.java
│ ├── Node.java
│ ├── TreeNode.java
│ ├── lectures/
│ │ ├── lecture04/
│ │ │ ├── Lc077_Combine.java
│ │ │ └── Lc078_SubSets.java
│ │ └── lecture05/
│ │ ├── Lc094_InOrderTraversal.java
│ │ ├── Lc105_BuildTree.java
│ │ ├── Lc236_LCA.java
│ │ ├── Lc297_Codec.java
│ │ ├── Lc429_LevelOrderNTree.java
│ │ └── Lc589_PreOrderNTree.java
│ ├── week01/
│ │ ├── Lc021_MergeTwoLists.java
│ │ └── Lc066_PlusOne.java
│ ├── week02/
│ │ ├── Lc146_LRUCache.java
│ │ └── Lc697_FindShortestSubArray.java
│ └── week03/
│ ├── Lc106_BuildTree.java
│ ├── Lc210_FindOrder2.java
│ └── NOTES.md
├── questions/
│ └── questions.md
├── solutions/
│ └── 剑指offer 题解.md
└── summary/
└── algorithm.md
SYMBOL INDEX (651 symbols across 155 files)
FILE: algorithms/src/array/BinarySearch.java
class BinarySearch (line 3) | public class BinarySearch {
method binarySearch (line 6) | public static int binarySearch(int[] array, int target) {
method binarySearchRecur (line 28) | public static int binarySearchRecur(int[] array, int target) {
method bs (line 33) | private static int bs(int[] array, int target, int lo, int hi) {
method bsFirst (line 50) | public static int bsFirst(int[] array, int target) {
method bsLast (line 74) | public static int bsLast(int[] array, int target) {
method bsFistGE (line 98) | public static int bsFistGE(int[] array, int target) {
method bsLastLE (line 120) | public static int bsLastLE(int[] array, int target) {
FILE: algorithms/src/array/BinarySearchTest.java
class BinarySearchTest (line 6) | public class BinarySearchTest {
method testBinarySearch (line 9) | @Test
method testBinarySearchRecur (line 35) | @Test
method testBsFirst (line 62) | @Test
method testBsLast (line 79) | @Test
method testBsFirstGE (line 96) | @Test
method testBsLastLE (line 113) | @Test
FILE: algorithms/src/array/GenericArray.java
class GenericArray (line 10) | public class GenericArray<T> {
method GenericArray (line 15) | public GenericArray(int capacity) {
method GenericArray (line 21) | public GenericArray() {
method getCapacity (line 26) | public int getCapacity() {
method getSize (line 31) | public int getSize() {
method isEmpty (line 36) | public boolean isEmpty() {
method set (line 41) | public void set(int index, T e) {
method get (line 47) | public T get(int index) {
method contains (line 53) | public boolean contains(T e) {
method find (line 65) | public int find(T e) {
method add (line 76) | public void add(int index, T e) {
method addFirst (line 89) | public void addFirst(T e) {
method addLast (line 94) | public void addLast(T e) {
method remove (line 99) | public T remove(int index) {
method removeFirst (line 116) | public T removeFirst() {
method removeLast (line 121) | public T removeLast() {
method removeElement (line 126) | public void removeElement(T e) {
method toString (line 133) | @Override
method resize (line 150) | private void resize(int capacity) {
method checkIndex (line 158) | private void checkIndex(int index) {
method checkIndexForRemove (line 164) | private void checkIndexForRemove(int index) {
FILE: algorithms/src/array/MinNumberInRotatedArray.java
class MinNumberInRotatedArray (line 3) | public class MinNumberInRotatedArray {
method getMinNumber (line 5) | public static int getMinNumber(int[] arr) {
method getMinInOrder (line 37) | private static int getMinInOrder(int[] arr, int l, int r) {
FILE: algorithms/src/array/MinNumberInRotatedArrayTest.java
class MinNumberInRotatedArrayTest (line 6) | public class MinNumberInRotatedArrayTest {
method testGetMinNumber (line 8) | @Test
FILE: algorithms/src/joseph/Joseph.java
class Joseph (line 18) | public class Joseph {
method lastRemain (line 19) | public int lastRemain(int n, int m) {
method lastRemainIter (line 31) | public int lastRemainIter(int n, int m) {
FILE: algorithms/src/linkedlist/FindMidNode.java
class FindMidNode (line 3) | public class FindMidNode {
method findMidNode (line 6) | public static Node findMidNode(Node head) {
method findMidNodeFast (line 29) | public static Node findMidNodeFast(Node head) {
method createNode (line 46) | public static Node createNode(int value) {
class Node (line 50) | public static class Node {
method Node (line 54) | public Node(int data, Node next) {
FILE: algorithms/src/linkedlist/FindMidNodeTest.java
class FindMidNodeTest (line 7) | public class FindMidNodeTest {
method testFindMidNode (line 9) | @Test
method testFindMidNodeFast (line 26) | @Test
FILE: algorithms/src/linkedlist/SingleLinkedList.java
class SingleLinkedList (line 3) | public class SingleLinkedList {
method findByValue (line 8) | public Node findByValue(int value) {
method findByIndex (line 20) | public Node findByIndex(int index) {
method insertToHead (line 35) | public void insertToHead(int value) {
method insertToHead (line 40) | public void insertToHead(Node newNode) {
method insertToTail (line 49) | public void insertToTail(int value) {
method insertToTail (line 54) | public void insertToTail(Node newNode) {
method insertAfter (line 73) | public void insertAfter(Node p, int value) {
method insertAfter (line 78) | public void insertAfter(Node p, Node newNode) {
method insertBefore (line 87) | public void insertBefore(Node p, int value) {
method insertBefore (line 92) | public void insertBefore(Node p, Node newNode) {
method deleteByNode (line 116) | public void deleteByNode(Node p) {
method deleteByValue (line 138) | public void deleteByValue(int value) {
method printAll (line 154) | public void printAll() {
method createNode (line 167) | public static Node createNode(int value) {
class Node (line 171) | public static class Node {
method Node (line 175) | public Node(int data, Node next) {
method getData (line 180) | public int getData() {
FILE: algorithms/src/linkedlist/SingleLinkedListTest.java
class SingleLinkedListTest (line 5) | public class SingleLinkedListTest {
method testSingleLinkedList (line 7) | @Test
FILE: algorithms/src/lru/LRU.java
class LRU (line 30) | public class LRU<K,V> implements Iterable<K> {
class Node (line 38) | private class Node {
method Node (line 44) | public Node(K k, V v) {
method LRU (line 50) | public LRU(int maxSize) {
method get (line 62) | public V get(K key) {
method put (line 75) | public void put(K key, V value) {
method removeTail (line 91) | private Node removeTail() {
method appendToHead (line 104) | private void appendToHead(Node node) {
method unlink (line 113) | private void unlink(Node node) {
method iterator (line 124) | @Override
class LRUIterator (line 129) | private class LRUIterator<K> implements Iterator<K> {
method hasNext (line 132) | @Override
method next (line 137) | @Override
FILE: algorithms/src/lru/LRUTest.java
class LRUTest (line 6) | public class LRUTest {
method testLRU (line 7) | @Test
FILE: algorithms/src/queue/ArrayQueue.java
class ArrayQueue (line 3) | public class ArrayQueue<T> implements Queue<T> {
method ArrayQueue (line 9) | public ArrayQueue(int capacity) {
method enqueue (line 17) | @Override
method dequeue (line 42) | @Override
method printAll (line 55) | public void printAll() {
method main (line 64) | public static void main(String[] args) {
FILE: algorithms/src/queue/CircularQueue.java
class CircularQueue (line 3) | public class CircularQueue<T> {
method CircularQueue (line 9) | public CircularQueue(int capacity) {
method enqueue (line 17) | public boolean enqueue(T item) {
method dequeue (line 29) | public T dequeue() {
method printAll (line 43) | public void printAll() {
method main (line 52) | public static void main(String[] args) {
FILE: algorithms/src/queue/ListQueue.java
class ListQueue (line 3) | public class ListQueue<T> implements Queue<T> {
method enqueue (line 9) | @Override
method dequeue (line 25) | @Override
method printAll (line 39) | public void printAll() {
class Node (line 48) | private static class Node<T>{
method Node (line 52) | public Node(T data, Node next) {
method getData (line 57) | public T getData() {
method main (line 62) | public static void main(String[] args) {
FILE: algorithms/src/queue/Queue.java
type Queue (line 3) | public interface Queue<T> {
method enqueue (line 4) | boolean enqueue(T item);
method dequeue (line 5) | T dequeue();
FILE: algorithms/src/stack/ArrayStack.java
class ArrayStack (line 3) | public class ArrayStack<T> implements Stack<T> {
method ArrayStack (line 9) | public ArrayStack(int capacity) {
method push (line 16) | @Override
method pop (line 31) | @Override
method peek (line 45) | @Override
method main (line 53) | public static void main(String[] args) {
FILE: algorithms/src/stack/DynamicArrayStack.java
class DynamicArrayStack (line 8) | public class DynamicArrayStack<T> implements Stack<T> {
method DynamicArrayStack (line 13) | public DynamicArrayStack(int capacity) {
method push (line 21) | @Override
method pop (line 35) | @Override
method peek (line 48) | @Override
method resize (line 56) | private void resize(int size) {
method main (line 65) | public static void main(String[] args) {
FILE: algorithms/src/stack/ListStack.java
class ListStack (line 3) | public class ListStack<T> implements Stack<T> {
method push (line 7) | @Override
method pop (line 22) | @Override
method peek (line 37) | @Override
class Node (line 45) | public static class Node<T> {
method Node (line 49) | public Node(T data, Node next) {
method getData (line 54) | public T getData() {
method main (line 59) | public static void main(String[] args) {
FILE: algorithms/src/stack/SampleBrowser.java
class SampleBrowser (line 6) | public class SampleBrowser {
FILE: algorithms/src/stack/Stack.java
type Stack (line 3) | public interface Stack<T> {
method push (line 4) | boolean push(T item);
method pop (line 5) | T pop();
method peek (line 6) | T peek();
FILE: leetcode/src/linkedlistcycle_141/LinkedListCycle.java
class LinkedListCycle (line 7) | public class LinkedListCycle {
method hasCycle (line 8) | public boolean hasCycle(ListNode head) {
class ListNode (line 25) | public static class ListNode {
method ListNode (line 28) | ListNode(int x) { val = x;}
FILE: leetcode/src/lrucache_146/LRUCache.java
class LRUCache (line 10) | public class LRUCache {
method LRUCache (line 16) | public LRUCache(int capacity) {
method get (line 27) | public int get(int key) {
method put (line 41) | public void put(int key, int value) {
method delete (line 58) | private void delete(Node node) {
method insertToHead (line 69) | private void insertToHead(Node node) {
method deleteTail (line 78) | private Node deleteTail() {
class Node (line 91) | private class Node {
method Node (line 97) | public Node (int key, int value) {
FILE: leetcode/src/mergetwosortedlist_21/Merge2SortedLists.java
class Merge2SortedLists (line 7) | public class Merge2SortedLists {
method mergeTwoLists (line 8) | public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
method mergeTwoListsRecur (line 39) | public ListNode mergeTwoListsRecur(ListNode l1, ListNode l2) {
class ListNode (line 51) | public static class ListNode {
method ListNode (line 54) | ListNode(int x) { val = x;}
FILE: leetcode/src/middleofthelinkedlist_876/MiddleNode.java
class MiddleNode (line 7) | public class MiddleNode {
method middleNode (line 8) | public ListNode middleNode(ListNode head) {
class ListNode (line 21) | public static class ListNode {
method ListNode (line 24) | ListNode(int x) { val = x;}
FILE: leetcode/src/palindromelinkedlist_234/PalindromeLinkedList.java
class PalindromeLinkedList (line 14) | public class PalindromeLinkedList {
method isPalindrome (line 15) | public boolean isPalindrome(ListNode head) {
class ListNode (line 55) | public static class ListNode {
method ListNode (line 58) | ListNode(int x) {
FILE: leetcode/src/removenthnodefromendoflist_19/RemoveNthNodeFromEndOfList.java
class RemoveNthNodeFromEndOfList (line 7) | public class RemoveNthNodeFromEndOfList {
method removeNthFromEnd (line 8) | public ListNode removeNthFromEnd(ListNode head, int n) {
class ListNode (line 34) | public static class ListNode {
method ListNode (line 37) | ListNode(int x) {
FILE: leetcode/src/reverselinkedlist_206/ReverseList.java
class ReverseList (line 7) | public class ReverseList {
method reverseList (line 8) | public ListNode reverseList(ListNode head) {
class ListNode (line 24) | public static class ListNode {
method ListNode (line 27) | ListNode(int x) {
FILE: leetcode/src/threesum_015/ThreeSum.java
class ThreeSum (line 3) | public class ThreeSum {
FILE: leetcode/src/twosum_001/TwoSum.java
class TwoSum (line 3) | public class TwoSum {
method main (line 4) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_03_FindDuplicatedNumInArray.java
class Ex_03_FindDuplicatedNumInArray (line 12) | public class Ex_03_FindDuplicatedNumInArray {
method duplicate (line 14) | public boolean duplicate(int numbers[], int [] duplication) {
method duplicateImprove (line 45) | public boolean duplicateImprove(int numbers[], int [] duplication) {
method swap (line 66) | private static void swap(int[] arr, int i, int j) {
FILE: offer/src/com/ex/offer/Ex_03_FindDuplicatedNumInWithoutChangeArray.java
class Ex_03_FindDuplicatedNumInWithoutChangeArray (line 8) | public class Ex_03_FindDuplicatedNumInWithoutChangeArray {
method duplicate (line 10) | public static int duplicate(int numbers[]) {
method countRange (line 40) | private static int countRange(int[] numbers, int start, int end) {
method main (line 55) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_04_FindNumIn2VArray.java
class Ex_04_FindNumIn2VArray (line 8) | public class Ex_04_FindNumIn2VArray {
method Find (line 10) | public static boolean Find(int target, int[][] array) {
method main (line 31) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_05_ReplaceSpace.java
class Ex_05_ReplaceSpace (line 7) | public class Ex_05_ReplaceSpace {
method replaceSpace (line 8) | public static String replaceSpace(StringBuffer str) {
method replaceBlank (line 23) | public static String replaceBlank(StringBuffer str) {
method main (line 56) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_06_PrintListFromTailToHead.java
class Ex_06_PrintListFromTailToHead (line 8) | public class Ex_06_PrintListFromTailToHead {
method printListFromTailToHead (line 10) | public static ArrayList<Integer> printListFromTailToHead(ListNode list...
method printListFromTailToHeadRecur (line 28) | public static ArrayList<Integer> printListFromTailToHeadRecur(ListNode...
method printListFromTailToHeadWithCollections (line 47) | public static ArrayList<Integer> printListFromTailToHeadWithCollection...
method main (line 58) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_07_ReConstructBT.java
class Ex_07_ReConstructBT (line 14) | public class Ex_07_ReConstructBT {
method reConstructBinaryTree (line 16) | public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
method reConstructBinaryTree (line 24) | private static TreeNode reConstructBinaryTree(int[] pre, int preStart,...
FILE: offer/src/com/ex/offer/Ex_08_DescendantNode.java
class Ex_08_DescendantNode (line 3) | public class Ex_08_DescendantNode {
class Node (line 5) | public static class Node {
method Node (line 11) | public Node(int data) {
method getNextNode (line 16) | public static Node getNextNode(Node node) {
method getLeftMost (line 32) | public static Node getLeftMost(Node node) {
method main (line 42) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_08_GetNextNodeInBT.java
class Ex_08_GetNextNodeInBT (line 7) | public class Ex_08_GetNextNodeInBT {
method GetNext (line 8) | public TreeLinkNode GetNext(TreeLinkNode pNode) {
method getMostLeft (line 25) | private TreeLinkNode getMostLeft(TreeLinkNode node) {
FILE: offer/src/com/ex/offer/Ex_09_QueueWithTwoStack.java
class Ex_09_QueueWithTwoStack (line 9) | public class Ex_09_QueueWithTwoStack {
method push (line 13) | public void push(int node) {
method pop (line 17) | public int pop() {
FILE: offer/src/com/ex/offer/Ex_09_StackWithTwoQueue.java
class Ex_09_StackWithTwoQueue (line 6) | public class Ex_09_StackWithTwoQueue {
method push (line 11) | public void push(int node) {
method pop (line 15) | public int pop() {
method main (line 33) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_10_Fibonacci.java
class Ex_10_Fibonacci (line 3) | public class Ex_10_Fibonacci {
method fib1 (line 5) | public static int fib1(int n) {
method fib2 (line 22) | public static int fib2(int n) {
method Fibonacci (line 26) | public static int Fibonacci(int n) {
method main (line 49) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_10_JumpFloor.java
class Ex_10_JumpFloor (line 3) | public class Ex_10_JumpFloor {
method jumpFloor (line 5) | public int jumpFloor(int target) {
method JumpFloor (line 13) | public int JumpFloor(int target) {
FILE: offer/src/com/ex/offer/Ex_10_JumpFloorII.java
class Ex_10_JumpFloorII (line 20) | public class Ex_10_JumpFloorII {
method JumpFloorII (line 22) | public static int JumpFloorII(int target) {
FILE: offer/src/com/ex/offer/Ex_10_RectCover.java
class Ex_10_RectCover (line 3) | public class Ex_10_RectCover {
method RectCover (line 4) | public int RectCover(int target) {
FILE: offer/src/com/ex/offer/Ex_11_MinNumOfRotatingArray.java
class Ex_11_MinNumOfRotatingArray (line 9) | public class Ex_11_MinNumOfRotatingArray {
method minNumberInRotateArray (line 11) | public static int minNumberInRotateArray(int [] array) {
method minInOrder (line 45) | private static int minInOrder(int[] array, int low, int high) {
method main (line 55) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_11_SortAges.java
class Ex_11_SortAges (line 3) | public class Ex_11_SortAges {
method sortAges (line 6) | public static void sortAges(int[] ages) {
method printArray (line 28) | public static void printArray(int[] arr) {
method main (line 35) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_12_HasPathInMatrix.java
class Ex_12_HasPathInMatrix (line 3) | public class Ex_12_HasPathInMatrix {
method hasPath (line 5) | public static boolean hasPath(char[] matrix, int rows, int cols, char[...
method hasPathCore (line 25) | public static boolean hasPathCore(char[] matrix, int rows, int cols, c...
method main (line 52) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_13_MovingCount.java
class Ex_13_MovingCount (line 3) | public class Ex_13_MovingCount {
method movingCount (line 5) | public int movingCount(int threshold, int rows, int cols) {
method helper (line 17) | public int helper(int threshold, int rows, int cols, int row, int col,...
method check (line 32) | public boolean check(int threshold, int rows, int cols, int row, int c...
method getDigitSum (line 42) | public int getDigitSum(int x) {
FILE: offer/src/com/ex/offer/Ex_14_MaxProductionAfterCutting.java
class Ex_14_MaxProductionAfterCutting (line 3) | public class Ex_14_MaxProductionAfterCutting {
method maxProduction (line 5) | public static int maxProduction(int n) {
method maxProductionWithGreedy (line 40) | public static int maxProductionWithGreedy(int n) {
method main (line 64) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_15_Count1.java
class Ex_15_Count1 (line 3) | public class Ex_15_Count1 {
method NumberOf1 (line 5) | public static int NumberOf1(int n) {
method NumberOf1Optimal (line 19) | public static int NumberOf1Optimal(int n) {
method main (line 30) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_15_CountDifferInMN.java
class Ex_15_CountDifferInMN (line 3) | public class Ex_15_CountDifferInMN {
method countDiffBetweenMN (line 11) | public static int countDiffBetweenMN(int m, int n) {
method main (line 22) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_15_IsPowerOf2.java
class Ex_15_IsPowerOf2 (line 3) | public class Ex_15_IsPowerOf2 {
method isPowerOf2 (line 12) | public static boolean isPowerOf2(int n) {
method main (line 26) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_16_Power.java
class Ex_16_Power (line 3) | public class Ex_16_Power {
method Power (line 14) | public static double Power(double base, int exponent) {
method PowerWithUnsignedExponent (line 33) | public static double PowerWithUnsignedExponent(double base, int expone...
method PowerWithUnsignedExponentOptimal (line 43) | public static double PowerWithUnsignedExponentOptimal(double base, int...
FILE: offer/src/com/ex/offer/Ex_17_AddTwoBigNumber.java
class Ex_17_AddTwoBigNumber (line 3) | public class Ex_17_AddTwoBigNumber {
method add (line 18) | public static String add(StringBuffer n1, StringBuffer n2) {
method main (line 68) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_17_Print1ToMaxNDigits.java
class Ex_17_Print1ToMaxNDigits (line 3) | public class Ex_17_Print1ToMaxNDigits {
method print1ToMaxNDigits_1 (line 9) | public static void print1ToMaxNDigits_1 (int n) {
method print1ToMaxNDigits_2 (line 33) | public static void print1ToMaxNDigits_2 (int n) {
method print1ToMaxNDigits_3 (line 53) | public static void print1ToMaxNDigits_3 (int n) {
method print1ToMaxNDigits_3_Recur (line 75) | public static void print1ToMaxNDigits_3_Recur(StringBuffer s, int n, i...
method Increment (line 87) | public static boolean Increment(StringBuffer s) {
method printNumber (line 120) | public static void printNumber(StringBuffer s) {
method main (line 136) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_18_DeleteDuplicatedNode.java
class Ex_18_DeleteDuplicatedNode (line 3) | public class Ex_18_DeleteDuplicatedNode {
method deleteDuplication (line 5) | public static ListNode deleteDuplication (ListNode pHead) {
method deleteDuplication1 (line 30) | public static ListNode deleteDuplication1 (ListNode pHead) {
method main (line 67) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_18_DeleteNodeInSList.java
class Ex_18_DeleteNodeInSList (line 3) | public class Ex_18_DeleteNodeInSList {
method deleteNode (line 5) | public static Node deleteNode(Node head, Node toBeDeleted) {
method main (line 30) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_19_Match.java
class Ex_19_Match (line 14) | public class Ex_19_Match {
method match (line 16) | public boolean match(char[] str, char[] pattern) {
method matchCore (line 24) | private boolean matchCore(char[] str, int strIndex, char[] pattern, in...
FILE: offer/src/com/ex/offer/Ex_20_IsNumber.java
class Ex_20_IsNumber (line 5) | public class Ex_20_IsNumber {
method isNumeric (line 13) | public boolean isNumeric(char[] str) {
method scanInteger (line 33) | private boolean scanInteger(char[] str) {
method scanUnsignedInteger (line 41) | private boolean scanUnsignedInteger(char[] str) {
method isNumberic1 (line 58) | public boolean isNumberic1(char[] str) {
method test (line 63) | @Test
FILE: offer/src/com/ex/offer/Ex_21_ReOrderArray.java
class Ex_21_ReOrderArray (line 5) | public class Ex_21_ReOrderArray {
method reOrderArray (line 7) | public void reOrderArray(int [] array) {
method reOrderArray1 (line 38) | public void reOrderArray1(int [] array) {
method reOrderArray2 (line 60) | public void reOrderArray2(int [] array) {
method swap (line 74) | private void swap(int[] array, int i, int j) {
method test (line 81) | @Test
FILE: offer/src/com/ex/offer/Ex_22_FindKthNodeToTail.java
class Ex_22_FindKthNodeToTail (line 5) | public class Ex_22_FindKthNodeToTail {
method FindKthToTail (line 14) | public ListNode FindKthToTail(ListNode head, int k) {
method test (line 35) | @Test
FILE: offer/src/com/ex/offer/Ex_22_FindMedianNodeInList.java
class Ex_22_FindMedianNodeInList (line 5) | public class Ex_22_FindMedianNodeInList {
method findMedian (line 7) | public ListNode findMedian(ListNode head) {
method test (line 21) | @Test
FILE: offer/src/com/ex/offer/Ex_23_EntryNodeInList.java
class Ex_23_EntryNodeInList (line 3) | public class Ex_23_EntryNodeInList {
method EntryNodeOfLoop (line 5) | public ListNode EntryNodeOfLoop(ListNode pHead) {
FILE: offer/src/com/ex/offer/Ex_24_ReverseSList.java
class Ex_24_ReverseSList (line 3) | public class Ex_24_ReverseSList {
method ReverseList (line 5) | public ListNode ReverseList(ListNode head) {
method reverseList (line 23) | public ListNode reverseList(ListNode head) {
FILE: offer/src/com/ex/offer/Ex_25_MergeList.java
class Ex_25_MergeList (line 5) | public class Ex_25_MergeList {
method Merge (line 7) | public ListNode Merge(ListNode list1, ListNode list2) {
method Merge1 (line 24) | public ListNode Merge1(ListNode list1, ListNode list2) {
method test (line 68) | @Test
method test1 (line 81) | @Test
FILE: offer/src/com/ex/offer/Ex_26_IsSubTree.java
class Ex_26_IsSubTree (line 4) | public class Ex_26_IsSubTree {
method HasSubtree (line 6) | public boolean HasSubtree(TreeNode root1, TreeNode root2) {
method doesTree1HasTree2 (line 12) | public boolean doesTree1HasTree2(TreeNode root1, TreeNode root2) {
FILE: offer/src/com/ex/offer/Ex_27_MirrorOfTree.java
class Ex_27_MirrorOfTree (line 3) | public class Ex_27_MirrorOfTree {
method Mirror (line 5) | public void Mirror(TreeNode root) {
method swapLeftAndRight (line 17) | public void swapLeftAndRight(TreeNode root) {
FILE: offer/src/com/ex/offer/Ex_28_SymmetricalTree.java
class Ex_28_SymmetricalTree (line 3) | public class Ex_28_SymmetricalTree {
method isSymmetrical (line 4) | boolean isSymmetrical(TreeNode pRoot) {
method isSymmetrical (line 11) | boolean isSymmetrical(TreeNode pRoot1, TreeNode pRoot2) {
method doesTree1HasTree2 (line 25) | public boolean doesTree1HasTree2(TreeNode root1, TreeNode root2) {
FILE: offer/src/com/ex/offer/Ex_29_PrintMatrixWithClockWise.java
class Ex_29_PrintMatrixWithClockWise (line 5) | public class Ex_29_PrintMatrixWithClockWise {
method printMatrix (line 6) | public ArrayList<Integer> printMatrix(int [][] matrix) {
method printMatrixWithCircle (line 28) | public ArrayList<Integer> printMatrixWithCircle(int[][] matrix, int r1...
FILE: offer/src/com/ex/offer/Ex_30_StackWithMinFunction.java
class Ex_30_StackWithMinFunction (line 5) | public class Ex_30_StackWithMinFunction {
method push (line 9) | public void push(int node) {
method pop (line 23) | public void pop() {
method top (line 30) | public int top() {
method min (line 37) | public int min() {
FILE: offer/src/com/ex/offer/Ex_31_IsPopOrder.java
class Ex_31_IsPopOrder (line 5) | public class Ex_31_IsPopOrder {
method IsPopOrder (line 6) | public boolean IsPopOrder(int [] pushA,int [] popA) {
FILE: offer/src/com/ex/offer/Ex_32_PrintTreeByLayer.java
class Ex_32_PrintTreeByLayer (line 7) | public class Ex_32_PrintTreeByLayer {
method Print (line 9) | ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
FILE: offer/src/com/ex/offer/Ex_32_PrintTreeWithZhi.java
class Ex_32_PrintTreeWithZhi (line 6) | public class Ex_32_PrintTreeWithZhi {
method Print (line 8) | public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
method Print1 (line 71) | public ArrayList<ArrayList<Integer>> Print1(TreeNode pRoot) {
FILE: offer/src/com/ex/offer/Ex_32_TraverseTreeByLayer.java
class Ex_32_TraverseTreeByLayer (line 22) | public class Ex_32_TraverseTreeByLayer {
method PrintFromTopToBottom (line 24) | public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
FILE: offer/src/com/ex/offer/Ex_33_VerifySequenceOfBST.java
class Ex_33_VerifySequenceOfBST (line 5) | public class Ex_33_VerifySequenceOfBST {
method VerifySequenceOfBST (line 6) | public boolean VerifySequenceOfBST(int [] sequence) {
method verifySequence (line 14) | public boolean verifySequence(int[] sequence, int start, int end) {
method test (line 58) | @Test
FILE: offer/src/com/ex/offer/Ex_34_FindPathInBT.java
class Ex_34_FindPathInBT (line 7) | public class Ex_34_FindPathInBT {
method FindPath (line 9) | public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int targe...
method findPath (line 22) | private void findPath(TreeNode root,
method test (line 45) | @Test
FILE: offer/src/com/ex/offer/Ex_34_FindPathInBT_1.java
class Ex_34_FindPathInBT_1 (line 7) | public class Ex_34_FindPathInBT_1 {
method FindPath (line 11) | public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int targe...
method findPath (line 19) | private void findPath(TreeNode root, int target) {
FILE: offer/src/com/ex/offer/Ex_34_FindPathInBT_2.java
class Ex_34_FindPathInBT_2 (line 5) | public class Ex_34_FindPathInBT_2 {
method FindPath (line 9) | public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int targe...
method findPath (line 17) | private void findPath(TreeNode root, int target, int sum) {
FILE: offer/src/com/ex/offer/Ex_35_CloneList.java
class Ex_35_CloneList (line 6) | public class Ex_35_CloneList {
method Clone (line 7) | public RandomListNode Clone(RandomListNode pHead)
method Clone1 (line 47) | public RandomListNode Clone1(RandomListNode pHead)
FILE: offer/src/com/ex/offer/Ex_36_ConvertBetweenBSTAndDList.java
class Ex_36_ConvertBetweenBSTAndDList (line 5) | public class Ex_36_ConvertBetweenBSTAndDList {
method Convert (line 9) | public TreeNode Convert(TreeNode pRootOfTree) {
method convert (line 14) | public void convert(TreeNode pRootOfTree) {
method ConvertIterative (line 34) | public TreeNode ConvertIterative(TreeNode pRootOfTree) {
FILE: offer/src/com/ex/offer/Ex_37_SerializeBT.java
class Ex_37_SerializeBT (line 3) | public class Ex_37_SerializeBT {
method Serialize (line 4) | String Serialize(TreeNode root) {
method serialize (line 15) | void serialize(TreeNode root, StringBuilder sb) {
method Deserialize (line 27) | TreeNode Deserialize(String str) {
method Deserialize (line 33) | TreeNode Deserialize(String[] strs) {
FILE: offer/src/com/ex/offer/Ex_38_EightQueen.java
class Ex_38_EightQueen (line 12) | public class Ex_38_EightQueen {
method solution (line 18) | public int solution() {
method queen (line 23) | private void queen(int row) {
method isPut (line 36) | private boolean isPut(int row) {
method test (line 45) | @Test
FILE: offer/src/com/ex/offer/Ex_38_StringCombination.java
class Ex_38_StringCombination (line 7) | public class Ex_38_StringCombination {
method Combination (line 8) | public ArrayList<String> Combination(String str) {
method combination (line 16) | private void combination(char[] chars, int startIndex, ArrayList<Strin...
method test (line 34) | @Test
FILE: offer/src/com/ex/offer/Ex_38_StringPermutation.java
class Ex_38_StringPermutation (line 6) | public class Ex_38_StringPermutation {
method Permutation (line 7) | public ArrayList<String> Permutation(String str) {
method permutation (line 16) | private void permutation(char[] chars, int startIndex, ArrayList<Strin...
method swap (line 33) | private void swap(char[] chars, int i, int j) {
FILE: offer/src/com/ex/offer/Ex_39_KthSmallestNumInArrayWithoutSort.java
class Ex_39_KthSmallestNumInArrayWithoutSort (line 3) | public class Ex_39_KthSmallestNumInArrayWithoutSort {
method kthNumIte (line 11) | public static int kthNumIte(int[] arr, int K) {
method kthNum (line 32) | public static int kthNum(int[] arr, int K) {
method kthNum (line 55) | public static int kthNum(int[] arr, int K, int low, int high) {
method partition (line 91) | public static int partition(int[] arr, int low, int high) {
method swap (line 129) | public static void swap(int[] arr, int i, int j) {
method main (line 135) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_39_MoreThanHalfNum.java
class Ex_39_MoreThanHalfNum (line 3) | public class Ex_39_MoreThanHalfNum {
method moreThanHalfNum (line 5) | public static int moreThanHalfNum(int[] array) {
method checkMoreThanHalf (line 36) | public static boolean checkMoreThanHalf(int[] arr, int result) {
method partition (line 52) | public static int partition(int[] arr, int low, int high) {
method swap (line 88) | public static void swap(int[] arr, int i, int j) {
method moreThanHalfNumWithoutChangeArray (line 94) | public static int moreThanHalfNumWithoutChangeArray(int[] array) {
method main (line 120) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_40_GetLeastKNumbers.java
class Ex_40_GetLeastKNumbers (line 5) | public class Ex_40_GetLeastKNumbers {
method getLeastKNumbers (line 7) | public static ArrayList<Integer> getLeastKNumbers(int[] input, int k) {
method kthNum (line 31) | public static int kthNum(int[] input, int k) {
method partition (line 51) | public static int partition(int[] arr, int low, int high) {
method swap (line 81) | public static void swap(int[] arr, int i, int j) {
method main (line 87) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_41_MedianInDataFlow.java
class Ex_41_MedianInDataFlow (line 6) | public class Ex_41_MedianInDataFlow {
method Insert (line 11) | public void Insert(Integer num) {
method GetMedian (line 35) | public Double GetMedian() {
method modifyTwoHeapSize (line 54) | private void modifyTwoHeapSize() {
class MinHeapComparator (line 64) | private static class MinHeapComparator implements Comparator<Integer> {
method compare (line 66) | @Override
class MaxHeapComparator (line 76) | private static class MaxHeapComparator implements Comparator<Integer> {
method compare (line 77) | @Override
FILE: offer/src/com/ex/offer/Ex_42_MaxSumOfSubArray.java
class Ex_42_MaxSumOfSubArray (line 4) | public class Ex_42_MaxSumOfSubArray {
method FindGreatestSumOfSubArray (line 5) | public int FindGreatestSumOfSubArray(int[] array) {
FILE: offer/src/com/ex/offer/Ex_43_NumberOf1Between1AndN.java
class Ex_43_NumberOf1Between1AndN (line 4) | public class Ex_43_NumberOf1Between1AndN {
method NumberOf1Between1AndN_Solution1 (line 5) | public int NumberOf1Between1AndN_Solution1(int n) {
method numberOf1 (line 18) | private int numberOf1(int num) {
method NumberOf1Between1AndN_Solution (line 30) | public int NumberOf1Between1AndN_Solution(int n) {
FILE: offer/src/com/ex/offer/Ex_44_ANumInArray.java
class Ex_44_ANumInArray (line 5) | public class Ex_44_ANumInArray {
method digitAt (line 6) | public int digitAt(int index) {
method countNumbersOf (line 24) | private int countNumbersOf(int digits) {
method digitAt (line 32) | private int digitAt(int index, int digits) {
method test (line 43) | @Test
FILE: offer/src/com/ex/offer/Ex_45_MinNumByConcatArray.java
class Ex_45_MinNumByConcatArray (line 7) | public class Ex_45_MinNumByConcatArray {
method PrintMinNumber (line 8) | public String PrintMinNumber(int [] numbers) {
class StrComparator (line 28) | private static class StrComparator implements Comparator<String> {
method compare (line 30) | @Override
FILE: offer/src/com/ex/offer/Ex_46_ConvertStringToIP.java
class Ex_46_ConvertStringToIP (line 16) | public class Ex_46_ConvertStringToIP {
method convertStringToIp1 (line 18) | public static int convertStringToIp1(String str) {
method process1 (line 34) | public static int process1(char[] chars, int i, int parts) {
method convertStringToIp2 (line 65) | public static int convertStringToIp2(String str) {
method getRandomNumberString (line 97) | public static String getRandomNumberString() {
method main (line 105) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/Ex_46_TranslationFromIntToString.java
class Ex_46_TranslationFromIntToString (line 8) | public class Ex_46_TranslationFromIntToString {
method translation (line 10) | public int translation(int num) {
method translation1 (line 42) | public int translation1(int num) {
method translationCore (line 53) | private int translationCore(char[] chars, int start) {
method test (line 76) | @Test
FILE: offer/src/com/ex/offer/Ex_47_MaxGiftValue.java
class Ex_47_MaxGiftValue (line 5) | public class Ex_47_MaxGiftValue {
method getMaxValue (line 6) | public int getMaxValue(int[][] matrix) {
method getMaxValue1 (line 33) | public int getMaxValue1(int[][] matrix) {
method process (line 41) | private int process(int[][] matrix, int startRow, int startCol) {
method test (line 64) | @Test
FILE: offer/src/com/ex/offer/Ex_48_LongestSubStringWithDuplication.java
class Ex_48_LongestSubStringWithDuplication (line 6) | public class Ex_48_LongestSubStringWithDuplication {
method longestSubString (line 7) | public int longestSubString(String str) {
method test (line 40) | @Test
FILE: offer/src/com/ex/offer/Ex_49_UglyNumber.java
class Ex_49_UglyNumber (line 5) | public class Ex_49_UglyNumber {
method getUglyNumber (line 7) | public int getUglyNumber(int index) {
method min (line 41) | private int min(int x, int y, int z) {
method getUglyNumber1 (line 47) | public int getUglyNumber1(int index) {
method isUgly (line 67) | public boolean isUgly(int number) {
method test (line 87) | @Test
FILE: offer/src/com/ex/offer/Ex_50_FirstNotRepeatedChar.java
class Ex_50_FirstNotRepeatedChar (line 5) | public class Ex_50_FirstNotRepeatedChar {
method FirstNotRepeatingChar (line 6) | public int FirstNotRepeatingChar(String str) {
method FirstNotRepeatingChar1 (line 34) | public int FirstNotRepeatingChar1(String str) {
FILE: offer/src/com/ex/offer/Ex_50_FirstNotRepeatedCharInDataFlow.java
class Ex_50_FirstNotRepeatedCharInDataFlow (line 3) | public class Ex_50_FirstNotRepeatedCharInDataFlow {
method Ex_50_FirstNotRepeatedCharInDataFlow (line 15) | public Ex_50_FirstNotRepeatedCharInDataFlow() {
method Insert (line 22) | public void Insert(char ch)
method FirstAppearingOnce (line 33) | public char FirstAppearingOnce()
FILE: offer/src/com/ex/offer/Ex_50_StringUtilsSolutions.java
class Ex_50_StringUtilsSolutions (line 7) | public class Ex_50_StringUtilsSolutions {
method deleteString (line 9) | public String deleteString(String str1, String str2) {
method deleteDuplicatedChar (line 29) | public String deleteDuplicatedChar(String str) {
method isAnagram (line 58) | public boolean isAnagram(String str1, String str2) {
method testDeleteString (line 86) | @Test
method testDeleteDuplicatedChar (line 93) | @Test
method testIsAnagram (line 99) | @Test
FILE: offer/src/com/ex/offer/Ex_51_InversePairs.java
class Ex_51_InversePairs (line 5) | public class Ex_51_InversePairs {
method InversePairs (line 6) | public int InversePairs(int [] array) {
method mergeSort (line 16) | private int mergeSort(int[] array, int low, int high) {
method merge (line 28) | private int merge(int[] array, int low, int mid, int high) {
FILE: offer/src/com/ex/offer/Ex_51_InversePairs_BigData.java
class Ex_51_InversePairs_BigData (line 5) | public class Ex_51_InversePairs_BigData {
method InversePairs (line 6) | public int InversePairs(int [] array) {
method mergeSort (line 16) | private int mergeSort(int[] array, int low, int high) {
method merge (line 29) | private int merge(int[] array, int low, int mid, int high) {
FILE: offer/src/com/ex/offer/Ex_52_FirstCommonNode.java
class Ex_52_FirstCommonNode (line 3) | public class Ex_52_FirstCommonNode {
method FindFirstCommonNode (line 4) | public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
method getLengthOfList (line 28) | private int getLengthOfList(ListNode pHead1) {
FILE: offer/src/com/ex/offer/Ex_53_GetMissingNumber.java
class Ex_53_GetMissingNumber (line 3) | public class Ex_53_GetMissingNumber {
method getMissingNumber (line 4) | public int getMissingNumber(int[] array) {
FILE: offer/src/com/ex/offer/Ex_53_GetNumberOfK.java
class Ex_53_GetNumberOfK (line 5) | public class Ex_53_GetNumberOfK {
method GetNumberOfK (line 6) | public int GetNumberOfK(int [] array , int k) {
method getFirstIndexOfK (line 21) | private int getFirstIndexOfK(int[] array, int k, int low, int high) {
method getLastIndexOfK (line 43) | private int getLastIndexOfK(int[] array, int k, int low, int high) {
method test (line 65) | @Test
FILE: offer/src/com/ex/offer/Ex_53_GetNumberSameAsIndex.java
class Ex_53_GetNumberSameAsIndex (line 5) | public class Ex_53_GetNumberSameAsIndex {
method getNumberSameAsIndex (line 7) | public int getNumberSameAsIndex(int[] array) {
method test (line 31) | @Test
FILE: offer/src/com/ex/offer/Ex_54_KthNodeInBST.java
class Ex_54_KthNodeInBST (line 3) | public class Ex_54_KthNodeInBST {
method KthNode (line 7) | TreeNode KthNode(TreeNode pRoot, int k)
FILE: offer/src/com/ex/offer/Ex_55_BalancedBT.java
class Ex_55_BalancedBT (line 3) | public class Ex_55_BalancedBT {
method IsBalanced_Solution (line 8) | public boolean IsBalanced_Solution(TreeNode root) {
method isBalance (line 12) | private boolean isBalance(TreeNode root) {
method IsBalanced_Solution1 (line 34) | public boolean IsBalanced_Solution1(TreeNode root) {
method isBalance (line 38) | public boolean isBalance(TreeNode root, int[] depth) {
method IsBalanced_Solution2 (line 57) | public boolean IsBalanced_Solution2(TreeNode root) {
method TreeDepth (line 73) | private int TreeDepth(TreeNode root) {
method IsBalanced_Solution3 (line 88) | public boolean IsBalanced_Solution3(TreeNode root) {
method getDepth (line 94) | private int getDepth(TreeNode root) {
FILE: offer/src/com/ex/offer/Ex_55_DepthOfBT.java
class Ex_55_DepthOfBT (line 3) | public class Ex_55_DepthOfBT {
method TreeDepth (line 4) | public int TreeDepth(TreeNode root) {
FILE: offer/src/com/ex/offer/Ex_56_AppearanceOnce.java
class Ex_56_AppearanceOnce (line 5) | public class Ex_56_AppearanceOnce {
method FindNumsAppearOnce (line 6) | public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
method findFirst1_Bit (line 28) | private int findFirst1_Bit(int num) {
method is1_Bit (line 39) | private boolean is1_Bit(int num, int index) {
FILE: offer/src/com/ex/offer/Ex_56_AppearanceOnce_Continued.java
class Ex_56_AppearanceOnce_Continued (line 5) | public class Ex_56_AppearanceOnce_Continued {
method FindNumAppearOnce (line 6) | public int FindNumAppearOnce(int[] array) {
method test (line 31) | @Test
FILE: offer/src/com/ex/offer/Ex_57_FindContinuousSequence.java
class Ex_57_FindContinuousSequence (line 7) | public class Ex_57_FindContinuousSequence {
method FindContinuousSequence (line 8) | public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
method full (line 37) | private ArrayList<Integer> full(int small, int big) {
method test (line 45) | @Test
FILE: offer/src/com/ex/offer/Ex_57_FindNumbersWithSum.java
class Ex_57_FindNumbersWithSum (line 7) | public class Ex_57_FindNumbersWithSum {
method FindNumbersWithSum (line 8) | public ArrayList<Integer> FindNumbersWithSum(int [] array, int sum) {
method test (line 54) | @Test
FILE: offer/src/com/ex/offer/Ex_58_ROL.java
class Ex_58_ROL (line 5) | public class Ex_58_ROL {
method LeftRotateString (line 6) | public String LeftRotateString(String str,int n) {
method reverse (line 20) | private void reverse(char[] chars, int start, int end) {
method test (line 28) | @Test
FILE: offer/src/com/ex/offer/Ex_58_ReverseSentence.java
class Ex_58_ReverseSentence (line 5) | public class Ex_58_ReverseSentence {
method ReverseSentence (line 6) | public String ReverseSentence(String str) {
method reverse (line 40) | private void reverse(char[] chars, int start, int end) {
method test (line 49) | @Test
FILE: offer/src/com/ex/offer/Ex_59_MaxNumOfSlidingWindow.java
class Ex_59_MaxNumOfSlidingWindow (line 8) | public class Ex_59_MaxNumOfSlidingWindow {
method maxInWindows (line 9) | public ArrayList<Integer> maxInWindows(int [] num, int size)
method test (line 44) | @Test
FILE: offer/src/com/ex/offer/Ex_59_QueueWithMax.java
class Ex_59_QueueWithMax (line 7) | public class Ex_59_QueueWithMax {
method push_back (line 11) | public void push_back(Integer x) {
method pop_front (line 21) | public Integer pop_front() {
method max (line 30) | public Integer max() {
FILE: offer/src/com/ex/offer/Ex_60_ProbabilityOfS.java
class Ex_60_ProbabilityOfS (line 7) | public class Ex_60_ProbabilityOfS {
method printProbability_1 (line 11) | public void printProbability_1(int number) {
method probability (line 31) | private void probability(int number, int[] sums) {
method probability (line 43) | private void probability(int number, int current, int sum, int[] sums) {
method printProbability_2 (line 62) | public void printProbability_2(int number) {
method test1 (line 99) | @Test
method test2 (line 105) | @Test
FILE: offer/src/com/ex/offer/Ex_61_ContinuousSequence.java
class Ex_61_ContinuousSequence (line 5) | public class Ex_61_ContinuousSequence {
method isContinuous (line 6) | public boolean isContinuous(int [] numbers) {
FILE: offer/src/com/ex/offer/Ex_62_Josephus.java
class Ex_62_Josephus (line 10) | public class Ex_62_Josephus {
method LastRemaining_Solution (line 11) | public int LastRemaining_Solution(int n, int m) {
method LastRemaining_Solution1 (line 40) | public int LastRemaining_Solution1(int n, int m) {
method test (line 51) | @Test
FILE: offer/src/com/ex/offer/Ex_63_MaxProfits.java
class Ex_63_MaxProfits (line 6) | public class Ex_63_MaxProfits {
method maxProfits (line 7) | public int maxProfits(int[] prices) {
method test (line 30) | @Test
FILE: offer/src/com/ex/offer/Ex_64_SumFrom1ToN.java
class Ex_64_SumFrom1ToN (line 5) | public class Ex_64_SumFrom1ToN {
method Sum_Solution (line 6) | public int Sum_Solution(int n) {
method test (line 12) | @Test
FILE: offer/src/com/ex/offer/Ex_65_AddWithoutCarry.java
class Ex_65_AddWithoutCarry (line 3) | public class Ex_65_AddWithoutCarry {
method Add (line 4) | public int Add(int num1,int num2) {
FILE: offer/src/com/ex/offer/Ex_65_SwapNumWithoutTemp.java
class Ex_65_SwapNumWithoutTemp (line 3) | public class Ex_65_SwapNumWithoutTemp {
method swap1 (line 4) | public int[] swap1 (int a, int b) {
method swap2 (line 16) | public int[] swap2 (int a, int b) {
FILE: offer/src/com/ex/offer/Ex_66_ConstructMultiplyArray.java
class Ex_66_ConstructMultiplyArray (line 3) | public class Ex_66_ConstructMultiplyArray {
method multiply (line 4) | public int[] multiply(int[] A) {
FILE: offer/src/com/ex/offer/Ex_67_StringToInt.java
class Ex_67_StringToInt (line 5) | public class Ex_67_StringToInt {
method StrToInt (line 13) | public int StrToInt(String str) {
method test (line 51) | @Test
FILE: offer/src/com/ex/offer/Ex_68_LowestCommonAncestor.java
class Ex_68_LowestCommonAncestor (line 3) | public class Ex_68_LowestCommonAncestor {
method commonAncestor (line 5) | public TreeNode commonAncestor(TreeNode root, TreeNode node1, TreeNode...
FILE: offer/src/com/ex/offer/ListNode.java
class ListNode (line 7) | public class ListNode {
method ListNode (line 11) | public ListNode(int val) {
FILE: offer/src/com/ex/offer/Node.java
class Node (line 6) | public class Node {
method Node (line 10) | Node (int val) {
FILE: offer/src/com/ex/offer/RandomListNode.java
class RandomListNode (line 6) | public class RandomListNode {
method RandomListNode (line 11) | RandomListNode(int label) {
FILE: offer/src/com/ex/offer/TestUtils.java
class TestUtils (line 5) | public class TestUtils {
method printArray (line 6) | public static void printArray(int[] arr) {
method sort (line 13) | public static void sort(int[] arr) {
method partition (line 17) | public static int partition(int[] arr, int low, int high) {
method swap (line 54) | public static void swap(int[] arr, int i, int j) {
method getDigitSum (line 61) | public static int getDigitSum(int x) {
method isOdd (line 79) | public static boolean isOdd(int x) {
method printStingToInt (line 87) | public static void printStingToInt(StringBuffer s) {
method Increment (line 104) | public static boolean Increment(StringBuffer s) {
method printList (line 133) | public static void printList(Node head) {
method printList_ListNode (line 146) | public static void printList_ListNode(ListNode head) {
method main (line 159) | public static void main(String[] args) {
FILE: offer/src/com/ex/offer/TreeLinkNode.java
class TreeLinkNode (line 7) | public class TreeLinkNode {
method TreeLinkNode (line 13) | TreeLinkNode(int val) {
FILE: offer/src/com/ex/offer/TreeNode.java
class TreeNode (line 6) | public class TreeNode {
method TreeNode (line 11) | TreeNode(int x) {
FILE: offer/src/com/ex/singleton/Singleton1.java
class Singleton1 (line 4) | public class Singleton1 {
method Singleton1 (line 11) | private Singleton1() {}
method getInstance (line 14) | public static Singleton1 getInstance() {
FILE: offer/src/com/ex/singleton/Singleton2.java
class Singleton2 (line 4) | public class Singleton2 {
method Singleton2 (line 7) | private Singleton2() {}
method getInstance (line 9) | public static Singleton2 getInstance() {
FILE: offer/src/com/ex/singleton/Singleton3.java
class Singleton3 (line 4) | public class Singleton3 {
method Singleton3 (line 9) | private Singleton3() {}
method getInstance (line 11) | public static Singleton3 getInstance() {
FILE: offer/src/com/ex/singleton/Singleton4.java
class Singleton4 (line 4) | public class Singleton4 {
class SingletonHolder (line 5) | private static class SingletonHolder {
method getInstance (line 9) | public static Singleton4 getInstance() {
FILE: offer/src/com/ex/singleton/Singleton5.java
type Singleton5 (line 4) | public enum Singleton5 {
method getId (line 9) | public int getId() {
method setId (line 13) | public void setId(int id) {
method main (line 17) | public static void main(String[] args) {
FILE: practice/src/io/gkd/ListNode.java
class ListNode (line 3) | public class ListNode {
method ListNode (line 7) | public ListNode() {
method ListNode (line 10) | public ListNode(int val) {
method ListNode (line 14) | public ListNode(int val, ListNode next) {
FILE: practice/src/io/gkd/Node.java
class Node (line 5) | public class Node {
method Node (line 9) | public Node() {}
method Node (line 11) | public Node(int _val) {
method Node (line 15) | public Node(int _val, List<Node> _children) {
FILE: practice/src/io/gkd/TreeNode.java
class TreeNode (line 3) | public class TreeNode {
method TreeNode (line 8) | public TreeNode() {}
method TreeNode (line 10) | public TreeNode(int val) {
method TreeNode (line 14) | public TreeNode(int val, TreeNode left, TreeNode right) {
FILE: practice/src/io/gkd/lectures/lecture04/Lc077_Combine.java
class Lc077_Combine (line 6) | public class Lc077_Combine {
method combine (line 8) | public List<List<Integer>> combine(int n, int k) {
method findSubsets (line 15) | private void findSubsets(int index) {
FILE: practice/src/io/gkd/lectures/lecture04/Lc078_SubSets.java
class Lc078_SubSets (line 10) | public class Lc078_SubSets {
method subsets (line 12) | public List<List<Integer>> subsets(int[] nums) {
method findSubsets (line 18) | private void findSubsets(int[] nums, int index) {
FILE: practice/src/io/gkd/lectures/lecture05/Lc094_InOrderTraversal.java
class Lc094_InOrderTraversal (line 8) | public class Lc094_InOrderTraversal {
method inorderTraversal (line 12) | public List<Integer> inorderTraversal(TreeNode root) {
method find (line 17) | public void find(TreeNode root) {
FILE: practice/src/io/gkd/lectures/lecture05/Lc105_BuildTree.java
class Lc105_BuildTree (line 19) | public class Lc105_BuildTree {
method buildTree (line 20) | public TreeNode buildTree(int[] preorder, int[] inorder) {
method build (line 24) | private TreeNode build(int[] preorder, int l1, int r1, int[] inorder, ...
FILE: practice/src/io/gkd/lectures/lecture05/Lc236_LCA.java
class Lc236_LCA (line 16) | public class Lc236_LCA {
method lowestCommonAncestor (line 22) | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNo...
method calcFather (line 41) | private void calcFather(TreeNode root) {
FILE: practice/src/io/gkd/lectures/lecture05/Lc297_Codec.java
class Lc297_Codec (line 13) | public class Lc297_Codec {
method serialize (line 22) | public String serialize(TreeNode root) {
method deserialize (line 28) | public TreeNode deserialize(String data) {
method calc (line 34) | private TreeNode calc() {
method traverse (line 46) | private void traverse(TreeNode root) {
FILE: practice/src/io/gkd/lectures/lecture05/Lc429_LevelOrderNTree.java
class Lc429_LevelOrderNTree (line 14) | public class Lc429_LevelOrderNTree {
method levelOrder (line 16) | public List<List<Integer>> levelOrder(Node root) {
class Pair (line 40) | static class Pair<K, V> {
method Pair (line 45) | public Pair(K key, V value) {
method getKey (line 50) | public K getKey() {
method getValue (line 54) | public V getValue() {
FILE: practice/src/io/gkd/lectures/lecture05/Lc589_PreOrderNTree.java
class Lc589_PreOrderNTree (line 13) | public class Lc589_PreOrderNTree {
method preorder (line 16) | public List<Integer> preorder(Node root) {
method find (line 21) | private void find(Node root) {
method preorderIter (line 29) | public List<Integer> preorderIter(Node root) {
FILE: practice/src/io/gkd/week01/Lc021_MergeTwoLists.java
class Lc021_MergeTwoLists (line 9) | public class Lc021_MergeTwoLists {
method mergeTwoLists (line 11) | public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
FILE: practice/src/io/gkd/week01/Lc066_PlusOne.java
class Lc066_PlusOne (line 7) | public class Lc066_PlusOne {
method plusOne (line 9) | public int[] plusOne(int[] digits) {
FILE: practice/src/io/gkd/week02/Lc146_LRUCache.java
class Lc146_LRUCache (line 11) | public class Lc146_LRUCache {
method Lc146_LRUCache (line 20) | public Lc146_LRUCache(int capacity) {
method get (line 30) | public int get(int key) {
method put (line 42) | public void put(int key, int value) {
method addToHead (line 57) | private void addToHead(Node node) {
method removeNode (line 67) | private void removeNode(Node node) {
class Node (line 72) | static class Node {
method Node (line 78) | public Node() {}
method Node (line 80) | public Node(int key, int val) {
FILE: practice/src/io/gkd/week02/Lc697_FindShortestSubArray.java
class Lc697_FindShortestSubArray (line 10) | public class Lc697_FindShortestSubArray {
method findShortestSubArray (line 11) | public int findShortestSubArray(int[] nums) {
FILE: practice/src/io/gkd/week03/Lc106_BuildTree.java
class Lc106_BuildTree (line 17) | public class Lc106_BuildTree {
method buildTree (line 18) | public TreeNode buildTree(int[] inorder, int[] postorder) {
method build (line 22) | private TreeNode build(int[] inorder, int l1, int r1, int[] postorder,...
FILE: practice/src/io/gkd/week03/Lc210_FindOrder2.java
class Lc210_FindOrder2 (line 6) | public class Lc210_FindOrder2 {
method findOrder (line 7) | public int[] findOrder(int numCourses, int[][] prerequisites) {
Condensed preview — 167 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (359K chars).
[
{
"path": ".gitignore",
"chars": 348,
"preview": "# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Packa"
},
{
"path": "README.md",
"chars": 9581,
"preview": "# [算法练级计划](https://mp.weixin.qq.com/s/6vuaECCmrxrchr5Hc11S5w)\n\n> **既然终要承受痛苦,那么尝试思考的痛总归比承受学习的苦更有意义。**\n\n在正式开始之前,邀请你阅读「[The"
},
{
"path": "algorithms/src/array/BinarySearch.java",
"chars": 3481,
"preview": "package array;\n\npublic class BinarySearch {\n // 最简单的二分查找算法:针对有序无重复元素数组\n // 迭代\n public static int binarySearch(i"
},
{
"path": "algorithms/src/array/BinarySearchTest.java",
"chars": 3580,
"preview": "package array;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\npublic class BinarySearchTest {\n\n // 测试示例(完备)\n @T"
},
{
"path": "algorithms/src/array/GenericArray.java",
"chars": 3555,
"preview": "package array;\n\n/**\n * 泛型动态数组\n *\n * @param <T>\n *\n */\n\npublic class GenericArray<T> {\n private T[] data;\n private "
},
{
"path": "algorithms/src/array/MinNumberInRotatedArray.java",
"chars": 1217,
"preview": "package array;\n\npublic class MinNumberInRotatedArray {\n\n public static int getMinNumber(int[] arr) {\n if (arr "
},
{
"path": "algorithms/src/array/MinNumberInRotatedArrayTest.java",
"chars": 728,
"preview": "package array;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\npublic class MinNumberInRotatedArrayTest {\n\n @Test\n "
},
{
"path": "algorithms/src/joseph/Joseph.java",
"chars": 905,
"preview": "package joseph;\n\n/**\n * Joseph Question\n *\n * Solution: 圆圈长度为n时的解f(n,m)可以看成是圆圈长度为n-1时的解f(n-1,m)加m。\n * 但是因为是循环的(圆圈),因此需要对"
},
{
"path": "algorithms/src/linkedlist/FindMidNode.java",
"chars": 1098,
"preview": "package linkedlist;\n\npublic class FindMidNode {\n\n // 1. T(n) = O(2*n) 遍历2次\n public static Node findMidNode(Node he"
},
{
"path": "algorithms/src/linkedlist/FindMidNodeTest.java",
"chars": 1544,
"preview": "package linkedlist;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\n\npublic class FindMidNodeTest {\n\n @Test\n pub"
},
{
"path": "algorithms/src/linkedlist/SingleLinkedList.java",
"chars": 3912,
"preview": "package linkedlist;\n\npublic class SingleLinkedList {\n\n private Node head = null;\n\n // 1. search\n public Node fi"
},
{
"path": "algorithms/src/linkedlist/SingleLinkedListTest.java",
"chars": 804,
"preview": "package linkedlist;\n\nimport org.junit.Test;\n\npublic class SingleLinkedListTest {\n\n @Test\n public void testSingleLi"
},
{
"path": "algorithms/src/lru/LRU.java",
"chars": 3053,
"preview": "package lru;\n\nimport java.util.HashMap;\nimport java.util.Iterator;\n\n/**\n * LRU Cache: 优先淘汰最久未使用的数据\n * Solution: 双向链表+Has"
},
{
"path": "algorithms/src/lru/LRUTest.java",
"chars": 827,
"preview": "package lru;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\npublic class LRUTest {\n @Test\n public void testLRU("
},
{
"path": "algorithms/src/queue/ArrayQueue.java",
"chars": 1753,
"preview": "package queue;\n\npublic class ArrayQueue<T> implements Queue<T> {\n private T[] items;\n private int capacity;\n pr"
},
{
"path": "algorithms/src/queue/CircularQueue.java",
"chars": 1559,
"preview": "package queue;\n\npublic class CircularQueue<T> {\n private T[] items;\n private int capacity;\n private int head;\n "
},
{
"path": "algorithms/src/queue/ListQueue.java",
"chars": 1647,
"preview": "package queue;\n\npublic class ListQueue<T> implements Queue<T> {\n\n Node head = null;\n Node tail = null;\n\n // T(N"
},
{
"path": "algorithms/src/queue/Queue.java",
"chars": 92,
"preview": "package queue;\n\npublic interface Queue<T> {\n boolean enqueue(T item);\n T dequeue();\n}\n"
},
{
"path": "algorithms/src/stack/ArrayStack.java",
"chars": 1386,
"preview": "package stack;\n\npublic class ArrayStack<T> implements Stack<T> {\n private T[] items; // 数组\n private int top; "
},
{
"path": "algorithms/src/stack/DynamicArrayStack.java",
"chars": 1694,
"preview": "package stack;\n\n/**\n * 支持动态扩容的栈\n *\n * @param <T>\n */\npublic class DynamicArrayStack<T> implements Stack<T> {\n private"
},
{
"path": "algorithms/src/stack/ListStack.java",
"chars": 1505,
"preview": "package stack;\n\npublic class ListStack<T> implements Stack<T> {\n private Node top = null;\n\n // T(N)=O(1)\n @Over"
},
{
"path": "algorithms/src/stack/SampleBrowser.java",
"chars": 158,
"preview": "package stack;\n\n/**\n * 浏览器页面的前进和后退功能\n */\npublic class SampleBrowser {\n\n private String currentPage;\n// private Sta"
},
{
"path": "algorithms/src/stack/Stack.java",
"chars": 99,
"preview": "package stack;\n\npublic interface Stack<T> {\n boolean push(T item);\n T pop();\n T peek();\n}\n"
},
{
"path": "appendix/instructions.md",
"chars": 498,
"preview": "# 上传与更新本地代码到Github\n\n1. 远程操作:\n * Github上创建Repo\n2. 本地操作:\n * git clone https://github.com/guokaide/leetcode\n * cd lee"
},
{
"path": "appendix/刷题笔记.md",
"chars": 55583,
"preview": "# 刷题笔记\n\n> It does not matter how slowly you go as long as you do not stop. \n\n## 如何有效学习数据结构与算法?\n\n### 如何精通一个领域?\n\n* Chunk "
},
{
"path": "leetcode/src/linkedlistcycle_141/LinkedListCycle.java",
"chars": 658,
"preview": "package linkedlistcycle_141;\n\n/**\n * 141. Linked List Cycle\n * https://leetcode.com/problems/linked-list-cycle/\n */\npubl"
},
{
"path": "leetcode/src/lrucache_146/LRUCache.java",
"chars": 2023,
"preview": "package lrucache_146;\n\n\nimport java.util.HashMap;\n\n/**\n * 146. LRU Cache\n * https://leetcode.com/problems/lru-cache/desc"
},
{
"path": "leetcode/src/mergetwosortedlist_21/Merge2SortedLists.java",
"chars": 1258,
"preview": "package mergetwosortedlist_21;\n\n/**\n * 21. Merge Two Sorted Lists\n * https://leetcode.com/problems/merge-two-sorted-list"
},
{
"path": "leetcode/src/middleofthelinkedlist_876/MiddleNode.java",
"chars": 551,
"preview": "package middleofthelinkedlist_876;\n\n/**\n * 876. Middle of the Linked List\n * https://leetcode.com/problems/middle-of-the"
},
{
"path": "leetcode/src/palindromelinkedlist_234/PalindromeLinkedList.java",
"chars": 1320,
"preview": "package palindromelinkedlist_234;\n\n/**\n * 234. Palindrome Linked List\n * https://leetcode.com/problems/palindrome-linked"
},
{
"path": "leetcode/src/removenthnodefromendoflist_19/RemoveNthNodeFromEndOfList.java",
"chars": 881,
"preview": "package removenthnodefromendoflist_19;\n\n/**\n* 19. Remove Nth Node From End of List\n* https://leetcode.com/problems/remov"
},
{
"path": "leetcode/src/reverselinkedlist_206/ReverseList.java",
"chars": 648,
"preview": "package reverselinkedlist_206;\n\n/**\n * 206. Reverse Linked List\n * https://leetcode.com/problems/reverse-linked-list/\n *"
},
{
"path": "leetcode/src/threesum_015/ThreeSum.java",
"chars": 49,
"preview": "package threesum_015;\n\npublic class ThreeSum {\n}\n"
},
{
"path": "leetcode/src/twosum_001/TwoSum.java",
"chars": 97,
"preview": "package twosum_001;\n\npublic class TwoSum {\n public static void main(String[] args) {\n\n }\n}\n"
},
{
"path": "offer/src/com/ex/offer/Attention.txt",
"chars": 2876,
"preview": "- 面试沟通\n (1)面试时,要经常和面试官沟通。沟通好题目条件、问题的意图之后再动手coding或者回答问题。\n (2)面试中,若面试官提出新的概念,面试者需要和面试官积极沟通,多问几个问题,把概念搞清楚。\n (3)面试"
},
{
"path": "offer/src/com/ex/offer/Ex_03_FindDuplicatedNumInArray.java",
"chars": 1809,
"preview": "package com.ex.offer;\n\nimport java.util.HashMap;\n\n/**\n * problem 3: 数组中重复的数字\n * 在一个长度为n的数组里的所有数字都在0到n-1的范围内。\n * 数组中某些数字是"
},
{
"path": "offer/src/com/ex/offer/Ex_03_FindDuplicatedNumInWithoutChangeArray.java",
"chars": 1456,
"preview": "package com.ex.offer;\n\n/**\n * problem 3: 不修改数组找出重复的数字。 [binary search]\n *\n * 特性:若数组中没有重复元素,则[x,y]范围内的数字个数为y-x+1,若超出这个个数,"
},
{
"path": "offer/src/com/ex/offer/Ex_04_FindNumIn2VArray.java",
"chars": 1276,
"preview": "package com.ex.offer;\n\n/**\n * 1.在一个二维数组中,每一行都按照从左到右递增的顺序排序,\n * 每一列都按照从上到下递增的顺序排序。请完成一个函数,\n * 输入这样的一个二维数组和一个整数,判断数组中是否含有该"
},
{
"path": "offer/src/com/ex/offer/Ex_05_ReplaceSpace.java",
"chars": 1777,
"preview": "package com.ex.offer;\n\n/**\n * 2.请实现一个函数,将一个字符串中的空格替换成“%20”。\n * 例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。\n */\npu"
},
{
"path": "offer/src/com/ex/offer/Ex_06_PrintListFromTailToHead.java",
"chars": 1831,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util"
},
{
"path": "offer/src/com/ex/offer/Ex_07_ReConstructBT.java",
"chars": 1237,
"preview": "package com.ex.offer;\n\n/**\n * 4.输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。\n * 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。\n * 例如输入前序遍历序列{1,2,4,7,3,5,6"
},
{
"path": "offer/src/com/ex/offer/Ex_08_DescendantNode.java",
"chars": 2458,
"preview": "package com.ex.offer;\n\npublic class Ex_08_DescendantNode {\n\n\tpublic static class Node {\n\t\tpublic int value;\n\t\tpublic Nod"
},
{
"path": "offer/src/com/ex/offer/Ex_08_GetNextNodeInBT.java",
"chars": 697,
"preview": "package com.ex.offer;\n\n\n/**\n * 后继节点\n */\npublic class Ex_08_GetNextNodeInBT {\n public TreeLinkNode GetNext(TreeLinkNod"
},
{
"path": "offer/src/com/ex/offer/Ex_09_QueueWithTwoStack.java",
"chars": 643,
"preview": "package com.ex.offer;\n\nimport java.util.Stack;\n\n/**\n * problem 9: 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。\n */\n\npublic"
},
{
"path": "offer/src/com/ex/offer/Ex_09_StackWithTwoQueue.java",
"chars": 1066,
"preview": "package com.ex.offer;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\n\npublic class Ex_09_StackWithTwoQueue {\n\n "
},
{
"path": "offer/src/com/ex/offer/Ex_10_Fibonacci.java",
"chars": 945,
"preview": "package com.ex.offer;\n\npublic class Ex_10_Fibonacci {\n\n public static int fib1(int n) {\n if (n <= 0) {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_10_JumpFloor.java",
"chars": 607,
"preview": "package com.ex.offer;\n\npublic class Ex_10_JumpFloor {\n\n public int jumpFloor(int target) {\n if (target == 1 ||"
},
{
"path": "offer/src/com/ex/offer/Ex_10_JumpFloorII.java",
"chars": 692,
"preview": "package com.ex.offer;\n\n/**\n * f(n)\n * f(1) = 1;\n * f(2) = f(2-1) + f(2-2) = 1 + 1 = 2;\n * f(3) = f(3-1) + f(3-2) + f(3-2"
},
{
"path": "offer/src/com/ex/offer/Ex_10_RectCover.java",
"chars": 419,
"preview": "package com.ex.offer;\n\npublic class Ex_10_RectCover {\n public int RectCover(int target) {\n if (target == 1 || "
},
{
"path": "offer/src/com/ex/offer/Ex_11_MinNumOfRotatingArray.java",
"chars": 1959,
"preview": "package com.ex.offer;\n\n/**\n * 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。\n * 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。\n * 例如数组{3,4,5,1,2}为{1,"
},
{
"path": "offer/src/com/ex/offer/Ex_11_SortAges.java",
"chars": 984,
"preview": "package com.ex.offer;\n\npublic class Ex_11_SortAges {\n\n // counting sort\n public static void sortAges(int[] ages) {"
},
{
"path": "offer/src/com/ex/offer/Ex_12_HasPathInMatrix.java",
"chars": 2128,
"preview": "package com.ex.offer;\n\npublic class Ex_12_HasPathInMatrix {\n\n public static boolean hasPath(char[] matrix, int rows, "
},
{
"path": "offer/src/com/ex/offer/Ex_13_MovingCount.java",
"chars": 1437,
"preview": "package com.ex.offer;\n\npublic class Ex_13_MovingCount {\n\n public int movingCount(int threshold, int rows, int cols) {"
},
{
"path": "offer/src/com/ex/offer/Ex_14_MaxProductionAfterCutting.java",
"chars": 1473,
"preview": "package com.ex.offer;\n\npublic class Ex_14_MaxProductionAfterCutting {\n\n public static int maxProduction(int n) {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_15_Count1.java",
"chars": 642,
"preview": "package com.ex.offer;\n\npublic class Ex_15_Count1 {\n\n public static int NumberOf1(int n) {\n int count = 0;\n "
},
{
"path": "offer/src/com/ex/offer/Ex_15_CountDifferInMN.java",
"chars": 558,
"preview": "package com.ex.offer;\n\npublic class Ex_15_CountDifferInMN {\n\n /**\n * 计算需要改变m的二进制表示中的多少位才能得到n.\n * @param m\n "
},
{
"path": "offer/src/com/ex/offer/Ex_15_IsPowerOf2.java",
"chars": 635,
"preview": "package com.ex.offer;\n\npublic class Ex_15_IsPowerOf2 {\n\n /**\n * 判断1个数是否是2的整数次幂,例如2 4 8 ...\n * 特点:若一个数是2的整数此幂,"
},
{
"path": "offer/src/com/ex/offer/Ex_16_Power.java",
"chars": 1336,
"preview": "package com.ex.offer;\n\npublic class Ex_16_Power {\n\n /**\n * f(n) = a ^ n\n * 1. a != 0\n * 2. n < 0 时, f(n) "
},
{
"path": "offer/src/com/ex/offer/Ex_17_AddTwoBigNumber.java",
"chars": 1688,
"preview": "package com.ex.offer;\n\npublic class Ex_17_AddTwoBigNumber {\n\n /**\n * 大数相加问题:\n * 大数相加不能直接使用基本的int类型,因为int可以表示的"
},
{
"path": "offer/src/com/ex/offer/Ex_17_Print1ToMaxNDigits.java",
"chars": 3333,
"preview": "package com.ex.offer;\n\npublic class Ex_17_Print1ToMaxNDigits {\n\n /**\n * 1. 实现基本功能,但是当n很大时,count会出现int范围不够的问题,改成lo"
},
{
"path": "offer/src/com/ex/offer/Ex_18_DeleteDuplicatedNode.java",
"chars": 2166,
"preview": "package com.ex.offer;\n\npublic class Ex_18_DeleteDuplicatedNode {\n\n public static ListNode deleteDuplication (ListNode"
},
{
"path": "offer/src/com/ex/offer/Ex_18_DeleteNodeInSList.java",
"chars": 1504,
"preview": "package com.ex.offer;\n\npublic class Ex_18_DeleteNodeInSList {\n\n public static Node deleteNode(Node head, Node toBeDel"
},
{
"path": "offer/src/com/ex/offer/Ex_19_Match.java",
"chars": 1852,
"preview": "package com.ex.offer;\n\n/**\n * 当模式中的第二个字符不是“*”时:\n * 1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。\n * 2、如果 字符串第一个字符和模"
},
{
"path": "offer/src/com/ex/offer/Ex_20_IsNumber.java",
"chars": 1842,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_20_IsNumber {\n /**\n * A.B[E|e]C\n * A.B: A B任意有"
},
{
"path": "offer/src/com/ex/offer/Ex_21_ReOrderArray.java",
"chars": 1919,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_21_ReOrderArray {\n\n public void reOrderArray(int [] ar"
},
{
"path": "offer/src/com/ex/offer/Ex_22_FindKthNodeToTail.java",
"chars": 1025,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_22_FindKthNodeToTail {\n /**\n * 1. 空链表\n * 2. k "
},
{
"path": "offer/src/com/ex/offer/Ex_22_FindMedianNodeInList.java",
"chars": 733,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_22_FindMedianNodeInList {\n\n public ListNode findMedian"
},
{
"path": "offer/src/com/ex/offer/Ex_23_EntryNodeInList.java",
"chars": 675,
"preview": "package com.ex.offer;\n\npublic class Ex_23_EntryNodeInList {\n\n public ListNode EntryNodeOfLoop(ListNode pHead) {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_24_ReverseSList.java",
"chars": 932,
"preview": "package com.ex.offer;\n\npublic class Ex_24_ReverseSList {\n\n public ListNode ReverseList(ListNode head) {\n if (h"
},
{
"path": "offer/src/com/ex/offer/Ex_25_MergeList.java",
"chars": 2415,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_25_MergeList {\n\n public ListNode Merge(ListNode list1,"
},
{
"path": "offer/src/com/ex/offer/Ex_26_IsSubTree.java",
"chars": 738,
"preview": "package com.ex.offer;\n\n// 此题目还可以将Tree A B 序列化,然后看B字符串是否在A字符串中,KMP算法\npublic class Ex_26_IsSubTree {\n\n public boolean H"
},
{
"path": "offer/src/com/ex/offer/Ex_27_MirrorOfTree.java",
"chars": 475,
"preview": "package com.ex.offer;\n\npublic class Ex_27_MirrorOfTree {\n\n public void Mirror(TreeNode root) {\n if (root == nu"
},
{
"path": "offer/src/com/ex/offer/Ex_28_SymmetricalTree.java",
"chars": 1025,
"preview": "package com.ex.offer;\n\npublic class Ex_28_SymmetricalTree {\n boolean isSymmetrical(TreeNode pRoot) {\n if (pRoo"
},
{
"path": "offer/src/com/ex/offer/Ex_29_PrintMatrixWithClockWise.java",
"chars": 1595,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\n\npublic class Ex_29_PrintMatrixWithClockWise {\n public ArrayList<I"
},
{
"path": "offer/src/com/ex/offer/Ex_30_StackWithMinFunction.java",
"chars": 807,
"preview": "package com.ex.offer;\n\nimport java.util.Stack;\n\npublic class Ex_30_StackWithMinFunction {\n Stack<Integer> stack = new"
},
{
"path": "offer/src/com/ex/offer/Ex_31_IsPopOrder.java",
"chars": 844,
"preview": "package com.ex.offer;\n\nimport java.util.Stack;\n\npublic class Ex_31_IsPopOrder {\n public boolean IsPopOrder(int [] pus"
},
{
"path": "offer/src/com/ex/offer/Ex_32_PrintTreeByLayer.java",
"chars": 1200,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.Queue;\n\npublic class Ex"
},
{
"path": "offer/src/com/ex/offer/Ex_32_PrintTreeWithZhi.java",
"chars": 2963,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\nimport java.util.Stack;\n\npublic class Ex_32_PrintTreeWithZhi {\n\n p"
},
{
"path": "offer/src/com/ex/offer/Ex_32_TraverseTreeByLayer.java",
"chars": 936,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.Queue;\n\n/**\n * 注1:\n * 树"
},
{
"path": "offer/src/com/ex/offer/Ex_33_VerifySequenceOfBST.java",
"chars": 1532,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_33_VerifySequenceOfBST {\n public boolean VerifySequenc"
},
{
"path": "offer/src/com/ex/offer/Ex_34_FindPathInBT.java",
"chars": 1606,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\n\npublic class Ex_34_FindPathInBT {\n\n publi"
},
{
"path": "offer/src/com/ex/offer/Ex_34_FindPathInBT_1.java",
"chars": 892,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\n\npublic class Ex_34_FindPathInBT_1 {\n Arra"
},
{
"path": "offer/src/com/ex/offer/Ex_34_FindPathInBT_2.java",
"chars": 888,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\n\npublic class Ex_34_FindPathInBT_2 {\n ArrayList<ArrayList<Integer>"
},
{
"path": "offer/src/com/ex/offer/Ex_35_CloneList.java",
"chars": 1624,
"preview": "package com.ex.offer;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class Ex_35_CloneList {\n public Random"
},
{
"path": "offer/src/com/ex/offer/Ex_36_ConvertBetweenBSTAndDList.java",
"chars": 1476,
"preview": "package com.ex.offer;\n\nimport java.util.Stack;\n\npublic class Ex_36_ConvertBetweenBSTAndDList {\n TreeNode head = null;"
},
{
"path": "offer/src/com/ex/offer/Ex_37_SerializeBT.java",
"chars": 1062,
"preview": "package com.ex.offer;\n\npublic class Ex_37_SerializeBT {\n String Serialize(TreeNode root) {\n StringBuilder sb ="
},
{
"path": "offer/src/com/ex/offer/Ex_38_EightQueen.java",
"chars": 1192,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\n// 8皇后问题与回溯法:https://www.cnblogs.com/bigmoyan/p/4521683.html\n//\n// 回溯法\n//"
},
{
"path": "offer/src/com/ex/offer/Ex_38_StringCombination.java",
"chars": 1086,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\n\npublic class Ex_38_StringCombination {\n p"
},
{
"path": "offer/src/com/ex/offer/Ex_38_StringPermutation.java",
"chars": 1221,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\n\npublic class Ex_38_StringPermutation {"
},
{
"path": "offer/src/com/ex/offer/Ex_39_KthSmallestNumInArrayWithoutSort.java",
"chars": 4702,
"preview": "package com.ex.offer;\n\npublic class Ex_39_KthSmallestNumInArrayWithoutSort {\n\n /**\n * 找到第K个最小的数字,同时RAND-PARTITION"
},
{
"path": "offer/src/com/ex/offer/Ex_39_MoreThanHalfNum.java",
"chars": 3001,
"preview": "package com.ex.offer;\n\npublic class Ex_39_MoreThanHalfNum {\n\n public static int moreThanHalfNum(int[] array) {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_40_GetLeastKNumbers.java",
"chars": 2289,
"preview": "package com.ex.offer;\n\nimport java.util.ArrayList;\n\npublic class Ex_40_GetLeastKNumbers {\n\n public static ArrayList<I"
},
{
"path": "offer/src/com/ex/offer/Ex_41_MedianInDataFlow.java",
"chars": 2146,
"preview": "package com.ex.offer;\n\nimport java.util.Comparator;\nimport java.util.PriorityQueue;\n\npublic class Ex_41_MedianInDataFlow"
},
{
"path": "offer/src/com/ex/offer/Ex_42_MaxSumOfSubArray.java",
"chars": 495,
"preview": "package com.ex.offer;\n\n// 此题目类似于:Ex_63_MaxProfits\npublic class Ex_42_MaxSumOfSubArray {\n public int FindGreatestSumOf"
},
{
"path": "offer/src/com/ex/offer/Ex_43_NumberOf1Between1AndN.java",
"chars": 1018,
"preview": "package com.ex.offer;\n\n//https://www.cnblogs.com/xuanxufeng/p/6854105.html\npublic class Ex_43_NumberOf1Between1AndN {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_44_ANumInArray.java",
"chars": 1041,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_44_ANumInArray {\n public int digitAt(int index) {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_45_MinNumByConcatArray.java",
"chars": 807,
"preview": "package com.ex.offer;\n\nimport java.util.Arrays;\nimport java.util.Comparator;\n\n// 最小字典序问题\npublic class Ex_45_MinNumByConc"
},
{
"path": "offer/src/com/ex/offer/Ex_46_ConvertStringToIP.java",
"chars": 3116,
"preview": "package com.ex.offer;\n\n/**\n * 附加题目\n *\n * problem 5: [String][递归][动态规划]\n *\n * 给定一个由数字组成的字符串, 请返回能返回多少种合法的ipv4组合。\n *\n * 知识"
},
{
"path": "offer/src/com/ex/offer/Ex_46_TranslationFromIntToString.java",
"chars": 1833,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\n/**\n * String -> Another String\n */\npublic class Ex_46_TranslationFromInt"
},
{
"path": "offer/src/com/ex/offer/Ex_47_MaxGiftValue.java",
"chars": 2005,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_47_MaxGiftValue {\n public int getMaxValue(int[][] matr"
},
{
"path": "offer/src/com/ex/offer/Ex_48_LongestSubStringWithDuplication.java",
"chars": 1165,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\n// 这个题目和Ex_42_MaxSumOfSubArray类似\npublic class Ex_48_LongestSubStringWithD"
},
{
"path": "offer/src/com/ex/offer/Ex_49_UglyNumber.java",
"chars": 2096,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_49_UglyNumber {\n // 保存所有丑数,同时只检查丑数,不检查非丑数\n public i"
},
{
"path": "offer/src/com/ex/offer/Ex_50_FirstNotRepeatedChar.java",
"chars": 1419,
"preview": "package com.ex.offer;\n\nimport java.util.HashMap;\n\npublic class Ex_50_FirstNotRepeatedChar {\n public int FirstNotRepea"
},
{
"path": "offer/src/com/ex/offer/Ex_50_FirstNotRepeatedCharInDataFlow.java",
"chars": 1083,
"preview": "package com.ex.offer;\n\npublic class Ex_50_FirstNotRepeatedCharInDataFlow {\n\n private static final int TABLE_SIZE = 25"
},
{
"path": "offer/src/com/ex/offer/Ex_50_StringUtilsSolutions.java",
"chars": 3099,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.HashMap;\n\npublic class Ex_50_StringUtilsSolutions {\n\n "
},
{
"path": "offer/src/com/ex/offer/Ex_51_InversePairs.java",
"chars": 1365,
"preview": "package com.ex.offer;\n\nimport java.util.Arrays;\n\npublic class Ex_51_InversePairs {\n public int InversePairs(int [] ar"
},
{
"path": "offer/src/com/ex/offer/Ex_51_InversePairs_BigData.java",
"chars": 1406,
"preview": "package com.ex.offer;\n\nimport java.util.Arrays;\n\npublic class Ex_51_InversePairs_BigData {\n public int InversePairs(i"
},
{
"path": "offer/src/com/ex/offer/Ex_52_FirstCommonNode.java",
"chars": 1090,
"preview": "package com.ex.offer;\n\npublic class Ex_52_FirstCommonNode {\n public ListNode FindFirstCommonNode(ListNode pHead1, Lis"
},
{
"path": "offer/src/com/ex/offer/Ex_53_GetMissingNumber.java",
"chars": 684,
"preview": "package com.ex.offer;\n\npublic class Ex_53_GetMissingNumber {\n public int getMissingNumber(int[] array) {\n if ("
},
{
"path": "offer/src/com/ex/offer/Ex_53_GetNumberOfK.java",
"chars": 2021,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_53_GetNumberOfK {\n public int GetNumberOfK(int [] arra"
},
{
"path": "offer/src/com/ex/offer/Ex_53_GetNumberSameAsIndex.java",
"chars": 817,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_53_GetNumberSameAsIndex {\n\n public int getNumberSameAs"
},
{
"path": "offer/src/com/ex/offer/Ex_54_KthNodeInBST.java",
"chars": 551,
"preview": "package com.ex.offer;\n\npublic class Ex_54_KthNodeInBST {\n\n int count = 0; // 递归全局变量\n\n TreeNode KthNode(TreeNode pR"
},
{
"path": "offer/src/com/ex/offer/Ex_55_BalancedBT.java",
"chars": 2903,
"preview": "package com.ex.offer;\n\npublic class Ex_55_BalancedBT {\n\n // Java没有引用和指针,可以使用全局变量,也可以使用数组引用\n int depth = 0;\n\n pu"
},
{
"path": "offer/src/com/ex/offer/Ex_55_DepthOfBT.java",
"chars": 360,
"preview": "package com.ex.offer;\n\npublic class Ex_55_DepthOfBT {\n public int TreeDepth(TreeNode root) {\n if (root == null"
},
{
"path": "offer/src/com/ex/offer/Ex_56_AppearanceOnce.java",
"chars": 1100,
"preview": "package com.ex.offer;\n\n//num1,num2分别为长度为1的数组。传出参数\n//将num1[0],num2[0]设置为返回结果\npublic class Ex_56_AppearanceOnce {\n publ"
},
{
"path": "offer/src/com/ex/offer/Ex_56_AppearanceOnce_Continued.java",
"chars": 973,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_56_AppearanceOnce_Continued {\n public int FindNumAppea"
},
{
"path": "offer/src/com/ex/offer/Ex_57_FindContinuousSequence.java",
"chars": 1426,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\n\npublic class Ex_57_FindContinuousSequence {\n"
},
{
"path": "offer/src/com/ex/offer/Ex_57_FindNumbersWithSum.java",
"chars": 1777,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\n\npublic class Ex_57_FindNumbersWithSum {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_58_ROL.java",
"chars": 807,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_58_ROL {\n public String LeftRotateString(String str,in"
},
{
"path": "offer/src/com/ex/offer/Ex_58_ReverseSentence.java",
"chars": 1491,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_58_ReverseSentence {\n public String ReverseSentence(St"
},
{
"path": "offer/src/com/ex/offer/Ex_59_MaxNumOfSlidingWindow.java",
"chars": 1315,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\n\npublic class Ex"
},
{
"path": "offer/src/com/ex/offer/Ex_59_QueueWithMax.java",
"chars": 735,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.LinkedList;\n\npublic class Ex_59_QueueWithMax {\n priva"
},
{
"path": "offer/src/com/ex/offer/Ex_60_ProbabilityOfS.java",
"chars": 2944,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\n// https://www.cnblogs.com/keedor/p/4474471.html\n// https://www.cnblogs.c"
},
{
"path": "offer/src/com/ex/offer/Ex_61_ContinuousSequence.java",
"chars": 799,
"preview": "package com.ex.offer;\n\nimport java.util.Arrays;\n\npublic class Ex_61_ContinuousSequence {\n public boolean isContinuous"
},
{
"path": "offer/src/com/ex/offer/Ex_62_Josephus.java",
"chars": 1229,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\n\n// 约瑟夫问题其实是一个环型链表\n// 假设 n > m, 则第一个要删除的位置是 i"
},
{
"path": "offer/src/com/ex/offer/Ex_63_MaxProfits.java",
"chars": 827,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\n// 此题目类似于Ex_42_MaxSumOfSubArray\npublic class Ex_63_MaxProfits {\n publi"
},
{
"path": "offer/src/com/ex/offer/Ex_64_SumFrom1ToN.java",
"chars": 327,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_64_SumFrom1ToN {\n public int Sum_Solution(int n) {\n "
},
{
"path": "offer/src/com/ex/offer/Ex_65_AddWithoutCarry.java",
"chars": 375,
"preview": "package com.ex.offer;\n\npublic class Ex_65_AddWithoutCarry {\n public int Add(int num1,int num2) {\n int sum = 0;"
},
{
"path": "offer/src/com/ex/offer/Ex_65_SwapNumWithoutTemp.java",
"chars": 721,
"preview": "package com.ex.offer;\n\npublic class Ex_65_SwapNumWithoutTemp {\n public int[] swap1 (int a, int b) {\n int[] res"
},
{
"path": "offer/src/com/ex/offer/Ex_66_ConstructMultiplyArray.java",
"chars": 646,
"preview": "package com.ex.offer;\n\npublic class Ex_66_ConstructMultiplyArray {\n public int[] multiply(int[] A) {\n int[] re"
},
{
"path": "offer/src/com/ex/offer/Ex_67_StringToInt.java",
"chars": 1668,
"preview": "package com.ex.offer;\n\nimport org.junit.Test;\n\npublic class Ex_67_StringToInt {\n /**\n * 说明:当输入不合法时,返回0。但是由于正常输出也可"
},
{
"path": "offer/src/com/ex/offer/Ex_68_LowestCommonAncestor.java",
"chars": 334,
"preview": "package com.ex.offer;\n\npublic class Ex_68_LowestCommonAncestor {\n // case1: 二叉树(二叉搜索树)\n public TreeNode commonAnce"
},
{
"path": "offer/src/com/ex/offer/ListNode.java",
"chars": 162,
"preview": "package com.ex.offer;\n\n/**\n * 单链表节点\n */\n\npublic class ListNode {\n int val;\n ListNode next;\n\n public ListNode(in"
},
{
"path": "offer/src/com/ex/offer/Node.java",
"chars": 142,
"preview": "package com.ex.offer;\n\n/**\n * 单链表节点\n */\npublic class Node {\n int val;\n Node next;\n\n Node (int val) {\n th"
},
{
"path": "offer/src/com/ex/offer/RandomListNode.java",
"chars": 231,
"preview": "package com.ex.offer;\n\n/**\n * 含有指向随机节点指针的单链表节点\n */\npublic class RandomListNode {\n int label;\n RandomListNode next "
},
{
"path": "offer/src/com/ex/offer/TestUtils.java",
"chars": 4228,
"preview": "package com.ex.offer;\n\nimport java.util.Arrays;\n\npublic class TestUtils {\n public static void printArray(int[] arr) {"
},
{
"path": "offer/src/com/ex/offer/TreeLinkNode.java",
"chars": 270,
"preview": "package com.ex.offer;\n\n/**\n * 含有指向父节点指针的二叉树节点\n * Ex_08_GetNextNodeInBT\n */\npublic class TreeLinkNode {\n int val;\n "
},
{
"path": "offer/src/com/ex/offer/TreeNode.java",
"chars": 169,
"preview": "package com.ex.offer;\n\n/**\n * 二叉树节点\n */\npublic class TreeNode {\n int val;\n TreeNode left;\n TreeNode right;\n\n "
},
{
"path": "offer/src/com/ex/singleton/Singleton1.java",
"chars": 416,
"preview": "package com.ex.singleton;\n\n// V1.0: 饿汉式\npublic class Singleton1 {\n // instance必须是static变量(类变量)\n private static Sin"
},
{
"path": "offer/src/com/ex/singleton/Singleton2.java",
"chars": 305,
"preview": "package com.ex.singleton;\n\n// V2.0: 懒汉式\npublic class Singleton2 {\n private static Singleton2 instance = null;\n\n pr"
},
{
"path": "offer/src/com/ex/singleton/Singleton3.java",
"chars": 600,
"preview": "package com.ex.singleton;\n\n// V3.0: 双重校验\npublic class Singleton3 {\n // volatile提供可见性(工作内存的值能立即在主内存中可见),\n // 保证getI"
},
{
"path": "offer/src/com/ex/singleton/Singleton4.java",
"chars": 274,
"preview": "package com.ex.singleton;\n\n// V4.0: 静态内部类\npublic class Singleton4 {\n private static class SingletonHolder {\n p"
},
{
"path": "offer/src/com/ex/singleton/Singleton5.java",
"chars": 355,
"preview": "package com.ex.singleton;\n\n// V5.0: 枚举方法\npublic enum Singleton5 {\n INSTANCE;\n\n private int id;\n\n public int get"
},
{
"path": "offer/src/com/ex/singleton/singleton.md",
"chars": 499,
"preview": "# 单例模式\n\n## 单例模式的好处\n单例模式适用于应用中频繁创建的对象,尤其是频繁创建的重量级对象。\n例如统一的配置文件。\n使用单例模式能够提升性能,减小内存开销。\n\n## 单例模式的实现\n### 1.饿汉式\n饿汉式加载类的时候,就会创建"
},
{
"path": "practice/Final.md",
"chars": 284,
"preview": "# 总结\n\n时间过得很快,不知不觉间,一切就结束了。\n\n无论课程多么精彩,似乎精彩总是他们的,我什么都没有。无论如何,感谢各位工作人员的辛勤付出。\n\n很多课程都没来得及消化和理解,后续仍然需要进一步的学习、总结、实践。\n\n复习总结列表:\n\n"
},
{
"path": "practice/README.md",
"chars": 12,
"preview": "# Practice\n\n"
},
{
"path": "practice/src/io/gkd/ListNode.java",
"chars": 286,
"preview": "package io.gkd;\n\npublic class ListNode {\n public int val;\n public ListNode next;\n\n public ListNode() {\n }\n\n "
},
{
"path": "practice/src/io/gkd/Node.java",
"chars": 299,
"preview": "package io.gkd;\n\nimport java.util.List;\n\npublic class Node {\n public int val;\n public List<Node> children;\n\n pu"
},
{
"path": "practice/src/io/gkd/TreeNode.java",
"chars": 351,
"preview": "package io.gkd;\n\npublic class TreeNode {\n public int val;\n public TreeNode left;\n public TreeNode right;\n\n p"
},
{
"path": "practice/src/io/gkd/lectures/lecture04/Lc077_Combine.java",
"chars": 845,
"preview": "package io.gkd.lectures.lecture04;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Lc077_Combine {\n\n "
},
{
"path": "practice/src/io/gkd/lectures/lecture04/Lc078_SubSets.java",
"chars": 917,
"preview": "package io.gkd.lectures.lecture04;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Medium\n * 78. https://lee"
},
{
"path": "practice/src/io/gkd/lectures/lecture05/Lc094_InOrderTraversal.java",
"chars": 472,
"preview": "package io.gkd.lectures.lecture05;\n\nimport io.gkd.TreeNode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic "
},
{
"path": "practice/src/io/gkd/lectures/lecture05/Lc105_BuildTree.java",
"chars": 1182,
"preview": "package io.gkd.lectures.lecture05;\n\nimport io.gkd.TreeNode;\n\n/**\n * Medium\n * 105. https://leetcode-cn.com/problems/cons"
},
{
"path": "practice/src/io/gkd/lectures/lecture05/Lc236_LCA.java",
"chars": 1320,
"preview": "package io.gkd.lectures.lecture05;\n\nimport io.gkd.TreeNode;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport "
},
{
"path": "practice/src/io/gkd/lectures/lecture05/Lc297_Codec.java",
"chars": 1367,
"preview": "package io.gkd.lectures.lecture05;\n\nimport io.gkd.TreeNode;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport"
},
{
"path": "practice/src/io/gkd/lectures/lecture05/Lc429_LevelOrderNTree.java",
"chars": 1504,
"preview": "package io.gkd.lectures.lecture05;\n\nimport io.gkd.Node;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport"
},
{
"path": "practice/src/io/gkd/lectures/lecture05/Lc589_PreOrderNTree.java",
"chars": 1093,
"preview": "package io.gkd.lectures.lecture05;\n\nimport io.gkd.Node;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java."
},
{
"path": "practice/src/io/gkd/week01/Lc021_MergeTwoLists.java",
"chars": 723,
"preview": "package io.gkd.week01;\n\nimport io.gkd.ListNode;\n\n/**\n * Easy\n * 21. https://leetcode-cn.com/problems/merge-two-sorted-li"
},
{
"path": "practice/src/io/gkd/week01/Lc066_PlusOne.java",
"chars": 460,
"preview": "package io.gkd.week01;\n\n/**\n * Easy\n * 66. https://leetcode-cn.com/problems/plus-one/submissions/\n */\npublic class Lc066"
},
{
"path": "practice/src/io/gkd/week02/Lc146_LRUCache.java",
"chars": 1981,
"preview": "package io.gkd.week02;\n\nimport java.util.HashMap;\n\n/**\n * Medium\n * 146. https://leetcode-cn.com/problems/lru-cache/\n * "
},
{
"path": "practice/src/io/gkd/week02/Lc697_FindShortestSubArray.java",
"chars": 1334,
"preview": "package io.gkd.week02;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Easy\n * 697. https://leetcode-cn.com/pro"
},
{
"path": "practice/src/io/gkd/week03/Lc106_BuildTree.java",
"chars": 1024,
"preview": "package io.gkd.week03;\n\nimport io.gkd.TreeNode;\n\n/**\n * Medium\n * 106. https://leetcode-cn.com/problems/construct-binary"
},
{
"path": "practice/src/io/gkd/week03/Lc210_FindOrder2.java",
"chars": 1142,
"preview": "package io.gkd.week03;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\n\npublic class Lc210_FindOrder2 {\n public"
},
{
"path": "practice/src/io/gkd/week03/NOTES.md",
"chars": 134,
"preview": "# 本周总结\n\n本周主要理解了树的相关内容,图的内容还在学习中。\n\n## 树\n\n* 树的定义\n* 二叉树\n * 完全二叉树\n * 满二叉树\n* 二(多)叉树的遍历\n* 基环树\n\n## 图\n\n* 链表、树、基环树、图的关系\n* 图"
},
{
"path": "questions/questions.md",
"chars": 9931,
"preview": "# Questions\n\n## 数组\n\n### 1. 数组与泛型动态数组\n[[Solution1](https://github.com/guokaide/algorithm/blob/master/summary/algorithm.md"
},
{
"path": "solutions/剑指offer 题解.md",
"chars": 5419,
"preview": "# 剑指offer 题解\n\n## 2. 实现单例模式\n\n### 什么是单例模式?\n\n**单例模式**,顾名思义就是整个系统只能有1个实例存在,不能再多了。\n\n### 单例模式的好处\n\n单例模式适用于应用中频繁创建的对象,尤其是频繁创建的重量"
},
{
"path": "summary/algorithm.md",
"chars": 7483,
"preview": "# Algorithm\n\n## 数组\n\n### 数组的基本概念\n\n**数组(Array)**:数组是一种**线性表**数据结构。它用一组**连续的内存空间**,来存储一组具有**相同数据类型**的数据。\n\n* 线性表与非线性表\n * 线"
}
]
About this extraction
This page contains the full source code of the guokaide/algorithm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 167 files (284.7 KB), approximately 95.7k tokens, and a symbol index with 651 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.