├── .DS_Store
├── .gitignore
├── .idea
├── Sword-pointing-to-offer.iml
├── encodings.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── LICENSE
├── README.md
├── 剑指offer I - leetcode版
├── image
│ ├── lc03.jpeg
│ ├── lc04.png
│ ├── lc05.png
│ ├── lc06.png
│ ├── lc07.png
│ ├── lc09.png
│ ├── lc10-1.png
│ ├── lc10-2.png
│ ├── lc11.png
│ ├── lc12-desc.png
│ ├── lc12.png
│ ├── lc13.png
│ ├── lc14-1.png
│ ├── lc14-2.png
│ ├── lc15.png
│ ├── lc16.png
│ ├── lc17.png
│ ├── lc18.png
│ ├── lc19.png
│ ├── lc20.png
│ ├── lc21.png
│ ├── lc22.png
│ ├── lc24.png
│ ├── lc25.png
│ ├── lc26.png
│ ├── lc27.png
│ ├── lc28.png
│ ├── lc29.png
│ ├── lc30.png
│ ├── lc31.png
│ ├── lc32-1.png
│ ├── lc32-2.png
│ ├── lc32-3.png
│ ├── lc33.png
│ ├── lc34.png
│ ├── lc35.png
│ ├── lc36.png
│ ├── lc37.png
│ ├── lc38.png
│ ├── lc39.png
│ ├── lc40.png
│ ├── lc41.png
│ └── lc42.png
└── 剑指Offer I - LeetCode CN 版本.md
└── 剑指offer-2012年书籍版
├── .DS_Store
├── Java
├── BinaryTreeNode.java
├── No02.java
├── No03.java
├── No04.java
├── No05.java
├── No06.java
├── No07.java
├── No08.java
├── No09.java
├── No10.java
├── No11.java
├── No12.java
├── No13.java
├── No14.java
├── No15.java
├── No15_2.java
├── No16.java
├── No17.java
├── No18.java
├── No19.java
├── No20.java
├── No21.java
├── No22.java
├── No23.java
├── No24.java
├── No25.java
├── No26.java
├── No27.java
├── No28.java
├── No29.java
├── No30.java
├── No31.java
├── No32.java
├── No33.java
├── No34.java
├── No35.java
├── No36.java
├── No37.java
├── No38.java
├── No39.java
├── No40.java
├── No41.java
├── No42.java
├── No43.java
├── No44.java
├── No45.java
└── No47.java
├── Kotlin
├── No02.kt
├── No03.kt
├── No04.kt
├── No05.kt
├── No06.kt
├── No07.kt
├── No08.kt
├── No09.kt
├── No10.kt
├── No11.kt
├── No12.kt
├── No13.kt
├── No14.kt
├── No15.kt
└── Node.kt
└── Pdf、Markdown
├── 剑指offer-java-md.md
└── 剑指offer-java-pdf.pdf
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
--------------------------------------------------------------------------------
/.idea/Sword-pointing-to-offer.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | CDI (Contexts and Dependency Injection)
13 |
14 |
15 | Concurrency annotation issuesJava
16 |
17 |
18 | Data flowJava
19 |
20 |
21 | GeneralJavaScript
22 |
23 |
24 | Groovy
25 |
26 |
27 | InitializationJava
28 |
29 |
30 | JSON and JSON5
31 |
32 |
33 | Java
34 |
35 |
36 | JavaScript
37 |
38 |
39 | RESTful Web Service
40 |
41 |
42 | Serialization issuesJava
43 |
44 |
45 | Threading issuesGroovy
46 |
47 |
48 | Threading issuesJava
49 |
50 |
51 |
52 |
53 | Angular
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 | 1559293530940
184 |
185 |
186 | 1559293530940
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 | 1.8
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### 剑指offer JAVA解
2 | * [2012年书籍版本](https://github.com/xurui1995/Sword-pointing-to-offer/blob/master/%E5%89%91%E6%8C%87offer-2012%E5%B9%B4%E4%B9%A6%E7%B1%8D%E7%89%88/Pdf%E3%80%81Markdown/%E5%89%91%E6%8C%87offer-java-md.md)
3 | * [Leetcode cn 剑指offer I](https://github.com/xurui1995/Sword-pointing-to-offer/blob/master/%E5%89%91%E6%8C%87offer%20I%20-%20leetcode%E7%89%88/%E5%89%91%E6%8C%87Offer%20I%20-%20LeetCode%20CN%20%E7%89%88%E6%9C%AC.md)
4 | * Leetcode cn 剑指offer II
5 | * 实现思路请参考书中讲解
6 | * 欢迎提交bug和更优解
7 |
8 |
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc03.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc03.jpeg
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc04.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc05.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc06.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc07.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc09.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc10-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc10-1.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc10-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc10-2.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc11.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc12-desc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc12-desc.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc12.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc13.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc14-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc14-1.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc14-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc14-2.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc15.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc16.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc17.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc18.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc19.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc20.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc21.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc22.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc24.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc25.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc26.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc27.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc28.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc29.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc30.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc31.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc32-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc32-1.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc32-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc32-2.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc32-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc32-3.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc33.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc34.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc35.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc35.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc36.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc37.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc38.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc39.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc40.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc41.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/image/lc42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer I - leetcode版/image/lc42.png
--------------------------------------------------------------------------------
/剑指offer I - leetcode版/剑指Offer I - LeetCode CN 版本.md:
--------------------------------------------------------------------------------
1 | # 剑指Offer I - LeetCode CN 版本
2 | ### _所有题目描述来自leetcode cn_
3 |
4 |
5 | ### 剑指 Offer 03. 数组中重复的数字
6 | ```
7 | 找出数组中重复的数字。
8 | 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
9 |
10 | 示例 1:
11 | 输入:
12 | [2, 3, 1, 0, 2, 5, 3]
13 | 输出:2 或 3
14 | ```
15 |
16 | ```
17 | class Solution {
18 | public int findRepeatNumber(int[] nums) {
19 | for(int i=0; i < nums.length; i++) {
20 | while(nums[i] != i) {
21 | if(nums[nums[i]] == nums[i] ) {
22 | return nums[i];
23 | }
24 | int temp = nums[i];
25 | nums[i] = nums[nums[i]];
26 | nums[temp] = temp;
27 | }
28 | }
29 | return -1;
30 | }
31 | }
32 | ```
33 | * 
34 |
35 | ### 剑指 Offer 04. 二维数组中的查找
36 | ```
37 | 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
38 |
39 | 示例:
40 | 现有矩阵 matrix 如下:
41 | [
42 | [1, 4, 7, 11, 15],
43 | [2, 5, 8, 12, 19],
44 | [3, 6, 9, 16, 22],
45 | [10, 13, 14, 17, 24],
46 | [18, 21, 23, 26, 30]
47 | ]
48 | 给定 target=5,返回true。
49 | 给定target=20,返回false。
50 | ```
51 |
52 | ```
53 | class Solution {
54 | public boolean findNumberIn2DArray(int[][] matrix, int target) {
55 | int m = matrix.length;
56 | if (m == 0) {
57 | return false;
58 | }
59 | int n = matrix[0].length;
60 | int i = 0, j = n - 1;
61 | while (i < m && i >= 0 && j < n && j >= 0) {
62 | if (matrix[i][j] == target) {
63 | return true;
64 | }
65 | if (matrix[i][j] > target) {
66 | j = j - 1;
67 | } else {
68 | i = i + 1;
69 | }
70 | }
71 | return false;
72 | }
73 | }
74 | ```
75 | * 
76 |
77 | ### 剑指 Offer 05. 替换空格
78 | ```
79 | 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
80 |
81 | 示例 1:
82 | 输入:s = "We are happy."
83 | 输出:"We%20are%20happy."
84 | ```
85 | ```
86 | class Solution {
87 | public String replaceSpace(String s) {
88 | return s.replace(" ","%20");
89 | }
90 | }
91 | ```
92 | * 
93 |
94 | ### 剑指 Offer 06. 从尾到头打印链表
95 | ```
96 | 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
97 |
98 | 示例 1:
99 | 输入:head = [1,3,2]
100 | 输出:[2,3,1]
101 | ```
102 | ```
103 | class Solution {
104 | public int[] reversePrint(ListNode head) {
105 | List list = new LinkedList();
106 | while (head != null) {
107 | list.add(head.val);
108 | head = head.next;
109 | }
110 | int[] ans = new int[list.size()];
111 | int index = ans.length - 1;
112 | for (int i : list) {
113 | ans[index--] = i;
114 | }
115 | return ans;
116 | }
117 | }
118 | ```
119 | * 
120 |
121 | ### 剑指 Offer 07. 重建二叉树
122 | ```
123 | 输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
124 | 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
125 |
126 | Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
127 | Output: [3,9,20,null,null,15,7]
128 | ```
129 | ```
130 | class Solution {
131 | HashMap inordertIndexMap = new HashMap();
132 | int[] preorder;
133 | int[] inorder;
134 |
135 | public TreeNode buildTree(int[] preorder, int[] inorder) {
136 | int n = inorder.length;
137 | if (n == 0) {
138 | return null;
139 | }
140 | this.preorder = preorder;
141 | this.inorder = inorder;
142 |
143 | for (int i = 0; i < n; i++) {
144 | inordertIndexMap.put(inorder[i], i);
145 | }
146 |
147 | return build(0, n - 1, 0, n - 1);
148 |
149 | }
150 |
151 | public TreeNode build(int pStart, int pEnd, int iStart, int iEnd) {
152 | if (pStart > pEnd) {
153 | return null;
154 | }
155 |
156 | TreeNode root = new TreeNode(preorder[pStart]);
157 | int index = inordertIndexMap.get(root.val);
158 | int leftLen = index - iStart;
159 | root.left = build(pStart + 1, pStart + leftLen, iStart, index - 1);
160 | root.right = build(pStart + leftLen + 1, pEnd, index + 1, iEnd);
161 | return root;
162 | }
163 | }
164 | ```
165 |
166 | * 
167 |
168 | ### 剑指 Offer 09. 用两个栈实现队列
169 | ```
170 | 用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead操作返回 -1 )
171 |
172 | 示例 1:
173 | 输入:
174 | ["CQueue","appendTail","deleteHead","deleteHead"]
175 | [[],[3],[],[]]
176 | 输出:[null,null,3,-1]
177 | ```
178 | ```
179 | class CQueue {
180 | Stack s1 = new Stack();
181 | Stack s2 = new Stack();
182 |
183 | public CQueue() {
184 |
185 | }
186 |
187 | public void appendTail(int value) {
188 | s1.push(value);
189 | }
190 |
191 | public int deleteHead() {
192 | if (s2.isEmpty()) {
193 | while (!s1.isEmpty()) {
194 | s2.push(s1.pop());
195 | }
196 | }
197 | if (s2.isEmpty()) {
198 | return -1;
199 | }
200 | return s2.pop();
201 | }
202 | }
203 | ```
204 | * 
205 |
206 | ### 剑指 Offer 10- I. 斐波那契数列
207 | ```
208 | 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
209 | F(0) = 0,F(1)= 1
210 | F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
211 | ```
212 |
213 | ```
214 | class Solution {
215 | int mod = 1000000007;
216 |
217 | public int fib(int n) {
218 | int[] dp = new int[2];
219 | dp[1] = 1;
220 | for (int i = 2; i <= n; i++) {
221 | dp[i & 1] = (dp[(i - 1) & 1] % mod + dp[(i - 2) & 1] % mod) % mod;
222 | }
223 | return dp[n & 1];
224 | }
225 | }
226 | ```
227 |
228 | * 
229 |
230 |
231 | ### 剑指 Offer 10- II. 青蛙跳台阶问题
232 | ```
233 | 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
234 |
235 | 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
236 | ```
237 |
238 | ```
239 | class Solution {
240 | int mod = 1000000007;
241 | public int numWays(int n) {
242 | int[] dp = new int[2];
243 | dp[0] = 1;
244 | dp[1] = 1;
245 | for (int i = 2; i <= n; i++) {
246 | dp[i & 1] = (dp[(i - 1) & 1] % mod + dp[(i - 2) & 1] % mod) % mod;
247 | }
248 | return dp[n & 1];
249 | }
250 | }
251 | ```
252 | * 
253 |
254 | ### 剑指 Offer 11. 旋转数组的最小数字
255 | ```
256 | 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
257 |
258 | 示例 1:
259 | 输入:[3,4,5,1,2]
260 | 输出:1
261 |
262 | 示例 2:
263 | 输入:[2,2,2,0,1]
264 | 输出:0
265 |
266 | ```
267 |
268 | ```
269 | class Solution {
270 | public int minArray(int[] nums) {
271 | int n = nums.length;
272 | int r = n - 1;
273 | if (nums[r] > nums[0]) {
274 | return nums[0];
275 | }
276 | while (r >= 0 && nums[r] == nums[0]) {
277 | r--;
278 | }
279 | if (r == -1) {
280 | return nums[0];
281 | }
282 | if (nums[r] > nums[0]) {
283 | return nums[0];
284 | }
285 | int l = 0;
286 | while (l < r) {
287 | int mid = l + r >> 1;
288 | if (nums[mid] < nums[0]) {
289 | r = mid;
290 | } else {
291 | l = mid + 1;
292 | }
293 | }
294 | return nums[r];
295 |
296 | }
297 | }
298 | ```
299 | * 
300 |
301 | ### 剑指 Offer 12. 矩阵中的路径
302 | ```
303 | 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
304 | 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
305 | ```
306 | * 
307 | ```
308 | class Solution {
309 | char[][] board;
310 | boolean[][] visited;
311 |
312 | public boolean exist(char[][] board, String word) {
313 | this.board = board;
314 | visited = new boolean[board.length][board[0].length];
315 | for (int i = 0; i < board.length; i++) {
316 | for (int j = 0; j < board[0].length; j++) {
317 | if (board[i][j] == word.charAt(0) && dfs(word, 0, i, j)) {
318 | return true;
319 | }
320 | }
321 | }
322 | return false;
323 |
324 | }
325 |
326 | public boolean dfs(String word, int index, int i, int j) {
327 | if (index == word.length()) {
328 | return true;
329 | }
330 | if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) {
331 | return false;
332 | }
333 | if (visited[i][j] || board[i][j] != word.charAt(index)) {
334 | return false;
335 | }
336 |
337 | visited[i][j] = true;
338 |
339 | boolean ans = dfs(word, index + 1, i + 1, j) || dfs(word, index + 1, i - 1, j)
340 | || dfs(word, index + 1, i, j + 1) || dfs(word, index + 1, i, j - 1);
341 |
342 | visited[i][j] = false;
343 | return ans;
344 | }
345 | }
346 | ```
347 | * 
348 |
349 | ### 剑指 Offer 13. 机器人的运动范围
350 | ```
351 | 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
352 | ```
353 |
354 | ```
355 | class Solution {
356 | public int movingCount(int m, int n, int k) {
357 | boolean[][] visited = new boolean[m][n];
358 | visited[0][0] = true;
359 | int ans = 0;
360 | Queue queue = new LinkedList();
361 |
362 | queue.offer(new int[]{0, 0});
363 | int[] x = {1, -1, 0, 0};
364 | int[] y = {0, 0, 1, -1};
365 | while (!queue.isEmpty()) {
366 | int size = queue.size();
367 | ans += size;
368 | for (int i = 0; i < size; i++) {
369 | int[] poll = queue.poll();
370 | for (int K = 0; K < 4; K++) {
371 | int newX = poll[0] + x[K];
372 | int newY = poll[1] + y[K];
373 | if (newX >= 0 && newX < m && newY >= 0 && newY < n && !visited[newX][newY]) {
374 | visited[newX][newY] = true;
375 | int num = 0;
376 | int temp = newX;
377 | while (temp != 0) {
378 | num += temp % 10;
379 | temp = temp / 10;
380 | }
381 | temp = newY;
382 | while (temp != 0) {
383 | num += temp % 10;
384 | temp = temp / 10;
385 | }
386 | if (num <= k) {
387 | queue.offer(new int[]{newX, newY});
388 | }
389 |
390 | }
391 | }
392 | }
393 | }
394 | return ans;
395 | }
396 | }
397 | ```
398 | * 
399 |
400 | ### 剑指 Offer 14- I. 剪绳子
401 | ```
402 | 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
403 |
404 | 示例 1:
405 | 输入: 2
406 | 输出: 1
407 | 解释: 2 = 1 + 1, 1 × 1 = 1
408 | ```
409 | ```
410 | class Solution {
411 | public int cuttingRope(int n) {
412 | if (n <= 3) {
413 | return n - 1;
414 | }
415 | int mod = n % 3;
416 | int cnt = n / 3;
417 | if (mod == 1) {
418 | return (int) (Math.pow(3.0, cnt - 1) * 4);
419 | }
420 | return (int) (Math.pow(3.0, cnt) * (mod == 0 ? 1 : mod));
421 | }
422 | }
423 | ```
424 | * 
425 |
426 | ### 剑指 Offer 14- II. 剪绳子 II
427 | ```
428 | 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m - 1] 。请问 k[0]*k[1]*...*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
429 | ```
430 | ```
431 | class Solution {
432 | int mod = 1000000007;
433 |
434 | public int cuttingRope(int n) {
435 | if (n <= 3) {
436 | return n - 1;
437 | }
438 | long ans = 1;
439 | while (n > 4) {
440 | ans = ans * 3 % mod;
441 | n -= 3;
442 | }
443 | ans = ans * n % mod;
444 | return (int) (ans);
445 | }
446 | }
447 | ```
448 | * 
449 |
450 | ### 剑指 Offer 15. 二进制中1的个数
451 | ```
452 | 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).)。
453 | 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
454 | ```
455 | ```
456 | public class Solution {
457 | // you need to treat n as an unsigned value
458 | public int hammingWeight(int n) {
459 | int ans = 0;
460 | while(n != 0) {
461 | n = n & (n-1);
462 | ans++;
463 | }
464 | return ans;
465 | }
466 | }
467 | ```
468 | * 
469 |
470 | ### 剑指 Offer 16. 数值的整数次方
471 | ```
472 | 实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
473 | 输入:x = 2.00000, n = 10
474 | 输出:1024.00000
475 | ```
476 |
477 | ```
478 | class Solution {
479 | public double myPow(double x, int n) {
480 | if (n == 0) {
481 | return 1;
482 | }
483 | if (n < 0) {
484 |
485 | return 1 / (myPow(x, -(n + 1)) * x);
486 | }
487 | int halfN = n / 2;
488 | double val = myPow(x, halfN);
489 | double ans = val * val;
490 | if (n % 2 == 1) {
491 | ans *= x;
492 | }
493 | return ans;
494 | }
495 | }
496 | ```
497 | * 
498 |
499 | ### 剑指 Offer 17. 打印从1到最大的n位数
500 | ```
501 | 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
502 |
503 | 示例 1:
504 | 输入: n = 1
505 | 输出: [1,2,3,4,5,6,7,8,9]
506 | ```
507 |
508 | ```
509 | class Solution {
510 | public int[] printNumbers(int n) {
511 | int max = (int) Math.pow(10, n) - 1;
512 | int[] ans = new int[max];
513 | for (int i = 0; i < max; i++) {
514 | ans[i] = i + 1;
515 | }
516 | return ans;
517 | }
518 | }
519 | ```
520 |
521 | * 
522 |
523 | ### 剑指 Offer 18. 删除链表的节点
524 | ```
525 | 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
526 | 返回删除后的链表的头节点。
527 |
528 | 注意:此题对比原题有改动
529 |
530 | 示例 1:
531 | 输入: head = [4,5,1,9], val = 5
532 | 输出: [4,1,9]
533 | 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
534 | ```
535 |
536 | ```
537 | class Solution {
538 | public ListNode deleteNode(ListNode head, int val) {
539 | ListNode hair = new ListNode();
540 | ListNode temp = hair;
541 | while (head != null) {
542 | if (head.val != val) {
543 | temp.next = head;
544 | temp = temp.next;
545 | head = head.next;
546 | temp.next = null;
547 | } else {
548 | head = head.next;
549 | }
550 |
551 | }
552 | return hair.next;
553 | }
554 | }
555 | ```
556 | * 
557 |
558 | ### 剑指 Offer 19. 正则表达式匹配
559 | ```
560 | 请实现一个函数用来匹配包含'. '和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"和"ab*a"均不匹配。
561 |
562 | 输入:
563 | s = "aa"
564 | p = "a*"
565 | 输出: true
566 | 解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
567 | ```
568 | ```
569 | class Solution {
570 | public boolean isMatch(String s, String p) {
571 | s = " " + s;
572 | p = " " + p;
573 | int m = s.length();
574 | int n = p.length();
575 | boolean[][] dp = new boolean[m][n];
576 | dp[0][0] = true;
577 | for (int i = 0; i < m; i++) {
578 | for (int j = 1; j < n; j++) {
579 | char sc = s.charAt(i);
580 | char pc = p.charAt(j);
581 | if ((sc == pc || pc == '.') && i >= 1) {
582 | dp[i][j] = dp[i - 1][j - 1];
583 | } else if (pc == '*') {
584 | dp[i][j] = dp[i][j - 2];
585 | char prev = p.charAt(j - 1);
586 | if (i >= 1 && (prev == sc || prev == '.')) {
587 | dp[i][j] = dp[i][j] || dp[i - 1][j - 2];
588 | dp[i][j] = dp[i][j] || dp[i - 1][j];
589 | }
590 | }
591 | }
592 | }
593 | return dp[m - 1][n - 1];
594 | }
595 | }
596 | ```
597 | * 
598 |
599 |
600 | ### 剑指 Offer 20. 表示数值的字符串
601 | ```
602 | 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
603 |
604 | 数值(按顺序)可以分成以下几个部分:
605 | 若干空格
606 | 一个 小数 或者 整数
607 | (可选)一个 'e' 或 'E' ,后面跟着一个 整数
608 | 若干空格
609 |
610 |
611 | 小数(按顺序)可以分成以下几个部分:
612 | (可选)一个符号字符('+' 或 '-')
613 | 下述格式之一:
614 | 至少一位数字,后面跟着一个点 '.'
615 | 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
616 | 一个点 '.' ,后面跟着至少一位数字
617 |
618 | 整数(按顺序)可以分成以下几个部分:
619 | (可选)一个符号字符('+' 或 '-')
620 | 至少一位数字
621 | 部分数值列举如下:
622 | ["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]
623 | 部分非数值列举如下:
624 | ["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]
625 | ```
626 | ```
627 | class Solution {
628 |
629 | static HashMap> map = new HashMap();
630 | static int blank = 0;
631 | static int sign = 1;
632 | static int digit = 2;
633 | static int dot = 3;
634 | static int e = 4;
635 |
636 |
637 | // 空格 0 { 空格 -> 0, 符号-> 1, 数字-> 2, 点-> 3}
638 | // 符号1 1 {数字 -> 2, 点 -> 3}
639 | // 数字1 2 {数字 -> 2, (e, E) -> 4 , 点-> 5, 空格->9 }
640 | // 无数字前缀的点 3 { 数字 -> 8 }
641 | // E 4 {符号 -> 6, 数字-> 7}
642 | // 有数字前缀的点 5 { 数字 -> 8, (e, E) -> 4, 空格 -> 9}
643 | // 符号2 6 {数字 -> 7}
644 | // e后面的数字 7 {空格->9, 数字->7}
645 | // 点后面的数字 8 {空格->9, 数字->8, (e, E) -> 4}
646 | // 结尾空格 9 {空格 -> 9}
647 |
648 |
649 | static {
650 | Map stat0 = new HashMap();
651 | stat0.put(blank, 0);
652 | stat0.put(sign, 1);
653 | stat0.put(digit, 2);
654 | stat0.put(dot, 3);
655 | map.put(0, stat0);
656 |
657 | Map stat1 = new HashMap();
658 | stat1.put(digit, 2);
659 | stat1.put(dot, 3);
660 | map.put(1, stat1);
661 |
662 | Map stat2 = new HashMap();
663 | stat2.put(digit, 2);
664 | stat2.put(e, 4);
665 | stat2.put(dot, 5);
666 | stat2.put(blank, 9);
667 | map.put(2, stat2);
668 |
669 | Map stat3 = new HashMap();
670 |
671 | stat3.put(digit, 8);
672 | map.put(3, stat3);
673 |
674 |
675 | Map stat4 = new HashMap();
676 | stat4.put(sign, 6);
677 | stat4.put(digit, 7);
678 | map.put(4, stat4);
679 |
680 |
681 | Map stat5 = new HashMap();
682 | stat5.put(digit, 8);
683 | stat5.put(e, 4);
684 | stat5.put(blank, 9);
685 | map.put(5, stat5);
686 |
687 | Map stat6 = new HashMap();
688 | stat6.put(digit, 7);
689 | map.put(6, stat6);
690 |
691 | Map stat7 = new HashMap();
692 | stat7.put(blank, 9);
693 | stat7.put(digit, 7);
694 | map.put(7, stat7);
695 | Map stat8 = new HashMap();
696 | stat8.put(digit, 8);
697 | stat8.put(e, 4);
698 | stat8.put(blank, 9);
699 | map.put(8, stat8);
700 |
701 |
702 | Map stat9 = new HashMap();
703 |
704 | stat9.put(blank, 9);
705 | map.put(9, stat9);
706 |
707 |
708 | }
709 |
710 | public boolean isNumber(String s) {
711 | int cur = 0;
712 | for (int i = 0; i < s.length(); i++) {
713 | char c = s.charAt(i);
714 | int action = -1;
715 | if (c == '.') {
716 | action = dot;
717 | } else if (c == 'e' || c == 'E') {
718 | action = e;
719 | } else if (c == ' ') {
720 | action = blank;
721 | } else if (c == '+' || c == '-') {
722 | action = sign;
723 | } else if (c >= '0' && c <= '9') {
724 | action = digit;
725 | }
726 | if (action == -1 || !map.get(cur).containsKey(action)) {
727 | return false;
728 | }
729 |
730 | cur = map.get(cur).get(action);
731 | }
732 | return cur == 2 || cur == 5 || cur == 7 || cur == 8 || cur == 9;
733 | }
734 | }
735 | ```
736 | * 
737 |
738 | ### 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
739 | ```
740 | 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
741 | ```
742 | ```
743 | class Solution {
744 | public int[] exchange(int[] nums) {
745 | int l = 0;
746 | int r = nums.length - 1;
747 | while (l < r) {
748 | while (l < r && nums[l] % 2 == 1) {
749 | l++;
750 | }
751 |
752 | while (l < r && nums[r] % 2 == 0) {
753 | r--;
754 | }
755 |
756 | if (l < r) {
757 | int temp = nums[l];
758 | nums[l] = nums[r];
759 | nums[r] = temp;
760 | }
761 | }
762 | return nums;
763 | }
764 | }
765 | ```
766 | * 
767 |
768 |
769 | ### 剑指 Offer 22. 链表中倒数第k个节点
770 | ```
771 | 输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
772 |
773 | 例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
774 | ```
775 | ```
776 | class Solution {
777 | public ListNode getKthFromEnd(ListNode head, int k) {
778 | ListNode slow = head;
779 | ListNode fast = head;
780 | for (int i = 0; i < k; i++) {
781 | fast = fast.next;
782 | }
783 | while (fast != null) {
784 | fast = fast.next;
785 | slow = slow.next;
786 | }
787 | return slow;
788 | }
789 | }
790 | ```
791 | * 
792 |
793 |
794 | ### 剑指 Offer 24. 反转链表
795 | ```
796 | 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
797 | ```
798 | ```
799 | class Solution {
800 | public ListNode reverseList(ListNode head) {
801 | if (head == null) {
802 | return null;
803 | }
804 | if (head.next == null) {
805 | return head;
806 | }
807 | ListNode newHead = reverseList(head.next);
808 | head.next.next = head;
809 | head.next = null;
810 | return newHead;
811 |
812 | }
813 | }
814 | ```
815 | * 
816 |
817 | ### 剑指 Offer 25. 合并两个排序的链表
818 | ```
819 | 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
820 |
821 | 示例1:
822 | 输入:1->2->4, 1->3->4
823 | 输出:1->1->2->3->4->4
824 | ```
825 | ```
826 | class Solution {
827 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
828 | ListNode hair = new ListNode(-1);
829 | ListNode temp = hair;
830 | while (l1 != null || l2 != null) {
831 | if (l2 == null || (l1 != null && l1.val <= l2.val)) {
832 | temp.next = l1;
833 | l1 = l1.next;
834 | temp = temp.next;
835 | temp.next = null;
836 | } else {
837 | temp.next = l2;
838 | l2 = l2.next;
839 | temp = temp.next;
840 |
841 | temp.next = null;
842 | }
843 | }
844 | return hair.next;
845 | }
846 | }
847 | ```
848 | * 
849 |
850 | ### 剑指 Offer 26. 树的子结构
851 | ```
852 | 输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
853 | B是A的子结构, 即 A中有出现和B相同的结构和节点值。
854 | ```
855 | ```
856 | class Solution {
857 | public boolean isSubStructure(TreeNode A, TreeNode B) {
858 | return (A != null && B != null) && (solve(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B));
859 | }
860 |
861 | boolean solve(TreeNode A, TreeNode B) {
862 | if (B == null) {
863 | return true;
864 | }
865 | if (A == null || A.val != B.val) {
866 | return false;
867 | }
868 | return solve(A.left, B.left) && solve(A.right, B.right);
869 | }
870 | }
871 | ```
872 | * 
873 |
874 | ### 剑指 Offer 27. 二叉树的镜像
875 | ```
876 | 请完成一个函数,输入一个二叉树,该函数输出它的镜像。
877 | ```
878 | ```
879 | class Solution {
880 | public TreeNode mirrorTree(TreeNode root) {
881 | if(root == null) {
882 | return null;
883 | }
884 | TreeNode temp = root.left;
885 | root.left = root.right;
886 | root.right = temp;
887 | mirrorTree(root.left);
888 | mirrorTree(root.right);
889 | return root;
890 | }
891 | }
892 | ```
893 | * 
894 |
895 | ### 剑指 Offer 28. 对称的二叉树
896 | ```
897 | 请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
898 | 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
899 |
900 | 1
901 | / \
902 | 2 2
903 | / \ / \
904 | 3 4 4 3
905 | 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
906 |
907 | 1
908 | / \
909 | 2 2
910 | \ \
911 | 3 3
912 | ```
913 | ```
914 | class Solution {
915 | public boolean isSymmetric(TreeNode root) {
916 | if (root == null) {
917 | return true;
918 | }
919 | return isSymmetric(root.left, root.right);
920 | }
921 |
922 | public boolean isSymmetric(TreeNode node1, TreeNode node2) {
923 | if (node1 == null && node2 == null) {
924 | return true;
925 | }
926 | if (node1 == null || node2 == null) {
927 | return false;
928 | }
929 | if (node1.val != node2.val) {
930 | return false;
931 | }
932 | return isSymmetric(node1.left, node2.right) && isSymmetric(node2.left, node1.right);
933 |
934 | }
935 | }
936 | ```
937 | * 
938 |
939 |
940 | ### 剑指 Offer 29. 顺时针打印矩阵
941 | ```
942 | 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
943 |
944 | 示例 1:
945 | 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
946 | 输出:[1,2,3,6,9,8,7,4,5]
947 | ```
948 | ```
949 | class Solution {
950 | public int[] spiralOrder(int[][] matrix) {
951 | int m = matrix.length;
952 | if (m == 0) {
953 | return new int[0];
954 | }
955 | int n = matrix[0].length;
956 | if (n == 0) {
957 | return new int[0];
958 | }
959 | int round = Math.min((m + 1) / 2, (n + 1) / 2);
960 | int[] ans = new int[m * n];
961 | int index = 0;
962 | int l = 0, t = 0, r = n - 1, b = m - 1;
963 | for (int x = 0; x < round; x++) {
964 | for (int i = l; i <= r; i++) {
965 | ans[index++] = matrix[t][i];
966 | }
967 | for (int i = t + 1; i <= b; i++) {
968 | ans[index++] = matrix[i][r];
969 | }
970 | for (int i = r - 1; i >= l && b != t; i--) {
971 | ans[index++] = matrix[b][i];
972 | }
973 | for (int i = b - 1; i > t && l != r; i--) {
974 | ans[index++] = matrix[i][l];
975 | }
976 | l++;
977 | t++;
978 | r--;
979 | b--;
980 | }
981 | return ans;
982 | }
983 | }
984 | ```
985 | * 
986 |
987 | ### 剑指 Offer 30. 包含min函数的栈
988 | ```
989 | 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
990 | MinStack minStack = new MinStack();
991 | minStack.push(-2);
992 | minStack.push(0);
993 | minStack.push(-3);
994 | minStack.min(); --> 返回 -3.
995 | minStack.pop();
996 | minStack.top(); --> 返回 0.
997 | minStack.min(); --> 返回 -2.
998 | ```
999 | ```
1000 | class MinStack {
1001 | Stack s1 = new Stack();
1002 | Stack s2 = new Stack();
1003 |
1004 | public MinStack() {
1005 |
1006 | }
1007 |
1008 | public void push(int x) {
1009 | s1.push(x);
1010 | if (s2.empty() || s2.peek() >= x) {
1011 | s2.push(x);
1012 | }
1013 | }
1014 |
1015 | public void pop() {
1016 | if (s1.pop().equals(s2.peek())) {
1017 | s2.pop();
1018 | }
1019 |
1020 | }
1021 |
1022 | public int top() {
1023 | return s1.peek();
1024 | }
1025 |
1026 | public int min() {
1027 | return s2.peek();
1028 | }
1029 | }
1030 | ```
1031 | * 
1032 |
1033 | ### 剑指 Offer 31. 栈的压入、弹出序列
1034 | ```
1035 | 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
1036 | 输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
1037 | 输出:true
1038 | 解释:我们可以按以下顺序执行:
1039 | push(1), push(2), push(3), push(4), pop() -> 4,
1040 | push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
1041 | ```
1042 | ```
1043 | class Solution {
1044 | public boolean validateStackSequences(int[] pushed, int[] popped) {
1045 | Stack s = new Stack();
1046 | int i = 0;
1047 | for (int num : pushed) {
1048 | s.push(num);
1049 | while (i < popped.length && !s.isEmpty() && popped[i] == s.peek()) {
1050 | s.pop();
1051 | i++;
1052 | }
1053 | }
1054 | return s.isEmpty();
1055 | }
1056 | }
1057 | ```
1058 | * 
1059 |
1060 | ### 剑指 Offer 32 - I. 从上到下打印二叉树
1061 | ```
1062 | 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
1063 | ```
1064 |
1065 | ```
1066 | class Solution {
1067 | public int[] levelOrder(TreeNode root) {
1068 | List ans = new ArrayList();
1069 | Queue queue = new LinkedList<>();
1070 | if (root != null) {
1071 | queue.offer(root);
1072 | }
1073 |
1074 | while (!queue.isEmpty()) {
1075 | int size = queue.size();
1076 | for (int i = 0; i < size; i++) {
1077 | TreeNode node = queue.poll();
1078 |
1079 | if (node.left != null) {
1080 | queue.offer(node.left);
1081 | }
1082 | if (node.right != null) {
1083 | queue.offer(node.right);
1084 | }
1085 | ans.add(node.val);
1086 | }
1087 | }
1088 | int[] array = new int[ans.size()];
1089 | for (int i = 0; i < ans.size(); i++) {
1090 | array[i] = ans.get(i);
1091 | }
1092 | return array;
1093 | }
1094 | }
1095 | ```
1096 |
1097 | * 
1098 |
1099 | ### 剑指 Offer 32 - II. 从上到下打印二叉树 II
1100 | ```
1101 | 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
1102 | ```
1103 | ```
1104 | class Solution {
1105 | public List> levelOrder(TreeNode root) {
1106 | Queue queue = new LinkedList();
1107 | List> ans = new ArrayList();
1108 | if (root == null) {
1109 | return ans;
1110 | }
1111 | queue.offer(root);
1112 | while (!queue.isEmpty()) {
1113 | int size = queue.size();
1114 | List list = new ArrayList();
1115 | for (int i = 0; i < size; i++) {
1116 | TreeNode node = queue.poll();
1117 | list.add(node.val);
1118 | if (node.left != null) {
1119 | queue.offer(node.left);
1120 | }
1121 | if (node.right != null) {
1122 | queue.offer(node.right);
1123 | }
1124 | }
1125 | ans.add(list);
1126 | }
1127 | return ans;
1128 | }
1129 | }
1130 | ```
1131 | * 
1132 |
1133 | ### 剑指 Offer 32 - III. 从上到下打印二叉树 III
1134 | ```
1135 | 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
1136 | ```
1137 | ```
1138 | class Solution {
1139 | public List> levelOrder(TreeNode root) {
1140 | List> ans = new ArrayList();
1141 | Queue queue = new LinkedList();
1142 | if(root != null) {
1143 | queue.offer(root);
1144 | }
1145 | boolean ltr = true;
1146 | while(!queue.isEmpty()) {
1147 | int size = queue.size();
1148 | List list = new ArrayList();
1149 | for(int i=0; i< size; i++) {
1150 | TreeNode node = queue.poll();
1151 | if(node.left != null) {
1152 | queue.offer(node.left);
1153 | }
1154 | if(node.right != null) {
1155 | queue.offer(node.right);
1156 | }
1157 | if(ltr) {
1158 | list.add(node.val);
1159 | } else {
1160 | list.add(0, node.val);
1161 | }
1162 | }
1163 | ltr = !ltr;
1164 | ans.add(list);
1165 | }
1166 | return ans;
1167 | }
1168 | }
1169 | ```
1170 | * 
1171 |
1172 | ### 剑指 Offer 33. 二叉搜索树的后序遍历序列
1173 | ```
1174 | 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
1175 | ```
1176 | ```
1177 | class Solution {
1178 | public boolean verifyPostorder(int[] postorder) {
1179 | int n = postorder.length;
1180 | return verify(0, n - 1, postorder);
1181 | }
1182 |
1183 | public boolean verify(int l, int r, int[] postorder) {
1184 | if (l >= r) {
1185 | return true;
1186 | }
1187 | int root = postorder[r];
1188 | int mid = r;
1189 | while (mid >= l && postorder[mid] >= root) {
1190 | mid--;
1191 | }
1192 | int next = mid;
1193 | while (next >= l) {
1194 | if (postorder[next] >= root) {
1195 | return false;
1196 | }
1197 | next--;
1198 | }
1199 | return verify(l, mid, postorder) && verify(mid + 1, r - 1, postorder);
1200 | }
1201 | }
1202 | ```
1203 | * 
1204 |
1205 | ### 剑指 Offer 34. 二叉树中和为某一值的路径
1206 | ```
1207 | 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
1208 | 叶子节点 是指没有子节点的节点。
1209 | ```
1210 | ```
1211 | class Solution {
1212 | List> ans = new ArrayList();
1213 | int target;
1214 |
1215 | public List> pathSum(TreeNode root, int target) {
1216 | if (root == null) {
1217 | return ans;
1218 | }
1219 | this.target = target;
1220 | dfs(root, new ArrayList<>(), 0);
1221 | return ans;
1222 | }
1223 |
1224 | public void dfs(TreeNode root, List temp, int sum) {
1225 | if (root.left == null && root.right == null) {
1226 | if (sum + root.val == target) {
1227 | temp.add(root.val);
1228 | ans.add(new ArrayList(temp));
1229 | temp.remove(temp.size() - 1);
1230 | }
1231 | }
1232 |
1233 | temp.add(root.val);
1234 |
1235 | if (root.left != null) {
1236 | dfs(root.left, temp, sum + root.val);
1237 | }
1238 | if (root.right != null) {
1239 | dfs(root.right, temp, sum + root.val);
1240 | }
1241 | temp.remove(temp.size() - 1);
1242 | }
1243 | }
1244 | ```
1245 | * 
1246 |
1247 | ### 剑指 Offer 35. 复杂链表的复制
1248 | ```
1249 | 请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
1250 | ```
1251 | ```
1252 | class Solution {
1253 | public Node copyRandomList(Node head) {
1254 | if (head == null) {
1255 | return null;
1256 | }
1257 | Node temp = head;
1258 | while (temp != null) {
1259 | Node next = temp.next;
1260 | temp.next = new Node(temp.val);
1261 | temp.next.next = next;
1262 | temp = next;
1263 | }
1264 | temp = head;
1265 | while (temp != null) {
1266 | Node next = temp.next;
1267 | next.random = temp.random == null ? null : temp.random.next;
1268 | temp = next.next;
1269 | }
1270 |
1271 | Node newHead = head.next;
1272 | temp = head;
1273 | while (temp != null) {
1274 | Node next = temp.next;
1275 | temp.next = temp.next == null ? null : temp.next.next;
1276 | temp = next;
1277 | }
1278 | return newHead;
1279 | }
1280 | }
1281 | ```
1282 |
1283 | * 
1284 |
1285 | ### 剑指 Offer 36. 二叉搜索树与双向链表
1286 | ```
1287 | 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
1288 |
1289 | ```
1290 | ```
1291 | class Solution {
1292 | public Node treeToDoublyList(Node root) {
1293 | if (root == null) {
1294 | return null;
1295 | }
1296 | Node[] ans = dfs(root);
1297 | ans[0].left = ans[1];
1298 | ans[1].right = ans[0];
1299 | return ans[0];
1300 | }
1301 |
1302 | public Node[] dfs(Node root) {
1303 | if (root.left == null && root.right == null) {
1304 | return new Node[]{root, root};
1305 | }
1306 | Node left = root;
1307 | if (root.left != null) {
1308 | Node[] l = dfs(root.left);
1309 | left = l[0];
1310 | l[1].right = root;
1311 | root.left = l[1];
1312 | }
1313 |
1314 | Node right = root;
1315 | if (root.right != null) {
1316 | Node[] r = dfs(root.right);
1317 | right = r[1];
1318 | r[0].left = root;
1319 | root.right = r[0];
1320 | }
1321 | return new Node[]{left, right};
1322 | }
1323 | }
1324 | ```
1325 |
1326 | * 
1327 |
1328 | ### 剑指 Offer 37. 序列化二叉树
1329 | ```
1330 | 请实现两个函数,分别用来序列化和反序列化二叉树。
1331 | 你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
1332 | ```
1333 | ```
1334 | public class Codec {
1335 |
1336 | // Encodes a tree to a single string.
1337 | public String serialize(TreeNode root) {
1338 | if (root == null) {
1339 | return "#";
1340 | }
1341 | return String.valueOf(root.val) + "," + serialize(root.left) + "," + serialize(root.right);
1342 | }
1343 |
1344 | // Decodes your encoded data to tree.
1345 | public TreeNode deserialize(String data) {
1346 | String[] strs = data.split(",");
1347 | Queue queue = new LinkedList<>(Arrays.asList(strs));
1348 | return dfs(queue);
1349 | }
1350 |
1351 | public TreeNode dfs(Queue queue) {
1352 | if (queue.isEmpty()) {
1353 | return null;
1354 | }
1355 | String root = queue.poll();
1356 | if (root.equals("#")) {
1357 | return null;
1358 | }
1359 | TreeNode node = new TreeNode(Integer.parseInt(root));
1360 | node.left = dfs(queue);
1361 | node.right = dfs(queue);
1362 | return node;
1363 | }
1364 | }
1365 | ```
1366 | * 
1367 |
1368 | ### 剑指 Offer 38. 字符串的排列
1369 | ```
1370 | 输入一个字符串,打印出该字符串中字符的所有排列。
1371 | 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
1372 | ```
1373 | ```
1374 | class Solution {
1375 | ArrayList list = new ArrayList();
1376 | boolean[] visited;
1377 | int n;
1378 |
1379 | public String[] permutation(String s) {
1380 | StringBuilder sb = new StringBuilder();
1381 | char[] arr = s.toCharArray();
1382 | n = arr.length;
1383 | visited = new boolean[n];
1384 | Arrays.sort(arr);
1385 | dfs(sb, arr);
1386 | return list.toArray(new String[0]);
1387 | }
1388 |
1389 | public void dfs(StringBuilder sb, char[] arr) {
1390 | if (sb.length() == n) {
1391 | list.add(sb.toString());
1392 | return;
1393 | }
1394 | for (int i = 0; i < n; i++) {
1395 | if (i >= 1 && !visited[i - 1] && arr[i - 1] == arr[i]) {
1396 | continue;
1397 | }
1398 | if (visited[i]) {
1399 | continue;
1400 | }
1401 | visited[i] = true;
1402 | sb.append(arr[i]);
1403 | dfs(sb, arr);
1404 | visited[i] = false;
1405 | sb.deleteCharAt(sb.length() - 1);
1406 | }
1407 | }
1408 | }
1409 | ```
1410 | * 
1411 |
1412 | ### 剑指 Offer 39. 数组中出现次数超过一半的数字
1413 | ```
1414 | 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
1415 | 你可以假设数组是非空的,并且给定的数组总是存在多数元素。
1416 | ```
1417 | ```
1418 | class Solution {
1419 | public int majorityElement(int[] nums) {
1420 | int c = nums[0];
1421 | int cnt = 1;
1422 | for (int i = 1; i < nums.length; i++) {
1423 | if (cnt == 0) {
1424 | c = nums[i];
1425 | cnt++;
1426 | } else if (nums[i] == c) {
1427 | cnt++;
1428 | } else {
1429 | cnt--;
1430 | }
1431 | }
1432 | return c;
1433 | }
1434 | }
1435 | ```
1436 | * 
1437 |
1438 | ### 剑指 Offer 40. 最小的k个数
1439 | ```
1440 | 输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
1441 | ```
1442 | ```
1443 | class Solution {
1444 | public int[] getLeastNumbers(int[] arr, int k) {
1445 | PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a);
1446 | for (int i : arr) {
1447 | pq.offer(i);
1448 | if (pq.size() > k) {
1449 | pq.poll();
1450 | }
1451 | }
1452 | int[] ans = new int[k];
1453 | int index = 0;
1454 | for (int i : pq) {
1455 | ans[index++] = i;
1456 | }
1457 | return ans;
1458 | }
1459 | }
1460 | ```
1461 | * 
1462 |
1463 |
1464 | ### 剑指 Offer 41. 数据流中的中位数
1465 | ```
1466 | 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
1467 |
1468 | 例如,
1469 | [2,3,4] 的中位数是 3
1470 | [2,3] 的中位数是 (2 + 3) / 2 = 2.5
1471 |
1472 | 设计一个支持以下两种操作的数据结构:
1473 | void addNum(int num) - 从数据流中添加一个整数到数据结构中。
1474 | double findMedian() - 返回目前所有元素的中位数。
1475 | ```
1476 | ```
1477 |
1478 | class MedianFinder {
1479 |
1480 | /**
1481 | * initialize your data structure here.
1482 | */
1483 | PriorityQueue queue1 = new PriorityQueue<>((v1, v2) -> v2 - v1);
1484 | PriorityQueue queue2 = new PriorityQueue();
1485 | int flag = -1;
1486 |
1487 | public MedianFinder() {
1488 |
1489 | }
1490 |
1491 | public void addNum(int num) {
1492 | if (flag == -1) {
1493 | queue1.offer(num);
1494 | flag = 0;
1495 | } else if (flag == 0) {
1496 | queue2.offer(num);
1497 | if (queue1.peek() > queue2.peek()) {
1498 | var temp = queue1.poll();
1499 | queue1.offer(queue2.poll());
1500 | queue2.offer(temp);
1501 | }
1502 | flag = 1;
1503 | } else {
1504 | if (num >= queue1.peek()) {
1505 | queue2.offer(num);
1506 | } else {
1507 | queue1.offer(num);
1508 | }
1509 | if (queue1.size() - queue2.size() >= 1) {
1510 | queue2.offer(queue1.poll());
1511 | } else if (queue2.size() - queue1.size() >= 2) {
1512 | queue1.offer(queue2.poll());
1513 | }
1514 | }
1515 | }
1516 |
1517 | public double findMedian() {
1518 | int size = queue1.size() + queue2.size();
1519 | if (size % 2 == 0) {
1520 | return (queue1.peek() * 1.0 + queue2.peek() * 1.0) / 2;
1521 | }
1522 | if (size == 1) {
1523 | return queue1.peek();
1524 | }
1525 | return queue2.peek();
1526 | }
1527 | }
1528 | ```
1529 | * 
1530 |
1531 | ### 剑指 Offer 42. 连续子数组的最大和
1532 | ```
1533 | 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
1534 | 要求时间复杂度为O(n)。
1535 | ```
1536 | ```
1537 | class Solution {
1538 | public int maxSubArray(int[] nums) {
1539 | int ans = Integer.MIN_VALUE;
1540 | int sum = 0;
1541 | for (int i = 0; i < nums.length; i++) {
1542 | if (sum >= 0) {
1543 | sum += nums[i];
1544 | } else {
1545 | sum = nums[i];
1546 | }
1547 | ans = Math.max(ans, sum);
1548 | }
1549 | return ans;
1550 | }
1551 | }
1552 | ```
1553 | * 
1554 |
1555 | ### 剑指 Offer 43. 1~n 整数中 1 出现的次数
1556 | ```
1557 | 输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
1558 | 例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
1559 | ```
1560 | ```
1561 | class Solution {
1562 | public int countDigitOne(int n) {
1563 | int ans = 0;
1564 | int range = 1;
1565 | int l = n / 10;
1566 | int cur = n % 10;
1567 | int r = 0;
1568 | while (!(l == 0 && cur == 0)) {
1569 | if (cur == 0) {
1570 | // 301 -> *1*
1571 | ans += l * range;
1572 | } else if (cur == 1) {
1573 | // 311
1574 | ans += l * range + r + 1;
1575 | } else {
1576 | // 321
1577 | ans += (l + 1) * range;
1578 | }
1579 |
1580 | r += cur * range;
1581 | cur = l % 10;
1582 | l /= 10;
1583 | range *= 10;
1584 | }
1585 | return ans;
1586 | }
1587 | }
1588 | ```
1589 | * 
1590 |
1591 | ### 剑指 Offer 44. 数字序列中某一位的数字
1592 | ```
1593 | 数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
1594 |
1595 | 请写一个函数,求任意第n位对应的数字。
1596 |
1597 | 输入:n = 3
1598 | 输出:3
1599 | ```
1600 | ```
1601 | class Solution {
1602 | public int findNthDigit(int n) {
1603 | if (n < 10) {
1604 | return n;
1605 | }
1606 | long cnt = 9;
1607 | long l = 1, r = 9, c = 1;
1608 |
1609 | while (cnt < n) {
1610 | r = r * 10 + 9;
1611 | l = l * 10;
1612 | c++;
1613 | cnt += c * (r - l + 1);
1614 | }
1615 | long s = cnt - c * (r - l + 1);
1616 | long gap = n - s - 1;
1617 | long gapC = gap / c;
1618 | long modC = gap % c;
1619 | long num = l + gapC;
1620 | String str = String.valueOf(num);
1621 | char ch = str.charAt((int) (modC));
1622 | return ch - '0';
1623 |
1624 | }
1625 | }
1626 | ```
1627 | * 
1628 |
1629 | ### 剑指 Offer 45. 把数组排成最小的数
1630 | ```
1631 | 输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
1632 | 输入: [10,2]
1633 | 输出: "102"
1634 | ```
1635 | ```
1636 | class Solution {
1637 | public String minNumber(int[] nums) {
1638 | String[] strs = new String[nums.length];
1639 | for(int i=0; i < nums.length; i++) {
1640 | strs[i] = String.valueOf(nums[i]);
1641 | }
1642 | Arrays.sort(strs, new Comparator() {
1643 |
1644 | public int compare(String a, String b) {
1645 | return (a + b).compareTo(b+a);
1646 | }
1647 | });
1648 | StringBuilder sb = new StringBuilder();
1649 | for(var str : strs) {
1650 | sb.append(str);
1651 | }
1652 | return sb.toString();
1653 | }
1654 | }
1655 | ```
1656 | * 
1657 |
1658 |
1659 | ### 剑指 Offer 46. 把数字翻译成字符串
1660 | ```
1661 | 给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
1662 | 输入: 12258
1663 | 输出: 5
1664 | 解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
1665 | ```
1666 | ```
1667 | class Solution {
1668 | public int translateNum(int num) {
1669 | char[] arr = String.valueOf(num).toCharArray();
1670 | int n = arr.length;
1671 |
1672 | int[] dp = new int[n];
1673 | // 1 2 2 5 8
1674 | // 1 2 3 5 5
1675 | dp[0] = 1;
1676 | for (int i = 1; i < n; i++) {
1677 | int c = arr[i] - '0';
1678 | int last = arr[i - 1] - '0';
1679 | dp[i] = dp[i - 1];
1680 | if (last * 10 + c >= 10 && last * 10 + c <= 25) {
1681 | dp[i] += i >= 2 ? dp[i - 2] : 1;
1682 | }
1683 | }
1684 | return dp[n - 1];
1685 | }
1686 | }
1687 | ```
1688 | * 
1689 |
1690 | ### 剑指 Offer 47. 礼物的最大价值
1691 | ```
1692 | 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,
1693 | 并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
1694 | 输入:
1695 | [
1696 | [1,3,1],
1697 | [1,5,1],
1698 | [4,2,1]
1699 | ]
1700 | 输出: 12
1701 | 解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
1702 |
1703 | ```
1704 | ```
1705 | class Solution {
1706 | public int maxValue(int[][] grid) {
1707 | int m = grid.length;
1708 | int n = grid[0].length;
1709 | for(int i=0; i < m; i++) {
1710 | for(int j=0; j < n; j++) {
1711 | int left = j>=1 ? grid[i][j-1] : 0;
1712 | int right = i>=1 ? grid[i-1][j] : 0;
1713 | grid[i][j] = Math.max(grid[i][j] + left, grid[i][j] + right);
1714 | }
1715 | }
1716 | return grid[m-1][n-1];
1717 |
1718 | }
1719 | }
1720 | ```
1721 |
1722 | * 
1723 |
1724 | ### 剑指 Offer 48. 最长不含重复字符的子字符串
1725 | ```
1726 | 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
1727 | 输入: "abcabcbb"
1728 | 输出: 3
1729 | 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
1730 | ```
1731 | ```
1732 | class Solution {
1733 | public int lengthOfLongestSubstring(String s) {
1734 | HashMap map = new HashMap();
1735 | int start=0;
1736 | int ans = 0;
1737 | for(int i=0; i < s.length(); i++) {
1738 | int last = map.getOrDefault(s.charAt(i), -1);
1739 | if(last == -1) {
1740 | ans = Math.max(ans, i- start + 1);
1741 | } else {
1742 | start = Math.max(start, last + 1);
1743 | ans = Math.max(ans, i- start + 1);
1744 | }
1745 | map.put(s.charAt(i), i);
1746 | }
1747 | return ans;
1748 | }
1749 | }
1750 | ```
1751 |
1752 | * 
1753 |
1754 |
1755 |
1756 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer-2012年书籍版/.DS_Store
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/BinaryTreeNode.java:
--------------------------------------------------------------------------------
1 | public class BinaryTreeNode {
2 | private int data;
3 | private BinaryTreeNode LchildNode;
4 | private BinaryTreeNode RchildNode;
5 |
6 | public BinaryTreeNode(int data) {
7 | super();
8 | this.data = data;
9 | }
10 |
11 | public int getData() {
12 | return data;
13 | }
14 |
15 | public void setData(int data) {
16 | this.data = data;
17 | }
18 |
19 | public BinaryTreeNode getLchildNode() {
20 | return LchildNode;
21 | }
22 |
23 | public void setLchildNode(BinaryTreeNode lchildNode) {
24 | LchildNode = lchildNode;
25 | }
26 |
27 | public BinaryTreeNode getRchildNode() {
28 | return RchildNode;
29 | }
30 |
31 | public void setRchildNode(BinaryTreeNode rchildNode) {
32 | RchildNode = rchildNode;
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No02.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 设计一个类,我们只能生成该类的一个实例。
3 | */
4 |
5 | public class No02 {
6 |
7 | }
8 |
9 | // 饿汉式 线程安全
10 | class A {
11 | private static final A instance = new A();
12 |
13 | private A() {
14 | }
15 |
16 | public static A getInstance() {
17 | return instance;
18 | }
19 | }
20 |
21 | // 懒汉式 线程安全写法
22 | class B {
23 | private static volatile B instance = null;
24 |
25 | private B() {
26 | }
27 |
28 | public static B getInstance() {
29 | if (instance == null) {
30 | synchronized (B.class) {
31 | if (instance == null)
32 | instance = new B();
33 | }
34 | }
35 | return instance;
36 | }
37 | }
38 |
39 | // 静态内部类方式 线程安全
40 | class C {
41 | private C() {
42 |
43 | }
44 |
45 | public static C getInstance() {
46 | return CHolder.INSTANCE;
47 | }
48 |
49 | private static class CHolder {
50 | private static final C INSTANCE = new C();
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No03.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 在一个二维数组中,每一行都按照从左到右递增
3 | * 的顺序排序,每一列都按照从上到下递增的顺序排序。
4 | * 请完成一个函数,输入这样的一个二维数组
5 | * 和一个整数,判断数组中是否函数该整数。
6 | */
7 |
8 | public class No03 {
9 |
10 | public static void main(String[] args) {
11 | int[][] arr = {{1, 2, 8, 9},
12 | {2, 4, 9, 12},
13 | {4, 7, 10, 13},
14 | {6, 8, 11, 15}};
15 |
16 | System.out.println(search(arr, 7));
17 | }
18 |
19 | private static boolean search(int[][] arr, int value) {
20 |
21 | int a = arr[0].length;
22 | int b = arr.length;
23 | int i = 0;
24 | int j = a - 1;
25 |
26 | while (i <= b - 1 && j >= 0) {
27 | if (arr[i][j] == value) {
28 | return true;
29 | }
30 | if (arr[i][j] > value) {
31 | j--;
32 | } else {
33 | i++;
34 | }
35 | }
36 | return false;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No04.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 请实现一个函数,把字符串中的每个空格替换成"%20"。
3 | * 例如输入"We are happy",则输出"We%20are%20happy"
4 | */
5 |
6 | public class No04 {
7 |
8 | public static void main(String[] args) {
9 | String str = "We are happy";
10 | char[] charArray = str.toCharArray();
11 | System.out.println(change(charArray));
12 | }
13 |
14 | private static String change(char[] charArray) {
15 |
16 | int n = charArray.length;
17 | int count = 0;
18 | for (int i = 0; i < charArray.length; i++) {
19 | if (charArray[i] == ' ') {
20 | count++;
21 | }
22 | }
23 | if (count == 0) {
24 | return null;
25 | }
26 | char[] temp = new char[n + 2 * count];
27 | int j = n + 2 * count - 1;
28 | int i = n - 1;
29 | while (i >= 0) {
30 | if (charArray[i] == ' ') {
31 | temp[j] = '0';
32 | temp[j - 1] = '2';
33 | temp[j - 2] = '%';
34 | j = j - 3;
35 | } else {
36 | temp[j] = charArray[i];
37 | j--;
38 | }
39 | i--;
40 | }
41 | return new String(temp);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No05.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个链表的头节点,从尾到头打印每个节点的值。
3 | */
4 |
5 | public class No05 {
6 |
7 | public static void main(String[] args) {
8 | Node node1 = new Node("A");
9 | Node node2 = new Node("B");
10 | Node node3 = new Node("C");
11 | Node node4 = new Node("D");
12 | Node node5 = new Node("E");
13 | node1.setNext(node2);
14 | node2.setNext(node3);
15 | node3.setNext(node4);
16 | node4.setNext(node5);
17 | Node newNode = reverse2(node1);
18 | while (newNode != null) {
19 | System.out.print(newNode.data + " ");
20 | newNode = newNode.getNext();
21 | }
22 |
23 |
24 | }
25 |
26 | private static Node reverse(Node head) {
27 | if (head.next == null) {
28 | return head;
29 | }
30 | Node reverseHead = reverse(head.getNext());
31 | head.getNext().setNext(head);
32 | head.setNext(null);
33 |
34 | return reverseHead;
35 |
36 | }
37 |
38 | private static Node reverse2(Node head) {
39 | Node pre = head;
40 | Node cur = head.getNext();
41 | Node temp;
42 | while (cur != null) {
43 | temp = cur.getNext();
44 | cur.setNext(pre);
45 | pre = cur;
46 | cur = temp;
47 | }
48 | head.setNext(null);
49 | return pre;
50 | }
51 | }
52 |
53 | class Node {
54 | String data;
55 | Node next;
56 |
57 | public Node(String data) {
58 | super();
59 | this.data = data;
60 | }
61 |
62 | public Node(String data, Node next) {
63 | super();
64 | this.data = data;
65 | this.next = next;
66 | }
67 |
68 | public String getData() {
69 | return data;
70 | }
71 |
72 | public void setData(String data) {
73 | this.data = data;
74 | }
75 |
76 | public Node getNext() {
77 | return next;
78 | }
79 |
80 | public void setNext(Node next) {
81 | this.next = next;
82 | }
83 |
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No06.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 根据前序遍历和中序遍历建立树
3 | */
4 |
5 | public class No06 {
6 |
7 | public static void main(String[] args) {
8 | String preOrder = "12473568";
9 | String midOrder = "47215386";
10 | BiTree tree = new BiTree(preOrder, midOrder, preOrder.length());
11 | tree.postRootTraverse(tree.root);
12 | }
13 |
14 | }
15 |
16 | class BiTree {
17 | TreeNode root;
18 |
19 | public BiTree(String preOrder, String midOrder, int count) {
20 | if (count <= 0) {
21 | return;
22 | }
23 | char c = preOrder.charAt(0);
24 | int i = 0;
25 | for (; i < count; i++) {
26 | if (midOrder.charAt(i) == c)
27 | break;
28 | }
29 |
30 | root = new TreeNode(c);
31 | root.setLchild(new BiTree(preOrder.substring(1, i + 1), midOrder.substring(0, i), i).root);
32 | root.setRchild(new BiTree(preOrder.substring(i + 1), midOrder.substring(i + 1), count - i - 1).root);
33 | }
34 |
35 |
36 | public void postRootTraverse(TreeNode root) {
37 | if (root != null) {
38 | postRootTraverse(root.getLchild());
39 | postRootTraverse(root.getRchild());
40 | System.out.print(root.getData());
41 | }
42 | }
43 | }
44 |
45 | class TreeNode {
46 | char data;
47 | TreeNode Lchild;
48 | TreeNode Rchild;
49 |
50 | public TreeNode(char data) {
51 | super();
52 | this.data = data;
53 | }
54 |
55 | public TreeNode(char data, TreeNode lchild, TreeNode rchild) {
56 | super();
57 | this.data = data;
58 | Lchild = lchild;
59 | Rchild = rchild;
60 | }
61 |
62 | public char getData() {
63 | return data;
64 | }
65 |
66 | public void setData(char data) {
67 | this.data = data;
68 | }
69 |
70 | public TreeNode getLchild() {
71 | return Lchild;
72 | }
73 |
74 | public void setLchild(TreeNode lchild) {
75 | Lchild = lchild;
76 | }
77 |
78 | public TreeNode getRchild() {
79 | return Rchild;
80 | }
81 |
82 | public void setRchild(TreeNode rchild) {
83 | Rchild = rchild;
84 | }
85 |
86 |
87 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No07.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | /**
4 | * 两个栈建立队列
5 | */
6 |
7 | public class No07 {
8 |
9 | private Stack s1 = new Stack();
10 | private Stack s2 = new Stack();
11 |
12 | public void offer(Object x) {
13 | s1.push(x);
14 |
15 | }
16 |
17 | public void poll() {
18 | if (s1.size() == 0 && s2.size() == 0) {
19 | try {
20 | throw new Exception("empty queue");
21 | } catch (Exception e) {
22 | e.printStackTrace();
23 | }
24 | } else {
25 | if (s2.size() != 0) {
26 | System.out.println(s2.peek().toString());
27 | s2.pop();
28 | } else {
29 | while (s1.size() > 0) {
30 | s2.push(s1.pop());
31 | }
32 | System.out.println(s2.peek().toString());
33 | s2.pop();
34 | }
35 | }
36 |
37 | }
38 |
39 | public static void main(String[] args) {
40 |
41 | No07 queue = new No07();
42 | queue.offer("a");
43 | queue.offer("b");
44 | queue.offer("c");
45 | queue.poll();
46 | queue.poll();
47 | queue.poll();
48 | queue.poll();
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No08.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 把一个数组最开始的若干个元素搬到数组的末尾,
3 | * 我们称之为数组的旋转。输入一个递增排序的数组
4 | * 的一个旋转,输出旋转数组的最小元素。例如数组
5 | * {3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
6 | */
7 |
8 | public class No08 {
9 |
10 | public static void main(String[] args) {
11 | int[] arr = {3, 4, 5, 1, 2};
12 | System.out.println(findMin(arr));
13 | }
14 |
15 | public static int findMin(int[] arr) {
16 | int left = 0;
17 | int right = arr.length - 1;
18 | if (arr[right] > arr[left]) {
19 | try {
20 | throw new Exception("非旋转数组");
21 | } catch (Exception e) {
22 | e.printStackTrace();
23 | return -1;
24 | }
25 | }
26 | while (left < right) {
27 | int mid = (left + right) / 2;
28 | //对于{1,0,1,1,1}之类的特殊处理
29 | if (arr[mid] == arr[left] && arr[left] == arr[right]) {
30 | return seachMin(arr, left, right);
31 | }
32 | if (right - left == 1)
33 | break;
34 | if (arr[mid] >= arr[left]) {
35 | left = mid;
36 | } else {
37 | right = mid;
38 | }
39 | }
40 | return arr[right];
41 | }
42 |
43 | private static int seachMin(int[] arr, int left, int right) {
44 | int result = arr[left];
45 | for (int i = left + 1; i <= right; ++i) {
46 | if (arr[i] < result)
47 | result = arr[i];
48 | }
49 | return result;
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No09.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 1,写一个函数,输入n,求斐波那契数列的第n项
3 | * 2,一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级台阶总共有多少种跳法
4 | */
5 |
6 | public class No09 {
7 |
8 | public static void main(String[] args) {
9 | System.out.println(fibonacci(5));
10 | System.out.println(getMethodNumber(10));
11 | }
12 |
13 | private static long fibonacci(int n) {
14 | long[] a = {0, 1};
15 | if (n < 2)
16 | return a[n];
17 | long fib1 = 0;
18 | long fib2 = 1;
19 | long fibN = 0;
20 | for (int i = 2; i <= n; i++) {
21 | fibN = fib1 + fib2;
22 | fib1 = fib2;
23 | fib2 = fibN;
24 | }
25 | return fibN;
26 |
27 | }
28 |
29 |
30 | private static int getMethodNumber(int n) {
31 | if (n == 0)
32 | return 0;
33 | if (n == 1)
34 | return 1;
35 | if (n == 2)
36 | return 2;
37 |
38 | return getMethodNumber(n - 1) + getMethodNumber(n - 2);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No10.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 请实现一个函数,输入一个整数,
3 | * 输出该二进制表示中1的个数。
4 | * 例如把9表示成二进制是1001, 有2位是1。
5 | * 因此如果输入9,该函数输出2。
6 | */
7 |
8 | public class No10 {
9 |
10 | public static void main(String[] args) {
11 | System.out.println(getNum(9));
12 | }
13 |
14 | public static int getNum(int n) {
15 | int num = 0;
16 | while (n != 0) {
17 | num++;
18 | n = (n - 1) & n;
19 | }
20 | return num;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No11.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 实现函数double Power(double base,int exponent),
3 | * 求base的exponent次方。不得使用库函数,
4 | * 同时不需要考虑大数问题。
5 | */
6 |
7 | public class No11 {
8 |
9 | public static void main(String[] args) {
10 | System.out.println(Power(2.0, 3));
11 | }
12 |
13 | public static double Power(double base, int exponent) {
14 | if (exponent == 0)
15 | return 1;
16 | if (exponent == 1)
17 | return base;
18 |
19 | double result = Power(base, exponent >> 1);
20 | result *= result;
21 | if ((exponent & 0x1) == 1) {
22 | result *= base;
23 | }
24 | return result;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No12.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入数字n,按顺序打印出从1最大的n位十进制数。
3 | * 比如输入3,则打印出1、2、3一直到最大的3位数即999
4 | */
5 |
6 | public class No12 {
7 |
8 | public static void main(String[] args) {
9 | printNum(3);
10 | }
11 |
12 | private static void printNum(int n) {
13 | if (n < 0)
14 | return;
15 | int[] array = new int[n];
16 | printArray(array, 0);
17 | }
18 |
19 | private static void printArray(int[] array, int n) {
20 |
21 | if (n != array.length) {
22 | for (int i = 0; i < 10; i++) {
23 | array[n] = i;
24 | printArray(array, n + 1);
25 | }
26 | } else {
27 | boolean flag = false;
28 | for (int j = 0; j < array.length; j++) {
29 | if (array[j] != 0) {
30 | flag = true;
31 | }
32 | if (flag) {
33 | System.out.print(array[j]);
34 | }
35 | }
36 | // 去掉空白行
37 | if (flag) {
38 | System.out.println();
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No13.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 给定单向链表的头指针和一个结点指针, 定义一个函数在O(1)时间删除该节点
3 | */
4 |
5 | public class No13 {
6 |
7 | public static void main(String[] args) {
8 | MyNode a = new MyNode("A");
9 | MyNode b = new MyNode("B");
10 | MyNode c = new MyNode("C");
11 | MyNode d = new MyNode("D");
12 | a.setNext(b);
13 | b.setNext(c);
14 | c.setNext(d);
15 | delete(a, d);
16 | MyNode temp = a;
17 | while (temp != null) {
18 | System.out.println(temp.getData());
19 | temp = temp.next;
20 | }
21 | }
22 |
23 | private static void delete(MyNode head, MyNode c) {
24 | // 如果是尾节点,只能遍历删除
25 | if (c.next == null) {
26 | while (head.next != c) {
27 | head = head.next;
28 | }
29 | head.next = null;
30 | } else if (head == c) {
31 | head = null;
32 | } else {
33 | c.setData(c.getNext().getData());
34 | c.setNext(c.getNext().getNext());
35 | }
36 |
37 | }
38 |
39 |
40 | }
41 |
42 | class MyNode {
43 | MyNode next;
44 | String data;
45 |
46 | public MyNode(String data) {
47 | super();
48 | this.data = data;
49 | }
50 |
51 | public MyNode getNext() {
52 | return next;
53 | }
54 |
55 | public void setNext(MyNode next) {
56 | this.next = next;
57 | }
58 |
59 | public String getData() {
60 | return data;
61 | }
62 |
63 | public void setData(String data) {
64 | this.data = data;
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No14.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,
3 | * 使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
4 | */
5 |
6 | public class No14 {
7 |
8 | public static void main(String[] args) {
9 | int[] array = {3, 7, 4, 8, 23, 56, 77, 89, 46, 11, 66, 77};
10 | mysort(array);
11 | for (int a : array) {
12 | System.out.println(" " + a);
13 | }
14 | }
15 |
16 | private static void mysort(int[] array) {
17 | if (array == null) {
18 | return;
19 | }
20 | int left = 0;
21 | int right = array.length - 1;
22 | while (left < right) {
23 | while (left < right && !isEven(array[left])) {
24 | left++;
25 | }
26 | while (left < right && isEven(array[right])) {
27 | right--;
28 | }
29 | if (left < right) {
30 | int temp = array[right];
31 | array[right] = array[left];
32 | array[left] = temp;
33 | }
34 | if (left >= right) {
35 | break;
36 | }
37 | }
38 | }
39 |
40 | private static boolean isEven(int i) {
41 | return (i & 0x1) == 0;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No15.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个链表,输出该链表中倒数第K个结点。
3 | * 为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。
4 | * 例如一个链表有6个结点,从头结点开始它们的值依次是1,2,3,4,5,6。
5 | * 这个链表的倒数第3个结点是值为4的结点。
6 | * (注意代码鲁棒性,考虑输入空指针,链表结点总数少于k,输入的k参数为0)
7 | */
8 |
9 | public class No15 {
10 |
11 | public static void main(String[] args) {
12 | Node15 a = new Node15("1");
13 | Node15 b = new Node15("2");
14 | Node15 c = new Node15("3");
15 | Node15 d = new Node15("4");
16 | Node15 e = new Node15("5");
17 | Node15 f = new Node15("6");
18 | a.setNext(b);
19 | b.setNext(c);
20 | c.setNext(d);
21 | d.setNext(e);
22 | e.setNext(f);
23 |
24 | System.out.print(FindDataFromTail(a, 5));
25 | }
26 |
27 | private static String FindDataFromTail(Node15 a, int k) {
28 |
29 | if (a == null)
30 | return null;
31 | if (k == 0) {
32 | System.out.println("k应该从1开始");
33 | return null;
34 | }
35 | Node15 Node1 = a;
36 | Node15 Node2 = null;
37 | for (int i = 0; i < k - 1; i++) {
38 | if (Node1.getNext() == null) {
39 | System.out.println("k不应该大于链表长度");
40 | return null;
41 | }
42 | Node1 = Node1.getNext();
43 | }
44 | Node2 = a;
45 |
46 | while (Node1.getNext() != null) {
47 | Node1 = Node1.getNext();
48 | Node2 = Node2.getNext();
49 | }
50 | return Node2.getData();
51 |
52 | }
53 | }
54 |
55 | class Node15 {
56 | private String data;
57 | private Node15 Next;
58 |
59 | public Node15(String data) {
60 | super();
61 | this.data = data;
62 | }
63 |
64 | public String getData() {
65 | return data;
66 | }
67 |
68 | public void setData(String data) {
69 | this.data = data;
70 | }
71 |
72 | public Node15 getNext() {
73 | return Next;
74 | }
75 |
76 | public void setNext(Node15 next) {
77 | Next = next;
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No15_2.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 求链表的中间结点。如果链表中结点总数为奇数,
3 | * 返回中间结点;如果结点总数为偶数,返回中间两个结点的任意一个
4 | */
5 |
6 | public class No15_2 {
7 | public static void main(String[] args) {
8 | Node15 a = new Node15("1");
9 | Node15 b = new Node15("2");
10 | Node15 c = new Node15("3");
11 | Node15 d = new Node15("4");
12 | Node15 e = new Node15("5");
13 | Node15 f = new Node15("6");
14 | Node15 g = new Node15("7");
15 |
16 | a.setNext(b);
17 | b.setNext(c);
18 | c.setNext(d);
19 | d.setNext(e);
20 | e.setNext(f);
21 | f.setNext(g);
22 | Node15 mid = getMid(a);
23 | System.out.println(mid.getData());
24 | }
25 |
26 | private static Node15 getMid(Node15 a) {
27 |
28 | if (a == null) {
29 | return null;
30 | }
31 | Node15 slow = a;
32 | Node15 fast = a;
33 | while (fast.getNext() != null && fast.getNext().getNext() != null) {
34 | slow = slow.getNext();
35 | fast = fast.getNext().getNext();
36 | }
37 |
38 | return slow;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No16.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 定义一个函数,输入一个链表的头结点,
3 | * 反转该链表并输出反转后链表的头结点
4 | */
5 |
6 | // 具体同No5
7 | public class No16 {
8 | }
9 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No17.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入两个递增排序的链表,合并这两个链表
3 | * 并使新链表中结点仍然是按照递增排序的。
4 | * 例如输入1->3->5->7和2->4->6->8,
5 | * 则合并之后的升序链表应该是1->2->3->4->5->6->7->8 。
6 | */
7 |
8 | public class No17 {
9 |
10 | public static void main(String[] args) {
11 | Node17 node1 = new Node17(1);
12 | Node17 node2 = new Node17(3);
13 | Node17 node3 = new Node17(5);
14 | Node17 node4 = new Node17(7);
15 | node1.setNext(node2);
16 | node2.setNext(node3);
17 | node3.setNext(node4);
18 | Node17 node5 = new Node17(2);
19 | Node17 node6 = new Node17(4);
20 | Node17 node7 = new Node17(6);
21 |
22 | node5.setNext(node6);
23 | node6.setNext(node7);
24 | Node17 head = merge(node1, node5);
25 | while (head != null) {
26 | System.out.print(head.getData() + " ");
27 | head = head.getNext();
28 | }
29 |
30 | }
31 |
32 | private static Node17 merge(Node17 a, Node17 b) {
33 | if (a == null && b == null)
34 | return null;
35 | if (a == null)
36 | return b;
37 | if (b == null)
38 | return a;
39 |
40 | Node17 head = a.getData() > b.getData() ? b : a;
41 | Node17 index1 = head.getNext();
42 | Node17 index2 = head == a ? b : a;
43 |
44 | while (index1 != null && index2 != null) {
45 | if (index1.getData() < index2.getData()) {
46 | head.setNext(index1);
47 | index1 = index1.getNext();
48 | } else {
49 | head.setNext(index2);
50 | index2 = index2.getNext();
51 | }
52 | head = head.getNext();
53 | }
54 |
55 | if (index1 == null) {
56 | while (index2 != null) {
57 | head.setNext(index2);
58 | index2 = index2.getNext();
59 | head = head.getNext();
60 | }
61 | } else {
62 | while (index1 != null) {
63 | head.setNext(index1);
64 | index1 = index1.getNext();
65 | head = head.getNext();
66 | }
67 | }
68 | return a.getData() > b.getData() ? b : a;
69 | }
70 | }
71 |
72 | class Node17 {
73 | int data;
74 | Node17 next;
75 |
76 | public Node17(int data) {
77 | super();
78 | this.data = data;
79 | }
80 |
81 | public int getData() {
82 | return data;
83 | }
84 |
85 | public void setData(int data) {
86 | this.data = data;
87 | }
88 |
89 | public Node17 getNext() {
90 | return next;
91 | }
92 |
93 | public void setNext(Node17 next) {
94 | this.next = next;
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No18.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入两颗二叉树A和B,判断B是不是A的子结构
3 | */
4 |
5 | public class No18 {
6 |
7 | public static void main(String[] args) {
8 |
9 | BinaryTreeNode node1 = new BinaryTreeNode(8);
10 | BinaryTreeNode node2 = new BinaryTreeNode(8);
11 | BinaryTreeNode node3 = new BinaryTreeNode(7);
12 | BinaryTreeNode node4 = new BinaryTreeNode(9);
13 | BinaryTreeNode node5 = new BinaryTreeNode(2);
14 | BinaryTreeNode node6 = new BinaryTreeNode(4);
15 | BinaryTreeNode node7 = new BinaryTreeNode(7);
16 | node1.setLchildNode(node2);
17 | node1.setRchildNode(node3);
18 | node2.setLchildNode(node4);
19 | node2.setRchildNode(node5);
20 | node5.setLchildNode(node6);
21 | node5.setRchildNode(node7);
22 |
23 | BinaryTreeNode a = new BinaryTreeNode(8);
24 | BinaryTreeNode b = new BinaryTreeNode(9);
25 | BinaryTreeNode c = new BinaryTreeNode(2);
26 | a.setLchildNode(b);
27 | a.setRchildNode(c);
28 | System.out.println(hasSubTree(node1, a));
29 | }
30 |
31 | private static boolean hasSubTree(BinaryTreeNode root1, BinaryTreeNode root2) {
32 | boolean result = false;
33 | if (root1 != null && root2 != null) {
34 | if (root1.getData() == root2.getData()) {
35 | result = doseTree1HaveTree2(root1, root2);
36 | if (!result) {
37 | result = hasSubTree(root1.getLchildNode(), root2);
38 | }
39 | if (!result)
40 | result = hasSubTree(root1.getRchildNode(), root2);
41 | }
42 | }
43 | return result;
44 |
45 | }
46 |
47 | private static boolean doseTree1HaveTree2(BinaryTreeNode root1,
48 | BinaryTreeNode root2) {
49 | if (root2 == null)
50 | return true;
51 | if (root1 == null)
52 | return false;
53 | if (root1.getData() != root2.getData()) {
54 | return false;
55 | }
56 |
57 | return doseTree1HaveTree2(root1.getLchildNode(), root2.getLchildNode())
58 | && doseTree1HaveTree2(root1.getRchildNode(), root2.getRchildNode());
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No19.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 请完成一个函数,输入一个二叉树,该函数输出它的镜像
3 | */
4 |
5 | public class No19 {
6 | public static void main(String[] args) {
7 | BinaryTreeNode node1 = new BinaryTreeNode(8);
8 | BinaryTreeNode node2 = new BinaryTreeNode(6);
9 | BinaryTreeNode node3 = new BinaryTreeNode(10);
10 | BinaryTreeNode node4 = new BinaryTreeNode(5);
11 | BinaryTreeNode node5 = new BinaryTreeNode(7);
12 | BinaryTreeNode node6 = new BinaryTreeNode(9);
13 | BinaryTreeNode node7 = new BinaryTreeNode(11);
14 | node1.setLchildNode(node2);
15 | node1.setRchildNode(node3);
16 | node2.setLchildNode(node4);
17 | node2.setRchildNode(node5);
18 | node3.setLchildNode(node6);
19 | node3.setRchildNode(node7);
20 | mirror(node1);
21 | print(node1);
22 | }
23 |
24 | private static void print(BinaryTreeNode root) {
25 | if (root != null) {
26 | System.out.println(root.getData());
27 | print(root.getLchildNode());
28 | print(root.getRchildNode());
29 | }
30 | }
31 |
32 | private static void mirror(BinaryTreeNode root) {
33 | if (root == null) {
34 | return;
35 | }
36 | if (root.getLchildNode() == null && root.getRchildNode() == null) {
37 | return;
38 | }
39 | BinaryTreeNode temp = root.getLchildNode();
40 | root.setLchildNode(root.getRchildNode());
41 | root.setRchildNode(temp);
42 | mirror(root.getLchildNode());
43 | mirror(root.getRchildNode());
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No20.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
3 | */
4 |
5 | public class No20 {
6 |
7 |
8 | public static void main(String[] args) {
9 | int[][] a = create(5, 5);
10 | print(a);
11 | clockWisePrint(a, 0, 4);
12 | }
13 |
14 | private static void clockWisePrint(int[][] a, int i, int j) {
15 | if (j < i)
16 | return;
17 | if (j == i) {
18 | System.out.print(a[i][j] + " ");
19 | return;
20 | }
21 | int y = i;
22 | while (y <= j) {
23 | System.out.print(a[i][y] + " ");
24 | y++;
25 | }
26 | y = i + 1;
27 | while (y <= j) {
28 | System.out.print(a[y][j] + " ");
29 | y++;
30 | }
31 | y = j - 1;
32 | while (y >= i) {
33 | System.out.print(a[j][y] + " ");
34 | y--;
35 | }
36 |
37 | y = j - 1;
38 | while (y >= i + 1) {
39 | System.out.print(a[y][i] + " ");
40 | y--;
41 | }
42 |
43 |
44 | clockWisePrint(a, i + 1, j - 1);
45 |
46 | }
47 |
48 | private static void print(int[][] a) {
49 | for (int i = 0; i < a.length; i++) {
50 | for (int j = 0; j < a[i].length; j++) {
51 | System.out.print(a[i][j] + " ");
52 | }
53 | System.out.println();
54 | }
55 | }
56 |
57 | public static int[][] create(int row, int line) {
58 | int[][] a = new int[row][line];
59 | int num = 1;
60 | for (int i = 0; i < row; i++) {
61 | for (int j = 0; j < line; j++) {
62 | a[i][j] = num++;
63 | }
64 | }
65 | return a;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No21.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | /**
4 | * 定义栈的数据结构,请在该类型中实现一个能够得到
5 | * 栈的最小元素的min函数。
6 | * 在该栈中,调用min、push以及pop的时间复杂度都是O(1)。
7 | */
8 |
9 | public class No21 {
10 |
11 | public static void main(String[] args) {
12 | MyStack a = new MyStack();
13 | System.out.println(a.min());
14 | a.push(10);
15 | a.push(11);
16 | System.out.println(a.min());
17 | }
18 |
19 | }
20 |
21 | class MyStack {
22 | private Stack stack1, stackHelp;
23 |
24 | public MyStack() {
25 | stack1 = new Stack();
26 | stackHelp = new Stack();
27 | }
28 |
29 | public void push(int num) {
30 | stack1.push(num);
31 | if (stackHelp.size() == 0 || num < stackHelp.peek()) {
32 | stackHelp.push(num);
33 | } else {
34 | stackHelp.push(stackHelp.peek());
35 | }
36 | }
37 |
38 | public void pop() {
39 | stack1.pop();
40 | stackHelp.pop();
41 |
42 | }
43 |
44 | public Integer min() {
45 | if (stackHelp.size() == 0) {
46 | return null;
47 | }
48 | return stackHelp.peek();
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No22.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | /**
4 | * 输入两个整数序列,第一个序列表示栈的压入顺序,
5 | * 请判断第二个序列是否为该栈的弹出顺序。
6 | * 假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈
7 | * 的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列
8 | * 但4、3、5、1、2就不可能是该压栈序列的弹出序列
9 | */
10 |
11 | public class No22 {
12 |
13 | public static void main(String[] args) {
14 | Integer[] pushOrder = {1, 2, 3, 4, 5};
15 | Integer[] popOrder = {4, 5, 3, 1, 2};
16 | System.out.println(isRight(pushOrder, popOrder, 5));
17 | }
18 |
19 | private static boolean isRight(Integer[] pushOrder, Integer[] popOrder, int n) {
20 |
21 | Stack stack = new Stack();
22 | int count = 0;
23 | for (int i = 0; i < popOrder.length; i++) {
24 | if (!stack.isEmpty() && stack.peek() == popOrder[i])
25 | stack.pop();
26 | else {
27 | if (count == pushOrder.length)
28 | return false;
29 | else {
30 | do {
31 | stack.push(pushOrder[count++]);
32 | }
33 | while (stack.peek() != popOrder[i] && count != pushOrder.length);
34 | if (stack.peek() == popOrder[i])
35 | stack.pop();
36 | else {
37 | return false;
38 | }
39 | }
40 | }
41 | }
42 | return true;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No23.java:
--------------------------------------------------------------------------------
1 | import java.util.LinkedList;
2 | import java.util.Queue;
3 |
4 | /**
5 | * 从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印
6 | */
7 |
8 | public class No23 {
9 |
10 | public static void main(String[] args) {
11 | BinaryTreeNode node1 = new BinaryTreeNode(8);
12 | BinaryTreeNode node2 = new BinaryTreeNode(6);
13 | BinaryTreeNode node3 = new BinaryTreeNode(10);
14 | BinaryTreeNode node4 = new BinaryTreeNode(5);
15 | BinaryTreeNode node5 = new BinaryTreeNode(7);
16 | BinaryTreeNode node6 = new BinaryTreeNode(9);
17 | BinaryTreeNode node7 = new BinaryTreeNode(11);
18 | node1.setLchildNode(node2);
19 | node1.setRchildNode(node3);
20 | node2.setLchildNode(node4);
21 | node2.setRchildNode(node5);
22 | node3.setLchildNode(node6);
23 | node3.setRchildNode(node7);
24 |
25 | printFromTopToBottom(node1);
26 | }
27 |
28 | private static void printFromTopToBottom(BinaryTreeNode root) {
29 | if (root == null)
30 | return;
31 | Queue queue = new LinkedList();
32 | queue.add(root);
33 | while (!queue.isEmpty()) {
34 | BinaryTreeNode node = queue.poll();
35 | System.out.println(node.getData());
36 | if (node.getLchildNode() != null) {
37 | queue.add(node.getLchildNode());
38 | }
39 | if (node.getRchildNode() != null) {
40 | queue.add(node.getRchildNode());
41 | }
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No24.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个整数数组,
3 | * 判断该数组是不是某二叉搜索树的后序遍历的结果。
4 | * 如果是则返回true,否则返回false。
5 | * 假设输入的数组的任意两个数字都互不相同
6 | */
7 |
8 | public class No24 {
9 |
10 | public static void main(String[] args) {
11 | int[] array = {5, 7, 6, 9, 11, 10, 8};
12 | // int[] array={7,4,6,5};
13 |
14 | boolean b = verfiySequenceOfBST(array, 0, 6);
15 | System.out.println(b);
16 | }
17 |
18 | private static boolean verfiySequenceOfBST(int[] array, int start, int end) {
19 |
20 | if (array == null || start > end || start < 0 || end < 0)
21 | return false;
22 |
23 | if (start == end)
24 | return true;
25 |
26 | int root = array[end];
27 |
28 | int i = start;
29 | for (; i <= end; i++) {
30 | if (array[i] > root)
31 | break;
32 | }
33 |
34 | int j = i;
35 | for (; j <= end; j++) {
36 | if (array[j] < root)
37 | return false;
38 | }
39 |
40 | boolean left = true;
41 | if (i > start) {
42 | left = verfiySequenceOfBST(array, start, i - 1);
43 | }
44 |
45 | boolean right = true;
46 | if (i < end) {
47 |
48 | right = verfiySequenceOfBST(array, i, end - 1);
49 | }
50 | return (left && right);
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No25.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | /**
4 | * 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。
5 | * 从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
6 | */
7 |
8 | public class No25 {
9 |
10 | public static void main(String[] args) {
11 |
12 | BinaryTreeNode root = new BinaryTreeNode(10);
13 | BinaryTreeNode node1 = new BinaryTreeNode(5);
14 | BinaryTreeNode node2 = new BinaryTreeNode(4);
15 | BinaryTreeNode node3 = new BinaryTreeNode(7);
16 | BinaryTreeNode node4 = new BinaryTreeNode(12);
17 | root.setLchildNode(node1);
18 | root.setRchildNode(node4);
19 | node1.setLchildNode(node2);
20 | node1.setRchildNode(node3);
21 | findPath(root, 22);
22 | }
23 |
24 | private static void findPath(BinaryTreeNode root, int i) {
25 | if (root == null)
26 | return;
27 | Stack stack = new Stack();
28 | int currentSum = 0;
29 | findPath(root, i, stack, currentSum);
30 | }
31 |
32 | private static void findPath(BinaryTreeNode root, int i,
33 | Stack stack, int currentSum) {
34 | currentSum += root.getData();
35 | stack.push(root.getData());
36 | if (root.getLchildNode() == null && root.getRchildNode() == null) {
37 | if (currentSum == i) {
38 | System.out.println("找到路径");
39 | for (int path : stack) {
40 | System.out.println(path + " ");
41 | }
42 | }
43 | }
44 | if (root.getLchildNode() != null) {
45 | findPath(root.getLchildNode(), i, stack, currentSum);
46 | }
47 | if (root.getRchildNode() != null) {
48 | findPath(root.getRchildNode(), i, stack, currentSum);
49 | }
50 |
51 | stack.pop();
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No26.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 请实现函数ComplexListNode* Clone(ComplexListNode* pHead),
3 | * 复制一个复杂链表。在复杂链表中,
4 | * 每个结点除了有一个m_pNext指针指向下一个结点外,
5 | * 还有一个m_pSibling指向链表中的任意结点或者NULL
6 | */
7 |
8 | public class No26 {
9 |
10 | public static void main(String[] args) {
11 | ComplexListNode node1 = new ComplexListNode(1);
12 | ComplexListNode node2 = new ComplexListNode(2);
13 | ComplexListNode node3 = new ComplexListNode(3);
14 | ComplexListNode node4 = new ComplexListNode(4);
15 | ComplexListNode node5 = new ComplexListNode(5);
16 | node1.next = node2;
17 | node2.next = node3;
18 | node3.next = node4;
19 | node4.next = node5;
20 | node1.sibling = node3;
21 | node2.sibling = node5;
22 | node4.sibling = node2;
23 | ComplexListNode result = clone(node1);
24 | while (result != null) {
25 | System.out.println(result.data);
26 | result = result.next;
27 | }
28 | }
29 |
30 | private static ComplexListNode clone(ComplexListNode head) {
31 | cloneNodes(head);
32 | copySibingNodes(head);
33 | return separateNodes(head);
34 | }
35 |
36 | private static ComplexListNode separateNodes(ComplexListNode head) {
37 | ComplexListNode node = head;
38 | ComplexListNode cloneHead = null;
39 | ComplexListNode cloneNode = null;
40 | if (node != null) {
41 | cloneNode = node.next;
42 | cloneHead = cloneNode;
43 | node.next = cloneNode.next;
44 | node = node.next;
45 | }
46 | while (node != null) {
47 | cloneNode.next = node.next;
48 | cloneNode = cloneNode.next;
49 | node.next = cloneNode.next;
50 | node = node.next;
51 | }
52 | return cloneHead;
53 | }
54 |
55 | private static void copySibingNodes(ComplexListNode head) {
56 | ComplexListNode node = head;
57 | while (node != null) {
58 | ComplexListNode cloneNode = node.next;
59 |
60 | if (node.sibling != null) {
61 | cloneNode.sibling = node.sibling.next;
62 | }
63 | node = cloneNode.next;
64 | }
65 |
66 | }
67 |
68 | private static void cloneNodes(ComplexListNode head) {
69 | ComplexListNode node = head;
70 | while (node != null) {
71 | ComplexListNode cloneNode = new ComplexListNode(node.data);
72 | cloneNode.next = node.next;
73 | node.next = cloneNode;
74 | node = cloneNode.next;
75 | }
76 | }
77 |
78 | }
79 |
80 | class ComplexListNode {
81 | int data;
82 | ComplexListNode next;
83 | ComplexListNode sibling;
84 |
85 | public ComplexListNode(int data) {
86 | super();
87 | this.data = data;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No27.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
3 | * 要求不能创建人和新的结点,只能调整树中结点指针的指向。
4 | */
5 |
6 | public class No27 {
7 |
8 | public static void main(String[] args) {
9 | BinaryTreeNode root = new BinaryTreeNode(10);
10 | BinaryTreeNode node1 = new BinaryTreeNode(6);
11 | BinaryTreeNode node2 = new BinaryTreeNode(14);
12 | BinaryTreeNode node3 = new BinaryTreeNode(4);
13 | BinaryTreeNode node4 = new BinaryTreeNode(8);
14 | BinaryTreeNode node5 = new BinaryTreeNode(12);
15 | BinaryTreeNode node6 = new BinaryTreeNode(16);
16 | root.setLchildNode(node1);
17 | root.setRchildNode(node2);
18 | node1.setLchildNode(node3);
19 | node1.setRchildNode(node4);
20 | node2.setLchildNode(node5);
21 | node2.setRchildNode(node6);
22 |
23 | BinaryTreeNode head = covert(root);
24 |
25 | while (head != null) {
26 | System.out.println(head.getData());
27 | head = head.getRchildNode();
28 | }
29 | }
30 |
31 | private static BinaryTreeNode covert(BinaryTreeNode root) {
32 | BinaryTreeNode lastNodeList = null;
33 | lastNodeList = convertNode(root, lastNodeList);
34 | while (lastNodeList != null && lastNodeList.getLchildNode() != null) {
35 | lastNodeList = lastNodeList.getLchildNode();
36 | }
37 | return lastNodeList;
38 | }
39 |
40 | private static BinaryTreeNode convertNode(BinaryTreeNode root,
41 | BinaryTreeNode lastNodeList) {
42 | if (root == null)
43 | return null;
44 | BinaryTreeNode current = root;
45 | if (current.getLchildNode() != null) {
46 | lastNodeList = convertNode(current.getLchildNode(), lastNodeList);
47 | }
48 |
49 | current.setLchildNode(lastNodeList);
50 |
51 | if (lastNodeList != null) {
52 | lastNodeList.setRchildNode(current);
53 | }
54 | lastNodeList = current;
55 | if (current.getRchildNode() != null) {
56 | lastNodeList = convertNode(current.getRchildNode(), lastNodeList);
57 | }
58 | return lastNodeList;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No28.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个字符串,打印出该字符串中字符的所有排列。
3 | * 例如输入字符串abc, 则打印出由字符串a、b、c所能
4 | * 排列出来的所有字符串abc、acb、bac、bca、cab和cba
5 | */
6 |
7 | public class No28 {
8 |
9 | public static void main(String[] args) {
10 | myPrint("abc");
11 | }
12 |
13 | private static void myPrint(String str) {
14 | if (str == null)
15 | return;
16 | char[] chs = str.toCharArray();
17 | myPrint(chs, 0);
18 | }
19 |
20 | private static void myPrint(char[] str, int i) {
21 | if (i >= str.length)
22 | return;
23 | if (i == str.length - 1) {
24 | System.out.println(String.valueOf(str));
25 | } else {
26 | for (int j = i; j < str.length; j++) {
27 | char temp = str[j];
28 | str[j] = str[i];
29 | str[i] = temp;
30 |
31 | myPrint(str, i + 1);
32 |
33 | temp = str[j];
34 | str[j] = str[i];
35 | str[i] = temp;
36 | }
37 | }
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No29.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 数组中有一个数字出现的次数超过数组长度的一半,
3 | * 请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。
4 | * 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
5 | */
6 |
7 | public class No29 {
8 |
9 | public static void main(String[] args) {
10 | int[] arr = {1, 2, 3, 2, 2, 2, 5, 4, 2};
11 | System.out.println(findNum(arr));
12 | }
13 |
14 | private static Integer findNum(int[] arr) {
15 | if (arr == null)
16 | return null;
17 |
18 | int result = arr[0];
19 | int count = 1;
20 |
21 | for (int i = 1; i < arr.length; i++) {
22 | if (count == 0) {
23 | result = arr[i];
24 | count = 1;
25 | } else if (arr[i] == result) {
26 | count++;
27 | } else {
28 | count--;
29 | }
30 | }
31 | return result;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No30.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 题目:输入n个整数,输出其中最小的k个。
3 | * 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
4 | */
5 | package sort;
6 |
7 | public class No30 {
8 |
9 | public static void main(String[] args) {
10 | int[] arr = {1, 3, 4, 2, 7, 8, 9, 10, 14, 16};
11 | System.out.println(minK(arr, 1));
12 | System.out.println(minK(arr, 2));
13 | System.out.println(minK(arr, 3));
14 | System.out.println(minK(arr, 4));
15 | System.out.println(minK(arr, 5));
16 | System.out.println(minK(arr, 6));
17 | }
18 |
19 | public static int minK(int[] arr, int k) {
20 | return minK(arr, k, 0, arr.length - 1);
21 | }
22 |
23 | public static int minK(int[] arr, int k, int start, int end) {
24 | int mid = partition(arr, start, end);
25 | if (mid - start == k - 1) {
26 | return arr[mid];
27 | } else if (mid - start > k - 1) {
28 | return minK(arr, k, start, mid - 1);
29 | } else {
30 | return minK(arr, k - 1 - (mid - start), mid + 1, end);
31 | }
32 | }
33 |
34 |
35 | public static int partition(int[] arr, int start, int end) {
36 | int key = arr[start];
37 | int keyIndex = start;
38 | start++;
39 | for (int i = start; i <= end; i++) {
40 | if (arr[i] < key) {
41 | swap(arr, i, start);
42 | start++;
43 | }
44 | }
45 | swap(arr, keyIndex, start - 1);
46 | return start - 1;
47 | }
48 |
49 |
50 | public static void swap(int[] arr, int i, int j) {
51 | int temp = arr[i];
52 | arr[i] = arr[j];
53 | arr[j] = temp;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No31.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个整型数组,数组里有正数,也有负数。
3 | * 数组中一个或连续的多个整数组成一个子数组。
4 | * 求所有子数组的和的最大值。要求时间复杂度为O(n)
5 | */
6 |
7 | public class No31 {
8 |
9 | public static void main(String[] args) {
10 | int[] arr = {1, -2, 3, 10, -4, 7, 2, -5};
11 | System.out.println(maxSub(arr));
12 | }
13 |
14 | private static int maxSub(int[] arr) {
15 | int max = 0;
16 | int n = arr.length;
17 | int sum = 0;
18 | for (int i = 0; i < n; i++) {
19 | sum += arr[i];
20 | if (sum > max)
21 | max = sum;
22 | else if (sum < 0)
23 | sum = 0;
24 | }
25 | return max;
26 |
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No32.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。
3 | * 例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现5次。
4 | */
5 |
6 | public class No32 {
7 |
8 | public static void main(String[] args) {
9 | System.out.println(countOne(115));
10 |
11 | }
12 |
13 | private static long countOne(int n) {
14 | long count = 0;
15 | long i = 1;
16 | long current = 0, after = 0, before = 0;
17 | while ((n / i) != 0) {
18 | current = (n / i) % 10;
19 | before = n / (i * 10);
20 | after = n - (n / i) * i;
21 |
22 | if (current > 1)
23 | count = count + (before + 1) * i;
24 | else if (current == 0)
25 | count = count + before * i;
26 | else if (current == 1)
27 | count = count + before * i + after + 1;
28 | i = i * 10;
29 | }
30 | return count;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No33.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,
3 | * 打印能拼接出所有数字中最小的一个。
4 | * 例如输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323
5 | */
6 |
7 | public class No33 {
8 |
9 | public static void main(String[] args) {
10 | int[] array = {321, 32, 3};
11 | printMin(array);
12 | }
13 |
14 | private static void printMin(int[] array) {
15 | int[] clone = array.clone();
16 | printMin(clone, 0, clone.length - 1);
17 | for (int i : clone)
18 | System.out.print(i);
19 | }
20 |
21 | private static void printMin(int[] array, int start, int end) {
22 |
23 | if (start < end) {
24 | int main_number = array[end];
25 | int small_cur = start;
26 | for (int j = start; j < end; j++) {
27 | if (isSmall(String.valueOf(array[j]), String.valueOf(main_number))) {
28 | int temp = array[j];
29 | array[j] = array[small_cur];
30 | array[small_cur] = temp;
31 | small_cur++;
32 | }
33 | }
34 | array[end] = array[small_cur];
35 | array[small_cur] = main_number;
36 | printMin(array, 0, small_cur - 1);
37 | printMin(array, small_cur + 1, end);
38 | }
39 |
40 | }
41 |
42 | public static boolean isSmall(String m, String n) {
43 | String left = m + n;
44 | String right = n + m;
45 | boolean result = false;
46 | for (int i = 0; i < left.length(); i++) {
47 | if (left.charAt(i) < right.charAt(i))
48 | return true;
49 | else if (left.charAt(i) > right.charAt(i))
50 | return false;
51 | }
52 |
53 | return result;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No34.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 我们把只包含因子2,3和5的数称作丑数。求按从小到大的顺序的第1500个丑数。
3 | * 例如6、8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做第一个丑数。
4 | */
5 |
6 | public class No34 {
7 |
8 | public static void main(String[] args) {
9 |
10 | System.out.println(getUgly(20));
11 |
12 | }
13 |
14 | private static int getUgly(int n) {
15 | if (n < 0)
16 | return 0;
17 | int[] uglyArray = new int[n];
18 | uglyArray[0] = 1;
19 | int multiply2 = 0;
20 | int multiply3 = 0;
21 | int multiply5 = 0;
22 | for (int i = 1; i < n; i++) {
23 | int min = getMin(uglyArray[multiply2] * 2, uglyArray[multiply3] * 3, uglyArray[multiply5] * 5);
24 | uglyArray[i] = min;
25 | System.out.println(uglyArray[i]);
26 | while (uglyArray[multiply2] * 2 == uglyArray[i])
27 | multiply2++;
28 | while (uglyArray[multiply3] * 3 == uglyArray[i])
29 | multiply3++;
30 | while (uglyArray[multiply5] * 5 == uglyArray[i])
31 | multiply5++;
32 | }
33 | return uglyArray[n - 1];
34 | }
35 |
36 | private static int getMin(int i, int j, int k) {
37 | int min = (i < j) ? i : j;
38 | return (min < k) ? min : k;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No35.java:
--------------------------------------------------------------------------------
1 | import java.util.LinkedHashMap;
2 |
3 | /**
4 | * 在字符串中找出第一个只出现一次的字符。
5 | * 如输入"abaccdeff",则输出'b'
6 | */
7 |
8 | public class No35 {
9 |
10 | public static void main(String[] args) {
11 | System.out.println(firstOnceNumber("abaccdeff"));
12 |
13 | }
14 |
15 | private static Character firstOnceNumber(String str) {
16 | if (str == null)
17 | return null;
18 | char[] strChar = str.toCharArray();
19 | LinkedHashMap hash = new LinkedHashMap();
20 | for (char item : strChar) {
21 | if (hash.containsKey(item))
22 | hash.put(item, hash.get(item) + 1);
23 | else
24 | hash.put(item, 1);
25 | }
26 | for (char key : hash.keySet()) {
27 | if (hash.get(key) == 1) {
28 | return key;
29 | }
30 | }
31 | return null;
32 |
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No36.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 在数组中的两个数字如果前面一个数字大于后面的数字, 则这两个数字组成一个逆序对。 输入一个数组,求出这个数组中的逆序对的总数
3 | */
4 |
5 | public class No36 {
6 |
7 | public static void main(String[] args) {
8 | int[] arr = {7, 5, 6, 4};
9 | System.out.println(getInversePairs(arr));
10 |
11 | }
12 |
13 | private static int getInversePairs(int[] arr) {
14 | if (arr == null)
15 | return 0;
16 | int[] clone = arr.clone();
17 | return mergeSort(arr, clone, 0, arr.length - 1);
18 | }
19 |
20 | private static int mergeSort(int[] array, int[] result, int start, int end) {
21 | if (start == end) {
22 | result[start] = array[start];
23 | return 0;
24 | }
25 | int length = (end - start) / 2;
26 | int left = mergeSort(result, array, start, start + length);
27 | int right = mergeSort(result, array, start + length + 1, end);
28 | int leftIndex = start + length;
29 | int rightIndex = end;
30 | int count = 0;
31 | int point = rightIndex;
32 | while (leftIndex >= start && rightIndex >= start + length + 1) {
33 | if (array[leftIndex] > array[rightIndex]) {
34 | result[point--] = array[leftIndex--];
35 | count += rightIndex - start - length;
36 |
37 | } else {
38 | result[point--] = array[rightIndex--];
39 | }
40 | }
41 | for (int i = leftIndex; i >= start; i--)
42 | result[point--] = array[i];
43 | for (int j = rightIndex; j >= start + length + 1; j--)
44 | result[point--] = array[j];
45 | return left + right + count;
46 |
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No37.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入两个单向链表,找出它们的第一个公共结点。
3 | */
4 |
5 | public class No37 {
6 |
7 | public static void main(String[] args) {
8 |
9 | ListNode head1 = new ListNode();
10 | ListNode second1 = new ListNode();
11 | ListNode third1 = new ListNode();
12 | ListNode forth1 = new ListNode();
13 | ListNode fifth1 = new ListNode();
14 | ListNode head2 = new ListNode();
15 | ListNode second2 = new ListNode();
16 | ListNode third2 = new ListNode();
17 | ListNode forth2 = new ListNode();
18 | head1.nextNode = second1;
19 | second1.nextNode = third1;
20 | third1.nextNode = forth1;
21 | forth1.nextNode = fifth1;
22 | head2.nextNode = second2;
23 | second2.nextNode = forth1;
24 | third2.nextNode = fifth1;
25 | head1.data = 1;
26 | second1.data = 2;
27 | third1.data = 3;
28 | forth1.data = 6;
29 | fifth1.data = 7;
30 | head2.data = 4;
31 | second2.data = 5;
32 | third2.data = 6;
33 | forth2.data = 7;
34 | System.out.println(findFirstCommonNode(head1, head2).data);
35 |
36 | }
37 |
38 | public static ListNode findFirstCommonNode(ListNode head1, ListNode head2) {
39 | int len1 = getListLength(head1);
40 | int len2 = getListLength(head2);
41 | ListNode longListNode = null;
42 | ListNode shortListNode = null;
43 | int dif = 0;
44 | if (len1 > len2) {
45 | longListNode = head1;
46 | shortListNode = head2;
47 | dif = len1 - len2;
48 | } else {
49 | longListNode = head2;
50 | shortListNode = head1;
51 | dif = len2 - len1;
52 | }
53 | for (int i = 0; i < dif; i++) {
54 | longListNode = longListNode.nextNode;
55 | }
56 | while (longListNode != null && shortListNode != null
57 | && longListNode != shortListNode) {
58 | longListNode = longListNode.nextNode;
59 | shortListNode = shortListNode.nextNode;
60 | }
61 | return longListNode;
62 | }
63 |
64 | private static int getListLength(ListNode head1) {
65 | int result = 0;
66 | if (head1 == null)
67 | return result;
68 | ListNode point = head1;
69 | while (point != null) {
70 | point = point.nextNode;
71 | result++;
72 | }
73 | return result;
74 | }
75 | }
76 |
77 | class ListNode {
78 | int data;
79 | ListNode nextNode;
80 | }
81 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No38.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 统计一个数字在排序数组中出现的次数。
3 | * 例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,
4 | * 由于3在这个数组中出现了4次,因此输出4
5 | */
6 |
7 | public class No38 {
8 |
9 | public static void main(String[] args) {
10 | int[] array = {1, 2, 3, 3, 3, 3, 4, 5};
11 | System.out.println(getNumberOfK(array, 3));
12 | }
13 |
14 | private static int getNumberOfK(int[] array, int k) {
15 | int num = 0;
16 | if (array != null) {
17 | int first = getFirstK(array, k, 0, array.length - 1);
18 | int last = getLastK(array, k, 0, array.length - 1);
19 | //System.out.println(last);
20 |
21 | if (first > -1 && last > -1)
22 | num = last - first + 1;
23 | }
24 | return num;
25 | }
26 |
27 | private static int getLastK(int[] array, int k, int start, int end) {
28 |
29 | if (start > end)
30 | return -1;
31 |
32 | int mid = (start + end) / 2;
33 |
34 | int midData = array[mid];
35 | if (midData == k) {
36 | if ((mid < array.length - 1 && array[mid + 1] != k) || mid == array.length - 1) {
37 |
38 | return mid;
39 | } else {
40 | start = mid + 1;
41 | }
42 | } else if (midData < k)
43 | start = mid + 1;
44 | else
45 | end = mid - 1;
46 | return getLastK(array, k, start, end);
47 | }
48 |
49 | private static int getFirstK(int[] array, int k, int start, int end) {
50 | if (start > end)
51 | return -1;
52 | int mid = (start + end) / 2;
53 | int midData = array[mid];
54 | if (midData == k) {
55 | if ((mid > 0 && array[mid - 1] != k) || mid == 0) {
56 | return mid;
57 | } else {
58 | end = mid - 1;
59 | }
60 | } else if (midData > k)
61 | end = mid - 1;
62 | else
63 | start = mid + 1;
64 |
65 | return getFirstK(array, k, start, end);
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No39.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一颗二叉树的根节点,求该树的深度。
3 | * 从根节点到叶节点依次经过的结点(含根、叶结点)形成树的一条路径,
4 | * 最长路径的长度为树的深度。
5 | */
6 |
7 | public class No39 {
8 |
9 | public static void main(String[] args) {
10 |
11 | }
12 |
13 | public int treeDepth(BinaryTreeNode root) {
14 |
15 | if (root == null) return 0;
16 |
17 | int left = treeDepth(root.getLchildNode());
18 |
19 | int right = treeDepth(root.getRchildNode());
20 |
21 | return (left > right) ? left + 1 : right + 1;
22 |
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No40.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 一个整型数组里除了两个数字之外,其他的数字都出现了两次。
3 | * 请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度O(1)
4 | */
5 |
6 | public class No40 {
7 |
8 | public static void main(String[] args) {
9 | int[] array = {2, 4, 3, 6, 3, 2, 5, 5};
10 | findNumsAppearOnce(array);
11 | }
12 |
13 | private static void findNumsAppearOnce(int[] array) {
14 | if (array == null)
15 | return;
16 | int num = 0;
17 | for (int i : array) {
18 | num ^= i;
19 | }
20 | int index = findFirstBitIs1(num);
21 | int number1 = 0;
22 | int number2 = 0;
23 | for (int i : array) {
24 | if (isBit1(i, index))
25 | number1 ^= i;
26 | else
27 | number2 ^= i;
28 | }
29 | System.out.println(number1);
30 | System.out.println(number2);
31 | }
32 |
33 | private static boolean isBit1(int number, int index) {
34 | number = number >> index;
35 | return (number & 1) == 0;
36 | }
37 |
38 | private static int findFirstBitIs1(int num) {
39 | int index = 0;
40 | while ((num & 1) == 0) {
41 | num = num >> 1;
42 | index++;
43 | }
44 | return index;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No41.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个递增排序的数组和一个数字s,
3 | * 在数组中查找两个数,使得它们的和正好是s。
4 | * 如果有多对数字的和等于s,输出任意一对即可
5 | */
6 |
7 | public class No41 {
8 |
9 | public static void main(String[] args) {
10 | int[] data = {1, 2, 4, 7, 11, 15};
11 | System.out.println(findNumberWithSum(data, 15));
12 | }
13 |
14 | private static boolean findNumberWithSum(int[] data, int sum) {
15 | boolean found = false;
16 | if (data == null)
17 | return found;
18 | int num1 = 0;
19 | int num2 = 0;
20 | int start = 0;
21 | int end = data.length - 1;
22 | while (start < end) {
23 | int curSum = data[start] + data[end];
24 | if (curSum == sum) {
25 | num1 = data[start];
26 | num2 = data[end];
27 | found = true;
28 | break;
29 | } else if (curSum > sum)
30 | end--;
31 | else
32 | start++;
33 | }
34 | System.out.println(num1);
35 | System.out.println(num2);
36 |
37 | return found;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No42.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。
3 | * 例如输入字符串"I am student.",则输出"student. a am I"
4 | */
5 |
6 | public class No42 {
7 |
8 |
9 | public static void main(String[] args) {
10 | String string = "I am a student.";
11 |
12 | reverseSentence(string);
13 | }
14 |
15 | private static void reverseSentence(String str) {
16 | if (str == null)
17 | return;
18 | char[] arr = str.toCharArray();
19 |
20 | reverse(arr, 0, arr.length - 1);
21 | int start = 0;
22 | int end = 0;
23 | for (char i = 0; i < arr.length; i++) {
24 | if (arr[i] == ' ') {
25 | reverse(arr, start, end);
26 | end++;
27 | start = end;
28 | } else if (i == arr.length) {
29 | end++;
30 | reverse(arr, start, end);
31 | } else {
32 | end++;
33 | }
34 | }
35 |
36 | for (char c : arr) {
37 | System.out.print(c);
38 | }
39 | }
40 |
41 | private static void reverse(char[] arr, int start, int end) {
42 | for (int i = start, j = end; i <= j; i++, j--) {
43 | char temp = arr[i];
44 | arr[i] = arr[j];
45 | arr[j] = temp;
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No43.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 把n个骰子仍在地上,所有骰子朝上一面的点数之和为s,
3 | * 输入n,打印出s的所有可能的值出现的概率
4 | */
5 |
6 | public class No43 {
7 |
8 | public static void main(String[] args) {
9 | printProbability(2);
10 | }
11 |
12 | private static void printProbability(int num) {
13 | if (num < 1)
14 | return;
15 | int gMaxValue = 6;
16 | int[][] probabilities = new int[2][];
17 | probabilities[0] = new int[gMaxValue * num + 1];
18 | probabilities[1] = new int[gMaxValue * num + 1];
19 | int flag = 0;
20 | for (int i = 1; i <= gMaxValue; i++) {
21 | probabilities[flag][i] = 1;
22 | }
23 | for (int k = 2; k <= num; k++) {
24 | for (int i = 0; i < k; i++) {
25 | probabilities[1 - flag][i] = 0;
26 | }
27 | for (int i = k; i <= gMaxValue * k; i++) {
28 | probabilities[1 - flag][i] = 0;
29 | for (int j = 1; j <= i && j <= gMaxValue; j++)
30 | probabilities[1 - flag][i] += probabilities[flag][i - j];
31 | }
32 | flag = 1 - flag;
33 |
34 | }
35 | double total = Math.pow(gMaxValue, num);
36 | for (int i = num; i <= gMaxValue * num; i++) {
37 |
38 | double ratio = (double) probabilities[flag][i] / total;
39 |
40 | System.out.print(i + " ");
41 |
42 | System.out.println(ratio);
43 |
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No44.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | /**
4 | * 从扑克牌中随机抽5张牌,判断是不是一个顺子,
5 | * 即这5张牌是不是连续的。2~10为数字本身,
6 | * A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字
7 | */
8 |
9 | public class No44 {
10 |
11 | public static void main(String[] args) {
12 | int[] array = {0, 4, 6, 8, 0};
13 | System.out.println(isContinuous(array));
14 |
15 | }
16 |
17 | private static boolean isContinuous(int[] arr) {
18 |
19 | if (arr == null || arr.length != 5)
20 | return false;
21 | Arrays.sort(arr);
22 | int numberZero = 0;
23 | int numberGap = 0;
24 | for (int i = 0; i < arr.length && arr[i] == 0; i++)
25 | numberZero++;
26 |
27 | int small = numberZero;
28 | int big = small + 1;
29 | while (big < arr.length) {
30 | if (arr[small] == arr[big])
31 | return false;
32 |
33 | numberGap += arr[big] - arr[small] - 1;
34 | small = big;
35 | big++;
36 | }
37 | return numberGap <= numberZero;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No45.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 0~n-1这n个数字排列成一个圆圈,
3 | * 从数字0开始每次从这个圆圈中删除第m个数字。
4 | * 求出这个圆圈里剩下的最后一个数字
5 | */
6 |
7 | public class No45 {
8 |
9 | public static void main(String[] args) {
10 | System.out.println(lastRemaining(6, 3));
11 | }
12 |
13 | public static int lastRemaining(int n, int m) {
14 | if (n < 1 || m < 1)
15 | return -1;
16 | int last = 0;
17 | for (int i = 2; i <= n; i++) {
18 | last = (last + m) % i;
19 | }
20 | return last;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Java/No47.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 写一个函数,求两个整数之和,
3 | * 要求函数体内部不能使用+、-、*、\四则与水暖符号
4 | */
5 |
6 | public class No47 {
7 |
8 | public static void main(String[] args) {
9 | System.out.println(add(5, 8));
10 | }
11 |
12 | private static int add(int num1, int num2) {
13 | int sum, carry;
14 | do {
15 | sum = num1 ^ num2;
16 | carry = (num1 & num2) << 1;
17 | num1 = sum;
18 | num2 = carry;
19 | } while (num2 != 0);
20 | return num1;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No02.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 设计一个类,我们只能生成该类的一个实例。
3 | */
4 |
5 | object SingletonA
6 |
7 | class SingletonB private constructor() {
8 | companion object {
9 | @Volatile private var instance: SingletonB? = null
10 |
11 | fun getInstance() = instance ?: synchronized(this) {
12 | instance ?: SingletonB().also { instance = it }
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No03.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 在一个二维数组中,每一行都按照从左到右递增
3 | * 的顺序排序,每一列都按照从上到下递增的顺序排序。
4 | * 请完成一个函数,输入这样的一个二维数组
5 | * 和一个整数,判断数组中是否函数该整数。
6 | */
7 |
8 | class No03 {
9 |
10 | fun main() {
11 | val arr =
12 | arrayOf(intArrayOf(1, 2, 8, 9),
13 | intArrayOf(2, 4, 9, 12),
14 | intArrayOf(4, 7, 10, 13),
15 | intArrayOf(6, 8, 11, 15))
16 |
17 | println(search(arr, 5))
18 | }
19 |
20 | fun search(arr: Array, value: Int) : Boolean {
21 | var i = 0
22 | var j = arr[0].size - 1
23 | while (i <= arr[0].size - 1 && j >= 0) {
24 | when{
25 | arr[i][j] == value -> return true
26 | arr[i][j] > value -> j--
27 | else -> i++
28 | }
29 | }
30 | return false
31 | }
32 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No04.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 请实现一个函数,把字符串中的每个空格替换成"%20"。
3 | * 例如输入"We are happy",则输出"We%20are%20happy"
4 | */
5 |
6 | class No04 {
7 |
8 | fun main() {
9 | val str = "We are happy"
10 | val charArray = str.toCharArray()
11 | println(change(charArray))
12 | }
13 |
14 | fun change(charArray: CharArray): String {
15 | val count = charArray.count { it == ' ' }
16 | val resultArray = CharArray(charArray.size + count * 2)
17 | var newIndex = resultArray.size - 1
18 | var originIndex = charArray.size - 1
19 |
20 | while (newIndex >= 0) {
21 | if (charArray[originIndex] != ' ') {
22 | resultArray[newIndex] = charArray[originIndex]
23 | newIndex--
24 | } else {
25 | resultArray[newIndex] = '0'
26 | resultArray[newIndex - 1] = '2'
27 | resultArray[newIndex - 2] = '%'
28 | newIndex -= 3
29 | }
30 | originIndex--
31 | }
32 | return resultArray.joinToString(separator = "")
33 | }
34 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No05.kt:
--------------------------------------------------------------------------------
1 | class No05 {
2 |
3 | fun main() {
4 | val node1 = Node("A")
5 | val node2 = Node("B")
6 | val node3 = Node("C")
7 | val node4 = Node("D")
8 | val node5 = Node("E")
9 | node1.next = node2
10 | node2.next = node3
11 | node3.next = node4
12 | node4.next = node5
13 |
14 | var newNode: Node? = reverseNode1(node1)
15 | // var newNode: Node? = reseverNode2(node1)
16 | while (newNode != null) {
17 | print(newNode.data)
18 | newNode = newNode.next
19 | }
20 | }
21 |
22 | fun reverseNode1(node: Node): Node {
23 | if (node.next == null) {
24 | return node
25 | }
26 | val reverseHead = reverseNode1(node.next!!)
27 | node.next!!.next = node
28 | node.next = null
29 | return reverseHead
30 | }
31 |
32 | fun reseverNode2(node: Node): Node {
33 | var pre = node
34 | var cur = pre.next
35 | pre.next = null
36 | var temp: Node? = null
37 | while (cur != null) {
38 | temp = cur.next
39 | cur.next = pre
40 | pre = cur
41 | cur = temp
42 | }
43 | return pre
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No06.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 根据前序遍历和中序遍历建立树
3 | */
4 |
5 | class No06 {
6 |
7 | fun main() {
8 | val preOrder = "12473568"
9 | val midOrder = "47215386"
10 | BiTree(preOrder, midOrder).also {
11 | it.print()
12 | }
13 | }
14 | }
15 |
16 | class BiTree(preOrder: String, midOrder: String) {
17 | var root: TreeNode? = null
18 |
19 | init {
20 | if (preOrder.isEmpty() || midOrder.isEmpty()) {
21 | root = null
22 | } else {
23 | if (preOrder.length == 1) {
24 | root = TreeNode(preOrder[0])
25 | } else {
26 | val rootData = preOrder[0]
27 | val rootIndex = midOrder.indexOf(rootData)
28 | root = TreeNode(rootData)
29 | root?.leftChild = BiTree(preOrder.substring(1, rootIndex + 1), midOrder.substring(0, rootIndex)).root
30 | root?.rightChild = BiTree(preOrder.substring(rootIndex + 1), midOrder.substring(rootIndex + 1)).root
31 | }
32 | }
33 | }
34 |
35 | fun print() {
36 | println("前序遍历:========= ")
37 | printPre(root)
38 | println("\n中序遍历:========= ")
39 | printMid(root)
40 | println("\n后序遍历:========= ")
41 | printPost(root)
42 | }
43 |
44 | fun printPre(rootNode: TreeNode?) {
45 | if (rootNode != null) {
46 | print(rootNode.data)
47 | printPre(rootNode.leftChild)
48 | printPre(rootNode.rightChild)
49 | }
50 | }
51 |
52 | fun printMid(rootNode: TreeNode?) {
53 | if (rootNode != null) {
54 | printMid(rootNode.leftChild)
55 | print(rootNode.data)
56 | printMid(rootNode.rightChild)
57 | }
58 | }
59 |
60 | fun printPost(rootNode: TreeNode?) {
61 | if (rootNode != null) {
62 | printPost(rootNode.leftChild)
63 | printPost(rootNode.rightChild)
64 | print(rootNode.data)
65 | }
66 | }
67 | }
68 |
69 | class TreeNode(var data: Char = ' ') {
70 | var leftChild: TreeNode? = null
71 | var rightChild: TreeNode? = null
72 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No07.kt:
--------------------------------------------------------------------------------
1 | import java.lang.Exception
2 | import java.util.*
3 |
4 |
5 | /**
6 | * 两个栈建立队列
7 | */
8 |
9 | class No07 {
10 |
11 | fun main() {
12 | val queue = MyQueue().apply {
13 | offer("a")
14 | offer("b")
15 | offer("c")
16 | println(peek())
17 | poll()
18 | println(peek())
19 | offer("d")
20 | poll()
21 | println(peek())
22 |
23 | }
24 | }
25 | }
26 |
27 | class MyQueue {
28 |
29 | private val stack1 = Stack()
30 | private val stack2 = Stack()
31 |
32 | fun offer(str: String) {
33 | stack1.push(str)
34 | }
35 |
36 | fun poll() {
37 | if (stack2.isEmpty()) {
38 | if (stack1.isEmpty()) {
39 | throw Exception("empty queue")
40 | } else {
41 | while (stack1.isNotEmpty()) {
42 | stack2.push(stack1.pop())
43 | }
44 |
45 | }
46 | }
47 | stack2.pop()
48 | }
49 |
50 | fun peek(): String {
51 | if (stack2.isEmpty()) {
52 | if (stack1.isEmpty()) {
53 | throw Exception("empty queue")
54 | } else {
55 | while (stack1.isNotEmpty()) {
56 | stack2.push(stack1.pop())
57 | }
58 |
59 | }
60 | }
61 | return stack2.peek()
62 | }
63 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No08.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 把一个数组最开始的若干个元素搬到数组的末尾,
3 | * 我们称之为数组的旋转。输入一个递增排序的数组
4 | * 的一个旋转,输出旋转数组的最小元素。例如数组
5 | * {3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
6 | */
7 |
8 | class No08 {
9 |
10 | fun main() {
11 | println(finMin(intArrayOf(3, 4, 5, 1, 2)))
12 | println(finMin(intArrayOf(1, 0, 1, 1, 1)))
13 | }
14 |
15 | private fun finMin(array: IntArray): Int {
16 | var leftIndex = 0
17 | var rightIndex = array.size - 1
18 | loop@ while (leftIndex < rightIndex) {
19 | val mid = (leftIndex + rightIndex) / 2
20 | when {
21 | array[mid] == array[leftIndex] && array[mid] == array[rightIndex] -> {
22 | array.sort(leftIndex, rightIndex + 1)
23 | return array[leftIndex]
24 | }
25 | (rightIndex - leftIndex) == 1 -> break@loop
26 | array[mid] >= array[leftIndex] -> leftIndex = mid
27 | else -> rightIndex = mid
28 | }
29 | }
30 | return array[rightIndex]
31 | }
32 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No09.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 1,写一个函数,输入n,求斐波那契数列的第n项
3 | * 2,一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级台阶总共有多少种跳法
4 | */
5 |
6 | class No09 {
7 |
8 | fun main() {
9 | for (i in 0..10) {
10 | print(fibonacci(i).toString() + ",")
11 | }
12 | }
13 |
14 | private fun fibonacci(i: Int): Long {
15 | if (i <= 1) {
16 | return i.toLong()
17 | }
18 |
19 | var fib1 = 0L
20 | var fib2 = 1L
21 | var fibN = 0L
22 |
23 | for (j in 2..i) {
24 | fibN = fib1 + fib2
25 | fib1 = fib2
26 | fib2 = fibN
27 | }
28 | return fibN
29 | }
30 |
31 | private fun getMethodNumber(n: Int): Int = if (n <= 2) n else getMethodNumber(n - 1) + getMethodNumber(n - 2)
32 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No10.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 请实现一个函数,输入一个整数,
3 | * 输出该二进制表示中1的个数。
4 | * 例如把9表示成二进制是1001, 有2位是1。
5 | * 因此如果输入9,该函数输出2。
6 | */
7 | class No10 {
8 | fun main() {
9 | println(getNum(9))
10 | }
11 |
12 | fun getNum(n: Int): Int {
13 | var temp = n
14 | var num = 0
15 | while (temp != 0) {
16 | num++
17 | temp = temp and (temp - 1)
18 | }
19 | return num
20 | }
21 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No11.kt:
--------------------------------------------------------------------------------
1 | import org.junit.Test
2 |
3 | /**
4 | * 实现函数double Power(double base,int exponent),
5 | * 求base的exponent次方。不得使用库函数,
6 | * 同时不需要考虑大数问题。
7 | */
8 |
9 | class No11 {
10 |
11 | fun main() {
12 | println(Power(3.0, 3))
13 | }
14 |
15 | fun Power(base: Double, exponent: Int): Double {
16 | if (exponent < 0) {
17 | return 0.0
18 | }
19 | if (exponent == 0) {
20 | return if (base == 0.0) {
21 | 0.0
22 | } else {
23 | 1.0
24 | }
25 | }
26 |
27 | if (exponent == 1) {
28 | return base
29 | }
30 |
31 | var result = Power(base, exponent shr 1)
32 | result *= result
33 | if (exponent and 1 == 1) {
34 | result *= base
35 | }
36 |
37 | return result
38 | }
39 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No12.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入数字n,按顺序打印出从1最大的n位十进制数。
3 | * 比如输入3,则打印出1、2、3一直到最大的3位数即999
4 | */
5 |
6 | class No12 {
7 |
8 | fun main() {
9 | printNum(4)
10 | }
11 |
12 | fun printNum(n: Int) {
13 | if (n <= 0) {
14 | return
15 | }
16 | printArray(Array(n) { 0 }, 0)
17 | }
18 |
19 | fun printArray(array: Array, index: Int) {
20 | when (index) {
21 | array.size -> {
22 | val numStr = array.joinToString(separator = "") { it.toString() }
23 | val nonZeroIndex = numStr.indexOfFirst { it != '0' }
24 | if (nonZeroIndex == -1) {
25 | println('0')
26 | } else {
27 | println(numStr.substring(nonZeroIndex))
28 | }
29 | }
30 | else -> {
31 | for (i in 0..9) {
32 | array[index] = i
33 | printArray(array, index + 1)
34 | }
35 | }
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No13.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 给定单向链表的头指针和一个结点指针, 定义一个函数在O(1)时间删除该节点
3 | */
4 |
5 | class No13 {
6 |
7 | fun main() {
8 | val node1 = Node("1")
9 | val node2 = Node("2")
10 | val node3 = Node("3")
11 | val node4 = Node("4")
12 | node1.next = node2
13 | node2.next = node3
14 | node3.next = node4
15 |
16 | var head = delete(node1, node3)
17 |
18 | while (head != null) {
19 | println(head.data)
20 | head = head.next
21 | }
22 | }
23 |
24 | fun delete(head: Node, target: Node): Node? {
25 | if (target.next == null) {
26 | // 只能遍历删除
27 | if (head == target) {
28 | return null
29 | } else {
30 | var temp: Node = head
31 | while (temp.next != target) {
32 | temp = temp.next!!
33 | }
34 | temp.next = temp.next?.next
35 | }
36 | } else {
37 | target.data = target.next?.data
38 | target.next = target.next?.next
39 | }
40 |
41 | return head
42 | }
43 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No14.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,
3 | * 使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
4 | */
5 |
6 | class No14 {
7 | fun main() {
8 | val array = intArrayOf(3, 7, 4, 8, 23, 56, 77, 89, 46, 11, 66, 77)
9 | mySort(array)
10 | println(array.joinToString { it.toString() })
11 | }
12 |
13 | private fun mySort(array: IntArray) {
14 | var left = 0
15 | var right = array.size - 1
16 | while (left < right) {
17 | while (left <= array.size - 1 && array[left] and 0x1 == 1) {
18 | left++
19 | }
20 |
21 | while (right >= 0 && array[right] and 0x1 == 0) {
22 | right--
23 | }
24 |
25 | if (left < right) {
26 | var temp = array[left]
27 | array[left] = array[right]
28 | array[right] = temp
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/No15.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * 输入一个链表,输出该链表中倒数第K个结点。
3 | * 为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。
4 | * 例如一个链表有6个结点,从头结点开始它们的值依次是1,2,3,4,5,6。
5 | * 这个链表的倒数第3个结点是值为4的结点。
6 | * (注意代码鲁棒性,考虑输入空指针,链表结点总数少于k,输入的k参数为0)
7 | */
8 |
9 | class No15 {
10 |
11 | fun main() {
12 | val a = Node("1")
13 | val b = Node("2")
14 | val c = Node("3")
15 | val d = Node("4")
16 | val e = Node("5")
17 | val f = Node("6")
18 | a.next = b
19 | b.next = c
20 | c.next = d
21 | d.next = e
22 | e.next = f
23 |
24 | println(getNodeFromTail(a, 1))
25 | println(getNodeFromTail(a, 2))
26 | println(getNodeFromTail(a, 3))
27 | println(getNodeFromTail(a, 4))
28 | }
29 |
30 |
31 | fun getNodeFromTail(head: Node, n: Int): Node? {
32 | var slow: Node? = head
33 | var fast: Node? = head
34 | for (i in 0 until n - 1) {
35 | fast = fast?.next
36 | if (fast == null) {
37 | return null
38 | }
39 | }
40 |
41 | while (fast?.next != null) {
42 | fast = fast.next
43 | slow = slow?.next
44 | }
45 |
46 | return slow
47 | }
48 | }
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Kotlin/Node.kt:
--------------------------------------------------------------------------------
1 | data class Node(var data: String? = null, var next: Node? = null)
--------------------------------------------------------------------------------
/剑指offer-2012年书籍版/Pdf、Markdown/剑指offer-java-pdf.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xurui1995/Sword-pointing-to-offer/7835496ba6371ed2695e9709a86d3596529be801/剑指offer-2012年书籍版/Pdf、Markdown/剑指offer-java-pdf.pdf
--------------------------------------------------------------------------------