├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── so
│ ├── Add47.java
│ ├── BinaryToLinked27.java
│ ├── BinaryTreeSearch6.java
│ ├── Calculate46.java
│ ├── CloneCLinkedList26.java
│ ├── Common.java
│ ├── DeleteDuplication57.java
│ ├── DeleteNode13.java
│ ├── DicesProbability43.java
│ ├── DoesTreeHave18.java
│ ├── DoubleSQueue7.java
│ ├── Duplicate51.java
│ ├── EnterLoop56.java
│ ├── Fibonacci9.java
│ ├── FinalClass48.java
│ ├── FindFirstCommonNode37.java
│ ├── FindGreatestSum31.java
│ ├── FindKthToTail15.java
│ ├── FindNumAppearOnce40.java
│ ├── FindNumber3.java
│ ├── FindNumbersWithSum41.java
│ ├── FindPath25.java
│ ├── FirstAppearingOnce55.java
│ ├── FirstNotRepeating35.java
│ ├── GetLeastNumbers30.java
│ ├── GetMedian64.java
│ ├── GetNumberOfK38.java
│ ├── HasPath66.java
│ ├── InversePairs36.java
│ ├── IsContinuous44.java
│ ├── IsNumber54.java
│ ├── IsPopOrder22.java
│ ├── IsSymmetrical59.java
│ ├── KthNode63.java
│ ├── LastRemaining45.java
│ ├── LevelPrintTree61.java
│ ├── MaxInWindows65.java
│ ├── MergeLinked17.java
│ ├── MinCParent50.java
│ ├── MinNumber8.java
│ ├── MirrorRecursively19.java
│ ├── MoreThanHalfNum29.java
│ ├── MovingCount67.java
│ ├── MultiplyArray52.java
│ ├── NextTreeNode58.java
│ ├── NumberOf1Bw32.java
│ ├── NumberOfBin10.java
│ ├── OddEvenNumber14.java
│ ├── Permutation28.java
│ ├── Power11.java
│ ├── PrintFromTopToBottom23.java
│ ├── PrintListReversing5.java
│ ├── PrintMatrixInCircle20.java
│ ├── PrintMinNumber33.java
│ ├── PrintToMaxOfNDigits12.java
│ ├── RegularMatch53.java
│ ├── ReplaceBlank4.java
│ ├── ReverseList16.java
│ ├── ReverseSentence42.java
│ ├── Serializer62.java
│ ├── SingletonPattern2.java
│ ├── StackWithMin21.java
│ ├── StrToInt49.java
│ ├── TreePath39.java
│ ├── UglyNumber34.java
│ ├── VerifySequenceOfBST24.java
│ └── ZTreePrint60.java
└── test
└── java
└── com
└── so
├── Test10.java
├── Test11.java
├── Test12.java
├── Test13.java
├── Test14.java
├── Test15.java
├── Test16.java
├── Test17.java
├── Test18.java
├── Test19.java
├── Test2.java
├── Test20.java
├── Test21.java
├── Test22.java
├── Test23.java
├── Test24.java
├── Test25.java
├── Test26.java
├── Test27.java
├── Test28.java
├── Test29.java
├── Test3.java
├── Test30.java
├── Test31.java
├── Test32.java
├── Test33.java
├── Test34.java
├── Test35.java
├── Test36.java
├── Test37.java
├── Test38.java
├── Test39.java
├── Test4.java
├── Test40.java
├── Test41.java
├── Test42.java
├── Test43.java
├── Test44.java
├── Test45.java
├── Test46.java
├── Test47.java
├── Test48.java
├── Test49.java
├── Test5.java
├── Test50.java
├── Test51.java
├── Test52.java
├── Test53.java
├── Test54.java
├── Test55.java
├── Test56.java
├── Test57.java
├── Test58.java
├── Test59.java
├── Test6.java
├── Test60.java
├── Test61.java
├── Test62.java
├── Test63.java
├── Test64.java
├── Test65.java
├── Test66.java
├── Test67.java
├── Test7.java
├── Test8.java
└── Test9.java
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore files
2 | .idea/*
3 | target/*
4 | SwordOffer.iml
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 GaoLeiQin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 《剑指offer》Java版代码
2 | 
3 |
4 | ##### 提供多种解法以及思路,并在OJ上全都通过
5 |
6 |
7 | ### 目录
8 |
9 | |题号|题目及题解|测试用例|
10 | |:-----|:----|:----|
11 | |第二题|[单例设计模式](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/SingletonPattern2.java)|[测试2](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test2.java)|
12 | |第三题|[二维数组中查找目标值](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FindNumber3.java)|[测试3](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test3.java)|
13 | |第四题|[替换字符串中的空格](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/ReplaceBlank4.java)|[测试4](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test4.java)|
14 | |第五题|[从尾到头打印链表](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/PrintListReversing5.java)|[测试5](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test5.java)|
15 | |第六题|[由前序和中序遍历重建二叉树](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/BinaryTreeSearch6.java)|[测试6](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test6.java)|
16 | |第七题|[用两个栈实现队列](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/DoubleSQueue7.java)|[测试7](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test7.java)|
17 | |第八题|[求旋转数组的最小数字](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/MinNumber8.java)|[测试8](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test8.java)|
18 | |第九题|[斐波那契数列的第n项(青蛙跳台阶)](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/Fibonacci9.java)|[测试9](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test9.java)|
19 | |第十题|[二进制中1的个数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/NumberOfBin10.java)|[测试10](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test10.java)|
20 | |第十一题|[数值的整数次方](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/Power11.java)|[测试11](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test11.java)|
21 | |第十二题|[打印1到最大的n位数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/PrintToMaxOfNDigits12.java)|[测试12](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test12.java)|
22 | |第十三题|[O(1)时间删除链表节点](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/DeleteNode13.java)|[测试13](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test13.java)|
23 | |第十四题|[使数组中的奇数位于偶数前面](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/OddEvenNumber14.java)|[测试14](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test14.java)|
24 | |第十五题|[找链表中倒数第K个节点](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FindKthToTail15.java)|[测试15](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test15.java)|
25 | |第十六题|[反转链表](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/ReverseList16.java)|[测试16](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test16.java)|
26 | |第十七题|[合并两个有序链表](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/MergeLinked17.java)|[测试17](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test17.java)|
27 | |第十八题|[判断二叉树A中是否包含子树B](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/DoesTreeHave18.java)|[测试18](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test18.java)|
28 | |第十九题|[二叉树的镜像](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/MirrorRecursively19.java)|[测试19](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test19.java)|
29 | |第二十题|[顺时针打印矩阵](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/PrintMatrixInCircle20.java)|[测试20](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test20.java)|
30 | |第二十一题|[包含min函数的栈](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/StackWithMin21.java)|[测试21](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test21.java)|
31 | |第二十二题|[判断一个栈是否是另一个栈的弹出序列](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/IsPopOrder22.java)|[测试22](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test22.java)|
32 | |第二十三题|[层序遍历二叉树](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/PrintFromTopToBottom23.java)|[测试23](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test23.java)|
33 | |第二十四题|[后序遍历二叉搜索树](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/VerifySequerceOfBST24.java)|[测试24](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test24.java)|
34 | |第二十五题|[二叉树中和为某值的路径](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FindPath25.java)|[测试25](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test25.java)|
35 | |第二十六题|[复杂链表的复制](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/CloneCLinkedList26.java)|[测试26](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test26.java)|
36 | |第二十七题|[二叉搜索树转换为双向链表](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/BinaryToLinked27.java)|[测试27](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test27.java)|
37 | |第二十八题|[打印字符串中所有字符的排列](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/Permutation28.java)|[测试28](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test28.java)|
38 | |第二十九题|[数组中出现次数超过一半的数字](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/MoreThanHalfNum29.java)|[测试29](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test29.java)|
39 | |第三十题|[找出最小的K个数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/GetLeastNumbers30.java)|[测试30](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test30.java)|
40 | |第三十一题|[连续子数组的最大和](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FindGreatestSum31.java)|[测试31](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test31.java)|
41 | |第三十二题|[从1到整数n中1出现的次数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/NumberOf1Bw32.java)|[测试32](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test32.java)|
42 | |第三十三题|[把数组中的数排成一个最小的数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/PrintMinNumber33.java)|[测试33](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test33.java)|
43 | |第三十四题|[求第N个丑数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/UglyNumber34.java)|[测试34](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test34.java)|
44 | |第三十五题|[第一个出现一次的字符](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FirstNotRepeating35.java)|[测试35](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test35.java)|
45 | |第三十六题|[数组中逆序对的个数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/InversePairs36.java)|[测试36](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test36.java)|
46 | |第三十七题|[两个链表的第一个公共节点](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FindFirstCommonNode37.java)|[测试37](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test37.java)|
47 | |第三十八题|[数字在排序数组中出现的次数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/GetNumberOfK38.java)|[测试38](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test38.java)|
48 | |第三十九题|[二叉树的深度](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/TreePath39.java)|[测试39](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test39.java)|
49 | |第四十题|[数组中只出现一次的两个数,而其他数都出现两次](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FindNumAppearOnce40.java)|[测试40](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test40.java)|
50 | |第四十一题|[和为s的连续整数序列](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FindNumbersWithSum41.java)|[测试41](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test41.java)|
51 | |第四十二题|[翻转字符串](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/ReverseSentence42.java)|[测试42](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test42.java)|
52 | |第四十三题|[n个骰子的点数及出现的概率](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/DicesProbability43.java)|[测试43](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test43.java)|
53 | |第四十四题|[扑克牌的顺子](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/IsContinuous44.java)|[测试44](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test44.java)|
54 | |第四十五题|[圆圈中最后剩下的数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/LastRemaining45.java)|[测试45](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test45.java)|
55 | |第四十六题|[1+2+3+...+n的和](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/Calculate46.java)|[测试46](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test46.java)|
56 | |第四十七题|[不用加减乘除做加法](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/Add47.java)|[测试47](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test47.java)|
57 | |第四十八题|[不能被继承的类](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FinalClass48.java)|[测试48](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test48.java)|
58 | |第四十九题|[字符串转换为整数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/StrToInt49.java)|[测试49](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test49.java)|
59 | |第五十题|[树中两个节点的最低公共祖先](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/MinCParent50.java)|[测试50](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test50.java)|
60 | |第五十一题|[找出重复的数](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/Duplicate51.java)|[测试51](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test51.java)|
61 | |第五十二题|[构建乘积数组](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/MultiplyArray52.java)|[测试52](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test52.java)|
62 | |第五十三题|[正则表达式匹配](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/RegularMatch53.java)|[测试53](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test53.java)|
63 | |第五十四题|[表示数值的字符串](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/IsNumber54.java)|[测试54](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test54.java)|
64 | |第五十五题|[字符流中第一个不重复的字符](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/FirstAppearingOnce55.java)|[测试55](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test55.java)|
65 | |第五十六题|[链表中环的入口节点](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/EnterLoop56.java)|[测试56](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test56.java)|
66 | |第五十七题|[删除链表中重复的节点](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/DeleteDuplication57.java)|[测试57](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test57.java)|
67 | |第五十八题|[二叉树的下一个节点](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/NextTreeNode58.java)|[测试58](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test58.java)|
68 | |第五十九题|[对称的二叉树](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/IsSymmetrical59.java)|[测试59](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test59.java)|
69 | |第六十题|[按之字形顺序打印二叉树](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/ZTreePrint60.java)|[测试60](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test60.java)|
70 | |第六十一题|[把二叉树打印成多行](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/LevelPrintTree61.java)|[测试61](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test61.java)|
71 | |第六十二题|[序列化二叉树](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/Serializer62.java)|[测试62](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test62.java)|
72 | |第六十三题|[二叉搜索树的第K个节点](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/main/java/com/so/KthNode63.java)|[测试63](https://github.com/GaoLeiQin/SwordOffer/blob/master/src/test/java/com/so/Test63.java)|
73 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | 4.0.0
6 |
7 | com.so
8 | sword-offer
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | junit
14 | junit
15 | 4.13.1
16 | test
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | maven-clean-plugin
25 | 3.1.0
26 |
27 |
28 | maven-resources-plugin
29 | 3.0.2
30 |
31 |
32 | maven-compiler-plugin
33 |
34 | 8
35 | 8
36 |
37 | 3.8.0
38 |
39 |
40 | maven-surefire-plugin
41 | 2.22.1
42 |
43 |
44 | maven-jar-plugin
45 | 3.0.2
46 |
47 |
48 | maven-install-plugin
49 | 2.5.2
50 |
51 |
52 | maven-deploy-plugin
53 | 2.8.2
54 |
55 |
56 | maven-site-plugin
57 | 3.7.1
58 |
59 |
60 | maven-project-info-reports-plugin
61 | 3.0.0
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/src/main/java/com/so/Add47.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第47题
5 | * 不用加减乘除做加法
6 | *
7 | * @author qgl
8 | * @date 2017/08/16
9 | */
10 | public class Add47 {
11 | /**
12 | * 求和
13 | * @param num1
14 | * @param num2
15 | * @return
16 | */
17 | public static int add(int num1,int num2) {
18 | while (num2 != 0) {
19 | int temp = num1 ^ num2;
20 | num2 = (num1 & num2) << 1;
21 | num1 = temp;
22 | }
23 | return num1;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/so/BinaryToLinked27.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第27题
5 | * 将二叉搜索树转换成一个排序的双向链表
6 | *
7 | * @author qgl
8 | * @date 2017/08/14
9 | */
10 | public class BinaryToLinked27 {
11 | /**
12 | * 二叉树
13 | */
14 | static class BinaryTreeNode {
15 | int data;
16 | BinaryTreeNode leftNode;
17 | BinaryTreeNode rightNode;
18 | }
19 |
20 | /**
21 | * 二叉树的转换
22 | * @param root
23 | * @return
24 | */
25 | public static BinaryTreeNode convert(BinaryTreeNode root) {
26 | //指向双向链表的尾节点
27 | BinaryTreeNode lastNode = convertNode(root, null);
28 | //找到转换后的链表的头节点
29 | BinaryTreeNode pHead = lastNode;
30 | while (pHead != null && pHead.leftNode != null) {
31 | pHead = pHead.leftNode;
32 | }
33 | //返回链表头节点
34 | return pHead;
35 | }
36 |
37 | public static BinaryTreeNode convertNode(BinaryTreeNode root, BinaryTreeNode lastNode) {
38 | if (root == null) {
39 | return null;
40 | }
41 | BinaryTreeNode current = root;
42 | //递归处理左子树
43 | if (current.leftNode != null) {
44 | lastNode = convertNode(current.leftNode, lastNode);
45 | }
46 | //将当前节点的左指针指向已经转换好的链表的最后一个位置
47 | current.leftNode = lastNode;
48 | //将已经转换好的链表的最后一个节点的右指针指向当前节点
49 | if (lastNode != null) {
50 | lastNode.rightNode = current;
51 | }
52 | //更新已经转换好的链表的最后一个节点
53 | lastNode = current;
54 | //递归处理右子树
55 | if (current.rightNode != null) {
56 | lastNode = convertNode(current.rightNode, lastNode);
57 | }
58 |
59 | return lastNode;
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/src/main/java/com/so/BinaryTreeSearch6.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Arrays;
4 |
5 | import com.so.Common.TreeNode;
6 |
7 | /**
8 | * 第6题
9 | * 输入二叉树的前序遍历和中序遍历结果,重建该二叉树。
10 | *
11 | * @author qgl
12 | * @date 2017/08/09
13 | */
14 | public class BinaryTreeSearch6 {
15 |
16 | /**
17 | * 解法一:递归(传入数组的拷贝)
18 | * 时间复杂度:O(n),空间复杂度:O(n)
19 | *
20 | * @param pre
21 | * @param in
22 | * @return
23 | */
24 | public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
25 | if (pre == null || in == null || pre.length == 0 || in.length == 0) {
26 | return null;
27 | }
28 | if (pre.length != in.length) {
29 | return null;
30 | }
31 |
32 | TreeNode root = new TreeNode(pre[0]);
33 | for (int i = 0; i < pre.length; i++) {
34 | if (pre[0] == in[i]) {
35 | root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
36 | root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
37 | }
38 | }
39 | return root;
40 | }
41 |
42 | /**
43 | * 解法二:递归:传入子数组的边界索引
44 | * 时间复杂度:O(n),空间复杂度:O(n)
45 | *
46 | * @param preorder
47 | * @param inorder
48 | * @return
49 | */
50 | public TreeNode reConstructBinaryTree2(int[] preorder, int[] inorder) {
51 | if (preorder == null || preorder.length == 0 ||
52 | inorder == null || inorder.length == 0) return null;
53 | return helper(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
54 | }
55 |
56 |
57 | private TreeNode helper(int[] preorder, int preL, int preR, int[] inorder, int inL, int inR) {
58 | if (preL > preR || inL > inR) {
59 | return null;
60 | }
61 | int rootVal = preorder[preL];
62 | int index = 0;
63 | while (index <= inR && inorder[index] != rootVal) {
64 | index++;
65 | }
66 | TreeNode root = new TreeNode(rootVal);
67 | root.left = helper(preorder, preL + 1, preL - inL + index, inorder, inL, index);
68 | root.right = helper(preorder, preL - inL + index + 1, preR, inorder, index + 1, inR);
69 | return root;
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/so/Calculate46.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第46题
5 | * 求1+2+...+n,不能使用乘除法,循环等
6 | *
7 | * @author qgl
8 | * @date 2017/08/16
9 | */
10 | public class Calculate46 {
11 |
12 | /**
13 | * 解法一,利用递归求和
14 | * @param n
15 | * @return
16 | */
17 | public static int sum(int n) {
18 | int sum = n;
19 | boolean result = (n > 0) && ((sum += sum(n-1)) > 0);
20 | return sum;
21 | }
22 |
23 | /**
24 | * 解法二:利用递归和全局变量求和
25 | */
26 | private static int sum2 = 0;
27 | public static int sum2(int n) {
28 | sum3(n);
29 | return sum2;
30 | }
31 |
32 | private static boolean sum3(int n) {
33 | sum2 += n;
34 | return (n > 0) && sum3(n - 1);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/so/CloneCLinkedList26.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第26题
5 | * 复制一个复杂链表
6 | *
7 | * @author qgl
8 | * @date 2017/08/13
9 | */
10 | public class CloneCLinkedList26 {
11 | /**
12 | * 复杂链表
13 | */
14 | public static class RandomListNode {
15 | int label;
16 | RandomListNode next = null;
17 | RandomListNode random = null;
18 |
19 | RandomListNode(int label) {
20 | this.label = label;
21 | }
22 | }
23 |
24 | /**
25 | * 解法一
26 | * @param pHead
27 | * @return
28 | */
29 | public static RandomListNode Clone1(RandomListNode pHead) {
30 | if (pHead == null) {
31 | return null;
32 | }
33 | RandomListNode pCur = pHead;
34 | //复制next 如原来是A->B->C 变成A->A'->B->B'->C->C'
35 | while (pCur != null) {
36 | RandomListNode node = new RandomListNode(pCur.label);
37 | node.next = pCur.next;
38 | pCur.next = node;
39 | pCur = node.next;
40 | }
41 | pCur = pHead;
42 | //复制random pCur是原来链表的结点 pCur.next是复制pCur的结点
43 | while (pCur != null) {
44 | if (pCur.random != null) {
45 | pCur.next.random = pCur.random.next;
46 | }
47 | pCur = pCur.next.next;
48 | }
49 | RandomListNode head = pHead.next;
50 | RandomListNode cur = head;
51 | pCur = pHead;
52 | //拆分链表
53 | while (pCur != null) {
54 | pCur.next = pCur.next.next;
55 | if (cur.next != null) {
56 | cur.next = cur.next.next;
57 | }
58 | cur = cur.next;
59 | pCur = pCur.next;
60 | }
61 | return head;
62 | }
63 |
64 | /**
65 | * 解法二
66 | * @param pHead
67 | * @return
68 | */
69 | public static RandomListNode Clone2(RandomListNode pHead) {
70 | if (pHead == null) {
71 | return null;
72 | }
73 | RandomListNode head = new RandomListNode(pHead.label);
74 | RandomListNode temp = head;
75 |
76 | while (pHead.next != null) {
77 | temp.next = new RandomListNode(pHead.next.label);
78 | if (pHead.random != null) {
79 | temp.random = new RandomListNode(pHead.random.label);
80 | }
81 | pHead = pHead.next;
82 | temp = temp.next;
83 | }
84 | return head;
85 | }
86 | }
87 |
88 |
--------------------------------------------------------------------------------
/src/main/java/com/so/Common.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 公共类
5 | *
6 | * @author qgl
7 | * @date 2019/07/01
8 | */
9 | public class Common {
10 | /**
11 | * 二叉树
12 | */
13 | public static class TreeNode {
14 | int val;
15 | TreeNode left;
16 | TreeNode right;
17 |
18 | TreeNode(int x) {
19 | val = x;
20 | }
21 | }
22 |
23 | /**
24 | * 链表
25 | */
26 | public static class ListNode {
27 | int val;
28 | ListNode next;
29 |
30 | ListNode(int val) {
31 | this.val = val;
32 | }
33 | }
34 |
35 | /**
36 | * 获取链表的所有节点
37 | *
38 | * @param head
39 | * @return
40 | */
41 | public static String getAllListNode(ListNode head) {
42 | StringBuilder sb = new StringBuilder();
43 | while (head != null) {
44 | sb.append(head.val).append(" → ");
45 | head = head.next;
46 | }
47 | return sb.length() < 1 ? null : sb.substring(0, sb.length() - 2);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/so/DeleteDuplication57.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第57题
5 | * 删除链表的重复节点
6 | *
7 | * @author qgl
8 | * @date 2017/08/30
9 | */
10 | public class DeleteDuplication57 {
11 | static class ListNode {
12 | int val;
13 | ListNode next = null;
14 |
15 | ListNode(int val) {
16 | this.val = val;
17 | }
18 | }
19 |
20 | public static ListNode deleteDuplication(ListNode pHead) {
21 | if (pHead == null) {
22 | return null;
23 | }
24 | // 新建一个节点,防止头结点被删除
25 | ListNode dummy = new ListNode(-1);
26 | dummy.next = pHead;
27 | ListNode p = pHead;
28 | // 指向前一个节点
29 | ListNode preNode = dummy;
30 |
31 | while (p != null && p.next != null) {
32 | if (p.val == p.next.val) {
33 | int val = p.val;
34 | // 向后重复查找
35 | while (p != null && p.val == val) {
36 | p = p.next;
37 | }
38 | // 赋值:相当于删除
39 | preNode.next = p;
40 | }else {
41 | // 如果当前节点和下一个节点值不等,则向后移动一位
42 | preNode = p;
43 | p = p.next;
44 | }
45 | }
46 | return dummy.next;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/so/DeleteNode13.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第13题
5 | * 给定单向链表的头指针和一个节点,在O(1)时间删除该节点。
6 | *
7 | * @author qgl
8 | * @date 2017/08/09
9 | */
10 | public class DeleteNode13 {
11 |
12 | /**
13 | * 自定义链表
14 | */
15 | static class ListNode {
16 | int data;
17 | ListNode nextNode;
18 | }
19 |
20 | /**
21 | * 删除链表的某个节点
22 | * @param head 头指针
23 | * @param deListNode 待删除的节点
24 | */
25 | public static void deleteNode(ListNode head, ListNode deListNode) {
26 | if (deListNode == null || head == null)
27 | return;
28 |
29 | if (head == deListNode) {
30 | head = null;
31 | } else {
32 | // 若删除节点是末尾节点,往后移一个
33 | if (deListNode.nextNode == null) {
34 | ListNode pointListNode = head;
35 | while (pointListNode.nextNode.nextNode != null) {
36 | pointListNode = pointListNode.nextNode;
37 | }
38 | pointListNode.nextNode = null;
39 | } else {
40 | deListNode.data = deListNode.nextNode.data;
41 | deListNode.nextNode = deListNode.nextNode.nextNode;
42 | }
43 | }
44 | }
45 | }
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/main/java/com/so/DicesProbability43.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * 第43题
8 | * 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s,输入n,打印出s的所有可能出现的概率
9 | *
10 | * @author qgl
11 | * @date 2017/08/16
12 | */
13 | public class DicesProbability43 {
14 |
15 | /**
16 | * 获取所有可能出现的情况
17 | * @param number 骰子数量
18 | */
19 | public static Map printProbability(int number) {
20 | Map probabilityMap = new HashMap<>();
21 | if (number < 1) {
22 | return probabilityMap;
23 | }
24 | int g_maxValue = 6;
25 | int[][] probabilities = new int[2][];
26 | probabilities[0] = new int[g_maxValue * number + 1];
27 | probabilities[1] = new int[g_maxValue * number + 1];
28 | int flag = 0;
29 |
30 | // 当第一次抛掷骰子时,有6种可能,每种可能出现一次
31 | // 第一个骰子投完的结果存到了probabilities[0]
32 | for (int i = 1; i <= g_maxValue; i++) {
33 | probabilities[0][i] = 1;
34 | }
35 |
36 | //从第二次开始掷骰子,假设第一个数组中的第n个数字表示骰子和为n出现的次数,
37 | for (int k = 2; k <= number; ++k) {
38 |
39 | // 第k次掷骰子,和最小为k,小于k的情况是不可能发生的,令不可能发生的次数设置为0!
40 | for (int i = 0; i < k; ++i) {
41 | probabilities[1 - flag][i] = 0;
42 | }
43 |
44 | // 第k次掷骰子,和最小为k,最大为g_maxValue*k
45 | for (int i = k; i <= g_maxValue * k; ++i) {
46 | // 初始化,因为这个数组要重复使用,上一次的值要清0
47 | probabilities[1 - flag][i] = 0;
48 | for (int j = 1; j <= i && j <= g_maxValue; ++j)
49 | probabilities[1 - flag][i] += probabilities[flag][i - j];
50 | }
51 |
52 | // 若flag=0,1-flag用的就是数组1,而flag=1,1-flag用的就是数组0
53 | flag = 1 - flag;
54 | }
55 |
56 | double total = Math.pow(g_maxValue, number);
57 | for (int sum = number; sum <= g_maxValue * number; sum++) {
58 | double ratio = (double) probabilities[flag][sum] / total;
59 | probabilityMap.put(sum, ratio);
60 | }
61 |
62 | return probabilityMap;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/so/DoesTreeHave18.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.TreeNode;
4 |
5 | /**
6 | * 第18题
7 | * 判断二叉树A中是否包含子树B
8 | *
9 | * @author qgl
10 | * @date 2017/08/10
11 | */
12 | public class DoesTreeHave18 {
13 | /**
14 | * 判断是否包含子树
15 | *
16 | * @param source
17 | * @param target
18 | * @return
19 | */
20 | public static boolean hasSubTree(TreeNode source, TreeNode target) {
21 | if (target == null) {
22 | return true;
23 | }
24 | if (source == null) {
25 | return false;
26 | }
27 |
28 | if (doesTree1HaveTree2(source, target)) {
29 | return true;
30 | }
31 | return hasSubTree(source.left, target) || hasSubTree(source.right, target);
32 | }
33 |
34 | /**
35 | * 递归遍历两棵树
36 | *
37 | * @param source
38 | * @param target
39 | * @return
40 | */
41 | public static boolean doesTree1HaveTree2(TreeNode source, TreeNode target) {
42 | if (source == null && target == null) {
43 | return true;
44 | }
45 | if (source == null || target == null) {
46 | return false;
47 | }
48 | if (source.val != target.val) {
49 | return false;
50 | }
51 |
52 | return doesTree1HaveTree2(source.left, target.left) && doesTree1HaveTree2(source.right, target.right);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/so/DoubleSQueue7.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Stack;
4 |
5 | /**
6 | * 第7题
7 | * 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
8 | *
9 | * @author qgl
10 | * @date 2017/08/09
11 | */
12 | public class DoubleSQueue7 {
13 | private Stack stack1 = new Stack<>();
14 | private Stack stack2 = new Stack<>();
15 |
16 | /**
17 | * 入栈
18 | * 时间复杂度:O(1),空间复杂度:O(n)
19 | *
20 | * @param node
21 | */
22 | public void push(int node) {
23 | stack1.push(node);
24 | }
25 |
26 | /**
27 | * 出栈
28 | * 时间(摊还)复杂度:O(1),空间复杂度:O(1)
29 | *
30 | * @return
31 | * @throws Exception
32 | */
33 | public int pop() throws Exception {
34 | if (stack1.isEmpty() && stack2.isEmpty()) {
35 | throw new Exception("栈为空!");
36 | }
37 |
38 | if (stack2.isEmpty()) {
39 | while(!stack1.isEmpty()) {
40 | stack2.push(stack1.pop());
41 | }
42 | }
43 | return stack2.pop();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/so/Duplicate51.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.HashSet;
4 |
5 | /**
6 | * 第51题
7 | * 在一个长度为n的数组里的所有数字都在0到n-1的范围内,找出数组中任意一个重复的数字
8 | *
9 | * @author qgl
10 | * @date 2017/08/29
11 | */
12 | public class Duplicate51 {
13 | /**
14 | * 解法一:利用题中数组的特点(数组中的元素小于数组长度)
15 | * 时间复杂度是O(n),空间复杂度是O(1)
16 | *
17 | * @param numbers
18 | * @return
19 | */
20 | public static Integer duplicate1(int numbers[]) {
21 | if (numbers == null || numbers.length == 0) {
22 | return null;
23 | }
24 | if (numbers.length == 1) {
25 | return numbers[0];
26 | }
27 |
28 | int length = numbers.length;
29 | for (int i = 0; i < length; i++) {
30 | int index = numbers[i];
31 | if (index >= length) {
32 | index -= length;
33 | }
34 | if (numbers[index] >= length) {
35 | return index;
36 | }
37 | numbers[index] += length;
38 | }
39 | return null;
40 | }
41 |
42 | /**
43 | * 解法二:利用辅助空间 HashSet
44 | * 时间复杂度是O(n),空间复杂度是O(n)
45 | *
46 | * @param numbers
47 | * @return
48 | */
49 | public static Integer duplicate2(int numbers[]) {
50 | if (numbers == null || numbers.length == 0) {
51 | return null;
52 | }
53 | if (numbers.length == 1) {
54 | return numbers[0];
55 | }
56 |
57 | int length = numbers.length;
58 | HashSet hashSet = new HashSet<>();
59 | for (int i = 0; i < length; i++) {
60 | if (!hashSet.add(numbers[i])) {
61 | return numbers[i];
62 | }
63 | }
64 | return null;
65 | }
66 |
67 | /**
68 | * 解法三:快慢指针
69 | *
70 | * @param numbers
71 | * @return
72 | */
73 | public static int duplicate3(int[] numbers) {
74 | if (numbers == null || numbers.length == 0) {
75 | return -1;
76 | }
77 | int slow = 0;
78 | int fast = 0;
79 | for (int i = 0; i < numbers.length; i++) {
80 | slow = numbers[slow];
81 | fast = numbers[numbers[fast]];
82 | if (fast == slow) {
83 | fast = 0;
84 | while (fast != slow) {
85 | fast = numbers[fast];
86 | slow = numbers[slow];
87 | }
88 | return slow;
89 | }
90 | }
91 | return -1;
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/so/EnterLoop56.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第56题
5 | * 找出环链表的入口结点
6 | *
7 | * @author qgl
8 | * @date 2017/08/30
9 | */
10 | public class EnterLoop56 {
11 | /**
12 | * 链表
13 | */
14 | static class ListNode {
15 | int val;
16 | ListNode next = null;
17 |
18 | ListNode(int val) {
19 | this.val = val;
20 | }
21 | }
22 |
23 | /**
24 | * 获取环形链表的入口节点
25 | *
26 | * @param pHead
27 | * @return
28 | */
29 | public static ListNode enterNodeOfLoop(ListNode pHead) {
30 | if (pHead == null || pHead.next == null) {
31 | return null;
32 | }
33 | ListNode slow = pHead;
34 | ListNode fast = pHead;
35 |
36 | while (fast != null && fast.next != null) {
37 | slow = slow.next;
38 | fast = fast.next.next;
39 | if (slow == fast) {
40 | fast = pHead;
41 | while (fast != slow) {
42 | fast = fast.next;
43 | slow = slow.next;
44 | }
45 | return slow;
46 | }
47 | }
48 | return null;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/so/Fibonacci9.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第9题
5 | * 输入一个整数n,求斐波那契数列的第n项。
6 | *
7 | * @author qgl
8 | * @date 2017/08/09
9 | */
10 | public class Fibonacci9 {
11 |
12 | /**
13 | * 解法一:定义三个局部变量,作为交换
14 | *
15 | * @param n
16 | * @return
17 | */
18 | public static int getFibonacci1(int n) {
19 | int result = 0;
20 | int preOne = 1;
21 | int preTwo = 0;
22 | if (n == 0) {
23 | return preTwo;
24 | }
25 | if (n == 1) {
26 | return preOne;
27 | }
28 | for (int i = 2; i <= n; i++) {
29 | result = preOne + preTwo;
30 | preTwo = preOne;
31 | preOne = result;
32 | }
33 | return result;
34 | }
35 |
36 | /**
37 | * 解法二 :只需要两个局部变量
38 | *
39 | * @param n
40 | * @return
41 | */
42 | public static long getFibonacci2(int n) {
43 | long number = 1;
44 | long sum = 1;
45 | if (n <= 0)
46 | return 0;
47 | if (n == 1 || n == 2) {
48 | return 1;
49 | }
50 |
51 | while (n-- > 2) {
52 | sum += number;
53 | number = sum - number;
54 | }
55 | return sum;
56 | }
57 |
58 | /**
59 | * 解法三:递归:效率低,有大量重复计算
60 | *
61 | * @param n
62 | * @return
63 | */
64 | public static int getFibonacci3(int n) {
65 | if (n < 0) {
66 | return -1;
67 | }
68 | if (n == 0) {
69 | return 0;
70 | }
71 | if (n == 1) {
72 | return 1;
73 | }
74 |
75 | return getFibonacci3(n - 1) + getFibonacci3(n - 2);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FinalClass48.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第48题
5 | * 不能被继承的类
6 | *
7 | * @author qgl
8 | * @date 2017/08/16
9 | */
10 | public class FinalClass48 {
11 |
12 | /**
13 | * 解法一:被final修饰的类不能被继承
14 | */
15 | // public final class FinalClass48 {
16 |
17 | /**
18 | * 解法二:私有构造器的类不能继承
19 | */
20 | private FinalClass48(){}
21 |
22 | public static FinalClass48 getInstance() {
23 | return new FinalClass48();
24 | }
25 |
26 | public static void deleteInstance(FinalClass48 instance) {
27 | instance=null;
28 | }
29 |
30 |
31 | }
--------------------------------------------------------------------------------
/src/main/java/com/so/FindFirstCommonNode37.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第37题
5 | * 求两个单向链表的第一个公共节点
6 | *
7 | * @author qgl
8 | * @date 2017/08/15
9 | */
10 | public class FindFirstCommonNode37 {
11 |
12 | /**
13 | * 链表
14 | */
15 | static class ListNode {
16 | int val;
17 | ListNode next = null;
18 |
19 | ListNode(int val) {
20 | this.val = val;
21 | }
22 | }
23 |
24 | /**
25 | * 解法一:长链表先走,需要遍历链表
26 | * @param pHead1
27 | * @param pHead2
28 | * @return
29 | */
30 | public static ListNode findFirstCommonNode1(ListNode pHead1, ListNode pHead2) {
31 | if (pHead1 == null || pHead2 == null) {
32 | return null;
33 | }
34 | ListNode p1 = pHead1;
35 | ListNode p2 = pHead2;
36 | int length1 = getListNodeLength(p1);
37 | int length2 = getListNodeLength(p2);
38 | int diff = 0;
39 | if (length1 - length2 > 0) {
40 | diff = length1 - length2;
41 | while (diff-- > 0) {
42 | pHead1 = pHead1.next;
43 | }
44 | } else {
45 | diff = length2 - length1;
46 | while (diff-- > 0) {
47 | pHead2 = pHead2.next;
48 | }
49 | }
50 |
51 | while (pHead1 != null && pHead2 != null) {
52 | if (pHead1 == pHead2) {
53 | return pHead1;
54 | }
55 | pHead1 = pHead1.next;
56 | pHead2 = pHead2.next;
57 | }
58 | return null;
59 | }
60 |
61 | /**
62 | * 获取链表长度
63 | * @param root
64 | * @return
65 | */
66 | private static int getListNodeLength(ListNode root) {
67 | int result = 0;
68 | if (root == null)
69 | return result;
70 | ListNode point = root;
71 |
72 | while (point != null) {
73 | point = point.next;
74 | result++;
75 | }
76 | return result;
77 | }
78 |
79 | /**
80 | * 解法二:不需要遍历链表
81 | * @param pHead1
82 | * @param pHead2
83 | * @return
84 | */
85 | public static ListNode findFirstCommonNode2(ListNode pHead1, ListNode pHead2) {
86 | if (pHead1 == null || pHead2 == null) {
87 | return null;
88 | }
89 |
90 | ListNode p1 = pHead1;
91 | ListNode p2 = pHead2;
92 | while (p1 != p2) {
93 | p1 = (p1 != null ? p1.next : pHead2);
94 | p2 = (p2 != null ? p2.next : pHead1);
95 | }
96 | return p1;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FindGreatestSum31.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第31题
5 | * 数组中一个或连续的多个整数组成一个子数组,求连续子数组的最大和
6 | *
7 | * @author qgl
8 | * @date 2017/08/14
9 | */
10 | public class FindGreatestSum31 {
11 | /**
12 | * 获取连续子数组的最大和
13 | *
14 | * @param array
15 | * @return
16 | */
17 | public static Integer findGreatestSum(int[] array) {
18 | if (array == null) {
19 | return null;
20 | }
21 | int greatest = 0;
22 | int curSum = 0;
23 |
24 | for (int i = 0; i < array.length; i++) {
25 | if (curSum + array[i] < 0) {
26 | greatest = 0;
27 | curSum = 0;
28 | } else {
29 | curSum += array[i];
30 | greatest = Math.max(greatest, curSum);
31 | }
32 | }
33 |
34 | return greatest;
35 | }
36 | }
--------------------------------------------------------------------------------
/src/main/java/com/so/FindKthToTail15.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.ListNode;
4 |
5 | /**
6 | * 第15题
7 | * 输入一个链表,输出该链表的倒数第K个结点
8 | *
9 | * @author qgl
10 | * @date 2017/08/10
11 | */
12 | public class FindKthToTail15 {
13 |
14 | /**
15 | * 解法一:一快一慢两个指针,快指针先走k步,然后两个指针同时走
16 | *
17 | * @param head
18 | * @param k
19 | * @return
20 | */
21 | public static ListNode findKthToTail(ListNode head, int k) {
22 | if (head == null || k < 1) {
23 | return null;
24 | }
25 | ListNode fast = head;
26 | ListNode slow = head;
27 | while (k-- > 1) {
28 | if (fast.next == null) {
29 | return null;
30 | }
31 | fast = fast.next;
32 | }
33 | while (fast.next != null) {
34 | fast = fast.next;
35 | slow = slow.next;
36 | }
37 | return slow;
38 | }
39 |
40 | /**
41 | * 解法二:不推荐,O(n^2),先获取链表长度,在用链表长度减去k的值,求得该值处的节点
42 | *
43 | * @param head
44 | * @param k
45 | * @return
46 | */
47 | public static ListNode findKthToTail2(ListNode head, int k) {
48 | int length = 0;
49 | ListNode p = head;
50 | while (p != null) {
51 | length++;
52 | p = p.next;
53 | }
54 | ListNode target = null;
55 | if (length == k) {
56 | target = head;
57 | }
58 |
59 | for (int i = 0; i < length - k; i++) {
60 | head = head.next;
61 | target = head;
62 | }
63 | return target;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FindNumAppearOnce40.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第40题
5 | * 一个整型数组里除了两个数字之外,其他的数字都出现了两次,找出这两个只出现了一次的数字
6 | *
7 | * @author qgl
8 | * @date 2017/08/16
9 | */
10 | public class FindNumAppearOnce40 {
11 |
12 | /**
13 | * 找出只出现了一次的数
14 | * @param array
15 | * @return
16 | */
17 | public static int[] findNumAppearOnce(int[] array) {
18 | int[] onceNumber = new int[2];
19 | if (array == null) {
20 | return null;
21 | }
22 | int number = 0;
23 | for (int i : array) {
24 | number ^= i;
25 | }
26 | int index = findFirstBitIs1(number);
27 |
28 | for (int i : array) {
29 | // 第index位是0的数,即第一个数
30 | if (isBit1(i, index)) {
31 | onceNumber[0] ^= i;
32 | } else {
33 | // 第index位是1的数,即第二个数
34 | onceNumber[1] ^= i;
35 | }
36 | }
37 | return onceNumber;
38 | }
39 |
40 | /**
41 | * 获取二进制中最右边是1的位置
42 | * @param number
43 | * @return
44 | */
45 | private static int findFirstBitIs1(int number) {
46 | int indexBit = 0;
47 |
48 | while ((number & 1) == 0) {
49 | number = number >> 1;
50 | ++indexBit;
51 | }
52 | return indexBit;
53 | }
54 |
55 | /**
56 | * 判断从右边起,第index位是不是0
57 | * @param number
58 | * @param index
59 | * @return
60 | */
61 | private static boolean isBit1(int number, int index) {
62 | number = number >> index;
63 | return (number & 1) == 0;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FindNumber3.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第3题
5 | * 一个二维数组,每一行从左到右递增,每一列从上到下递增.
6 | * 输入一个二维数组和一个整数,判断数组中是否含有整数
7 | *
8 | * @author qgl
9 | * @date 2017/08/07
10 | */
11 | public class FindNumber3 {
12 |
13 | /**
14 | * 解法一:双指针
15 | * 时间复杂度:O(mn),空间复杂度:O(1)
16 | *
17 | * @param array
18 | * @param target
19 | * @return
20 | */
21 | public static boolean find(int[][] array, int target) {
22 | if (array == null || array.length == 0) {
23 | return false;
24 | }
25 | int row = 0;
26 | int column = array[0].length - 1;
27 |
28 | while (row < array.length && column >= 0) {
29 | if (array[row][column] == target) {
30 | return true;
31 | }
32 | if (array[row][column] > target) {
33 | column--;
34 | } else {
35 | row++;
36 | }
37 | }
38 | return false;
39 | }
40 |
41 | /**
42 | * 解法二:二分法
43 | * 时间复杂度:O(log mn),空间复杂度:O(1)
44 | *
45 | * @param array
46 | * @param target
47 | * @return
48 | */
49 | /*
50 | public static boolean find2(int[][] array, int target) {
51 | if (array == null || array.length == 0) {
52 | return false;
53 | }
54 |
55 | int left = 0;
56 | int right = array.length * array[0].length - 1;
57 | int col = array[0].length;
58 |
59 | while (left <= right) {
60 | int mid = (left + right) / 2;
61 | int value = array[mid / col][mid % col];
62 |
63 | if (value == target) {
64 | return true;
65 | } else if (value < target) {
66 | left = mid + 1;
67 | } else {
68 | right = mid - 1;
69 | }
70 | }
71 |
72 | return false;
73 | }
74 | */
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FindNumbersWithSum41.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.ArrayList;
4 |
5 | /**
6 | * 第41题
7 | * 41.1 输入一个递增排序的数组和一个数字s.在数组中查找两个数使他们的和为s,如果有多对数字的和等于s,输出两个数的乘积最小的一对
8 | * 41.2 输入一个整数s,求所有和为s的连续正数序列
9 | * @author qgl
10 | * @date 2017/08/16
11 | */
12 | public class FindNumbersWithSum41 {
13 |
14 | /**
15 | * 获取和为s的两个数
16 | * @param sortedArray
17 | * @param s
18 | * @return
19 | */
20 | public static ArrayList findNumbersWithSum(int[] sortedArray, int s) {
21 | ArrayList list = new ArrayList<>();
22 | if (sortedArray == null) {
23 | return list;
24 | }
25 | int left = 0;
26 | int right = sortedArray.length - 1;
27 |
28 | while (right > left) {
29 | long curSum = sortedArray[right] + sortedArray[left];
30 | if (curSum == s) {
31 | list.add(sortedArray[left]);
32 | list.add(sortedArray[right]);
33 | break;
34 | } else {
35 | if (curSum > s)
36 | right--;
37 | else
38 | left++;
39 | }
40 | }
41 | return list;
42 | }
43 |
44 | /**
45 | * 获取所有和为s的连续正数序列
46 | * @param s
47 | * @return
48 | */
49 | public static ArrayList> findContinuousSequence(int s) {
50 | ArrayList> arrayList = new ArrayList<>();
51 | if (s < 4) {
52 | return arrayList;
53 | }
54 | int small = 1;
55 | int big = 2;
56 |
57 | while (small < (s + 1) / 2) {
58 | int curSum = 0;
59 | for (int i = small; i <= big; i++) {
60 | curSum += i;
61 | }
62 |
63 | if (curSum == s) {
64 | ArrayList list = new ArrayList<>();
65 | for (int i = small; i <= big; i++) {
66 | list.add(i);
67 | }
68 | arrayList.add(list);
69 | small++;
70 | } else if (curSum > s) {
71 | small++;
72 | } else {
73 | big++;
74 | }
75 | }
76 | return arrayList;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FindPath25.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.*;
4 |
5 | import com.so.Common.TreeNode;
6 |
7 | /**
8 | * 第25题
9 | * 输入一个二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径
10 | *
11 | * @author qgl
12 | * @date 2017/08/13
13 | */
14 | public class FindPath25 {
15 | private ArrayList> listAll = new ArrayList<>();
16 | private ArrayList list = new ArrayList<>();
17 |
18 | /**
19 | * 利用list寻找全路径
20 | *
21 | * @param root
22 | * @param target
23 | * @return
24 | */
25 | public ArrayList> FindPath(TreeNode root, int target) {
26 | if (root == null) {
27 | return listAll;
28 | }
29 | list.add(root.val);
30 | target -= root.val;
31 |
32 | if (target == 0 && root.left == null && root.right == null) {
33 | listAll.add(new ArrayList<>(list));
34 | }
35 | FindPath(root.left, target);
36 | FindPath(root.right, target);
37 | // 回退
38 | list.remove(list.size() - 1);
39 | return listAll;
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FirstAppearingOnce55.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第55题
5 | * 请实现一个函数用来找出字符流中第一个只出现一次的字符
6 | *
7 | * @author qgl
8 | * @date 2017/08/30
9 | */
10 | public class FirstAppearingOnce55 {
11 | static char[] chars = new char[256];
12 | static StringBuilder sb = new StringBuilder();
13 |
14 | /**
15 | * 输入字符流
16 | *
17 | * @param inputChars
18 | */
19 | public static void insertChars(char[] inputChars) {
20 | for (char ch : inputChars) {
21 | sb.append(ch);
22 | chars[ch]++;
23 | }
24 | }
25 |
26 | /**
27 | * 获取字符流中第一个不重复的字符
28 | *
29 | * @return
30 | */
31 | public static Character getFirstAppearingOnce() {
32 | char[] str = sb.toString().toCharArray();
33 | for (char c : str) {
34 | if (chars[c] == 1) {
35 | return c;
36 | }
37 | }
38 | return null;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/so/FirstNotRepeating35.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.LinkedHashMap;
4 | import java.util.Set;
5 |
6 | /**
7 | * 第35题
8 | * 在字符串中找出第一个只出现一次的字符
9 | *
10 | * @author qgl
11 | * @date 2017/08/15
12 | */
13 | public class FirstNotRepeating35 {
14 | /**
15 | * 获取第一个只出现一次的字符的下标
16 | *
17 | * @param str
18 | * @return
19 | */
20 | public static int getFirstNotRepeatingCharIndex(String str) {
21 | if (str == null) {
22 | return -1;
23 | }
24 | char[] strChar = str.toCharArray();
25 | // 按照插入顺序保存key的位置
26 | LinkedHashMap hash = new LinkedHashMap();
27 | for (char item : strChar) {
28 | if (hash.containsKey(item)) {
29 | hash.put(item, hash.get(item) + 1);
30 | } else {
31 | hash.put(item, 1);
32 | }
33 | }
34 |
35 | for (int i = 0; i < str.length(); i++) {
36 | char c = str.charAt(i);
37 | if (hash.get(c) == 1) {
38 | System.out.println("第一个只出现一次的字符是:" + c);
39 | return i;
40 | }
41 | }
42 |
43 | return -1;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/so/GetLeastNumbers30.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 |
6 | /**
7 | * 第30题
8 | * 输入N个整数,找出其中最小的k个数
9 | *
10 | * @author qgl
11 | * @date 2017/08/14
12 | */
13 | public class GetLeastNumbers30 {
14 |
15 | /**
16 | * 获取最小的k个数
17 | *
18 | * @param array
19 | * @param k
20 | * @return
21 | */
22 | public static ArrayList getLeastNumbers(int[] array, int k) {
23 | ArrayList list = new ArrayList<>();
24 | if (array == null || k < 1 || k > array.length) {
25 | return list;
26 | }
27 | int[] kArray = Arrays.copyOfRange(array, 0, k);
28 |
29 | //根据输入数组前k个数建立最大堆
30 | for (int i = kArray.length / 2; i >= 0; i--) {
31 | maxHeapIfy(kArray, i, kArray.length);
32 | }
33 |
34 | //从k开始与根节点比较,若大于根节点,舍去,若小于,取代根节点,重排最大堆
35 | for (int i = k; i < array.length; i++) {
36 | if (array[i] < kArray[0]) {
37 | kArray[0] = array[i];
38 | maxHeapIfy(kArray, 0, kArray.length);
39 | }
40 | }
41 |
42 | for (int i = kArray.length - 1; i >= 0; i--) {
43 | list.add(kArray[i]);
44 | }
45 |
46 | return list;
47 | }
48 |
49 | /**
50 | * 调整大根堆
51 | *
52 | * @param array
53 | * @param root
54 | * @param length
55 | */
56 | private static void maxHeapIfy(int[] array, int root, int length) {
57 | int left = 2 * root + 1;
58 |
59 | if (left >= length) {
60 | return;
61 | }
62 |
63 | if (left + 1 < length && array[left] < array[left + 1]) {
64 | left++;
65 | }
66 |
67 | if (array[left] > array[root]) {
68 | swap(array, left, root);
69 | maxHeapIfy(array, left, length);
70 | }
71 | }
72 |
73 | private static void swap(int[] array, int i, int j) {
74 | int tmp = array[i];
75 | array[i] = array[j];
76 | array[j] = tmp;
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/so/GetMedian64.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.Comparator;
6 | import java.util.PriorityQueue;
7 |
8 | /**
9 | * 第64题
10 | * 求数据流中的中位数
11 | *
12 | * @author qgl
13 | * @date 2017/08/31
14 | */
15 | public class GetMedian64 {
16 |
17 | /**
18 | * 插入数据
19 | *
20 | * @param arr
21 | */
22 | public static void insertArray(int[] arr) {
23 | for (int num : arr) {
24 | insertByMergeSort(num);
25 | insertByHeapSort(num);
26 | }
27 | }
28 |
29 | private static ArrayList list = new ArrayList<>();
30 |
31 | /**
32 | * 对插入的数据进行(归并)排序
33 | *
34 | * @param num
35 | */
36 | private static void insertByMergeSort(Integer num) {
37 | list.add(num);
38 | Collections.sort(list);
39 | }
40 |
41 | /**
42 | * 解法一:利用集合类的排序方法
43 | *
44 | * @return
45 | */
46 | public static Double getMedian1() {
47 | int mid = list.size() / 2;
48 |
49 | if (list.size() % 2 == 0) {
50 | Double sum = Double.valueOf(list.get(mid)) + Double.valueOf(list.get(mid - 1));
51 | return sum / 2;
52 | }
53 | return Double.valueOf(list.get(mid));
54 | }
55 |
56 | private static int count = 0;
57 | private static PriorityQueue minHeap = new PriorityQueue<>();
58 | private static PriorityQueue maxHeap = new PriorityQueue<>(16, new Comparator() {
59 | @Override
60 | public int compare(Integer o1, Integer o2) {
61 | return o2.compareTo(o1);
62 | }
63 | });
64 |
65 | /**
66 | * 对插入的数据进行(堆)排序
67 | *
68 | * @param num
69 | */
70 | private static void insertByHeapSort(Integer num) {
71 | count++;
72 | // 当数据的个数为奇数时,进入大根堆
73 | if ((count & 1) == 1) {
74 | minHeap.offer(num);
75 | maxHeap.offer(minHeap.poll());
76 | } else {
77 | maxHeap.offer(num);
78 | minHeap.offer(maxHeap.poll());
79 | }
80 | }
81 |
82 | /**
83 | * 解法二:利用优先级队列构建堆进行排序
84 | *
85 | * @return
86 | */
87 | public static Double getMedian2() {
88 | if (count == 0) {
89 | return null;
90 | }
91 |
92 | // 当数据个数是奇数时,中位数就是大根堆的顶点
93 | if ((count & 1) == 1) {
94 | return (double) maxHeap.peek();
95 | } else {
96 | return (double) (minHeap.peek() + maxHeap.peek()) / 2;
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/so/GetNumberOfK38.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 第38题
7 | * 统计一个数字在排序数组中出现的次数
8 | *
9 | * @author qgl
10 | * @date 2017/08/15
11 | */
12 | public class GetNumberOfK38 {
13 | //
14 | public static int getNumberOfK(int[] arraySorted, int k) {
15 | // 若数组为空
16 | if (arraySorted == null || arraySorted.length == 0) {
17 | return 0;
18 | }
19 | // 若数组中只有一个数
20 | if (arraySorted.length == 1) {
21 | if (arraySorted[0] == k) {
22 | return 1;
23 | }
24 | return 0;
25 | }
26 |
27 | int result = 0;
28 | int mid = arraySorted.length / 2;
29 |
30 | if (k < arraySorted[mid]) {
31 | getNumberOfK(Arrays.copyOfRange(arraySorted, 0, mid), k);
32 | } else if (k > arraySorted[mid]) {
33 | getNumberOfK(Arrays.copyOfRange(arraySorted, mid, arraySorted.length), k);
34 | } else {
35 | result += getCount(arraySorted, mid);
36 | }
37 |
38 | return result;
39 | }
40 |
41 | /**
42 | * K与中间的值相等时,从中间值前后分别查找
43 | *
44 | * @param arraySorted
45 | * @param mid
46 | * @return
47 | */
48 | private static int getCount(int[] arraySorted, int mid) {
49 | int k = arraySorted[mid];
50 | int result = 0;
51 |
52 | for (int i = mid; i < arraySorted.length; i++) {
53 | if (arraySorted[i] == k) {
54 | result++;
55 | } else {
56 | break;
57 | }
58 | }
59 |
60 | for (int i = mid - 1; i >= 0; i--) {
61 | if (arraySorted[i] == k) {
62 | result++;
63 | } else {
64 | break;
65 | }
66 | }
67 | return result;
68 | }
69 | }
--------------------------------------------------------------------------------
/src/main/java/com/so/HasPath66.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第66题
5 | * 判断在一个矩阵中是否存在一条包含某字符串所有字符的路径
6 | *
7 | * @author qgl
8 | * @date 2017/08/31
9 | */
10 | public class HasPath66 {
11 | /**
12 | * 回溯法
13 | * @param matrix
14 | * @param rows
15 | * @param cols
16 | * @param str
17 | * @return
18 | */
19 | public static boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
20 | int flag[] = new int[matrix.length];
21 | for (int i = 0; i < rows; i++) {
22 | for (int j = 0; j < cols; j++) {
23 | if (helper(matrix, rows, cols, i, j, str, 0, flag))
24 | return true;
25 | }
26 | }
27 | return false;
28 | }
29 |
30 | /**
31 | * 判断是否匹配
32 | * @param matrix
33 | * @param rows
34 | * @param cols
35 | * @param i
36 | * @param j
37 | * @param str
38 | * @param k
39 | * @param flag
40 | * @return
41 | */
42 | private static boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) {
43 | int index = i * cols + j;
44 | if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1)
45 | return false;
46 |
47 | if(k == str.length - 1)
48 | return true;
49 | flag[index] = 1;
50 |
51 | if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag)
52 | || helper(matrix, rows, cols, i + 1, j, str, k + 1, flag)
53 | || helper(matrix, rows, cols, i, j - 1, str, k + 1, flag)
54 | || helper(matrix, rows, cols, i, j + 1, str, k + 1, flag)) {
55 | return true;
56 | }
57 | flag[index] = 0;
58 | return false;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/so/InversePairs36.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 第36题
7 | * 数组中的两个数字如果前面一个数字大于后面一个数字,
8 | * 则这两个数字组成一个逆序对,输入一个数组,求逆序对的总数
9 | *
10 | * @author qgl
11 | * @date 2017/08/15
12 | */
13 | public class InversePairs36 {
14 | /**
15 | * 获取逆序对的总数
16 | * @param array
17 | * @return
18 | */
19 | public static int inversePairs(int[] array) {
20 | if (array == null || array.length == 0) {
21 | return 0;
22 | }
23 | return getInversePairs(array, Arrays.copyOf(array, array.length), 0, array.length - 1) ;
24 | }
25 |
26 | private static int getInversePairs(int[] array, int[] copy, int low, int high) {
27 | if (low == high) {
28 | return 0;
29 | }
30 | int mid = (low + high) >> 1;
31 | int leftCount = getInversePairs(array, copy, low, mid);
32 | int rightCount = getInversePairs(array, copy, mid + 1, high);
33 | int count = 0;
34 | int i = mid;
35 | int j = high;
36 | int locCopy = high;
37 | while (i >= low && j > mid) {
38 | if (array[i] > array[j]) {
39 | count += j - mid;
40 | copy[locCopy--] = array[i--];
41 | // 防止数值过大而求余
42 | count %= 1000000007;
43 | } else {
44 | copy[locCopy--] = array[j--];
45 | }
46 | }
47 |
48 | for (int a = i; a >= low; a--) {
49 | copy[locCopy--] = array[a];
50 | }
51 | for (int b = j; b > mid; b--) {
52 | copy[locCopy--] = array[b];
53 | }
54 | for (int s = low; s <= high; s++) {
55 | array[s] = copy[s];
56 | }
57 | return (leftCount + rightCount + count) % 1000000007;
58 | }
59 |
60 | /** 记录逆序对的数量 */
61 | private int count = 0;
62 |
63 | /**
64 | * 解法二:获取逆序对的总数
65 | *
66 | * @param array 输入的数组长度较大时有bug
67 | * @return
68 | */
69 | public int inversePairs2(int[] array) {
70 | if (array == null) {
71 | return 0;
72 | }
73 | mergeSort(array, 0, array.length - 1);
74 | return count;
75 | }
76 |
77 | private void mergeSort(int[] data, int start, int end) {
78 | int mid = (start + end) / 2;
79 | if (start < end) {
80 | mergeSort(data, start, mid);
81 | mergeSort(data, mid + 1, end);
82 | merge(data, start, mid, end);
83 | }
84 | }
85 |
86 | public void merge(int[] data, int start, int mid, int end) {
87 | int arr[] = new int[end - start + 1];
88 | int c = 0;
89 | int s = start;
90 | int index = mid + 1;
91 | while (start <= mid && index <= end) {
92 | if (data[start] < data[index]) {
93 | arr[c++] = data[start++];
94 | } else {
95 | count += index - start;
96 | // 防止数值过大而求余
97 | count %= 1000000007;
98 | arr[c++] = data[index++];
99 | }
100 | }
101 |
102 | while (start <= mid) {
103 | arr[c++] = data[start++];
104 | }
105 |
106 | while (index <= end) {
107 | arr[c++] = data[index++];
108 | }
109 |
110 | for (int d : arr) {
111 | data[s++] = d;
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/com/so/IsContinuous44.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 第44题
7 | * 判断扑克牌中的顺子,0表示大小王(可以是任意数)
8 | * 1表示A,2~10为本身,11表示J,12表示Q,13表示K
9 | *
10 | * @author qgl
11 | * @date 2017/08/16
12 | */
13 | public class IsContinuous44 {
14 |
15 | /**
16 | * 判断是否是顺子
17 | * @param numbers
18 | * @return
19 | */
20 | public static boolean isContinuous(int [] numbers) {
21 | if (numbers == null || numbers.length == 0) {
22 | return false;
23 | }
24 | int count = 0;
25 | int diff = 0;
26 | Arrays.sort(numbers);
27 |
28 | for (int i = 0; i < numbers.length - 1; i++) {
29 | if (numbers[i] == 0) {
30 | count++;
31 | continue;
32 | }
33 | if (numbers[i] == numbers[i+1]) {
34 | return false;
35 | }
36 |
37 | diff += numbers[i+1] - numbers[i] - 1;
38 | }
39 |
40 | return diff <= count;
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/java/com/so/IsNumber54.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第54题
5 | * 判断字符串是否表示数值(包括整数和小数)
6 | *
7 | * @author qgl
8 | * @date 2017/08/30
9 | */
10 | public class IsNumber54 {
11 |
12 | /**
13 | * 解法一:逐个字符进行判断
14 | *
15 | * @param str
16 | * @return
17 | */
18 | public static boolean isNumber1(char[] str) {
19 | if (str == null) {
20 | return false;
21 | }
22 | int index = 0;
23 | int eCount = 0;
24 | int point = 0;
25 | // 如果第一个字符是符号就跳过
26 | if (str[0] == '-' || str[0] == '+')
27 | index++;
28 |
29 | for (int i = index; i < str.length; i++) {
30 | if (str[i] == '-' || str[i] == '+') {
31 | if (str[i - 1] != 'e' && str[i - 1] != 'E')
32 | return false;
33 | continue;
34 | }
35 |
36 | if (str[i] == 'e' || str[i] == 'E') {
37 | eCount++;
38 | if (eCount > 1)
39 | return false;
40 | if (i == 0 || str[i - 1] < 48 || str[i - 1] > 57 || i == str.length - 1)
41 | return false;
42 | point++;
43 | continue;
44 | }
45 |
46 | if (str[i] == '.') {
47 | point++;
48 | if (point > 1)
49 | return false;
50 | continue;
51 | }
52 | // 出现非数字且不是e/E则返回false(小数点和符号用continue跳过了)
53 | if ((str[i] < 48 || str[i] > 57) && (str[i] != 'e') && (str[i] != 'E'))
54 | return false;
55 | }
56 | return true;
57 | }
58 |
59 | /**
60 | * 解法二:正则表达式
61 | ? 表示零次或一次匹配前面的字符或子表达式 * 表示零次或多次匹配前面的字符或子表达式
62 | + 表示一次或多次匹配前面的字符或子表达式 . 表示匹配除了换行符的任何单个字符
63 | *
64 | * @param str
65 | * @return
66 | */
67 | public static boolean isNumber2(char[] str) {
68 | String s = String.valueOf(str);
69 | return s.matches("[+-]?[0-9]*(\\.[0-9]*)?([eE][+-]?[0-9]+)?");
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/so/IsPopOrder22.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Stack;
4 | import java.util.Vector;
5 |
6 | /**
7 | * 第22题
8 | * 输入两个整数序列,第一个序列表示压入顺序,判断第二个序列是否为弹出顺序
9 | *
10 | * @author qgl
11 | * @date 2017/08/10
12 | */
13 | public class IsPopOrder22 {
14 |
15 | /**
16 | * 利用栈判断一个序列是否是另一个序列的弹出顺序
17 | * @param pushList 压入顺序序列
18 | * @param popList 弹出顺序序列
19 | * @return 判断结果
20 | */
21 | public static boolean isPopOrder(int[] pushList, int[] popList) {
22 | if (pushList == null || popList == null) {
23 | return false;
24 | }
25 |
26 | int point = 0;
27 | Stack stack = new Stack();
28 |
29 | for (int i = 0; i < pushList.length; i++) {
30 | stack.push(pushList[i]);
31 | while (!stack.isEmpty() && stack.peek() == popList[point]) {
32 | stack.pop();
33 | point++;
34 | }
35 | }
36 | return stack.isEmpty();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/so/IsSymmetrical59.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.TreeNode;
4 |
5 | import java.util.Stack;
6 |
7 | /**
8 | * 第59题
9 | * 判断二叉树是否是对称的
10 | *
11 | * @author qgl
12 | * @date 2017/08/30
13 | */
14 | public class IsSymmetrical59 {
15 |
16 | /**
17 | * 判断二叉树是不是对称的
18 | * @param pRoot
19 | * @return
20 | */
21 | public static boolean isSymmetrical(TreeNode pRoot){
22 | return pRoot == null || isCommon(pRoot.left, pRoot.right);
23 | }
24 |
25 | /**
26 | * 判断左右子树是否相等
27 | * @param leftNode
28 | * @param rightNode
29 | * @return
30 | */
31 | public static boolean isCommon(TreeNode leftNode, TreeNode rightNode) {
32 | if (leftNode == null && rightNode == null) {
33 | return true;
34 | }
35 | if (leftNode == null || rightNode == null) {
36 | return false;
37 | }
38 |
39 | return leftNode.val == rightNode.val && isCommon(leftNode.left,rightNode.right) && isCommon(leftNode.right,rightNode.left);
40 | }
41 |
42 | /**
43 | * 解法二:迭代
44 | * 时间复杂度:O(n),空间复杂度:O(n)
45 | *
46 | * @param root
47 | * @return
48 | */
49 | public static boolean isSymmetric2(TreeNode root) {
50 | Stack stack = new Stack<>();
51 | stack.push(root);
52 | stack.push(root);
53 | while (!stack.isEmpty()) {
54 | TreeNode t1 = stack.pop();
55 | TreeNode t2 = stack.pop();
56 | if (t1 == null && t2 == null) {
57 | continue;
58 | }
59 | if (t1 == null || t2 == null) {
60 | return false;
61 | }
62 | if (t1.val != t2.val) {
63 | return false;
64 | }
65 | stack.push(t1.left);
66 | stack.push(t2.right);
67 | stack.push(t1.right);
68 | stack.push(t2.left);
69 | }
70 | return true;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/so/KthNode63.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.TreeNode;
4 |
5 | import java.util.Stack;
6 |
7 | /**
8 | * 第63题
9 | * 给定一棵二叉搜索树,请找出其中的第k小的结点
10 | *
11 | * @author qgl
12 | * @date 2017/08/30
13 | */
14 | public class KthNode63 {
15 | /**
16 | * 解法一:递归
17 | *
18 | * @param pRoot
19 | * @param k
20 | * @return
21 | */
22 | private int count = 0;
23 | public TreeNode KthNode(TreeNode pRoot, int k) {
24 | if(pRoot == null) {
25 | return null;
26 | }
27 | TreeNode node = KthNode(pRoot.left, k);
28 | if(node != null) {
29 | return node;
30 | }
31 | count++;
32 | if(count == k) {
33 | return pRoot;
34 | }
35 | node = KthNode(pRoot.right, k);
36 | return node;
37 | }
38 |
39 | /**
40 | * 解法二:非递归,借用栈查找
41 | *
42 | * @param pRoot
43 | * @param k
44 | * @return
45 | */
46 | public TreeNode getKthNode2(TreeNode pRoot, int k) {
47 | if (pRoot == null || k < 1) {
48 | return null;
49 | }
50 | int index = 0;
51 | TreeNode root = pRoot;
52 | Stack s = new Stack<>();
53 | while (root != null || !s.isEmpty()) {
54 | while (root != null) {
55 | s.push(root);
56 | root = root.left;
57 | }
58 |
59 | if (!s.isEmpty()) {
60 | root = s.pop();
61 | index++;
62 | if (index == k) {
63 | return root;
64 | }
65 | root = root.right;
66 | }
67 | }
68 | return null;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/so/LastRemaining45.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.LinkedList;
4 |
5 | /**
6 | * 第45题
7 | * 0,1...n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字.
8 | * 求这个圈圈里剩下的最后一个数字
9 | *
10 | * @author qgl
11 | * @date 2017/08/16
12 | */
13 | public class LastRemaining45 {
14 |
15 | /**
16 | * 解法一:借助链表
17 | * @param n
18 | * @param m
19 | * @return
20 | */
21 | public static int lastRemain1(int n, int m) {
22 | LinkedList list = new LinkedList();
23 | int index = 0;
24 |
25 | for (int i = 0; i < n; i ++) {
26 | list.add(i);
27 | }
28 |
29 | while (list.size() > 1) {
30 | index = (index + m - 1) % list.size();
31 | list.remove(index);
32 | }
33 | return list.size() == 1 ? list.get(0) : -1;
34 | }
35 |
36 | /**
37 | * 解法二:公式法
38 | * @param n
39 | * @param m
40 | * @return
41 | */
42 | public static int lastRemain2(int n, int m) {
43 | if (n < 1 || m < 1) {
44 | return -1;
45 | }
46 | int last = 0;
47 | for (int i = 2; i <= n; i ++) {
48 | // i个人时删除数的索引等于i-1个人时删除数的索引+k(再对i取余)
49 | last = (last + m) % i;
50 | }
51 | return last;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/so/LevelPrintTree61.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.*;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第61题
8 | * 把二叉树打印成多行,从上到下按层打印二叉树,同一层结点从左至右输出。
9 | *
10 | * @author qgl
11 | * @date 2017/08/30
12 | */
13 | public class LevelPrintTree61 {
14 | /**
15 | * 从左至右打印每行二叉树
16 | * @param pRoot
17 | * @return
18 | */
19 | public static ArrayList> printTreeNodeByLeftToRight(TreeNode pRoot) {
20 | ArrayList> res = new ArrayList<>();
21 | if (pRoot == null) {
22 | return res;
23 | }
24 | Queue queue = new LinkedList<>();
25 | queue.add(pRoot);
26 | ArrayList tmp = new ArrayList<>();
27 | int start = 0;
28 | int end = 1;
29 |
30 | while (!queue.isEmpty()) {
31 | TreeNode node = queue.poll();
32 | tmp.add(node.val);
33 | start++;
34 | if (node.left != null) {
35 | queue.offer(node.left);
36 | }
37 | if (node.right != null) {
38 | queue.offer(node.right);
39 | }
40 |
41 | if (start == end) {
42 | start = 0;
43 | end = queue.size();
44 | res.add(new ArrayList<>(tmp));
45 | tmp.clear();
46 | }
47 | }
48 | return res;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MaxInWindows65.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * 第65题
7 | * 求滑动窗口的最大值
8 | *
9 | * @author qgl
10 | * @date 2017/08/31
11 | */
12 | public class MaxInWindows65 {
13 |
14 | /**
15 | * 解法一:两个for循环
16 | *
17 | * @param num
18 | * @param size
19 | * @return
20 | */
21 | public static ArrayList maxInWindows1(int[] num, int size) {
22 | ArrayList list = new ArrayList<>();
23 | if (num == null || size < 1 || num.length < size)
24 | return list;
25 | int length = num.length - size + 1;
26 |
27 | for (int i = 0; i < length; i++) {
28 | int current = size + i;
29 | int max = num[i];
30 | for (int j = i; j < current; j++) {
31 | if (max < num[j]) {
32 | max = num[j];
33 | }
34 | }
35 | list.add(max);
36 | }
37 | return list;
38 | }
39 |
40 | /**
41 | * 解法二:时间复杂度更低的双端队列
42 | *
43 | * @param num
44 | * @param size
45 | * @return
46 | */
47 | public static ArrayList maxInWindows2(int[] num, int size) {
48 | ArrayList res = new ArrayList<>();
49 | if (size == 0) return res;
50 | ArrayDeque q = new ArrayDeque<>();
51 |
52 | for (int i = 0; i < num.length; i++) {
53 | int begin = i - size + 1;
54 | if (q.isEmpty())
55 | q.add(i);
56 | else if (begin > q.peekFirst())
57 | q.pollFirst();
58 |
59 | while ((!q.isEmpty()) && num[q.peekLast()] <= num[i])
60 | q.pollLast();
61 | q.add(i);
62 | if (begin >= 0)
63 | res.add(num[q.peekFirst()]);
64 | }
65 | return res;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MergeLinked17.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.ListNode;
4 |
5 | /**
6 | * 第17题
7 | * 输入两个递增的链表,合并这两个链表并使新链表仍然是递增的
8 | *
9 | * @author qgl
10 | * @date 2017/08/10
11 | */
12 | public class MergeLinked17 {
13 | /**
14 | * 解法一:递归
15 | * 时间复杂度:O(m+n),空间复杂度:O(m+n)
16 | *
17 | * @param list1
18 | * @param list2
19 | * @return
20 | */
21 | public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
22 | if (list1 == null) {
23 | return list2;
24 | }
25 | if (list2 == null) {
26 | return list1;
27 | }
28 |
29 | if (list1.val < list2.val) {
30 | list1.next = mergeTwoLists(list1.next, list2);
31 | return list1;
32 | } else {
33 | list2.next = mergeTwoLists(list1, list2.next);
34 | return list2;
35 | }
36 | }
37 |
38 | /**
39 | * 解法二:迭代
40 | * 时间复杂度:O(m+n),空间复杂度:O(1)
41 | *
42 | * @param list1
43 | * @param list2
44 | * @return
45 | */
46 | public static ListNode mergeTwoLists2(ListNode list1, ListNode list2) {
47 | ListNode preHead = new ListNode(-1);
48 | ListNode pre = preHead;
49 |
50 | while (list1 != null && list2 != null) {
51 | if (list1.val < list2.val) {
52 | pre.next = list1;
53 | list1 = list1.next;
54 | } else {
55 | pre.next = list2;
56 | list2 = list2.next;
57 | }
58 | pre = pre.next;
59 | }
60 |
61 | pre.next = list1 == null ? list2 : list1;
62 | return preHead.next;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MinCParent50.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Stack;
4 |
5 | /**
6 | * 第50题
7 | * 寻找树的两个节点的最低公共祖先
8 | *
9 | * @author qgl
10 | * @date 2017/09/02
11 | */
12 | public class MinCParent50 {
13 |
14 | static class BinaryTreeNode {
15 | public int value;
16 | public BinaryTreeNode leftNode;
17 | public BinaryTreeNode rightNode;
18 | public BinaryTreeNode parentNode;
19 |
20 | public BinaryTreeNode(int value) {
21 | this.value = value;
22 | }
23 | }
24 |
25 | /**
26 | * 若树是二叉搜素树,递归调用二叉树
27 | * 时间复杂度是O(log n),空间复杂度是O(1)
28 | *
29 | * @param rootParent
30 | * @param root
31 | * @param node1
32 | * @param node2
33 | * @return
34 | */
35 | public static BinaryTreeNode getLowestCommonAncestor1(BinaryTreeNode rootParent, BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2) {
36 | if (root == null || node1 == null || node2 == null) {
37 | return null;
38 | }
39 | if ((root.value - node1.value) * (root.value - node2.value) < 0) {
40 | return root;
41 | } else if ((root.value - node1.value) * (root.value - node2.value) > 0) {
42 | BinaryTreeNode newRoot = ((root.value > node1.value) && (root.value > node2.value))
43 | ? root.leftNode : root.rightNode;
44 | return getLowestCommonAncestor1(root, newRoot, node1, node2);
45 | } else {
46 | return rootParent;
47 | }
48 | }
49 |
50 | /**
51 | * 若树是普通树,并没有指向父节点的指针,获取node节点的路径时间复杂度为O(n)
52 | * 时间复杂度是O(n),空间复杂度是O(log n)
53 | *
54 | * @param root
55 | * @param node1
56 | * @param node2
57 | * @return
58 | */
59 | public static BinaryTreeNode getLowestCommonAncestor2(BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2) {
60 | if (root == null || node1 == null || node2 == null) {
61 | return null;
62 | }
63 | Stack path1 = new Stack();
64 | boolean flag1 = getThePathOfTheNode(root, node1, path1);
65 | if (!flag1) {//树上没有node1节点
66 | return null;
67 | }
68 | Stack path2 = new Stack();
69 | boolean flag2 = getThePathOfTheNode(root, node2, path2);
70 | if (!flag2) {//树上没有node2节点
71 | return null;
72 | }
73 | if (path1.size() > path2.size()) { //让两个路径等长
74 | while (path1.size() != path2.size()) {
75 | path1.pop();
76 | }
77 | } else {
78 | while (path1.size() != path2.size()) {
79 | path2.pop();
80 | }
81 | }
82 | if (path1 == path2) {//当两个节点在一条路径上时
83 | path1.pop();
84 | return path1.pop();
85 | } else {
86 | BinaryTreeNode p = path1.pop();
87 | BinaryTreeNode q = path2.pop();
88 | while (q != p) {
89 | p = path1.pop();
90 | q = path2.pop();
91 | }
92 | return p;
93 | }
94 | }
95 |
96 | /**
97 | * 若树是普通树,但有指向父节点的指针,类似于求两个链表的第一个公共节点。由于每个节点的深度最多为log n
98 | * 时间复杂度为O(log n),空间复杂度O(1)
99 | *
100 | * @param root
101 | * @param node1
102 | * @param node2
103 | * @return
104 | */
105 | public static BinaryTreeNode getLowestCommonAncestor3(BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2) {
106 | if (root == null || node1 == null || node2 == null) {
107 | return null;
108 | }
109 | int depth1 = findTheDepthOfTheNode(node1, node2);
110 | if (depth1 == -1) {
111 | return node2.parentNode;
112 | }
113 | int depth2 = findTheDepthOfTheNode(node2, node1);
114 | if (depth2 == -1) {
115 | return node1.parentNode;
116 | }
117 | //p指向较深的节点q指向较浅的节点
118 | BinaryTreeNode p = depth1 > depth2 ? node1 : node2;
119 | BinaryTreeNode q = depth1 > depth2 ? node2 : node1;
120 | int depth = Math.abs(depth1 - depth2);
121 | while (depth > 0) {
122 | p = p.parentNode;
123 | depth--;
124 | }
125 | while (p != q) {
126 | p = p.parentNode;
127 | q = q.parentNode;
128 | }
129 | return p;
130 | }
131 |
132 | /**
133 | * 获得根节点到node节点的路径
134 | *
135 | * @param root
136 | * @param node
137 | * @param path
138 | * @return
139 | */
140 | public static boolean getThePathOfTheNode(BinaryTreeNode root, BinaryTreeNode node, Stack path) {
141 | path.push(root);
142 | if (root == node) {
143 | return true;
144 | }
145 | boolean found = false;
146 | if (root.leftNode != null) {
147 | found = getThePathOfTheNode(root.leftNode, node, path);
148 | }
149 | if (!found && root.rightNode != null) {
150 | found = getThePathOfTheNode(root.rightNode, node, path);
151 | }
152 | if (!found) {
153 | path.pop();
154 | }
155 | return found;
156 | }
157 |
158 | /**
159 | * 求node1的深度
160 | * 如果node1和node2在一条路径上,则返回-1,否则返回node1的深度
161 | *
162 | * @param node1
163 | * @param node2
164 | * @return
165 | */
166 | public static int findTheDepthOfTheNode(BinaryTreeNode node1, BinaryTreeNode node2) {
167 | int depth = 0;
168 | while (node1.parentNode != null) {
169 | node1 = node1.parentNode;
170 | depth++;
171 | if (node1 == node2) {
172 | return -1;
173 | }
174 | }
175 | return depth;
176 | }
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MinNumber8.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第8题
5 | * 输入一个非递减排序数组的一个旋转,输出旋转数组的最小元素。
6 | *
7 | * @author qgl
8 | * @date 2017/08/09
9 | */
10 | public class MinNumber8 {
11 |
12 | /**
13 | * 解法一:二分查找(寻找变化点)
14 | * 时间复杂度:O(log n),空间复杂度:O(1)
15 | *
16 | * @param array
17 | * @return
18 | */
19 | public static int minInReversingList(int[] array) {
20 | if (array == null || array.length == 0) {
21 | return -1;
22 | }
23 | if (array.length == 1 || array[array.length - 1] > array[0]) {
24 | return array[0];
25 | }
26 |
27 | int left = 0;
28 | int right = array.length - 1;
29 | while (left <= right) {
30 | int mid = (left + right) / 2;
31 | if (array[mid] > array[mid + 1]) {
32 | return array[mid + 1];
33 | }
34 | if (array[mid - 1] > array[mid]) {
35 | return array[mid];
36 | }
37 |
38 | if (array[mid] > array[0]) {
39 | left = mid + 1;
40 | } else {
41 | right = mid - 1;
42 | }
43 | }
44 |
45 | return -1;
46 | }
47 |
48 | /**
49 | * 解法二:二分查找(最左下标)
50 | * 时间复杂度:O(log n),空间复杂度:O(1)
51 | *
52 | * @param nums
53 | * @return
54 | */
55 | public int minInReversingList2(int[] nums) {
56 | if (nums == null || nums.length == 0) {
57 | return -1;
58 | }
59 |
60 | int left = 0;
61 | int right = nums.length - 1;
62 | while (left < right) {
63 | int mid = (left + right) / 2;
64 | if (nums[mid] > nums[right]) {
65 | left = mid + 1;
66 | } else {
67 | right = mid;
68 | }
69 | }
70 | return nums[left];
71 | }
72 |
73 | /**
74 | * 第8.1题:若非递减排序数组中有重复元素,求最小元素
75 | * 时间复杂度:O(log n),空间复杂度:O(1)
76 | *
77 | * @param nums
78 | * @return
79 | */
80 | public int findMin(int[] nums) {
81 | if (nums == null || nums.length == 0) {
82 | return -1;
83 | }
84 |
85 | int left = 0;
86 | int right = nums.length - 1;
87 | while (left < right) {
88 | int mid = (left + right) / 2;
89 | if (nums[mid] > nums[right]) {
90 | left = mid + 1;
91 | } else if (nums[mid] < nums[right]) {
92 | right = mid;
93 | } else {
94 | right--;
95 | }
96 | }
97 | return nums[left];
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MirrorRecursively19.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Stack;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第19题
8 | * 输入一个二叉树,输出它的镜像
9 | *
10 | * @author qgl
11 | * @date 2017/08/10
12 | */
13 | public class MirrorRecursively19 {
14 |
15 | /**
16 | * 解法一:递归
17 | * @param root
18 | */
19 | public void Mirror(TreeNode root) {
20 | if (root == null) {
21 | return;
22 | }
23 | TreeNode tmp = root.left;
24 | root.left = root.right;
25 | root.right = tmp;
26 |
27 | Mirror(root.left);
28 | Mirror(root.right);
29 | }
30 |
31 | /**
32 | * 解法二:非递归,利用栈
33 | * @param root
34 | * @return
35 | */
36 | public void Mirror2(TreeNode root) {
37 | if (root == null) {
38 | return ;
39 | }
40 | Stack stack = new Stack<>();
41 |
42 | while (root != null || !stack.isEmpty()) {
43 | while (root != null) {
44 | // 交换左右子节点
45 | TreeNode temp = root.left;
46 | root.left = root.right;
47 | root.right = temp;
48 | stack.push(root);
49 | root = root.left;
50 | }
51 |
52 | root = stack.pop();
53 | root = root.right;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MoreThanHalfNum29.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第29题
5 | * 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字
6 | *
7 | * @author qgl
8 | * @date 2017/08/14
9 | */
10 | public class MoreThanHalfNum29 {
11 | /**
12 | * 获取数组中出现次数超过数组长度一半的数字
13 | *
14 | * @param nums
15 | * @return
16 | */
17 | public static int moreThanHalfNum(int[] nums) {
18 | int count = 0;
19 | int candidate = 0;
20 |
21 | for (int num : nums) {
22 | if (count == 0) {
23 | candidate = num;
24 | }
25 | count += (num == candidate) ? 1 : -1;
26 | }
27 |
28 | return checkMoreThanHalf(nums, candidate) ? candidate : 0;
29 | }
30 |
31 | /**
32 | * 检查输入的数字出现的次数是否超过数组长度一半
33 | *
34 | * @param array
35 | * @param number
36 | * @return
37 | */
38 | private static boolean checkMoreThanHalf(int[] array, Integer number) {
39 | int times = 0;
40 | for (int i : array) {
41 | if (i == number) {
42 | times++;
43 | }
44 | }
45 | return times * 2 >= array.length;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MovingCount67.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第67题
5 | * 机器人的运动范围,一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,
6 | * 但是不能进入行坐标和列坐标的数位之和大于k的格子。求机器人能够达到多少个格子
7 | *
8 | * @author qgl
9 | * @date 2017/08/31
10 | */
11 | public class MovingCount67 {
12 |
13 | /**
14 | * 机器人能到达的格子数
15 | * @param k
16 | * @param rows
17 | * @param cols
18 | * @return
19 | */
20 | public static int movingCount(int k, int rows, int cols) {
21 | int[][] flag = new int[rows][cols]; // 记录是否已经走过
22 | return helper(0, 0, rows, cols, flag, k);
23 | }
24 |
25 | /**
26 | * 递归查找
27 | * @param i
28 | * @param j
29 | * @param rows
30 | * @param cols
31 | * @param flag
32 | * @param k
33 | * @return
34 | */
35 | private static int helper(int i, int j, int rows, int cols, int[][] flag, int k) {
36 | if (i < 0 || i >= rows || j < 0 || j >= cols ||
37 | numSum(i) + numSum(j) > k || flag[i][j] == 1) {
38 | return 0;
39 | }
40 | flag[i][j] = 1;
41 | return helper(i - 1, j, rows, cols, flag, k)
42 | + helper(i + 1, j, rows, cols, flag, k)
43 | + helper(i, j - 1, rows, cols, flag, k)
44 | + helper(i, j + 1, rows, cols, flag, k) + 1;
45 | }
46 |
47 | /**
48 | * 求输入数的每一位之和
49 | * @param i
50 | * @return
51 | */
52 | private static int numSum(int i) {
53 | int sum = 0;
54 | while (i > 0) {
55 | sum += i % 10;
56 | i = i / 10;
57 | }
58 | return sum;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/so/MultiplyArray52.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第52题
5 | * 构建乘积数组
6 | *
7 | * @author qgl
8 | * @date 2017/08/29
9 | */
10 | public class MultiplyArray52 {
11 |
12 | /**
13 | * 利用矩阵法构建乘积数组
14 | *
15 | * @param A
16 | * @return
17 | */
18 | public static int[] multiply(int[] A) {
19 | int length = A.length;
20 | int[] B = new int[length];
21 | if (length != 0) {
22 | B[0] = 1;
23 | //计算下三角连乘
24 | for (int i = 1; i < length; i++) {
25 | B[i] = B[i - 1] * A[i - 1];
26 | }
27 | int temp = 1;
28 | //计算上三角连乘
29 | for (int j = length - 2; j >= 0; j--) {
30 | temp *= A[j + 1];
31 | B[j] *= temp;
32 | }
33 | }
34 | return B;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/so/NextTreeNode58.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第58题
5 | * 给定一个二叉树的某个结点,请找出中序遍历顺序的下一个结点并且返回
6 | *
7 | * @author qgl
8 | * @date 2017/08/30
9 | */
10 | public class NextTreeNode58 {
11 | /**
12 | * 二叉树
13 | */
14 | static class TreeLinkNode {
15 | int val;
16 | TreeLinkNode left = null;
17 | TreeLinkNode right = null;
18 | TreeLinkNode next = null;
19 |
20 | TreeLinkNode(int val) {
21 | this.val = val;
22 | }
23 | }
24 |
25 | /**
26 | * 获取输入节点的下一个节点
27 | *
28 | * @param pNode
29 | * @return
30 | */
31 | public static TreeLinkNode getTreeLinkNextNode(TreeLinkNode pNode) {
32 | if (pNode == null) {
33 | return null;
34 | }
35 | if (pNode.right != null) {
36 | pNode = pNode.right;
37 | while (pNode.left != null) {
38 | pNode = pNode.left;
39 | }
40 | return pNode;
41 | }
42 |
43 | while (pNode.next != null) {
44 | // 找第一个当前节点是父节点左孩子的节点
45 | if (pNode.next.left == pNode)
46 | return pNode.next;
47 | pNode = pNode.next;
48 | }
49 | return null;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/so/NumberOf1Bw32.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第32题
5 | * 输入一个整数n,求从1到n这N个十进制表示中1出现的次数
6 | *
7 | * @author qgl
8 | * @date 2017/08/14
9 | */
10 | public class NumberOf1Bw32 {
11 |
12 | /**
13 | * 解法一
14 | * 主要思路:设定整数点作为位置点i(对应n的个位、十位等),分别对每个数位上有多少包含1的点进行分析
15 | * 根据设定的整数位置,对n进行分割,分为高位和低位
16 | * 当i表示百位,且百位对应的数>=2,如n=31456,i=100,则a=314,b=56,此时百位为1的次数有a/10+1=32(最高两位0~31),
17 | * 每一次都包含100个连续的点,即共有(a%10+1)*100个点的百位为1
18 | * 当i表示百位,且百位对应的数为1,如n=31156,i=100,则a=311,b=56,此时百位对应的就是1,则共有a%10(最高两位0-30)次是
19 | * 包含100个连续点,当最高两位为31(即a=311),本次只对应局部点00~56,共b+1次,所有点加起来共有(a%10*100)+(b+1),这些点百位对应为1
20 | * 当i表示百位,且百位对应的数为0,如n=31056,i=100,则a=310,b=56,此时百位为1的次数有a/10=31(最高两位0~30)
21 | * 综合以上三种情况,当百位对应0或>=2时,有(a+8)/10次包含所有100个点,还有当百位为1(a%10==1),需要增加局部点b+1
22 | * 补8是因为当百位为0,则a/10==(a+8)/10,当百位>=2,补8会产生进位位,效果等同于(a/10+1)
23 | *
24 | * @param n
25 | * @return
26 | */
27 | public static int NumberOf1Between1AndN1(int n) {
28 | int count = 0;
29 |
30 | for (int i = 1; i <= n; i *= 10) {
31 | int a = n / i; // 高位
32 | int b = n % i; // 低位
33 | count += (a + 8) / 10 * i;
34 | if (a % 10 == 1) {
35 | count += b + 1;
36 | }
37 | }
38 | return count;
39 | }
40 |
41 | /**
42 | * 解法二
43 | *
44 | * @param n
45 | * @return
46 | */
47 | public static long NumberOf1Between1AndN2(long n) {
48 | long count = 0; // 1的个数
49 | long i = 1; // 当前位
50 | long current = 0, after = 0, before = 0;
51 |
52 | while ((n / i) != 0) {
53 | before = n / (i * 10); // 高位
54 | current = (n / i) % 10; // 当前位
55 | after = n - (n / i) * i; // 低位
56 |
57 | if (current == 0) {
58 | //如果为0,出现1的次数由高位决定,等于高位数字 * 当前位数
59 | count = count + before * i;
60 | } else if (current == 1) {
61 | //如果为1,出现1的次数由高位和低位决定,高位*当前位+低位+1
62 | count = count + before * i + after + 1;
63 | } else if (current > 1) {
64 | // 如果大于1,出现1的次数由高位决定,(高位数字+1)* 当前位数
65 | count = count + (before + 1) * i;
66 | }
67 | //前移一位
68 | i = i * 10;
69 | }
70 | return count;
71 | }
72 |
73 | /**
74 | * 解法三:不推荐,时间复杂度高
75 | *
76 | * @param n
77 | * @return
78 | */
79 | public static int NumberOf1Between1AndN3(int n) {
80 | if (n <= 0) {
81 | return 0;
82 | }
83 | int count = 0;
84 |
85 | for (int i = 1; i < n + 1; i++) {
86 | String s = String.valueOf(i);
87 | for (int j = 0; j < s.length(); j++) {
88 | if ('1' == s.charAt(j)) {
89 | count++;
90 | }
91 | }
92 | }
93 | return count;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/so/NumberOfBin10.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第10题
5 | * 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
6 | *
7 | * @author qgl
8 | * @date 2017/08/09
9 | */
10 | public class NumberOfBin10 {
11 |
12 | /**
13 | * 思路:把一个整数减去1再和原整数与,就会把整数最右边一个1变成0
14 | *
15 | * @param n
16 | * @return
17 | */
18 | public static int numberOfBin(int n) {
19 | int count = 0;
20 |
21 | while (n != 0) {
22 | count++;
23 | n = (n - 1) & n;
24 | }
25 | return count;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/so/OddEvenNumber14.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第14题
5 | * 输入一个整数数组,实现一个函数来调整数组中的数字的顺序,
6 | * 使得所有奇数位于数组的前半部分,偶数位于后半部分
7 | *
8 | * @author qgl
9 | * @date 2017/08/10
10 | */
11 | public class OddEvenNumber14 {
12 |
13 | /**
14 | * 解法一:移动偶数位置
15 | * 时间复杂度 O(n²),空间复杂度 O(1)
16 | *
17 | * @param array
18 | */
19 | public void reOrderArray(int[] array) {
20 | if (array == null || array.length == 0) {
21 | return;
22 | }
23 |
24 | for (int i = 1; i < array.length; i++) {
25 | int j = i - 1;
26 | if (array[i] % 2 != 0) {
27 | while (j >= 0) {
28 | if (array[j] % 2 != 0) {
29 | break;
30 | }
31 | if (array[j] % 2 == 0) {
32 | int t = array[j + 1];
33 | array[j + 1] = array[j];
34 | array[j] = t;
35 | j--;
36 | }
37 | }
38 | }
39 | }
40 | }
41 |
42 | /**
43 | * 解法二:双指针法
44 | * 时间复杂度 O(n),空间复杂度 O(1)
45 | *
46 | * @param array
47 | */
48 | public void reOrderArray2(int[] array) {
49 | if (array == null || array.length == 0) {
50 | return;
51 | }
52 |
53 | int left = 0;
54 | int right = array.length - 1;
55 | while (left < right) {
56 | while (left < right && array[left] % 2 != 0) {
57 | left++;
58 | }
59 | while (left < right && array[right] % 2 == 0) {
60 | right--;
61 | }
62 |
63 | if (left < right) {
64 | int tmp = array[left];
65 | array[left] = array[right];
66 | array[right] = tmp;
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/so/Permutation28.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * 第28题
7 | * 输入一个字符串,打印出字符串中字符的所有排列
8 | *
9 | * @author qgl
10 | * @date 2017/08/14
11 | */
12 | public class Permutation28 {
13 |
14 | /**
15 | * 解法一:while循环
16 | *
17 | * @param str
18 | * @return
19 | */
20 | public static String permutation1(String str) {
21 | if (str == null || str.length() == 0) {
22 | return null;
23 | }
24 | StringBuilder sb = new StringBuilder();
25 | if (str.length() == 1) {
26 | sb.append(str);
27 | return String.valueOf(sb);
28 | }
29 |
30 | char[] output = str.toCharArray();
31 | int point = 0;
32 | sb.append(output).append(",");
33 | swap(output, point, ++point);
34 |
35 | while (!String.valueOf(output).equals(str)) {
36 | sb.append(output).append(",");
37 | if (point == output.length - 1) {
38 | swap(output, point, 0);
39 | point = 0;
40 | } else {
41 | swap(output, point, ++point);
42 | }
43 | }
44 |
45 | return String.valueOf(sb);
46 | }
47 |
48 | /**
49 | * 解法二:递归
50 | *
51 | * @param str
52 | * @return
53 | */
54 | public static ArrayList Permutation(String str) {
55 | ArrayList res = new ArrayList<>();
56 | if (str == null || str.length() == 0) {
57 | return res;
58 | }
59 | helper(res, 0, str.toCharArray());
60 | // 符合结果的输出顺序
61 | Collections.sort(res);
62 | return res;
63 |
64 | }
65 |
66 | private static void helper(ArrayList res, int index, char[] s) {
67 | if (index == s.length - 1) {
68 | res.add(String.valueOf(s));
69 | return;
70 | }
71 |
72 | for (int i = index; i < s.length; i++) {
73 | if (i == index || s[index] != s[i]) {
74 | swap(s, index, i);
75 | helper(res, index + 1, s);
76 | swap(s, index, i);
77 | }
78 | }
79 | }
80 |
81 | /**
82 | * 交换两个字符的位置
83 | *
84 | * @param output
85 | * @param i
86 | * @param j
87 | */
88 | public static void swap(char[] output, int i, int j) {
89 | char temp = output[i];
90 | output[i] = output[j];
91 | output[j] = temp;
92 | }
93 | }
--------------------------------------------------------------------------------
/src/main/java/com/so/Power11.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第11题
5 | * 求base的exponent次方,不得使用库函数,不需要考虑大数问题
6 | *
7 | * @author qgl
8 | * @date 2017/08/09
9 | */
10 | public class Power11 {
11 |
12 | /**
13 | * 对输入的数进行条件判断后计算结果
14 | *
15 | * @param base
16 | * @param exponent
17 | * @return
18 | * @throws Exception
19 | */
20 | public static double power(double base, int exponent) throws Exception {
21 | double result = 0.0;
22 |
23 | if (equal(base, 0.0) && exponent < 0) {
24 | throw new Exception("0的负数次幂无意义");
25 | }
26 |
27 | if (equal(exponent, 0)) {
28 | return 1.0;
29 | }
30 |
31 | if (exponent < 0) {
32 | result = powerWithExponent(1.0 / base, -exponent);
33 | } else {
34 | result = powerWithExponent(base, exponent);
35 | }
36 |
37 | return result;
38 | }
39 |
40 | /**
41 | * 幂计算
42 | *
43 | * @param base
44 | * @param exponent
45 | * @return
46 | */
47 | private static double powerWithExponent(double base, int exponent) {
48 | double result = 1.0;
49 |
50 | for (int i = 1; i <= exponent; i++) {
51 | result = result * base;
52 | }
53 |
54 | return result;
55 | }
56 |
57 | /**
58 | * 判断两个double型数值是否相等(有误差)
59 | *
60 | * @param num1
61 | * @param num2
62 | * @return
63 | */
64 | private static boolean equal(double num1, double num2) {
65 | return (num1 - num2 > -0.0000001) && num1 - num2 < 0.0000001;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/so/PrintFromTopToBottom23.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.ArrayList;
4 | import java.util.LinkedList;
5 | import com.so.Common.TreeNode;
6 | import java.util.Queue;
7 |
8 | /**
9 | * 第23题
10 | * 层序遍历二叉树
11 | *
12 | * @author qgl
13 | * @date 2017/08/11
14 | */
15 | public class PrintFromTopToBottom23 {
16 | /**
17 | * 解法一:迭代
18 | * 时间复杂度:O(n),空间复杂度:O(n)
19 | *
20 | * @param root
21 | * @return
22 | */
23 | public ArrayList PrintFromTopToBottom(TreeNode root) {
24 | ArrayList list = new ArrayList<>();
25 | if (root == null) {
26 | return list;
27 | }
28 | Queue queue = new LinkedList<>();
29 | queue.offer(root);
30 |
31 | while (!queue.isEmpty()) {
32 | TreeNode node = queue.poll();
33 | list.add(node.val);
34 | if (node.left != null) {
35 | queue.offer(node.left);
36 | }
37 | if (node.right != null) {
38 | queue.offer(node.right);
39 | }
40 | }
41 | return list;
42 | }
43 |
44 | /**
45 | * 解法二:递归
46 | * 时间复杂度:O(n),空间复杂度:O(n)
47 | *
48 | * @param root
49 | * @return
50 | */
51 | public ArrayList PrintFromTopToBottom2(TreeNode root) {
52 | ArrayList list = new ArrayList();
53 | if (root == null) {
54 | return list;
55 | }
56 |
57 | list.add(root.val);
58 | levelOrder(root, list);
59 | return list;
60 | }
61 |
62 | public void levelOrder(TreeNode root, ArrayList list) {
63 | if (root == null) {
64 | return;
65 | }
66 |
67 | if (root.left != null) {
68 | list.add(root.left.val);
69 | }
70 | if (root.right != null) {
71 | list.add(root.right.val);
72 | }
73 | levelOrder(root.left, list);
74 | levelOrder(root.right, list);
75 | }
76 | }
77 |
78 |
79 |
--------------------------------------------------------------------------------
/src/main/java/com/so/PrintListReversing5.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Stack;
5 | import com.so.Common.ListNode;
6 |
7 | /**
8 | * 第5题 从尾到头打印链表
9 | * 输入一个链表,从尾到头打印链表每个节点的值
10 | *
11 | * @author qgl
12 | * @date 2017/08/08
13 | */
14 | public class PrintListReversing5 {
15 |
16 | /**
17 | * 解法一:利用栈输出
18 | * @param headNode
19 | */
20 | public static ArrayList printListReverse1(ListNode headNode) {
21 | ArrayList list = new ArrayList<>();
22 | Stack stack = new Stack<>();
23 | while (headNode != null) {
24 | stack.push(headNode);
25 | headNode = headNode.next;
26 | }
27 |
28 | while (!stack.isEmpty()) {
29 | list.add(stack.pop().val);
30 | }
31 | return list;
32 | }
33 |
34 | /**
35 | * 解法二:递归(其实底层还是栈)
36 | * @param headNode
37 | * @return
38 | */
39 | public static ArrayList printListReverse2(ListNode headNode) {
40 | ArrayList list = new ArrayList();
41 |
42 | if (headNode != null) {
43 | if (headNode.next != null) {
44 | list = printListReverse2(headNode.next);
45 | }
46 | list.add(headNode.val);
47 | }
48 | return list;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/so/PrintMatrixInCircle20.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.ArrayList;
4 |
5 | /**
6 | * 第20题
7 | * 顺时针打印矩阵
8 | *
9 | * @author qgl
10 | * @date 2017/08/10
11 | */
12 | public class PrintMatrixInCircle20 {
13 |
14 | /**
15 | * 打印矩阵
16 | * @param matrix
17 | * @return
18 | */
19 | public static ArrayList printMatrix(int[][] matrix) {
20 | ArrayList list = new ArrayList<>();
21 | if (matrix == null)
22 | return list;
23 | int start = 0;
24 | while (matrix[0].length > start * 2 && matrix.length > start * 2) {
25 | saveOneCircle(matrix, start, list);
26 | start++;
27 | }
28 | return list;
29 | }
30 |
31 | /**
32 | * 记录矩阵的环
33 | * @param matrix
34 | * @param start
35 | * @param list
36 | */
37 | private static void saveOneCircle(int[][] matrix, int start, ArrayList list) {
38 | int endX = matrix[0].length - 1 - start; // 列
39 | int endY = matrix.length - 1 - start; // 行
40 | // 从左往右
41 | for (int i = start; i <= endX; i++)
42 | list.add(matrix[start][i]);
43 | // 从上往下
44 | if (start < endY) {
45 | for (int i = start + 1; i <= endY; i++)
46 | list.add(matrix[i][endX]);
47 | }
48 | // 从右往左(判断是否会重复打印)
49 | if (start < endX && start < endY) {
50 | for (int i = endX - 1; i >= start; i--)
51 | list.add(matrix[endY][i]);
52 | }
53 | // 从下往上(判断是否会重复打印)
54 | if (start < endX && start < endY - 1) {
55 | for (int i = endY - 1; i >= start + 1; i--)
56 | list.add(matrix[i][start]);
57 | }
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/so/PrintMinNumber33.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Arrays;
4 | import java.util.Comparator;
5 |
6 | /**
7 | * 第33题
8 | * 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印出能拼接出的所有数字中的最小的一个。
9 | *
10 | * @author qgl
11 | * @date 2017/08/14
12 | */
13 | public class PrintMinNumber33 {
14 | /**
15 | * 解法一:自定义快排
16 | * @param array
17 | * @return
18 | */
19 | public static String printMinNumber1(int[] array) {
20 | int[] clone = array.clone();
21 | StringBuilder sb = new StringBuilder();
22 | printMin(clone, 0, clone.length - 1);
23 | for (int i : clone) {
24 | sb.append(i);
25 | }
26 | return sb.toString();
27 | }
28 |
29 | /**
30 | * 比较+快排
31 | * @param array
32 | * @param start
33 | * @param end
34 | */
35 | public static void printMin(int[] array, int start, int end) {
36 | if (start < end) {
37 | int main_number = array[end];
38 | int small_cur = start;
39 | for (int j = start; j < end; j++) {
40 | // array[j]、main_number的组合较小,就把array[j]换到最前面
41 | if (isSmall(String.valueOf(array[j]), String.valueOf(main_number))) {
42 | int temp = array[j];
43 | array[j] = array[small_cur];
44 | array[small_cur] = temp;
45 | small_cur++;
46 | }
47 | }
48 |
49 | array[end] = array[small_cur];
50 | array[small_cur] = main_number;
51 | printMin(array, 0, small_cur - 1);
52 | printMin(array, small_cur + 1, end);
53 | }
54 | }
55 |
56 | /**
57 | * 比较两个字符的大小(判断m是否比n小)
58 | * @param m
59 | * @param n
60 | * @return
61 | */
62 | private static boolean isSmall(String m, String n) {
63 | String left = m + n;
64 | String right = n + m;
65 |
66 | for (int i = 0; i < left.length(); i++) {
67 | if (left.charAt(i) < right.charAt(i)) {
68 | return true;
69 | }
70 | if (left.charAt(i) > right.charAt(i))
71 | return false;
72 | }
73 | return false;
74 | }
75 |
76 | /**
77 | * 解法二:使用JDK的归并排序
78 | * @param numbers
79 | * @return
80 | */
81 | public static String printMinNumber2(int[] numbers) {
82 | if (numbers == null || numbers.length == 0)
83 | return "";
84 | int len = numbers.length;
85 | String[] str = new String[len];
86 | StringBuilder sb = new StringBuilder();
87 | for (int i = 0; i < len; i++) {
88 | str[i] = String.valueOf(numbers[i]);
89 | }
90 | Arrays.sort(str, new Comparator() {
91 | @Override
92 | public int compare(String s1, String s2) {
93 | String c1 = s1 + s2;
94 | String c2 = s2 + s1;
95 | return c1.compareTo(c2);
96 | }
97 | });
98 |
99 | for (int i = 0; i < len; i++) {
100 | sb.append(str[i]);
101 | }
102 | return sb.toString();
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/com/so/PrintToMaxOfNDigits12.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第12题
5 | * 打印1到最大的n位数
6 | *
7 | * @author qgl
8 | * @date 2017/08/09
9 | */
10 | public class PrintToMaxOfNDigits12 {
11 |
12 | /**
13 | * 创建数组并校验输入值
14 | *
15 | * @param n
16 | */
17 | public static void printToMaxOfNDigits(int n) {
18 | int[] array = new int[n];
19 | if (n <= 0)
20 | return;
21 | printArray(array, 0);
22 | }
23 |
24 | /**
25 | * 输出数值
26 | *
27 | * @param array
28 | * @param n
29 | */
30 | private static void printArray(int[] array, int n) {
31 | for (int i = 0; i < 10; i++) {
32 | if (n != array.length) {
33 | array[n] = i;
34 | printArray(array, n + 1);
35 | } else {
36 | boolean isFirstNo0 = false;
37 | for (int j = 0; j < array.length; j++) {
38 | if (array[j] != 0) {
39 | System.out.print(array[j]);
40 | if (!isFirstNo0)
41 | isFirstNo0 = true;
42 | } else {
43 | if (isFirstNo0)
44 | System.out.print(array[j]);
45 | }
46 | }
47 | System.out.println();
48 | return;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/so/RegularMatch53.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第53题
5 | * 正则表达式匹配字符串,实现一个函数用来匹配包括'.'和'*'的正则表达式
6 | * 其中'*'表示它前面的字符可以出现任意次(包含0次)
7 | *
8 | * @author qgl
9 | * @date 2017/08/29
10 | */
11 | public class RegularMatch53 {
12 |
13 | /**
14 | * 是否匹配
15 | * @param str
16 | * @param pattern
17 | * @return
18 | */
19 | public static boolean match(char[] str, char[] pattern) {
20 | if (str == null || pattern == null) {
21 | return false;
22 | }
23 | // 若字符串的长度为1
24 | if (str.length == 1 && pattern.length == 1) {
25 | return str[0] == pattern[0] || pattern[0] == '.';
26 | }
27 |
28 | return matchIndex(str,0,pattern,0);
29 | }
30 |
31 | public static boolean matchIndex(char[] str,int sIndex, char[] pattern, int pIndex) {
32 | // str和pattern同时到达末尾,则匹配成功
33 | if (sIndex == str.length && pIndex == pattern.length)
34 | return true;
35 | // 若pattern先到尾,而str没有到达末尾,则匹配失败
36 | if (sIndex != str.length && pIndex == pattern.length)
37 | return false;
38 | // 若pattern第二个字符是*
39 | if (pIndex + 1 < pattern.length && pattern[pIndex + 1] == '*') {
40 | if (sIndex != str.length && pattern[pIndex] == str[sIndex] ||
41 | sIndex != str.length && pattern[pIndex] == '.') {
42 | return matchIndex(str,sIndex+1,pattern,pIndex+2)
43 | || matchIndex(str,sIndex,pattern,pIndex+2)
44 | || matchIndex(str,sIndex+1,pattern,pIndex);
45 | } else {
46 | return matchIndex(str,sIndex,pattern,pIndex+2);
47 | }
48 | }
49 | // 若pattern第二个字符不是*
50 | if (sIndex != str.length && pattern[pIndex] == str[sIndex] ||
51 | sIndex != str.length && pattern[pIndex] == '.')
52 | return matchIndex(str,sIndex+1,pattern,pIndex+1);
53 | return false;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/so/ReplaceBlank4.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第4题
5 | * 将一个字符串中的空格替换成"%20"
6 | *
7 | * @author qgl
8 | * @date 2017/08/07
9 | */
10 | public class ReplaceBlank4 {
11 |
12 | /**
13 | * 解法一:使用StringBuffer
14 | *
15 | * @param input
16 | * @return
17 | */
18 | public static String replaceBlank1(String input) {
19 | if (input == null) {
20 | return null;
21 | }
22 | StringBuffer outputBuffer = new StringBuffer();
23 |
24 | for (int i = 0; i < input.length(); i++) {
25 | if (input.charAt(i) == ' ') {
26 | outputBuffer.append("%20");
27 | } else {
28 | outputBuffer.append(String.valueOf(input.charAt(i)));
29 | }
30 | }
31 | return new String(outputBuffer);
32 | }
33 |
34 | /**
35 | * 解法二:使用StringBuilder
36 | *
37 | * @param input
38 | * @return
39 | */
40 | public static String replaceBlank2(String input) {
41 | if (input == null) {
42 | return null;
43 | }
44 | StringBuilder sb = new StringBuilder();
45 |
46 | for (int i = 0; i < input.length(); i++) {
47 | if (String.valueOf(input.charAt(i)).equals(" ")) {
48 | sb.append("%20");
49 | } else {
50 | sb.append(input.charAt(i));
51 | }
52 | }
53 | return String.valueOf(sb);
54 | }
55 |
56 | /**
57 | * 解法三:从后往前复制
58 | *
59 | * @param input
60 | * @return
61 | */
62 | public static String replaceBlank3(String input) {
63 | if (input == null) {
64 | return null;
65 | }
66 | int blankNum = 0;
67 | int length = input.length();
68 | int newLength = 0;
69 | for (int i = 0; i < length; i++) {
70 | if (input.charAt(i) == ' ') {
71 | blankNum++;
72 | }
73 | }
74 | // 替换后的字符串长度
75 | newLength = length + 2 * blankNum;
76 | char[] newChars = new char[newLength];
77 | int index = newLength - 1;
78 | for (int i = length - 1; i >= 0; i--) {
79 | if (input.charAt(i) == ' ') {
80 | newChars[index--] = '0';
81 | newChars[index--] = '2';
82 | newChars[index--] = '%';
83 | } else {
84 | newChars[index--] = input.charAt(i);
85 | }
86 | }
87 | return new String(newChars);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/so/ReverseList16.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.ListNode;
4 |
5 | /**
6 | * 第16题 反转链表
7 | * 输入一个链表的头结点,反转该链表并输出翻转后的头结点
8 | *
9 | * @author qgl
10 | * @date 2017/08/10
11 | */
12 | public class ReverseList16 {
13 | /**
14 | * 解法一:迭代:两个指针,反向输出
15 | * 时间复杂度:O(n),空间复杂度:O(1)
16 | *
17 | * @param head
18 | * @return
19 | */
20 | public static ListNode reverseList1(ListNode head) {
21 | ListNode pre = null;
22 | ListNode curr = head;
23 |
24 | while (curr != null) {
25 | ListNode tmp = curr.next;
26 | curr.next = pre;
27 | pre = curr;
28 | curr = tmp;
29 | }
30 | return pre;
31 | }
32 |
33 | /**
34 | * 解法二:迭代:单指针依次往后移动,改变原节点间的指向
35 | * 时间复杂度:O(n),空间复杂度:O(1)
36 | *
37 | * @param head
38 | * @return
39 | */
40 | public static ListNode reverseList2(ListNode head) {
41 | ListNode pre = null;
42 |
43 | while (head != null) {
44 | ListNode p = head.next;
45 | head.next = pre;
46 | pre = head;
47 | head = p;
48 | }
49 | return pre;
50 | }
51 |
52 | /**
53 | * 解法三:递归
54 | * 时间复杂度:O(n),空间复杂度:O(n)
55 | *
56 | * @param head
57 | * @return
58 | */
59 | public static ListNode reverseList3(ListNode head) {
60 | if (head == null || head.next == null) {
61 | return head;
62 | }
63 |
64 | ListNode p = reverseList3(head.next);
65 | head.next.next = head.next;
66 | head.next = null;
67 | return p;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/so/ReverseSentence42.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第42题
5 | * 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变
6 | *
7 | * @author qgl
8 | * @date 2017/08/16
9 | */
10 | public class ReverseSentence42 {
11 | /**
12 | * 翻转字符串内的单词顺序
13 | *
14 | * @param sentence
15 | * @return
16 | */
17 | public static String reverseSentence(String sentence) {
18 | if (sentence == null || sentence.length() == 0 || sentence.trim().length() == 0) {
19 | return sentence;
20 | }
21 | String blank = " ";
22 | String sentenceReverse = reverse(sentence);
23 | String[] splitStrings = sentenceReverse.split(blank);
24 | StringBuilder sb = new StringBuilder();
25 |
26 | for (int i = 0; i < splitStrings.length - 1; i++) {
27 | sb.append(reverse(splitStrings[i])).append(blank);
28 | }
29 | sb.append(reverse(splitStrings[splitStrings.length - 1]));
30 | return String.valueOf(sb);
31 | }
32 |
33 | /**
34 | * 翻转字符串
35 | *
36 | * @param str
37 | * @return
38 | */
39 | public static String reverse(String str) {
40 | StringBuilder sb = new StringBuilder();
41 | for (int i = str.length() - 1; i >= 0; i--) {
42 | sb.append(str.substring(i, i + 1));
43 | }
44 | return String.valueOf(sb);
45 | }
46 |
47 | /**
48 | * 字符串的左旋
49 | *
50 | * @param sentence abcdefg
51 | * @param index 2
52 | * @return cdefgab
53 | */
54 | public static String leftRotateString(String sentence, int index) {
55 | if (sentence == null || index > sentence.length() || index < 0) {
56 | return null;
57 | }
58 | String sentenceReverse = reverse(sentence);
59 | String[] splitStrings = {sentenceReverse.substring(0, sentence.length() - index),
60 | sentenceReverse.substring(sentence.length() - index, sentence.length())};
61 | StringBuilder sb = new StringBuilder();
62 | for (String s : splitStrings) {
63 | sb.append(reverse(s));
64 | }
65 | return String.valueOf(sb);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/so/Serializer62.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.TreeNode;
4 |
5 | /**
6 | * 第62题
7 | * 二叉树的序列化与反序列化
8 | *
9 | * @author qgl
10 | * @date 2017/08/30
11 | */
12 | public class Serializer62 {
13 |
14 | /**
15 | * 序列化二叉树 (前序遍历)
16 | *
17 | * @param root
18 | * @return
19 | */
20 | public static String serialize(TreeNode root) {
21 | StringBuffer sb = new StringBuffer();
22 | if (root == null) {
23 | sb.append("#,");
24 | return sb.toString();
25 | }
26 |
27 | sb.append(root.val + ",");
28 | sb.append(serialize(root.left));
29 | sb.append(serialize(root.right));
30 | return sb.toString();
31 | }
32 |
33 | private static int index = -1;
34 |
35 | /**
36 | * 反序列化二叉树
37 | *
38 | * @param str
39 | * @return
40 | */
41 | public static TreeNode deserialize(String str) {
42 | index++;
43 | int len = str.length();
44 | String[] strArray = str.split(",");
45 | TreeNode node = null;
46 |
47 | if (index >= len) {
48 | return null;
49 | }
50 |
51 | if (!strArray[index].equals("#")) {
52 | node = new TreeNode(Integer.valueOf(strArray[index]));
53 | node.left = deserialize(str);
54 | node.right = deserialize(str);
55 | }
56 | return node;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/so/SingletonPattern2.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第2题 单例设计模式
5 | * 设计一个类,只能生成该类的一个实例。
6 | *
7 | * @author qgl
8 | * @date 2019/06/21
9 | */
10 | public class SingletonPattern2 {}
11 |
12 | /**
13 | * 1.饿汉式:线程安全,耗费资源
14 | */
15 | class HugerSingleton1 {
16 | //该对象的引用不可修改
17 | private static final HugerSingleton1 ourInstance = new HugerSingleton1();
18 | public static HugerSingleton1 getInstance() {
19 | return ourInstance;
20 | }
21 | private HugerSingleton1() {}
22 | }
23 |
24 | /**
25 | * 2.饿汉式:在静态代码块实例对象
26 | */
27 | class HugerSingleton2 {
28 | private static HugerSingleton2 ourInstance;
29 | static {
30 | ourInstance = new HugerSingleton2();
31 | }
32 | public static HugerSingleton2 getInstance() {
33 | return ourInstance;
34 | }
35 | private HugerSingleton2() {}
36 | }
37 |
38 | /**
39 | * 3.懒汉式:非线程安全
40 | */
41 | class Singleton1 {
42 | private static Singleton1 ourInstance;
43 | public static Singleton1 getInstance() {
44 | if (null == ourInstance) {
45 | ourInstance = new Singleton1();
46 | }
47 | return ourInstance;
48 | }
49 | private Singleton1() {}
50 | }
51 |
52 | /**
53 | * 4.线程安全的懒汉式:给方法加锁
54 | */
55 | class Singleton2 {
56 | private static Singleton2 ourInstance;
57 | public synchronized static Singleton2 getInstance() {
58 | if (null == ourInstance) {
59 | ourInstance = new Singleton2();
60 | }
61 | return ourInstance;
62 | }
63 | private Singleton2() {}
64 | }
65 |
66 | /**
67 | * 5.线程安全的懒汉式:双重检查锁(同步代码块)
68 | */
69 | class Singleton3 {
70 | private static Singleton3 ourInstance;
71 | public static Singleton3 getInstance() {
72 | if (null == ourInstance) {
73 | synchronized (Singleton3.class) {
74 | if (null == ourInstance) {
75 | ourInstance = new Singleton3();
76 | }
77 | }
78 | }
79 | return ourInstance;
80 | }
81 | private Singleton3() {}
82 | }
83 |
84 | /**
85 | * 6.线程安全的懒汉式:静态内部类(推荐)
86 | */
87 | class Singleton4 {
88 | private static class SingletonHolder {
89 | private static Singleton4 ourInstance = new Singleton4();
90 | }
91 | public static Singleton4 getInstance() {
92 | return SingletonHolder.ourInstance;
93 | }
94 | private Singleton4() {
95 | }
96 | }
97 |
98 | /**
99 | * 7.线程安全的懒汉式:枚举
100 | */
101 | enum Singleton5 {
102 | INSTANCE;
103 | public void whateverMethod() {
104 | // do something
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/com/so/StackWithMin21.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Stack;
4 |
5 | /**
6 | * 第21题
7 | * 定义一个栈,在该类型中实现一个能够得到栈的最小元素的Min函数。
8 | *
9 | * @author qgl
10 | * @date 2017/08/10
11 | */
12 | public class StackWithMin21 {
13 |
14 | /**
15 | * 解法一:栈使用JDK的 Stack
16 | */
17 | static Stack stack1 = new Stack<>();
18 | static Stack stack2 = new Stack<>();
19 |
20 | public static void push(int node) {
21 | stack1.push(node);
22 | if (stack2.isEmpty()) {
23 | stack2.push(node);
24 | } else {
25 | if (stack2.peek() > node) {
26 | stack2.push(node);
27 | }
28 | }
29 | }
30 |
31 | public static void pop() {
32 | if (stack1.pop() == stack2.peek()) {
33 | stack2.pop();
34 | }
35 | }
36 |
37 | public static int top() {
38 | return stack1.peek();
39 | }
40 |
41 | public static int min() {
42 | return stack2.peek();
43 | }
44 |
45 | /**
46 | * 解法二:栈使用自定义的 MyStack
47 | */
48 | private static MyStack minStack = new MyStack<>();
49 | private static MyStack dataStack = new MyStack<>();
50 |
51 | public static void push2(Integer item) {
52 | dataStack.push(item);
53 | if (minStack.length == 0 || item <= minStack.head.data) {
54 | minStack.push(item);
55 | } else {
56 | minStack.push(minStack.head.data);
57 | }
58 | }
59 |
60 | public static Integer pop2() {
61 | if (dataStack.length == 0 || minStack.length == 0)
62 | return null;
63 | minStack.pop();
64 | return dataStack.pop();
65 | }
66 |
67 | public static Integer min2() {
68 | if (minStack.length == 0)
69 | return null;
70 | return minStack.head.data;
71 | }
72 |
73 | static class MyStack {
74 | public ListNode head;
75 | public int length;
76 |
77 | public void push(K item) {
78 | ListNode node = new ListNode();
79 | node.data = item;
80 | node.nextNode = head;
81 | head = node;
82 | length++;
83 | }
84 |
85 | public K pop() {
86 | if (head == null)
87 | return null;
88 | ListNode temp = head;
89 | head = head.nextNode;
90 | length--;
91 | return temp.data;
92 |
93 | }
94 | }
95 |
96 | static class ListNode {
97 | K data;
98 | ListNode nextNode;
99 | }
100 |
101 | }
102 |
103 |
--------------------------------------------------------------------------------
/src/main/java/com/so/StrToInt49.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第49题
5 | * 输入一个字符串,包括数字字母符号,可以为空,如果是合法的数值表达则返回该数字,否则返回0
6 | *
7 | * @author qgl
8 | * @date 2017/08/29
9 | */
10 | public class StrToInt49 {
11 |
12 | /**
13 | * 将字符串转换为整数
14 | * @param str
15 | * @return
16 | */
17 | public static int StrToInt(String str) {
18 | if (str == null || str.length() == 0) {
19 | return 0;
20 | }
21 | int mark = 0;
22 | int number = 0;
23 | char[] chars = str.toCharArray();
24 |
25 | if (chars[0] == '-') {
26 | mark = 1;
27 | }
28 |
29 | for (int i = mark; i < chars.length; i++) {
30 | if (chars[i] == '+') {
31 | continue;
32 | }
33 |
34 | if (chars[i] < 48 || chars[i] > 57) {
35 | return 0;
36 | }
37 |
38 | number = number * 10 + chars[i] - 48;
39 | }
40 | return mark == 0 ? number : -number;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/so/TreePath39.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第39题
5 | * 输入根节点求树的深度
6 | *
7 | * @author qgl
8 | * @date 2017/08/15
9 | */
10 | public class TreePath39 {
11 | static class BinaryTreeNode {
12 | int data;
13 | BinaryTreeNode leftNode;
14 | BinaryTreeNode rightNode;
15 | }
16 |
17 | /**
18 | * 获取树的深度
19 | *
20 | * @param root
21 | * @return
22 | */
23 | public static int treePath(BinaryTreeNode root) {
24 | if (root == null) {
25 | return 0;
26 | }
27 | int left = treePath(root.leftNode);
28 | int right = treePath(root.rightNode);
29 | return left > right ? (left + 1) : (right + 1);
30 | }
31 |
32 | /**
33 | * 判断输入的二叉树是不是平衡二叉树
34 | * (如果二叉树任意节点的左右子树深度相差不超过1,就是平衡的)
35 | *
36 | * @param root
37 | * @return
38 | */
39 | public static boolean isBalanced(BinaryTreeNode root) {
40 | if (root == null) {
41 | return true;
42 | }
43 | int left = treePath(root.leftNode);
44 | int right = treePath(root.rightNode);
45 | return Math.abs(left - right) <= 1;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/so/UglyNumber34.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | /**
4 | * 第34题
5 | * 求从小到大的第1500个丑数(只包含因子2,3,5的数为丑数,1是第一个丑数)
6 | *
7 | * @author qgl
8 | * @date 2017/08/15
9 | */
10 | public class UglyNumber34 {
11 |
12 | /**
13 | * 获取第n个丑数
14 | *
15 | * @param n
16 | * @return
17 | */
18 | public static int getUglyNumber(int n) {
19 | if (n <= 0) {
20 | return 0;
21 | }
22 | int[] arr = new int[n];
23 | arr[0] = 1;
24 | int multiply2 = 0;
25 | int multiply3 = 0;
26 | int multiply5 = 0;
27 |
28 | for (int i = 1; i < n; i++) {
29 | int min = Math.min(arr[multiply2] * 2, Math.min(arr[multiply3] * 3, arr[multiply5] * 5));
30 | arr[i] = min;
31 | if (arr[multiply2] * 2 == min) {
32 | multiply2++;
33 | }
34 | if (arr[multiply3] * 3 == min) {
35 | multiply3++;
36 | }
37 | if (arr[multiply5] * 5 == min) {
38 | multiply5++;
39 | }
40 | }
41 | return arr[n - 1];
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/so/VerifySequenceOfBST24.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 第24题
7 | * 输入一个数组,判断数组是不是二叉搜索树的后序遍历结果
8 | *
9 | * @author qgl
10 | * @date 2017/08/11
11 | */
12 | public class VerifySequenceOfBST24 {
13 |
14 | /**
15 | * 判断输入的数组是否是二叉搜索树的后序遍历结果
16 | * @param sequence
17 | * @return
18 | */
19 | public static boolean VerifySquenceOfBST(int[] sequence) {
20 | if (sequence == null || sequence.length == 0) {
21 | return false;
22 | }
23 |
24 | int rstart = 0;
25 | int rootIndex = sequence.length - 1;
26 | for (int i = 0; i < rootIndex; i++) {
27 | if (sequence[i] < sequence[rootIndex])
28 | rstart++;
29 | }
30 |
31 | if (rstart == 0) {
32 | VerifySquenceOfBST(Arrays.copyOfRange(sequence,0,rootIndex));
33 | return true;
34 | }
35 |
36 | for (int i = rstart; i < rootIndex; i++) {
37 | if (sequence[i] <= sequence[rootIndex]) {
38 | return false;
39 | }
40 | }
41 | VerifySquenceOfBST(Arrays.copyOfRange(sequence,0,rstart));
42 | VerifySquenceOfBST(Arrays.copyOfRange(sequence,rstart,rootIndex));
43 | return true;
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/src/main/java/com/so/ZTreePrint60.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import java.util.*;
4 |
5 | import com.so.Common.TreeNode;
6 |
7 | /**
8 | * 第60题
9 | * 之字形打印二叉树
10 | *
11 | * @author qgl
12 | * @date 2017/08/30
13 | */
14 | public class ZTreePrint60 {
15 | /**
16 | * 解法一:迭代
17 | *
18 | * @param root
19 | * @return
20 | */
21 | public static List> Print(TreeNode root) {
22 | List> res = new ArrayList<>();
23 | if (root == null) {
24 | return res;
25 | }
26 | Queue queue = new LinkedList<>();
27 | queue.add(root);
28 | int depth = 0;
29 | while (!queue.isEmpty()) {
30 | LinkedList tmp = new LinkedList<>();
31 | int size = queue.size();
32 | for (int i = 0; i < size; i++) {
33 | TreeNode node = queue.poll();
34 | if (depth % 2 == 0) {
35 | tmp.add(node.val);
36 | } else {
37 | tmp.addFirst(node.val);
38 | }
39 | if (node.left != null) {
40 | queue.add(node.left);
41 | }
42 | if (node.right != null) {
43 | queue.add(node.right);
44 | }
45 | }
46 | res.add(tmp);
47 | depth++;
48 | }
49 | return res;
50 | }
51 |
52 | /**
53 | * 解法二:递归
54 | *
55 | * @param root
56 | * @return
57 | */
58 | public List> zigzagLevelOrder(TreeNode root) {
59 | List> res = new ArrayList<>();
60 | helper(res, root, 0);
61 | return res;
62 |
63 | }
64 |
65 | private void helper(List> res, TreeNode root, int depth) {
66 | if (root == null) {
67 | return;
68 | }
69 | if (res.size() == depth) {
70 | res.add(new LinkedList<>());
71 | }
72 | if (depth % 2 == 0) {
73 | res.get(depth).add(root.val);
74 | } else {
75 | res.get(depth).add(0, root.val);
76 | }
77 | helper(res, root.left, depth + 1);
78 | helper(res, root.right, depth + 1);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test10.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第10题
7 | * 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
8 | *
9 | * @author qgl
10 | * @date 2019/02/24
11 | */
12 | public class Test10 {
13 | @Test
14 | public void test10() throws Exception {
15 | int number = 7;
16 | System.out.println(number + " 的二进制表示中1的个数:" + NumberOfBin10.numberOfBin(number));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test11.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第11题
7 | * 求base的exponent次方,不得使用库函数,不需要考虑大数问题
8 | *
9 | * @author qgl
10 | * @date 2019/02/25
11 | */
12 | public class Test11 {
13 | @Test
14 | public void test11() throws Exception {
15 | double base = 2.0;
16 | int exponent = 10;
17 | System.out.println(base + "^" + exponent + " = " + Power11.power(base, exponent));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test12.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第12题
7 | * 打印1到最大的n位数
8 | *
9 | * @author qgl
10 | * @date 2019/02/26
11 | */
12 | public class Test12 {
13 | @Test
14 | public void test12() throws Exception {
15 | int n = 3;
16 | PrintToMaxOfNDigits12.printToMaxOfNDigits(n);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test13.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第13题
7 | * 给定单向链表的头指针和一个节点,在O(1)时间删除该节点。
8 | *
9 | * @author qgl
10 | * @date 2019/02/27
11 | */
12 | public class Test13 {
13 | @Test
14 | public void test13() throws Exception {
15 | DeleteNode13.ListNode head = new DeleteNode13.ListNode();
16 | DeleteNode13.ListNode second = new DeleteNode13.ListNode();
17 | DeleteNode13.ListNode third = new DeleteNode13.ListNode();
18 | head.nextNode = second;
19 | second.nextNode = third;
20 | head.data = 1;
21 | second.data = 2;
22 | third.data = 3;
23 |
24 | // 删除链表第二个节点
25 | DeleteNode13.deleteNode(head, second);
26 |
27 | // 输出链表的值
28 | printListNode(head);
29 | }
30 |
31 | /**
32 | * 输出链表的所有值
33 | * @param head
34 | */
35 | public void printListNode(DeleteNode13.ListNode head) {
36 | DeleteNode13.ListNode tmp = head;
37 | while (tmp != null) {
38 | System.out.println(tmp.data);
39 | tmp = tmp.nextNode;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test14.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 |
7 | /**
8 | * 第14题
9 | * 输入一个整数数组,实现一个函数来调整数组中的数字的顺序,
10 | * 使得所有奇数位于数组的前半部分,偶数位于后半部分
11 | *
12 | * @author qgl
13 | * @date 2019/02/28
14 | */
15 | public class Test14 {
16 | @Test
17 | public void test14() throws Exception {
18 | OddEvenNumber14 oddEvenNumber14 = new OddEvenNumber14();
19 | int[] array = {1, 2, 3, 4, 5, 6, 7, 8};
20 | oddEvenNumber14.reOrderArray(array);
21 | System.out.println("解法一:移动偶数位置 " + Arrays.toString(array));
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test15.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.ListNode;
5 |
6 | /**
7 | * 第15题
8 | * 输入一个链表,输出该链表的倒数第K个结点
9 | *
10 | * @author qgl
11 | * @date 2019/03/01
12 | */
13 | public class Test15 {
14 | @Test
15 | public void test15() throws Exception {
16 | ListNode head = new ListNode(1);
17 | ListNode second = new ListNode(2);
18 | ListNode third = new ListNode(3);
19 | ListNode forth = new ListNode(4);
20 | head.next = second;
21 | second.next = third;
22 | third.next = forth;
23 |
24 | ListNode kthToTail = FindKthToTail15.findKthToTail(head, 5);
25 | System.out.println("解法一:" + Common.getAllListNode(kthToTail));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test16.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.ListNode;
5 |
6 | /**
7 | * 第16题 反转链表
8 | * 输入一个链表的头结点,反转该链表并输出翻转后的头结点
9 | *
10 | * @author qgl
11 | * @date 2019/03/02
12 | */
13 | public class Test16 {
14 | @Test
15 | public void test16() throws Exception {
16 | ListNode head = new ListNode(1);
17 | ListNode second = new ListNode(2);
18 | ListNode third = new ListNode(3);
19 | ListNode forth = new ListNode(4);
20 | head.next = second;
21 | second.next = third;
22 | third.next = forth;
23 |
24 | ListNode listNode = ReverseList16.reverseList1(head);
25 | System.out.println("解法一:" + Common.getAllListNode(listNode));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test17.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.ListNode;
5 |
6 | /**
7 | * 第17题
8 | * 输入两个递增的链表,合并这两个链表并使新链表仍然是递增的
9 | *
10 | * @author qgl
11 | * @date 2019/03/03
12 | */
13 | public class Test17 {
14 | @Test
15 | public void test17() throws Exception {
16 | ListNode head = new ListNode(1);
17 | ListNode second = new ListNode(3);
18 | ListNode third = new ListNode(5);
19 | ListNode forth = new ListNode(7);
20 | head.next = second;
21 | second.next = third;
22 | third.next = forth;
23 |
24 | ListNode head2 = new ListNode(2);
25 | ListNode second2 = new ListNode(4);
26 | ListNode third2= new ListNode(6);
27 | ListNode forth2 = new ListNode(8);
28 | head2.next = second2;
29 | second2.next = third2;
30 | third2.next = forth2;
31 |
32 | ListNode listNode = MergeLinked17.mergeTwoLists(head, head2);
33 | System.out.println("解法一:" + Common.getAllListNode(listNode));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test18.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.TreeNode;
4 | import org.junit.Test;
5 |
6 | /**
7 | * 第18题
8 | * 判断二叉树A中是否包含子树B
9 | *
10 | * @author qgl
11 | * @date 2019/03/04
12 | */
13 | public class Test18 {
14 | @Test
15 | public void test18() throws Exception {
16 | TreeNode root1 = new TreeNode(3);
17 | TreeNode node1 = new TreeNode(4);
18 | TreeNode node2 = new TreeNode(5);
19 | TreeNode node3 = new TreeNode(1);
20 | TreeNode node4 = new TreeNode(2);
21 | TreeNode node5 = new TreeNode(0);
22 | TreeNode node6 = new TreeNode(0);
23 | root1.left = node1;
24 | root1.right = node2;
25 | node1.left = node3;
26 | node1.right = node4;
27 | node4.left = node5;
28 | node4.right = node6;
29 |
30 | TreeNode root2 = new TreeNode(4);
31 | TreeNode a = new TreeNode(1);
32 | TreeNode b = new TreeNode(2);
33 | root2.left = a;
34 | root2.right = b;
35 |
36 | System.out.println("是否包含 " + DoesTreeHave18.hasSubTree(root1, root2));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test19.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第19题
8 | * 输入一个二叉树,输出它的镜像
9 | *
10 | * @author qgl
11 | * @date 2019/03/05
12 | */
13 | public class Test19 {
14 | @Test
15 | public void test19() throws Exception {
16 | TreeNode root = new TreeNode(8);
17 | TreeNode node1 = new TreeNode(5);
18 | TreeNode node2 = new TreeNode(7);
19 | TreeNode node3 = new TreeNode(9);
20 | TreeNode node4 = new TreeNode(2);
21 | TreeNode node5 = new TreeNode(4);
22 | TreeNode node6 = new TreeNode(1);
23 | root.left = node1;
24 | root.right = node2;
25 | node1.left = node3;
26 | node1.right = node4;
27 | node4.left = node5;
28 | node4.right = node6;
29 | /*
30 | 原二叉树 二叉树的镜像
31 | 8 8
32 | / \ / \
33 | 5 7 7 5
34 | / \ / \
35 | 9 2 2 9
36 | / \ / \
37 | 4 1 1 4
38 | */
39 |
40 | System.out.println("原二叉树的根节点的右子树 = " + root.right.val);
41 | MirrorRecursively19 mirror = new MirrorRecursively19();
42 | mirror.Mirror(root);
43 | System.out.println("解法一:递归,二叉树的镜像 根节点的右子树 = " + root.right.val);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test2.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第2题 单例设计模式
7 | * 设计一个类,只能生成该类的一个实例。
8 | *
9 | * @author qgl
10 | * @date 2019/06/22
11 | */
12 | public class Test2 {
13 | @Test
14 | public void test2() {
15 | Singleton1 singleton = Singleton1.getInstance();
16 | Singleton1 singleton2 = Singleton1.getInstance();
17 | System.out.println("使用单例模式获取对象,是否是同一个实例:" + singleton.equals(singleton2));
18 | // Singleton1 singleton3 = new Singleton1();
19 | // System.out.println("使用new创建对象,是否是同一个实例:" + singleton.equals(singleton3));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test20.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第20题
7 | * 顺时针打印矩阵
8 | *
9 | * @author qgl
10 | * @date 2019/03/06
11 | */
12 | public class Test20 {
13 | @Test
14 | public void test20() throws Exception {
15 | int[][] array = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
16 | System.out.println("顺时针输出矩阵:" + PrintMatrixInCircle20.printMatrix(array));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test21.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第21题
7 | * 定义一个栈,在该类型中实现一个能够得到栈的最小元素的Min函数。
8 | *
9 | * @author qgl
10 | * @date 2019/03/07
11 | */
12 | public class Test21 {
13 | @Test
14 | public void test21() throws Exception {
15 | StackWithMin21.push(3);
16 | StackWithMin21.push(1);
17 | StackWithMin21.push(4);
18 | StackWithMin21.push(9);
19 | System.out.println("解法一,使用JDK的 Stack 栈,最小值:" + StackWithMin21.min());
20 |
21 | StackWithMin21.push2(3);
22 | StackWithMin21.push2(1);
23 | StackWithMin21.push2(4);
24 | StackWithMin21.push2(9);
25 | System.out.println("解法二,自定义的 MyStack 栈,最小值:" + StackWithMin21.min2());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test22.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第22题
7 | * 输入两个整数序列,第一个序列表示压入顺序,判断第二个序列是否为弹出顺序
8 | *
9 | * @author qgl
10 | * @date 2019/03/08
11 | */
12 | public class Test22 {
13 | @Test
14 | public void test22() throws Exception {
15 | int[] pushList = {1, 2, 3, 4, 5};
16 | int[] popList = {4, 3, 5, 2, 1};
17 |
18 | System.out.println("是否是弹出顺序:" + IsPopOrder22.isPopOrder(pushList, popList));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test23.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第23题
8 | * 层序遍历二叉树
9 | *
10 | * @author qgl
11 | * @date 2019/03/09
12 | */
13 | public class Test23 {
14 | @Test
15 | public void test23() throws Exception {
16 | TreeNode root = new TreeNode(8);
17 | TreeNode node1 = new TreeNode(9);
18 | TreeNode node2 = new TreeNode(7);
19 | TreeNode node3 = new TreeNode(10);
20 | TreeNode node4 = new TreeNode(2);
21 | TreeNode node5 = new TreeNode(4);
22 | TreeNode node6 = new TreeNode(1);
23 | root.left = node1;
24 | root.right = node2;
25 | node1.left = node3;
26 | node1.right = node4;
27 | node4.left = node5;
28 | node4.right = node6;
29 |
30 | /*
31 | 原二叉树
32 | 8
33 | / \
34 | 9 7
35 | / \
36 | 10 2
37 | / \
38 | 4 1
39 | */
40 |
41 | PrintFromTopToBottom23 printFromTopToBottom23 = new PrintFromTopToBottom23();
42 | System.out.print("层序输出的二叉树:" + printFromTopToBottom23.PrintFromTopToBottom(root));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test24.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第24题
7 | * 输入一个数组,判断数组是不是二叉搜索树的后序遍历结果
8 | *
9 | * @author qgl
10 | * @date 2019/03/10
11 | */
12 | public class Test24 {
13 | @Test
14 | public void test24() throws Exception {
15 | int[] array = {4, 8, 6, 12, 16, 14, 10};
16 | System.out.println("结果:" + VerifySequenceOfBST24.VerifySquenceOfBST(array));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test25.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第25题
8 | * 输入一个二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径
9 | *
10 | * @author qgl
11 | * @date 2019/03/11
12 | */
13 | public class Test25 {
14 | @Test
15 | public void test25() throws Exception {
16 | TreeNode root = new TreeNode(8);
17 | TreeNode node1 = new TreeNode(9);
18 | TreeNode node2 = new TreeNode(7);
19 | TreeNode node3 = new TreeNode(10);
20 | TreeNode node4 = new TreeNode(2);
21 | TreeNode node5 = new TreeNode(4);
22 | TreeNode node6 = new TreeNode(1);
23 | root.left = node1;
24 | root.right = node2;
25 | node1.left = node3;
26 | node1.right = node4;
27 | node4.left = node5;
28 | node4.right = node6;
29 |
30 | FindPath25 findPath25 = new FindPath25();
31 | System.out.println("所有路径:" + findPath25.FindPath(root, 20));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test26.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第26题
7 | * 复制一个复杂链表
8 | *
9 | * @author qgl
10 | * @date 2019/03/12
11 | */
12 | public class Test26 {
13 | @Test
14 | public void test26() throws Exception {
15 | CloneCLinkedList26.RandomListNode root = new CloneCLinkedList26.RandomListNode(1);
16 | CloneCLinkedList26.RandomListNode node1 = new CloneCLinkedList26.RandomListNode(2);
17 | CloneCLinkedList26.RandomListNode node2 = new CloneCLinkedList26.RandomListNode(3);
18 | CloneCLinkedList26.RandomListNode node3 = new CloneCLinkedList26.RandomListNode(4);
19 | CloneCLinkedList26.RandomListNode node4 = new CloneCLinkedList26.RandomListNode(5);
20 | node1.next = node2;
21 | node2.next = node3;
22 | node3.next = node4;
23 | root.random = node1;
24 | node1.random = root;
25 | node3.random = node1;
26 |
27 | System.out.println("解法一:" + CloneCLinkedList26.Clone1(root).label);
28 | System.out.println("解法二:" + CloneCLinkedList26.Clone2(root).label);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test27.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第27题
7 | * 将二叉搜索树转换成一个排序的双向链表
8 | *
9 | * @author qgl
10 | * @date 2019/03/13
11 | */
12 | public class Test27 {
13 | @Test
14 | public void test27() throws Exception {
15 | BinaryToLinked27.BinaryTreeNode root1 = new BinaryToLinked27.BinaryTreeNode();
16 | BinaryToLinked27.BinaryTreeNode node1 = new BinaryToLinked27.BinaryTreeNode();
17 | BinaryToLinked27.BinaryTreeNode node2 = new BinaryToLinked27.BinaryTreeNode();
18 | BinaryToLinked27.BinaryTreeNode node3 = new BinaryToLinked27.BinaryTreeNode();
19 | BinaryToLinked27.BinaryTreeNode node4 = new BinaryToLinked27.BinaryTreeNode();
20 | BinaryToLinked27.BinaryTreeNode node5 = new BinaryToLinked27.BinaryTreeNode();
21 | BinaryToLinked27.BinaryTreeNode node6 = new BinaryToLinked27.BinaryTreeNode();
22 | root1.leftNode = node1;
23 | root1.rightNode = node2;
24 | node1.leftNode = node3;
25 | node1.rightNode = node4;
26 | node4.leftNode = node5;
27 | node4.rightNode = node6;
28 | root1.data = 8;
29 | node1.data = 9;
30 | node2.data = 7;
31 | node3.data = 10;
32 | node4.data = 2;
33 | node5.data = 4;
34 | node6.data = 1;
35 |
36 | BinaryToLinked27.convert(root1);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test28.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第28题
7 | * 输入一个字符串,打印出字符串中字符的所有排列
8 | *
9 | * @author qgl
10 | * @date 2019/03/14
11 | */
12 | public class Test28 {
13 | @Test
14 | public void test28() throws Exception {
15 | String testStr = "try";
16 | System.out.println("解法一:while循环,结果:" + Permutation28.permutation1(testStr));
17 | System.out.println("解法二:递归,结果:" + Permutation28.Permutation(testStr));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test29.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第29题
7 | * 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字
8 | *
9 | * @author qgl
10 | * @date 2019/03/15
11 | */
12 | public class Test29 {
13 | @Test
14 | public void test29() throws Exception {
15 | int[] array = {1, 2, 3, 4, 5, 4, 5, 5, 5, 6, 7, 5, 5, 5};
16 | System.out.println("数组中出现次数超过数组长度一半的数字是:" + MoreThanHalfNum29.moreThanHalfNum(array));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test3.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第3题
7 | * 一个二维数组,每一行从左到右递增,每一列从上到下递增.
8 | * 输入一个二维数组和一个整数,判断数组中是否含有整数
9 | *
10 | * @author qgl
11 | * @date 2019/02/17
12 | */
13 | public class Test3 {
14 | @Test
15 | public void test3() {
16 | int[][] testArray = {{1, 7, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
17 | int target = 6;
18 | System.out.println("解法一:两个指针,数组中是否含有" + target + " :" + FindNumber3.find(testArray, target));
19 | System.out.println("解法二:二分法,数组中是否含有" + target + " :" + FindNumber3.find(testArray, target));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test30.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 |
7 | /**
8 | * 第30题
9 | * 输入N个整数,找出其中最小的k个数
10 | *
11 | * @author qgl
12 | * @date 2019/03/16
13 | */
14 | public class Test30 {
15 | @Test
16 | public void test30() throws Exception {
17 | int[] array = {4, 5, 1, 6, 2, 7, 3, 2};
18 | int k = 3;
19 | System.out.println("最小的" + k + "个数是:" + GetLeastNumbers30.getLeastNumbers(array, k));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test31.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 |
7 | /**
8 | * 第31题
9 | * 数组中一个或连续的多个整数组成一个子数组,求连续子数组的最大和
10 | *
11 | * @author qgl
12 | * @date 2019/03/17
13 | */
14 | public class Test31 {
15 | @Test
16 | public void test30() throws Exception {
17 | int[] array = {1, -2, 3, 10, -4, 7, 2, -5};
18 | System.out.println("连续子数组的最大和是:" + FindGreatestSum31.findGreatestSum(array));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test32.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第32题
7 | * 输入一个整数n,求从1到n这N个十进制表示中1出现的次数
8 | *
9 | * @author qgl
10 | * @date 2019/03/18
11 | */
12 | public class Test32 {
13 | @Test
14 | public void test32() throws Exception {
15 | System.out.println("解法一,1出现的次数:" + NumberOf1Bw32.NumberOf1Between1AndN1(13));
16 | System.out.println("解法二,1出现的次数:" + NumberOf1Bw32.NumberOf1Between1AndN2(13));
17 | System.out.println("解法三,1出现的次数:" + NumberOf1Bw32.NumberOf1Between1AndN3(13));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test33.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第33题
7 | * 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印出能拼接出的所有数字中的最小的一个。
8 | *
9 | * @author qgl
10 | * @date 2019/03/19
11 | */
12 | public class Test33 {
13 | @Test
14 | public void test32() throws Exception {
15 | int[] array = {3, 19, 32, 5, 26};
16 | System.out.println("解法一,自定义快排:" + PrintMinNumber33.printMinNumber1(array));
17 | System.out.println("解法二,JDK的归排:" + PrintMinNumber33.printMinNumber2(array));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test34.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第34题
7 | * 求从小到大的第1500个丑数(只包含因子2,3,5的数为丑数,1是第一个丑数)
8 | *
9 | * @author qgl
10 | * @date 2019/03/20
11 | */
12 | public class Test34 {
13 | @Test
14 | public void test34() throws Exception {
15 | int num = 100;
16 | System.out.println("第 " + num + " 个丑数是 " + UglyNumber34.getUglyNumber(num));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test35.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第35题
7 | * 在字符串中找出第一个只出现一次的字符
8 | *
9 | * @author qgl
10 | * @date 2019/03/21
11 | */
12 | public class Test35 {
13 | @Test
14 | public void test35() throws Exception {
15 | String str = "abdbatccdeff";
16 | System.out.println("第一个只出现一次的字符的下标是:" + FirstNotRepeating35.getFirstNotRepeatingCharIndex(str));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test36.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第36题
7 | * 数组中的两个数字如果前面一个数字大于后面一个数字,
8 | * 则这两个数字组成一个逆序对,输入一个数组,求逆序对的总数
9 | *
10 | * @author qgl
11 | * @date 2019/03/22
12 | */
13 | public class Test36 {
14 | @Test
15 | public void test36() throws Exception {
16 | int[] array = {1, 2, 3, 4, 5, 6, 7, 0};
17 | int[] array2 = {364, 637, 341, 406, 747, 995, 234, 971, 571, 219, 993, 407, 416, 366, 315, 301, 601, 650, 418, 355, 460, 505, 360, 965, 516, 648, 727, 667, 465, 849, 455, 181, 486, 149, 588, 233, 144, 174, 557, 67, 746, 550, 474, 162, 268, 142, 463, 221, 882, 576, 604, 739, 288, 569, 256, 936, 275, 401, 497, 82, 935, 983, 583, 523, 697, 478, 147, 795, 380, 973, 958, 115, 773, 870, 259, 655, 446, 863, 735, 784, 3, 671, 433, 630, 425, 930, 64, 266, 235, 187, 284, 665, 874, 80, 45, 848, 38, 811, 267, 575};
18 | System.out.println("逆序对总数:" + InversePairs36.inversePairs(array));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test37.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第37题
7 | * 求两个单向链表的第一个公共节点
8 | *
9 | * @author qgl
10 | * @date 2019/03/23
11 | */
12 | public class Test37 {
13 | @Test
14 | public void test37() throws Exception {
15 | FindFirstCommonNode37.ListNode head1 = new FindFirstCommonNode37.ListNode(1);
16 | FindFirstCommonNode37.ListNode second1 = new FindFirstCommonNode37.ListNode(2);
17 | FindFirstCommonNode37.ListNode third1 = new FindFirstCommonNode37.ListNode(3);
18 | FindFirstCommonNode37.ListNode forth1 = new FindFirstCommonNode37.ListNode(6);
19 | FindFirstCommonNode37.ListNode fifth1 = new FindFirstCommonNode37.ListNode(7);
20 | FindFirstCommonNode37.ListNode head2 = new FindFirstCommonNode37.ListNode(1);
21 | FindFirstCommonNode37.ListNode second2 = new FindFirstCommonNode37.ListNode(5);
22 | FindFirstCommonNode37.ListNode third2 = new FindFirstCommonNode37.ListNode(6);
23 | FindFirstCommonNode37.ListNode forth2 = new FindFirstCommonNode37.ListNode(8);
24 | head1.next = second1;
25 | second1.next = third1;
26 | third1.next = forth1;
27 | forth1.next = fifth1;
28 | head2.next = second2;
29 | second2.next = forth1;
30 | third2.next = forth2;
31 |
32 | System.out.println("解法一:第一个公共节点是:" + FindFirstCommonNode37.findFirstCommonNode1(head1, head2).val);
33 | System.out.println("解法二:第一个公共节点是:" + FindFirstCommonNode37.findFirstCommonNode2(head1, head2).val);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test38.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第38题
7 | * 统计一个数字在排序数组中出现的次数
8 | *
9 | * @author qgl
10 | * @date 2019/03/24
11 | */
12 | public class Test38 {
13 | @Test
14 | public void test38() throws Exception {
15 | int[] testArray = {1, 3, 3, 6, 7, 8, 8, 8, 8, 9};
16 | int num = 8;
17 | System.out.println("解法一:" + num + " 在排序数组中出现的次数:" + GetNumberOfK38.getNumberOfK(testArray, num));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test39.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第39题
7 | * 输入根节点求树的深度
8 | *
9 | * @author qgl
10 | * @date 2019/03/25
11 | */
12 | public class Test39 {
13 | @Test
14 | public void test39() throws Exception {
15 | TreePath39.BinaryTreeNode root1 = new TreePath39.BinaryTreeNode();
16 | TreePath39.BinaryTreeNode node1 = new TreePath39.BinaryTreeNode();
17 | TreePath39.BinaryTreeNode node2 = new TreePath39.BinaryTreeNode();
18 | TreePath39.BinaryTreeNode node3 = new TreePath39.BinaryTreeNode();
19 | TreePath39.BinaryTreeNode node4 = new TreePath39.BinaryTreeNode();
20 | TreePath39.BinaryTreeNode node5 = new TreePath39.BinaryTreeNode();
21 | TreePath39.BinaryTreeNode node6 = new TreePath39.BinaryTreeNode();
22 | root1.leftNode = node1;
23 | root1.rightNode = node2;
24 | node1.leftNode = node3;
25 | node1.rightNode = node4;
26 | node4.leftNode = node5;
27 | node4.rightNode = node6;
28 | root1.data = 8;
29 | node1.data = 9;
30 | node2.data = 7;
31 | node3.data = 10;
32 | node4.data = 2;
33 | node5.data = 4;
34 | node6.data = 1;
35 |
36 | /*
37 | 二叉树
38 | 8
39 | / \
40 | 9 7
41 | / \
42 | 10 2
43 | / \
44 | 4 1
45 | */
46 |
47 | System.out.println("树的深度:" + TreePath39.treePath(root1));
48 | System.out.println("是否是平衡二叉树:" + TreePath39.isBalanced(root1));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test4.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第4题
7 | * 将一个字符串中的空格替换成"%20"
8 | *
9 | * @author qgl
10 | * @date 2019/02/18
11 | */
12 | public class Test4 {
13 | @Test
14 | public void test4() {
15 | String beforeStr = " ab g gt r ";
16 | System.out.println("解法一:使用StringBuffer, 替换前:" + beforeStr + " 替换后:" + ReplaceBlank4.replaceBlank1(beforeStr));
17 | System.out.println("解法二:使用StringBuilder,替换前:" + beforeStr + " 替换后:" + ReplaceBlank4.replaceBlank2(beforeStr));
18 | System.out.println("解法三:从后往前复制, 替换前:" + beforeStr + " 替换后:" + ReplaceBlank4.replaceBlank3(beforeStr));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test40.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 |
7 | /**
8 | * 第40题
9 | * 一个整型数组里除了两个数字之外,其他的数字都出现了两次,找出这两个只出现了一次的数字
10 | *
11 | * @author qgl
12 | * @date 2019/03/26
13 | */
14 | public class Test40 {
15 | @Test
16 | public void test40() throws Exception {
17 | int[] array = {4, 6, 7, 4, 9, 8, 6, 8};
18 | System.out.println("只出现了一次的数字:" + Arrays.toString(FindNumAppearOnce40.findNumAppearOnce(array)));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test41.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第41题
7 | * 输入一个递增排序的数组和一个数字s.在数组中查找两个数使他们的和为s,如果有多对数字的和等于s,输出两个数的乘积最小的一对
8 | *
9 | * @author qgl
10 | * @date 2019/03/27
11 | */
12 | public class Test41 {
13 | @Test
14 | public void test41() throws Exception {
15 | int[] array = {1, 2, 4, 6, 7, 8, 12, 15};
16 | int s = 10;
17 | System.out.println("和为s的两个数:" + FindNumbersWithSum41.findNumbersWithSum(array, s));
18 | System.out.println("所有和为s的连续正数序列:" + FindNumbersWithSum41.findContinuousSequence(s));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test42.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第42题
7 | * 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变
8 | *
9 | * @author qgl
10 | * @date 2019/03/28
11 | */
12 | public class Test42 {
13 | @Test
14 | public void test42() throws Exception {
15 | String str = "you maybe became a stronger";
16 | System.out.println("翻转句子的单词顺序:" + ReverseSentence42.reverseSentence(str));
17 |
18 | String rotationStr = "a pen I have ";
19 | System.out.println("字符串的左旋:" + ReverseSentence42.leftRotateString(rotationStr,5));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test43.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第43题
7 | * 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s,输入n,打印出s的所有可能出现的概率
8 | *
9 | * @author qgl
10 | * @date 2019/03/29
11 | */
12 | public class Test43 {
13 | @Test
14 | public void test43() throws Exception {
15 | int diceNum = 2;
16 | System.out.println("所有可能出现的概率:" + DicesProbability43.printProbability(diceNum));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test44.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第44题
7 | * 判断扑克牌中的顺子,0表示大小王(可以是任意数)
8 | * 1表示A,2~10为本身,11表示J,12表示Q,13表示K
9 | *
10 | * @author qgl
11 | * @date 2019/03/30
12 | */
13 | public class Test44 {
14 | @Test
15 | public void test44() throws Exception {
16 | int[] array = {2, 6, 4, 5, 0};
17 | System.out.println("是否是顺子:" + IsContinuous44.isContinuous(array));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test45.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第45题
7 | * 0,1...n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字.
8 | * 求这个圈圈里剩下的最后一个数字
9 | *
10 | * @author qgl
11 | * @date 2019/03/31
12 | */
13 | public class Test45 {
14 | @Test
15 | public void test45() throws Exception {
16 | int n = 7;
17 | int m = 2;
18 | System.out.println("解法一,借助链表,圈圈里剩下的最后一个数字:" + LastRemaining45.lastRemain1(n,m));
19 | System.out.println("解法二,公式法,圈圈里剩下的最后一个数字:" + LastRemaining45.lastRemain2(n,m));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test46.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第46题
7 | * 求1+2+...+n,不能使用乘除法,循环等
8 | *
9 | * @author qgl
10 | * @date 2019/04/01
11 | */
12 | public class Test46 {
13 | @Test
14 | public void test46() throws Exception {
15 | int n = 10;
16 | System.out.println("解法一,利用递归,求1 + ...+ " + n + " 的和:" + Calculate46.sum(n));
17 | System.out.println("解法二,利用递归和全局变量,求1 + ...+ " + n + " 的和:" + Calculate46.sum2(n));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test47.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第47题
7 | * 不用加减乘除做加法
8 | *
9 | * @author qgl
10 | * @date 2019/04/02
11 | */
12 | public class Test47 {
13 | @Test
14 | public void test47() throws Exception {
15 | int num1 = 5;
16 | int num2 = 11;
17 | System.out.println("求和:" + num1 + " + " + num2 + " = " + Add47.add(num1, num2));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test48.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第48题
7 | * 不能被继承的类
8 | *
9 | * @author qgl
10 | * @date 2019/04/03
11 | */
12 | public class Test48 {
13 | /**
14 | * 继承FinalClass48类会报错
15 | */
16 | // class TestClass48 extends FinalClass48{}
17 |
18 | @Test
19 | public void test48() throws Exception {
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test49.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第49题
7 | * 将一个字符串转换成一个整数。数值为0或者字符串不是一个合法的数值则返回0
8 | *
9 | * @author qgl
10 | * @date 2019/04/04
11 | */
12 | public class Test49 {
13 |
14 | @Test
15 | public void test49() throws Exception {
16 | String str = "+015303";
17 | String str2 = "p015c303";
18 | System.out.println("字符串转换为整数:" + StrToInt49.StrToInt(str));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test5.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.ListNode;
4 | import org.junit.Test;
5 |
6 | /**
7 | * 第5题 从尾到头打印链表
8 | * 输入一个链表,从尾到头打印链表每个节点的值
9 | *
10 | * @author qgl
11 | * @date 2019/02/19
12 | */
13 | public class Test5 {
14 | @Test
15 | public void test5() {
16 | ListNode node1 = new ListNode(3);
17 | ListNode node2 = new ListNode(6);
18 | ListNode node3 = new ListNode(9);
19 | node1.next = node2;
20 | node2.next = node3;
21 | System.out.println("解法一:利用栈输出,反转后:" + PrintListReversing5.printListReverse1(node1));
22 | System.out.println("解法二:递归,反转后:" + PrintListReversing5.printListReverse2(node1));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test50.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import static com.so.MinCParent50.*;
6 |
7 | /**
8 | * 第50题
9 | * 寻找树的两个节点的最低公共祖先
10 | *
11 | * @author qgl
12 | * @date 2019/04/06
13 | */
14 | public class Test50 {
15 |
16 | @Test
17 | public void test50() throws Exception {
18 | MinCParent50.BinaryTreeNode A = new MinCParent50.BinaryTreeNode(4);
19 | MinCParent50.BinaryTreeNode B = new MinCParent50.BinaryTreeNode(2);
20 | MinCParent50.BinaryTreeNode C = new MinCParent50.BinaryTreeNode(6);
21 | MinCParent50.BinaryTreeNode D = new MinCParent50.BinaryTreeNode(1);
22 | MinCParent50.BinaryTreeNode E = new MinCParent50.BinaryTreeNode(3);
23 | MinCParent50.BinaryTreeNode F = new MinCParent50.BinaryTreeNode(5);
24 | MinCParent50.BinaryTreeNode G = new MinCParent50.BinaryTreeNode(7);
25 | A.leftNode = B;
26 | A.rightNode = C;
27 | B.leftNode = D;
28 | B.rightNode = E;
29 | C.leftNode = F;
30 | C.rightNode = G;
31 |
32 | MinCParent50.BinaryTreeNode res1 = getLowestCommonAncestor1(null, A, D, E);
33 | MinCParent50.BinaryTreeNode res2 = getLowestCommonAncestor2(A, E, F);
34 | System.out.println("1 和 3 的最低公共祖先是:" + res1.value);
35 | System.out.println("3 和 5 的最低公共祖先是:" + res2.value);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test51.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import static com.so.MinCParent50.*;
6 |
7 | /**
8 | * 第51题
9 | * 在一个长度为n的数组里的所有数字都在0到n-1的范围内,找出数组中任意一个重复的数字
10 | *
11 | * @author qgl
12 | * @date 2019/04/07
13 | */
14 | public class Test51 {
15 |
16 | @Test
17 | public void test51() throws Exception {
18 | int[] arr = {6, 5, 3, 5, 2, 1, 5};
19 | System.out.println("解法三,快慢指针:" + Duplicate51.duplicate3(arr));
20 | System.out.println("解法二,利用HashSet:" + Duplicate51.duplicate2(arr));
21 | System.out.println("解法一,利用数组的特点:" + Duplicate51.duplicate1(arr));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test52.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 |
7 | /**
8 | * 第52题
9 | * 构建乘积数组
10 | *
11 | * @author qgl
12 | * @date 2019/04/08
13 | */
14 | public class Test52 {
15 |
16 | @Test
17 | public void test52() throws Exception {
18 | int[] arr = {2, 3, 4, 5};
19 | System.out.println("乘积数组:" + Arrays.toString(MultiplyArray52.multiply(arr)));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test53.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 |
7 | /**
8 | * 第53题
9 | * 正则表达式匹配字符串,实现一个函数用来匹配包括'.'和'*'的正则表达式
10 | * 其中'*'表示它前面的字符可以出现任意次(包含0次)
11 | *
12 | * @author qgl
13 | * @date 2019/04/09
14 | */
15 | public class Test53 {
16 |
17 | @Test
18 | public void test53() throws Exception {
19 | String str = "aaa";
20 | String pattern = "a.a";
21 | System.out.println("是否匹配:" + RegularMatch53.match(str.toCharArray(),pattern.toCharArray()));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test54.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | /**
7 | * 第54题
8 | * 判断字符串是否表示数值(包括整数和小数)
9 | *
10 | * @author qgl
11 | * @date 2019/04/10
12 | */
13 | public class Test54 {
14 |
15 | @Test
16 | public void test54() throws Exception {
17 | String str = "3011o63l";
18 | String str2 = "123.45e+6";
19 | System.out.println("解法一:逐个字符进行判断 是否表示数值:" + IsNumber54.isNumber1(str.toCharArray()));
20 | System.out.println("解法二:用正则表达式判断 是否表示数值:" + IsNumber54.isNumber2(str.toCharArray()));
21 |
22 | // Assert.assertTrue(IsNumber54.isNumber1(str.toCharArray()));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test55.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第55题
7 | * 请实现一个函数用来找出字符流中第一个只出现一次的字符
8 | *
9 | * @author qgl
10 | * @date 2019/04/11
11 | */
12 | public class Test55 {
13 |
14 | @Test
15 | public void test55() throws Exception {
16 | String str = "3A15t63e";
17 | String str2 = "3A61e5A613e5";
18 | FirstAppearingOnce55.insertChars(str.toCharArray());
19 | System.out.println("字符流中第一个只出现一次的字符是:" + FirstAppearingOnce55.getFirstAppearingOnce());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test56.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第56题
7 | * 找出环链表的入口结点
8 | *
9 | * @author qgl
10 | * @date 2019/04/12
11 | */
12 | public class Test56 {
13 |
14 | @Test
15 | public void test56() throws Exception {
16 | EnterLoop56.ListNode root = new EnterLoop56.ListNode(6);
17 | EnterLoop56.ListNode first = new EnterLoop56.ListNode(1);
18 | EnterLoop56.ListNode second = new EnterLoop56.ListNode(2);
19 | EnterLoop56.ListNode three = new EnterLoop56.ListNode(3);
20 | EnterLoop56.ListNode four = new EnterLoop56.ListNode(4);
21 | root.next = first;
22 | first.next = second;
23 | second.next = three;
24 | three.next = four;
25 | four.next = root;
26 |
27 | System.out.println("环链表的入口结点:" + EnterLoop56.enterNodeOfLoop(root).val);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test57.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第57题
7 | * 删除链表的重复节点
8 | *
9 | * @author qgl
10 | * @date 2019/04/13
11 | */
12 | public class Test57 {
13 |
14 | @Test
15 | public void test57() throws Exception {
16 | DeleteDuplication57.ListNode head = new DeleteDuplication57.ListNode(6);
17 | DeleteDuplication57.ListNode first = new DeleteDuplication57.ListNode(1);
18 | DeleteDuplication57.ListNode second = new DeleteDuplication57.ListNode(3);
19 | DeleteDuplication57.ListNode three = new DeleteDuplication57.ListNode(3);
20 | DeleteDuplication57.ListNode four = new DeleteDuplication57.ListNode(5);
21 | head.next = first;
22 | first.next = second;
23 | second.next = three;
24 | three.next = four;
25 |
26 | System.out.println("原链表:" + printfListNode(head));
27 | System.out.println("删除链表的重复节点后:" + printfListNode(DeleteDuplication57.deleteDuplication(head)));
28 | }
29 |
30 | /**
31 | * 打印链表
32 | * @param head
33 | * @return
34 | */
35 | public String printfListNode(DeleteDuplication57.ListNode head) {
36 | StringBuilder sb = new StringBuilder();
37 | while (head != null) {
38 | sb.append(head.val).append("→");
39 | head = head.next;
40 | }
41 | return sb.toString().substring(0, sb.length() - 1);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test58.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第58题
7 | * 给定一个二叉树的某个结点,请找出中序遍历顺序的下一个结点并且返回
8 | *
9 | * @author qgl
10 | * @date 2019/04/14
11 | */
12 | public class Test58 {
13 |
14 | @Test
15 | public void test58() throws Exception {
16 | NextTreeNode58.TreeLinkNode root = new NextTreeNode58.TreeLinkNode(4);
17 | NextTreeNode58.TreeLinkNode first = new NextTreeNode58.TreeLinkNode(2);
18 | NextTreeNode58.TreeLinkNode second = new NextTreeNode58.TreeLinkNode(6);
19 | NextTreeNode58.TreeLinkNode three = new NextTreeNode58.TreeLinkNode(1);
20 | NextTreeNode58.TreeLinkNode four = new NextTreeNode58.TreeLinkNode(3);
21 | root.left = first;
22 | root.right = second;
23 | first.left = three;
24 | first.right = four;
25 |
26 | System.out.println("输入节点的下一个节点值:" + NextTreeNode58.getTreeLinkNextNode(first).val);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test59.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第59题
8 | * 判断二叉树是否是对称的
9 | *
10 | * @author qgl
11 | * @date 2019/04/15
12 | */
13 | public class Test59 {
14 |
15 | @Test
16 | public void test59() throws Exception {
17 | TreeNode root = new TreeNode(8);
18 | TreeNode node1 = new TreeNode(5);
19 | TreeNode node2 = new TreeNode(5);
20 | TreeNode node3 = new TreeNode(9);
21 | TreeNode node4 = new TreeNode(2);
22 | TreeNode node5 = new TreeNode(2);
23 | TreeNode node6 = new TreeNode(9);
24 | root.left = node1;
25 | root.right = node2;
26 | node1.left = node3;
27 | node1.right = node4;
28 | node2.left = node5;
29 | node2.right = node6;
30 |
31 | System.out.println("二叉树是否对称:" + IsSymmetrical59.isSymmetrical(root));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test6.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第6题
8 | * 输入二叉树的前序遍历和中序遍历结果,重建该二叉树.
9 | *
10 | * @author qgl
11 | * @date 2019/02/20
12 | */
13 | public class Test6 {
14 | @Test
15 | public void test6() {
16 | // 前序遍历结果
17 | int[] pre = {1, 2, 4, 7, 3, 5, 6, 8};
18 | // 中序遍历结果
19 | int[] in = {4, 7, 2, 1, 5, 3, 8, 6};
20 | TreeNode root = BinaryTreeSearch6.reConstructBinaryTree(pre, in);
21 | System.out.print("重建后的二叉树(层序输出):" + new PrintFromTopToBottom23().PrintFromTopToBottom(root));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test60.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第60题
8 | * 之字形打印二叉树
9 | *
10 | * @author qgl
11 | * @date 2019/04/16
12 | */
13 | public class Test60 {
14 |
15 | @Test
16 | public void test60() throws Exception {
17 | TreeNode root = new TreeNode(7);
18 | TreeNode node1 = new TreeNode(5);
19 | TreeNode node2 = new TreeNode(8);
20 | TreeNode node3 = new TreeNode(3);
21 | TreeNode node4 = new TreeNode(6);
22 | TreeNode node5 = new TreeNode(9);
23 | TreeNode node6 = new TreeNode(11);
24 | root.left = node1;
25 | root.right = node2;
26 | node1.left = node3;
27 | node1.right = node4;
28 | node2.left = node5;
29 | node2.right = node6;
30 |
31 | System.out.println("之字形打印二叉树:" + ZTreePrint60.Print(root));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test61.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 | import com.so.Common.TreeNode;
5 |
6 | /**
7 | * 第61题
8 | * 把二叉树打印成多行,从上到下按层打印二叉树,同一层结点从左至右输出。
9 | *
10 | * @author qgl
11 | * @date 2019/04/17
12 | */
13 | public class Test61 {
14 |
15 | @Test
16 | public void test61() throws Exception {
17 | TreeNode root = new TreeNode(7);
18 | TreeNode node1 = new TreeNode(5);
19 | TreeNode node2 = new TreeNode(8);
20 | TreeNode node3 = new TreeNode(3);
21 | TreeNode node4 = new TreeNode(6);
22 | TreeNode node5 = new TreeNode(9);
23 | TreeNode node6 = new TreeNode(11);
24 | root.left = node1;
25 | root.right = node2;
26 | node1.left = node3;
27 | node1.right = node4;
28 | node2.left = node5;
29 | node2.right = node6;
30 |
31 | System.out.println("从左至右打印每行二叉树:" + LevelPrintTree61.printTreeNodeByLeftToRight(root));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test62.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.TreeNode;
4 | import org.junit.Test;
5 |
6 | /**
7 | * 第62题
8 | * 二叉树的序列化与反序列化
9 | *
10 | * @author qgl
11 | * @date 2019/04/18
12 | */
13 | public class Test62 {
14 |
15 | @Test
16 | public void test62() throws Exception {
17 | TreeNode root = new TreeNode(7);
18 | TreeNode node1 = new TreeNode(5);
19 | TreeNode node2 = new TreeNode(8);
20 | TreeNode node3 = new TreeNode(3);
21 | TreeNode node4 = new TreeNode(6);
22 | TreeNode node5 = new TreeNode(9);
23 | TreeNode node6 = new TreeNode(11);
24 | root.left = node1;
25 | root.right = node2;
26 | node1.left = node3;
27 | node1.right = node4;
28 | node2.left = node5;
29 | node2.right = node6;
30 |
31 | String serializerTree = Serializer62.serialize(root);
32 | System.out.println("序列化二叉树:" + serializerTree);
33 | System.out.println("反序列化二叉树后,从左至右输出:" + LevelPrintTree61.printTreeNodeByLeftToRight(Serializer62.deserialize(serializerTree)));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test63.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import com.so.Common.TreeNode;
4 | import org.junit.Test;
5 |
6 | /**
7 | * 第63题
8 | * 给定一棵二叉搜索树,请找出其中的第k小的结点
9 | *
10 | * @author qgl
11 | * @date 2019/04/19
12 | */
13 | public class Test63 {
14 |
15 | @Test
16 | public void test63() throws Exception {
17 | TreeNode root = new TreeNode(7);
18 | TreeNode node1 = new TreeNode(5);
19 | TreeNode node2 = new TreeNode(9);
20 | TreeNode node3 = new TreeNode(3);
21 | TreeNode node4 = new TreeNode(6);
22 | TreeNode node5 = new TreeNode(8);
23 | TreeNode node6 = new TreeNode(11);
24 | root.left = node1;
25 | root.right = node2;
26 | node1.left = node3;
27 | node1.right = node4;
28 | node2.left = node5;
29 | node2.right = node6;
30 |
31 | KthNode63 kthNode63 = new KthNode63();
32 | int k = 3;
33 | System.out.println("解法一:递归查找:" + kthNode63.KthNode(root, k).val);
34 | System.out.println("解法二:非递归,借用栈查找:" + kthNode63.getKthNode2(root, k).val);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test64.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第64题
7 | * 求数据流中的中位数
8 | *
9 | * @author qgl
10 | * @date 2019/04/20
11 | */
12 | public class Test64 {
13 |
14 | @Test
15 | public void test64() throws Exception {
16 | int[] arr = {2, 4, 5, 8, 15, 10, 7, 9};
17 | GetMedian64.insertArray(arr);
18 | System.out.println("解法一:利用集合类的归并排序获取中位数:" + GetMedian64.getMedian1());
19 | System.out.println("解法二:利用优先级队列构建堆进行排序后获取中位数:" + GetMedian64.getMedian2());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test65.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第65题
7 | * 求滑动窗口的最大值
8 | *
9 | * @author qgl
10 | * @date 2019/04/21
11 | */
12 | public class Test65 {
13 |
14 | @Test
15 | public void test65() throws Exception {
16 | int[] arr = {2, 3, 4, 2, 6, 2, 5, 1};
17 | int windowsSize = 3;
18 | System.out.println("解法一:两个for循环,获取滑动窗口的最大值:" + MaxInWindows65.maxInWindows1(arr, windowsSize));
19 | System.out.println("解法二:双端队列,获取滑动窗口的最大值:" + MaxInWindows65.maxInWindows2(arr, windowsSize));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test66.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第66题
7 | * 判断在一个矩阵中是否存在一条包含某字符串所有字符的路径
8 | *
9 | * @author qgl
10 | * @date 2019/04/22
11 | */
12 | public class Test66 {
13 |
14 | @Test
15 | public void test66() throws Exception {
16 | char[] arr = {'a', 'b', 'c', 'e', 's', 'f', 'c', 's', 'a', 'd', 'e', 'e'};
17 | int rows = 3;
18 | int columns = 4;
19 | char[] str = {'b', 'c', 'c', 'e', 'd'};
20 | char[] str2 = {'a', 'b', 'c', 'b'};
21 | System.out.println("矩阵中是否存在该路径:" + HasPath66.hasPath(arr, rows, columns, str));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test67.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第67题
7 | * 机器人的运动范围,一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,
8 | * 但是不能进入行坐标和列坐标的数位之和大于k的格子。求机器人能够达到多少个格子
9 | *
10 | * @author qgl
11 | * @date 2019/04/23
12 | */
13 | public class Test67 {
14 |
15 | @Test
16 | public void test67() throws Exception {
17 | int rows = 3;
18 | int columns = 4;
19 | int k = 18;
20 | System.out.println("机器人能够达到多少个格子:" + MovingCount67.movingCount(rows, columns, k));
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test7.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第7题
7 | * 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
8 | *
9 | * @author qgl
10 | * @date 2019/02/21
11 | */
12 | public class Test7 {
13 | @Test
14 | public void test7() throws Exception {
15 | DoubleSQueue7 doubleSQueue7 = new DoubleSQueue7();
16 | doubleSQueue7.push(2);
17 | doubleSQueue7.push(5);
18 | doubleSQueue7.push(8);
19 | System.out.println("出队列:" + doubleSQueue7.pop());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test8.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第8题
7 | * 输入一个非递减排序数组的一个旋转,输出旋转数组的最小元素。
8 | *
9 | * @author qgl
10 | * @date 2019/02/22
11 | */
12 | public class Test8 {
13 | @Test
14 | public void test8() throws Exception {
15 | int[] array = {6, 7, 9, 1, 3, 5, 5};
16 | System.out.println("旋转数组的最小元素:" + MinNumber8.minInReversingList(array));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/so/Test9.java:
--------------------------------------------------------------------------------
1 | package com.so;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * 第9题
7 | * 输入一个整数n,求斐波那契数列的第n项。
8 | *
9 | * @author qgl
10 | * @date 2019/02/23
11 | */
12 | public class Test9 {
13 | @Test
14 | public void test9() throws Exception {
15 | int n = 9;
16 | System.out.println("解法一:三个局部变量,斐波那契数列的第 " + n + " 项是:" + Fibonacci9.getFibonacci1(n));
17 | System.out.println("解法二:两个局部变量,斐波那契数列的第 " + n + " 项是:" + Fibonacci9.getFibonacci2(n));
18 | System.out.println("解法三: 使用递归,斐波那契数列的第 " + n + " 项是:" + Fibonacci9.getFibonacci3(n));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------