diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000..48d5f81 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,10 @@ +--- +name: Custom issue template +about: Describe this issue template's purpose here. +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d6193c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea/ +.DS_Store +composer.lock +vendor \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..7ee229d --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at 542684913@qq.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..cc8499a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ +What does “open source” mean? + +When a project is open source, that means anybody can view, use, modify, and distribute your project for any purpose. These permissions are enforced through an open source license. + +Open source is powerful because it lowers the barriers to adoption, allowing ideas to spread quickly. + +To understand how it works, imagine your friend is having a potluck, and you bring a cherry pie. + +Everybody tries the pie (use) +The pie is a hit! They ask you for the recipe, which you provide (view) +One friend, Alex, who’s a pastry chef, suggests reducing the sugar (modify) +Another friend, Lisa, asks to use it for a dinner next week (distribute) +By comparison, a closed source process would be going to a restaurant and ordering a slice of cherry pie. You must pay a fee to eat the pie, and the restaurant probably won’t give you their recipe. If you copied their pie exactly and sold it under your own name, the restaurant could take action against you. + +Why do people open source their work? diff --git a/LICENSE b/LICENSE index 748bc09..8d0adb8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,376 +1,21 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. - -Contact GitHub API Training Shop Blog About -© 2017 GitHub, Inc. Terms Privacy Security Status Help \ No newline at end of file +MIT License + +Copyright (c) 2017 Shaowei pu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README-EN.md b/README-EN.md new file mode 100644 index 0000000..8aeeaef --- /dev/null +++ b/README-EN.md @@ -0,0 +1,167 @@ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +## Simple structure, + +``` +├──Package +│ ├── Sort +│ │ ├── BubbleSort.php +│ │ ├── QuickSort.php +│ │ ├── ShellSort.php +│ │ ├── MergeSort.php +│ │ ├── InsertSort.php +│ │ └── SelectSort.php +│ │ +│ ├── Query 查找篇 +│ │ ├── BinaryQuery.php +│ │ ├── InseertQuery.php +│ │ ├── FibonacciQuery.php +│ │ ├── BFSQuery.php +│ │ ├── Kmp.php +│ │ ├── DijkstraQuery.php +│ │ └── QulickQuery.php +│ │ +│ └── Other 其他 +│ ├── MonkeyKing.php +│ ├── DynamicProgramming.php +│ ├── Fibonacci.php +│ ├── StealingApples.php +│ ├── HanoiGames.php +│ ├── BidirectionalQueue.php +│ ├── ColorBricks.php +│ ├── GetCattle.php +│ ├── OnlyNumbers.php +│ ├── Interval.php +│ ├── Maze.php +│ ├── AntsClimb.php +│ ├── Encryption.php +│ ├── ElevatorDispatch.php +│ ├── kmp.php +│ ├── TraversalOfBinary.php +│ ├── PointInTriangle.php +│ └── BigSmallReplace.php +│ └── Knapsack.php +│ └── Solution.php +│ └── RotationSort.php +│ └── Square.php +│ └── Prim.php +│ └── CartesianProduct.php +│ └── Square.php +│ └── Judge.php +│ └── Factorial.php +| └── HashTable.php +| └── RotateSort.php +│ +├──LICENSE +└──README.md +``` + +## What to do? + +``` +To record their understanding algorithms, data structure, the process of simple comprehensive and detailed as possible, let the learning algorithm using flexible, refueling(ง •̀_•́)ง +``` + +## logarithmic + +log10100 It's equivalent to saying, "how many tens do you multiply?" the answer is, of course, two +so log10100=2,The logarithmic operation is the inverse of the power operation + +| left | right | +| ------------------ | --------------------- | +| 23 = 8 | log28 = 3 | +| 24 = 16 | log216 = 4 | +| 25 = 32 | log232 = 5 | + +If you don't, we won't wait for you + +## The elapsed time + +Take binary search for example, how much time can you save by using it? Simply look for the Numbers and if the list contains 100 Numbers, you need to guess 100 times. +In other words, the number of guesses is the same as the length of the list, which is called linear time, while binary search is different if the list contains 100 elements +It takes up to seven times, and if the list contains four billion digits, it should be guessed 32 times, while the running time of the subsearch is logarithmic time `O(log)` + +## Big O notation + +The big O notation is a special representation of how fast the algorithm can be. There's a diaosi. In fact, you often have to copy other people's code. +In this case, you know how fast these algorithms are + +- The running time of the algorithm increases at different speeds + - For example, the difference between a simple find and a binary search + +| element | Easy to find | Binary search | +| ------------- | ------------ | ------------- | +| 100 | 100ms | 7ms | +| 10000 | 10s | 14ms | +| 1 000 000 000 | 11day | 30ms | + +- ` O ` said hair is pointed out that how fast algorithms, such as list contains ` n ` element, a simple search need to check each element, so you need to perform ` n ` time operations + Using large ` O ` said ` O (n) to make this operation `, binary search need to perform logn using large ` O ` said to`O(log n)` + - Some common big O runtime +- O(log n) ,It's also called log time, and this algorithm includes binary algorithms +- O(n),Also known as linear time, this algorithm includes simple lookups. +- O(n * log n) Quick sort +- O(n2),Selection sort +- O(n!) Factorial time + - Here is the point +- The speed of the algorithm is not the time, but the growth of operands +- When we talk about the speed of the algorithm, what we're talking about is how fast will it run as the input increases +- The running time of the algorithm is expressed in large O notation +- O(log n) is faster than O (n), and the more elements that need to be searched, the more the former is faster than the latter + +## A simple comparison of recursion and loops: + +1. From a procedural point of view, the recursion manifests itself as calling itself, and the loop does not have this form. +2. Recursive proceed from the ultimate goal of the problem, and gradually to a complex problem into a simple problem, and simple question solution and complicated problem, at the same time the presence of the benchmark, can eventually get a problem, is the reverse. And the circulation is from the simple question, step by step forward development, finally get the question, is positive. +3. Any cycle can be represented by recursion, but it is necessary to use the loop to achieve recursion (except for one-way recursion and tail recursion), and the stack structure must be introduced to stack the stack. + 4.In general, non-recursive efficiency is higher than recursion. And recursive function calls are expensive and recursive times are limited by stack size. + +## Progressive learning + +1. Fork 我的项目并提交你的 `idea` +2. Pull Request +3. Merge + +## 纠错 + +If you find something wrong, you can initiate a [issue](https://github.com/PuShaoWei/designPatterns-go/issues)or [pull request](https://github.com/PuShaoWei/designPatterns-go/pulls),I will correct it in time + +> 补充:发起pull request的commit message请参考文章[Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html) + +## Contributors + +Thanks for the issue or pull request of the following friends: + +- [hailwood ](https://github.com/hailwood) + +- [zhangxuanru](https://github.com/zhangxuanru) + +- [ifreesec](https://github.com/ifreesec) + +- [openset](https://github.com/openset) + +- [Neroxiezi](https://github.com/Neroxiezi) + + ## License + +MIT diff --git a/README.md b/README.md index 9229c40..5217772 100644 --- a/README.md +++ b/README.md @@ -1,116 +1,264 @@ -用 PHP 的方式实现的各类算法合集 -=============== +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+> 每周最少一更,求出题,求虐待 At least once a week, ask for problems and abuse
## 简易结构
-
- ├──Package
- │ ├── Sort 排序篇
- │ │ ├── BubbleSort.php 冒泡排序
- │ │ ├── QuickSort.php 快速排序
- │ │ ├── ShellSort.php 希尔排序
- │ │ └── MergeSort.php 归并排序
- │ │
- │ ├── Query 查询篇
- │ │ ├── BinaryQuery.php 二分查找
- │ │ └── 快速查找
- │ │
- │ └── Other 其他
- │ └── BigSmallReplace.php Hello World 输出 Olleh Dlrow
- │
- ├──LICENSE
- └──README.md
-
-## 时间复杂度
-
-> #### 时间频度
- 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。
- 但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。
- 并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。
- 一个算法中的语句执行次数称为语句频度或时间频度。记为 `T(n)`。
-
-> #### 时间复杂度
- 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。
- 但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。
- 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,
- 若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。
- 记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。时间频度不同,但时间复杂度可能相同。
- 如:T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。
- 按数量级递增排列,常见的时间复杂度有:常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),..., k次方阶O(nk),指数阶O(2n)。
- 随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
-
-> #### 最坏时间复杂度和平均时间复杂度
- 最坏情况下的时间复杂度称最坏时间复杂度。一般不特别说明,讨论的时间复杂度均是最坏情况下的时间复杂度。
- 这样做的原因是:最坏情况下的时间复杂度是算法在任何输入实例上运行时间的上界,这就保证了算法的运行时间不会比任何更长。
- 在最坏情况下的时间复杂度为T(n)=0(n),它表示对于任何输入实例,该算法的运行时间不可能大于0(n)。
- 平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。指数阶0(2n),显然,时间复杂度为指数阶0(2n)的算法效率极低,当n值稍大时就无法应用。
-
-> #### 求时间复杂度
-> 如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。
+
```
- x=91; y=100;
- while(y>0) if(x>100) {x=x-10;y--;} else x++;
-```
-解答: T(n)=O(1),
-这个程序看起来有点吓人,总共循环运行了1100次,但是我们看到n没有?
-没。这段程序的运行是和n无关的,
-就算它再循环一万年,我们也不管他,只是一个常数阶的函数
-- 当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。
+├──Package
+│ ├── Sort 排序篇
+│ │ ├── BubbleSort.php 冒泡排序
+│ │ ├── HeapSort.php 堆排序 大根堆
+│ │ ├── MBaseSort.php 基数排序 MSD
+│ │ ├── LBaseSort.php 基数排序 LSD
+│ │ ├── QuickSort.php 快速排序
+│ │ ├── ShuttleSort.php 飞梭排序
+│ │ ├── ShellSort.php 希尔排序
+│ │ ├── MergeSort.php 归并排序
+│ │ ├── InsertSort.php 插入排序
+│ │ └── SelectSort.php 选择排序
+│ │
+│ ├── Query 查找篇
+│ │ ├── BinaryQuery.php 二分查找
+│ │ ├── InseertQuery.php 插入查找
+│ │ ├── FibonacciQuery.php 斐波那契查找
+│ │ ├── BFSQuery.php 广度优先查找
+│ ├── Kmp.php 算法导论-KMP算法
+│ ├── DijkstraQuery.php 迪克斯特拉算法
+│ │ └── QulickQuery.php 快速查找
+│ │
+│ ├── Structure 数据结构
+│ │ ├── StackExample.php 堆栈 先进后出 LIFO (Last In First Out)
+│ │ ├── LinearChain.php 线性表 单链存储
+│ │ └── LinearOrder.php 线性表 顺序存储
+│ │ └── BinarySearchTree.php 二叉搜索树
+│ │
+│ ├── Tools 小工具集
+│ │ └── SystemSwitch.php 堆栈实现进制转换
+│ │
+│ └── Other 其他
+│ ├── MonkeyKing.php 约瑟夫环
+│ ├── DynamicProgramming.php 动态规划
+│ ├── Fibonacci.php 斐波那契数列
+│ ├── StealingApples.php 偷苹果求余
+│ ├── HanoiGames.php 汉诺塔游戏
+│ ├── BidirectionalQueue.php 双向队列
+│ ├── ColorBricks.php 彩色砖块
+│ ├── GetCattle.php 牛年求牛
+│ ├── OnlyNumbers.php 求唯一数
+│ ├── PokerGames.php 洗扑克牌
+│ ├── Interval.php 抽奖区间算法
+│ ├── Maze.php 迷宫寻址算法
+│ ├── AntsClimb.php 蚂蚁爬杆算法
+│ ├── Encryption.php 对称加密算法
+│ ├── ElevatorDispatch.php 编程之美-电梯调度算法
+│ ├── PointInTriangle.php 向量叉集计算点是否在三角形中
+│ ├── TraversalOfBinary.php 二叉树非递归遍历算法实现
+│ ├── Knapsack.php 贪心算法之背包问题实现
+│ └── BigSmallReplace.php Hello World 输出 Olleh Dlrow
+│ └── Solution.php Facebook面试题之岛屿周长算法
+│ └── RotationSort.php Facebook面试题之顺时针回旋算法
+│ └── Square.php Facebook面试题之判断四个点能否组成正方形算法
+│ └── Prim.php Prim算法(最小生成树算法)
+│ └── CartesianProduct.php 笛卡尔积算法
+│ └── Square.php 面试题之平面任意四点能否组成一个矩形
+│ └── Judge.php 面试题之扑克牌中任选五张判断是不是顺子
+│ └── Factorial.php 面试题之N的阶乘末尾有多少个0
+| └── HashTable.php HashTable
+| └── RotateSort.php 面试题之风车旋转排序算法
+│
+├──LICENSE
+└──README.md
+```
+
+## 要做什么?
+
```
- x=1;
-for(i=1;i<=n;i++)
- for(j=1;j<=i;j++)
- for(k=1;k<=j;k++)
- x++;
+记录自己理解算法,数据结构的过程,尽可能的简单全面以及详细,让算法学习运用灵活自如,加油(ง •̀_•́)ง
```
-该程序段中频度最大的语句是(5),内循环的执行次数虽然与问题规模n没有直接关系,但是却与外层循环的变量取值有关,而最外层循环的次数直接与n有关,
-因此可以从内层循环向外层分析语句(5)的执行次数: 则该程序段的时间复杂度为T(n)=O(n3/6+低次项)=O(n3)
-- 算法的时间复杂度不仅仅依赖于问题的规模,还与输入实例的初始状态有关。
-在数值A[0..n-1]中查找给定值K的算法大致如下:
+
+## 当然
+
```
-i=n-1;
-while(i>=0&&(A[i]!=k))
- i--;
-return i;
+用 PHP 实现算法并替代官方提供的函数是愚蠢的事情 .但这决不代表斟酌算法就是件无意义的事 , 每个算法都是一种思想的结晶 , 学习优秀的思想 , 开拓思维
```
-此算法中的语句(3)的频度不仅与问题规模n有关,还与输入实例中A的各元素取值及K的取值有关:
- - ①若A中没有与K相等的元素,则语句(3)的频度f(n)=n;
- - ②若A的最后一个元素等于K, 则语句(3)的频度f(n)是常数0。
-
-- 时间复杂度评价性能
- 有两个算法A1和A2求解同一问题,时间复杂度分别是T1(n)=100n2,T2(n)=5n3。
- (1)当输入量n<20时,有T1(n)>T2(n),后者花费的时间较少。
- (2)随着问题规模n的增大,两个算法的时间开销之比5n3/100n2=n/20亦随着增大。即当问题规模较大时,算法A1比算法A2要有效地多。
- 它们的渐近时间复杂度O(n2)和O(n3)从宏观上评价了这两个算法在时间方面的质量。
- 在算法分析时,往往对算法的时间复杂度和渐近时间复杂度不予区分,而经常是将渐近时间复杂度T(n)=O(f(n))简称为时间复杂度,
- 其中的f(n)一般是算法中频度最大的语句频度。
-
-## 空间复杂度
- 一个程序的空间复杂度是指运行完一个程序所需内存的大小。
- 利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,
- 还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。
-> #### 固定部分
- 这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
-> #### 可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
- 一个算法所需的存储空间用f(n)表示。S(n)=O(f(n)) 其中n为问题的规模,S(n)表示空间复杂度。
+
+## 什么是算法?
+
+直白地说,算法就是任何明确定义的计算过程,它接收一些值或集合作为输入,并产生一些值或集合作为输出。这样,算法就是将输入转换为输出的一系列计算过程。来源:Thomas H. Cormen, Chales E. Leiserson (2009), 《算法导论第三版》。
+
+简而言之,我们可以说算法就是用来解决一个特定任务的一系列步骤(是的,不止计算机在使用算法,人类也同样如此)。目前,一个有效的算法应该含有三个重要特性:
+
+- 它必须是有限的:如果你设计的算法永无休止地尝试解决问题,那么它是无用的。
+- 它必须具备明确定义的指令:算法的每一步都必须准确定义,在任何场景下指令都应当没有歧义。
+- 它必须是有效的:一个算法被设计用以解决某个问题,那么它就应当能解决这个问题,并且仅仅使用纸和笔就能证明该算法是收敛的。
+
+## 对数
+
+log10100 相当于问"将多少个10相乘的结果为100",答案当然是2个了
+因此log10100=2,即对数运算是幂运算的逆运算
+
+| left | right |
+| ------------------ | --------------------- |
+| 23 = 8 | log28 = 3 |
+| 24 = 16 | log216 = 4 |
+| 25 = 32 | log232 = 5 |
+
+## 运行时间
+
+以二分查找为例,使用它可节省多少时间呢?简单查找逐个地检查数字,如果列表包含100个数字,最多需要猜100次。
+换而言之最多需要猜测的次数与列表长度相同,这被称为线性时间(linear time),而二分查找则不同,如果列表包含100个元素
+最多需要7次,如果列表包含40亿个数字,最多需猜32次,而分查找的运行时间为对数时间 `O(log)`
+
+## 大O表示法
+
+大O表示法是一种特殊的表示法 ,指出了算法的速度有多快。有个屌用啊,实际上,你经常要去复制别人的代码。
+在这种情况下,知道这些算法的速度有快有慢
+
+- 算法的运行时间以不同的速度增加
+ - 例如简单查找与二分查找的区别
+
+| 元素 | 简单查找 | 二分查找 |
+| ----------------- | ----- | ---- |
+| 100个元素 | 100ms | 7ms |
+| 10000个元素 | 10s | 14ms |
+| 1 000 000 000 个元素 | 11天 | 30ms |
+
+- 大`O`表示法指出了算法有多快,例如列表包含`n`个元素,简单查找需要检查每个元素,因此需要执行`n`次操作
+ 使用大`O`表示法这个运行时间为`O(n)`,二分查找需要执行logn次操作,使用大`O`表示为`O(log n)`
+ - 一些常见的大O运行时间
+- O(log n) ,也叫对数时间,这样的算法包括二分算法
+- O(n),也叫线性时间,这样的算法包括简单查找。
+- O(n * log n) 快速排序
+- O(n2),选择排序
+- O(n!) 即阶乘时间
+ - 这里是重点
+- 算法的速度指的并非时间,而是操作数的增速
+- 谈论算法的速度时间时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加
+- 算法的运行时间用大O表示法表示
+- O(log n)比O(n)快,当需要搜索的元素越多时,前者比后者快的越多
+
+## 编写解决实际问题的程序过程
+
+- 如何用数据形式描述问题,即将问题抽象为一个数学模型
+- 问题所涉及到的数据量的大小及数据之间的关系
+- 如何在计算机中储存数据及体现数据之间的关系
+- 处理数据时需要对数据执行的操作
+- 编写的程序的性能是否良好
+
+## 数据(Data)
+
+- 是客观事物的符号表示,在计算机科学中指的是所有能输入到计算机中并被计算机程序处理的符号的总称。
+- 数据元素(Data Element) :是数据的基本单位,在程序中通常作为一个整体来进行考虑和处理。一个数据元素可由若干个数据项(Data Item)组成。
+- 数据项(Data Item) : 是数据的不可分割的最小单位。数据项是对客观事物某一方面特性的数据描述。
+- 数据对象(Data Object) :是性质相同的数据元素的集合,是数据的一个子集。如字符集合C={‘A’,’B’,’C,…} 。
+- 数据结构 :相互之间具有一定联系的数据元素的集合。
+- 数据的逻辑结构 : 数据元素之间的相互关系称为逻辑结构。
+- 数据操作 : 对数据要进行的运算
+- 数据类型(Data Type):指的是一个值的集合和定义在该值集上的一组操作的总称。
+
+## 数据的逻辑结构有四种基本类型
+
+- 集合:结构中数据元素之间除了“属于同一个集合"外,再也没有其他的关系
+- 线性结构:结构中的数据元素存在一对一的关系
+- 树形结构:结构中的数据元素存在一对多的关系
+- 网状或者图状结构:结构中的数据元素存在多对多的关系
+
+## 数据结构的储存方式
+
+由数据元素之间的关系在计算机中有两种不同的表示方法——顺序表示和非顺序表示,从则导出两种储存方式,顺序储存结构和链式储存结构
+
+- 顺序存储结构:用数据元素在存储器中的相对位置来表示数据元素之间的逻辑结构(关系),数据元素存放的地址是连续的
+- 链式存储结构:在每一个数据元素中增加一个存放另一个元素地址的指针(pointer),用该指针来表示数据元素之间的逻辑结构(关系),数据元素存放的地址是否连续没有要求
+
+数据的逻辑结构和物理结构是密不可分的两个方面,一个算法的设计取决于所选定的逻辑结构,而算法的实现依赖于所采用的存储结构
+
+## 算法(Algorithm)
+
+是对特定问题求解方法(步骤)的一种描述,是指令的有限序列,其中每一条指令表示一个或多个操作。
+
+> 算法具有以下五个特性
+
+- 有穷性: 一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成
+- 确定性:算法中每一条指令必须有确切的含义,不存在二义性,且算法只有一个入口和一个出口
+- 可行性: 一个算法是能行的,即算法描述的操作都可以通过已经实现的基本运算执行有限次来实现
+- 输入: 一个算法有零个或多个输入,这些输入取自于某个特定的对象集合
+- 输出: 一个算法有一个或多个输出,这些输出是同输入有着某些特定关系的量
+
+> 算法和程序是两个不同的概念
+
+一个计算机程序是对一个算法使用某种程序设计语言的具体实现。算法必须可终止意味着不是所有的计算机程序都是算法。
+
+> 评价一个好的算法有以下几个标准
+
+- 正确性(Correctness ): 算法应满足具体问题的需
+- 可读性(Readability): 算法应容易供人阅读和交流,可读性好的算法有助于对算法的理解和修改
+- 健壮性(Robustness): 算法应具有容错处理,当输入非法或错误数据时,算法应能适当地作出反应或进行处理,而不会产生莫名其妙的输出结果
+- 通用性(Generality): 算法应具有一般性 ,即算法的处理结果对于一般的数据集合都成立
+
+> 效率与存储量需求: 效率指的是算法执行的时间;存储量需求指算法执行过程中所需要的最大存储空间,一般地,这两者与问题的规模有关
+
+## 算法的时间复杂度
+
+算法中基本操作重复执行的次数是问题规模n的某个函数,其时间量度记作T(n)=O(f(n)),称作算法的渐近时间复杂度(Asymptotic Time complexity),简称时间复杂度
+
+## 算法的空间复杂度
+
+是指算法编写成程序后,在计算机中运行时所需存储空间大小的度量,记作:S(n)=O(f(n)),其中n为问题规模
+
+## 递归和循环的简单比较:
+
+1. 从程序上看,递归表现为自己调用自己,循环则没有这样的形式。
+2. 递归是从问题的最终目标出发,逐渐将复杂问题化为简单问题,并且简单的问题的解决思路和复杂问题一样,同时存在基准情况,就能最终求得问题,是逆向的。而循环是从简单问题出发,一步步的向前发展,最终求得问题,是正向的。
+3. 任意循环都是可以用递归来表示的,但是想用循环来实现递归(除了单向递归和尾递归),都必须引入栈结构进行压栈出栈。
+4. 一般来说,非递归的效率高于递归。而且递归函数调用是有开销的,递归的次数受堆栈大小的限制。
## 一起进步学习
- 1. Fork 我的项目
- 2. Pull Request
- 3. Merge
+
+1. Fork 我的项目并提交你的 `idea`
+2. Pull Request
+3. Merge
## 纠错
如果大家发现有什么不对的地方,可以发起一个[issue](https://github.com/PuShaoWei/arithmetic-php/issues)或者[pull request](https://github.com/PuShaoWei/arithmetic-php/pulls),我会及时纠正
+
> 补充:发起pull request的commit message请参考文章[Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html)
+
+## 致谢
+
+感谢以下朋友的issue或pull request:
+
+- [hailwood ](https://github.com/hailwood)
+
+- [zhangxuanru](https://github.com/zhangxuanru)
+
+- [ifreesec](https://github.com/ifreesec)
+
+- [openset](https://github.com/openset)
+
+- [Neroxiezi](https://github.com/Neroxiezi)
+
+ ## License
+
+MIT
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..ac1360d
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,17 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version | Supported |
+| ------- | ------------------ |
+| 5.1.x | :white_check_mark: |
+| 5.0.x | :x: |
+| 4.0.x | :white_check_mark: |
+| < 4.0 | :x: |
+
+## Reporting a Vulnerability
+
+Please report security issues to 计算-';
+ print_r($pathCalculate);
+ echo '排序-';
+ asort($pathCalculate);
+ print_r($pathCalculate);
+ }
+
+ /**
+ * add2
+ *
+ * @param $directionArr
+ * @param $count
+ * @param $i
+ * @return mixed
+ */
+ protected function add2($directionArr, $count, $i)
+ {
+ if (0 > $i) {
+ return $directionArr;
+ }
+ if (0 === $directionArr[$i]) {
+ $directionArr[$i] = 1;
+ return $directionArr;
+ }
+ $directionArr[$i] = 0;
+ return $this->add2($directionArr, $count, $i - 1);
+ }
+
+ /**
+ * path
+ *
+ * @param $positionArr
+ * @return array
+ */
+ protected function path($positionArr)
+ {
+ // 生成测试路径
+ $pathCalculate = array ();
+ $count = count($positionArr);
+ $directionArr = array_fill(0, $count, 0);
+
+ // 朝向
+ $end = str_repeat('1', $count);
+ while (true) {
+ $path = implode('', $directionArr);
+ $total = $this->calculate($positionArr, $directionArr);
+ $pathCalculate['路径:' . $path] = $total;
+ if ($end == $path) { // 遍历完成
+ break;
+ }
+ $directionArr = $this->add2($directionArr, $count, $count - 1);
+ }
+ return $pathCalculate;
+ }
+
+ /**
+ * calculate
+ *
+ * @param $positionArr
+ * @param $directionArr
+ * @return int
+ */
+ protected function calculate($positionArr, $directionArr)
+ {
+ $total = 0;
+ // 总用时
+ $length = 27;
+ // 木杆长度
+ while ($positionArr) {
+ $total++; // 步增耗时
+ $nextArr = array (); // 下一步位置
+ foreach ($positionArr as $key => $value) {
+ if (0 == $directionArr[$key]) {
+ $next = $value - 1; // 向0方向走一步
+ } else {
+ $next = $value + 1; // 向1方向走一步
+ }
+ if (0 == $next) { // 在0方向走出
+ continue;
+ }
+ if ($length == $next) { // 在1方向走出
+ continue;
+ }
+ $nextArr[$key] = $next;
+ }
+ $positionArr = $nextArr;// 将$positionArr置为临时被查找数组
+
+ foreach ($nextArr as $key => $value) {
+ $findArr = array_keys($positionArr, $value);
+ if (count($findArr) < 2) {
+ // 没有重合的位置
+ continue;
+ }
+ foreach ($findArr as $findIndex) {
+ $directionArr[$findIndex] = $directionArr[$findIndex] ? 0 : 1;
+ // 反向处理
+ unset($positionArr[$findIndex]);
+ // 防止重复查找计算
+ }
+ }
+ $positionArr = $nextArr;
+ // 将$positionArr置为下一步结果数组
+ }
+ return $total;
+ }
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+// 蚂蚁位置
+$position = array (3, 7, 11, 17, 23);
+// 测试用例
+(new AntsClimb($position))->run();
\ No newline at end of file
diff --git a/src/Other/BidirectionalQueue.php b/src/Other/BidirectionalQueue.php
new file mode 100644
index 0000000..099d705
--- /dev/null
+++ b/src/Other/BidirectionalQueue.php
@@ -0,0 +1,152 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 双向队列的实现及应用
+ * -------------------------------------------------------------
+ * 思路分析: 考察PHP几个内置数组的函数
+ * 双向队列是一种双向开口的连续线性空间,可以高效的在头尾两端插入和删除元素
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+class BidirectionalQueue
+{
+ /**
+ * @var array
+ */
+ public $queue = [];
+ public $maxLength = 0; // 对列最大长度,0表示不限
+ public $type = 0; // 对列类型
+ public $frontNum = 0; // 前端插入的数量
+ public $rearNum = 0; // 后端插入的数量
+
+ const C_AT_BOTH_ENDS = 1; // 1:两端均可输入输出
+ const C_FRONT_ONLY_INPUT = 2; // 2:前端只能输入,后端可输入输出
+ const C_FRONT_ONLY_OUTPUT = 3; // 3:前端只能输出,后端可输入输出
+ const C_BACK_ONLY_INPUT = 4; // 4:后端只能输入,前端可输入输出
+ const C_BACK_ONLY_OUTPUT = 5; // 5:后端只能输出,前端可输入输出
+ const C_BOTH_WAY_ONLY_INPUT = 6; // 6:两端均可输入输出,在哪端输入只能从哪端输出
+
+ /**
+ * BidirectionalQueue 初始化.
+ *
+ * @param int $type
+ * @param int $maxLength
+ */
+ public function __construct($type = self::C_AT_BOTH_ENDS, $maxLength = 0)
+ {
+ var_dump($this->getConfig());
+ $this->_type = in_array($type, [1, 2, 3, 4, 5, 6]) ? $type : self::C_AT_BOTH_ENDS;
+ $this->_maxLength = intval($maxLength);
+ }
+
+ /**
+ * addFirst 前端入列
+ *
+ * @param $item
+ * @return int
+ */
+ public function addFirst($item)
+ {
+ return array_unshift($this->queue, $item);
+ }
+
+ /**
+ * addLast 尾部入列
+ *
+ * @param $item
+ * @return int
+ */
+ public function addLast($item)
+ {
+ return array_push($this->queue, $item);
+ }
+
+ /**
+ * removeFirst 头部出列
+ *
+ * @return mixed
+ */
+ public function removeFirst()
+ {
+ return array_shift($this->queue);
+ }
+
+ /**
+ * removeLast 尾部出列
+ *
+ * @return mixed
+ */
+ public function removeLast()
+ {
+ return array_pop($this->queue);
+ }
+
+ /**
+ * 清空队列
+ */
+ public function makeEmpty()
+ {
+ unset($this->queue);
+ }
+
+ /**
+ * 获取列头
+ *
+ * @return mixed
+ */
+ public function getFirst()
+ {
+ return reset($this->queue);
+ }
+
+ /**
+ * 获取列尾
+ *
+ * @return mixed
+ */
+ public function getLast()
+ {
+ return end($this->queue);
+ }
+
+ /**
+ * 获取长度
+ *
+ * @return int
+ */
+ public function getLength()
+ {
+ return count($this->queue);
+ }
+
+ /**
+ * 获取配置常量
+ */
+ protected function getConfig()
+ {
+ return [
+ self::C_AT_BOTH_ENDS, // 1:两端均可输入输出
+ self::C_FRONT_ONLY_INPUT, // 2:前端只能输入,后端可输入输出
+ self::C_FRONT_ONLY_OUTPUT, // 3:前端只能输出,后端可输入输出
+ self::C_BACK_ONLY_INPUT, // 4:后端只能输入,前端可输入输出
+ self::C_BACK_ONLY_OUTPUT, // 5:后端只能输出,前端可输入输出
+ self::C_BOTH_WAY_ONLY_INPUT, // 6:两端均可输入输出,在哪端输入只能从哪端输出
+ ];
+ }
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
+new BidirectionalQueue();
\ No newline at end of file
diff --git a/src/Other/BigSmallReplace.php b/src/Other/BigSmallReplace.php
new file mode 100644
index 0000000..547a7b8
--- /dev/null
+++ b/src/Other/BigSmallReplace.php
@@ -0,0 +1,55 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * Hello World 输出 Olleh Dlrow
+ * -------------------------------------------------------------
+ * SWAT 输出 TAWS
+ * I am A sTudent 输出 I ma A tNeduts
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * BigSmallReplace
+ *
+ * @param $str
+ * @return string
+ */
+function BigSmallReplace($str)
+{
+ // Cutting words
+ $first = preg_split("/[\s]+/", $str);
+ $result = [];
+
+ // Start
+ foreach ($first as $f_value) {
+ $str_len = strlen($f_value) - 1;
+ $i = 0;
+ $temp = '';
+ while ($str_len >= 0) {
+ if (ord($f_value[$str_len]) > 64 && ord($f_value[$str_len]) < 91) {
+ $temp .= strtoupper($f_value[$i]);
+ } else if (ord($f_value[$str_len]) > 96 && ord($f_value[$str_len]) < 123) {
+ $temp .= strtolower($f_value[$i]);
+ }
+ $i++;
+ $str_len--;
+ }
+ array_push($result, strrev($temp));
+ }
+ return implode(' ', $result);
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+var_dump(BigSmallReplace('Hello World'));
diff --git a/src/Other/CartesianProduct.php b/src/Other/CartesianProduct.php
new file mode 100644
index 0000000..63f027d
--- /dev/null
+++ b/src/Other/CartesianProduct.php
@@ -0,0 +1,61 @@
+params = func_get_args();
+ }
+ public function combineDika()
+ {
+ $result = [];
+ if(count($this->params[0])!=count($this->params[0], 1)){
+ $this->params = $this->params[0];
+ }
+ $cnt = count($this->params);
+ foreach($this->params[0] as $item) {
+ $result[] = [$item];
+ }
+ for($i = 1; $i < $cnt; $i++) {
+ $result = $this->combineArray($result,$this->params[$i]);
+ }
+ return $result;
+ }
+
+ private function combineArray($arr_a, $arr_b)
+ {
+ $result = [];
+ foreach ($arr_a as $item) {
+ foreach ($arr_b as $item2) {
+ $temp = $item;
+ $temp[] = $item2;
+ $result[] = $temp;
+ }
+ }
+ return $result;
+ }
+}
+
+$color = array('白色','黑色','红色');
+$size = array('透气','防滑');
+$local = array('37码','38码','39码');
+
+$obj = new CartesianProduct($color,$size,$local);
+print_r($obj->combineDika());
+
+$sets = array(
+ array('白色','黑色','红色'),
+ array('透气','防滑'),
+ array('37码','38码','39码'),
+ array('男款','女款')
+);
+
+$obj1 = new CartesianProduct($sets);
+print_r($obj1->combineDika());
\ No newline at end of file
diff --git a/src/Other/ColorBricks.php b/src/Other/ColorBricks.php
new file mode 100644
index 0000000..d3a498d
--- /dev/null
+++ b/src/Other/ColorBricks.php
@@ -0,0 +1,98 @@
+
+ * @date 2017/9/1
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:
+ * 例如: s = "ABAB",那么小易有六种排列的结果:
+ * "AABB","ABAB","ABBA","BAAB", "BBAA" "BABA",
+ * 1-2 0 2-3 0-1 0-3 1-2
+ * "ABAB", 0
+ * "BAAB", 0-1
+ * "AABB", 0-2
+ * "BABA" 0-3
+ * "ABBA", 1-2
+ * "BBAA" 1-3
+ * -------------------------------------------------------------
+ * 小易有一些彩色的砖块。每种颜色由一个大写字母表示。各个颜色砖块看起来都完全一样。
+ * 现在有一个给定的字符串s,s中每个字符代表小易的某个砖块的颜色。小易想把他所有的砖块排成一行。
+ * 如果最多存在一对不同颜色的相邻砖块,那么这行砖块就很漂亮的。
+ * -------------------------------------------------------------
+ * 请你帮助小易计算有多少种方式将他所有砖块排成漂亮的一行。(如果两种方式所对应的砖块颜色序列是相同的,那么认为这两种方式是一样的。)
+ * -------------------------------------------------------------
+ * 例如: s = "ABAB",那么小易有六种排列的结果:
+ * "AABB","ABAB","ABBA","BAAB","BABA","BBAA"
+ * 其中只有"AABB"和"BBAA"满足最多只有一对不同颜色的相邻砖块。
+ * -------
+ * 输入描述:
+ * 输入包括一个字符串s,字符串s的长度length(1 ≤ length ≤ 50), [s中的每一个字符都为一个大写字母(A到Z)]。
+ * 输出描述:
+ * 输出一个整数,表示小易可以有多少种方式。
+ * -------
+ * 输入例子1:
+ * ABAB
+ * 输出例子1:
+ * 2
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * ColorBricks
+ *
+ * @param $inputting
+ * @return bool|int
+ */
+function ColorBricks($inputting)
+{
+ $count = strlen($inputting);
+ $ascii = ord($inputting);
+
+ if (!($ascii > 64 && $ascii < 91)) {
+ return false;
+ }
+ if (!(1 <= $count && $count <= 50)) {
+ return false;
+ }
+
+ $container = array ();
+ $max = floor($count / 2);
+
+ for ($i = 0; $i < $max; $i++) {
+ for ($j = 1; $j < $count; $j++) {
+ $temp = $inputting[$j];
+ $inputting[$j] = $inputting[0];
+ $inputting[0] = $temp;
+ array_push($container, $inputting);
+ }
+ }
+ $containerCount = count($container);
+ $counter = 0;
+
+ for ($i = 0; $i < $max; $i++) {
+ $success = false;
+ for ($j = 0; $j < $containerCount; $j++) {
+ $str = $container[$j];
+ if ($str[$i] == $str[0]) {
+ $success = true;
+ }
+ }
+ if ($success) {
+ $counter++;
+ }
+ }
+ return $counter;
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+echo ColorBricks("AABB");
\ No newline at end of file
diff --git a/src/Other/DynamicProgramming.php b/src/Other/DynamicProgramming.php
new file mode 100644
index 0000000..53b6ad3
--- /dev/null
+++ b/src/Other/DynamicProgramming.php
@@ -0,0 +1,64 @@
+
+ * @date 2017/8/28
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:动态规划原理思想,max(opt(i-1,w),wi+opt(i-1,w-wi)) 当中最大值,opt(i-1,w-wi)指上一个最优解
+ * -------------------------------------------------------------
+ * 一个承受最大重量为W的背包,现在有n个物品,每个物品重量为t, 每个物品的价值为v。
+ * 要使得这个背包重量最大(但不能超过W),同时又需要背包的价值最大
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * DynamicProgramming
+ *
+ * @param $maxSize
+ * @param $goods
+ * @param $cost
+ * @return mixed
+ */
+function DynamicProgramming($maxSize, $goods, $cost)
+{
+ $container = [];
+ $goodsCount = count($goods);
+
+ //初始化
+ for ($i = 0; $i <= $maxSize; $i++) {
+ $container[0][$i] = 0;
+ }
+ for ($j = 0; $j <= $goodsCount; $j++) {
+ $container[$j][0] = 0;
+ }
+ for ($j = 1; $j <= $goodsCount; $j++) {
+ for ($i = 1; $i <= $maxSize; $i++) {
+ $container[$j][$i] = $container[$j - 1][$i];
+ //不大于最大的w=15
+ if ($goods[$j - 1] <= $maxSize) {
+ if (!isset($container[$j - 1][$i - $goods[$j - 1]])) {
+ continue;
+ }
+ //wi+opt(i-1,wi)
+ $tmp = $container[$j - 1][$i - $goods[$j - 1]] + $cost[$j - 1];
+ //opt(i-1,w),wi+opt(i-1,w-wi) => 进行比较
+ if ($tmp > $container[$j][$i]) {
+ $container[$j][$i] = $tmp;
+ }
+ }
+ }
+ }
+ return $container[$j - 1][$i - 1];
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+echo DynamicProgramming(15, array (3, 4, 5, 6), array (8, 7, 4, 9));
diff --git a/src/Other/ElevatorDispatch.php b/src/Other/ElevatorDispatch.php
new file mode 100644
index 0000000..d1811ba
--- /dev/null
+++ b/src/Other/ElevatorDispatch.php
@@ -0,0 +1,111 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 解决方案:
+ * (1)使用简单的方法,直接将楼层从1到n开始遍历
+ * sum(person[i] * |i - j| ) 此表达式为一个双重循环,i与j均为1-n的循环。
+ * j下标表示电梯停靠的楼层。
+ * person数组表示,对应i层的下电梯的人数。此算法负责度为o(n*n)
+ * 对应的j是上述和为最小的一层即为所求。 上面的算法复杂度为o(n)
+ *
+ * (2)下面考虑一个简单的算法,使其复杂度达到o(n)
+ * 考虑假如电梯停靠在某一楼层i处,假设在i处下楼的客人为$first_layer,
+ * 在i以上楼层的客人数目为$first_layer_above ,在i一下楼层的客人数目为$first_layer_below。
+ * 且将电梯在i层停止时,全部人员的路程之和记为T。
+ *
+ * 那么加入电梯在i-1层停的话,则原来i层之上的人需要多爬一层,即增加了$first_layer_above
+ * 第i层的人需要多爬一层,则结果增加了$first_layer, i层之下的人则少爬了一层,结果减去$first_layer_below
+ * 所以第i-1层的结果为$time- $first_layer_below + $first_layer + $first_layer_above 。即结果可以即为$time-($first_layer_below - $first_layer - $first_layer_above)
+ *
+ *
+ * 下面考虑在i+1层的结果,若电梯在i+1层停止的话,原来i层之上的客户都会少爬一层,
+ * 则结果减少$first_layer_above ,而i层之下的人员则都会多爬一层即增加了$first_layer_below ,第i层的人员都会多爬一层
+ * 即为增加了$first_layer 。则结果为$time+ $first_layer_below + $first_layer - $first_layer_above
+ *
+ * 综上我们得出,
+ * (1)若$first_layer_below > $first_layer + $first_layer_above的时候, 我们在第i-1层 选择电梯停止最好。
+ * (2)若$first_layer_below + $first_layer < $first_layer_above的时候, 我们选择在第i+1层停止电梯最好。
+ *
+ * 下面我们可以先计算出来当i=1时候的T ,然后判断是否需要在i+1层停止,若是i+1层的花费
+ * 大于i层,则我们可以继续计算,否则退出。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+class ElevatorDispatch
+{
+ protected $n = 10;
+ protected $person;
+ protected $time = 0; //先计算出在第一层停止的时候 所需要的花费
+ protected $first_layer_below = 0; //在第一层以下下的人数
+ protected $first_layer;
+ protected $first_layer_above = 0;//在第一层之上下电梯的人数
+ public $floor = 1;//存储停靠的楼层
+
+ public function __construct($person = [])
+ {
+ if (empty($person)) {
+ $this->person = [0, 2, 5, 7, 3, 5, 2, 6, 2, 6, 3];
+ }
+ $this->first_layer = $this->person[1]; //在第一层处下的人数
+
+ }
+
+ public function compute()
+ {
+
+ //先计算出第1层停止需要爬取的楼层数目
+ for ($i = 2; $i <= $this->n; $i++) {
+ $this->time += $this->person[$i] * ($i - 1);
+ $this->first_layer_above += $this->person[$i];
+ }
+ for ($j = 2; $j <= $this->n; $j++) {
+ if ($this->first_layer_below + $this->first_layer <= $this->first_layer_above) { //说明第i+1层的结果会大于第i层
+ $this->time += $this->first_layer_below + $this->first_layer - $this->first_layer_above;
+ $this->first_layer_below += $this->first_layer;
+ $this->first_layer = $this->person[$j];
+ $this->first_layer_above -= $this->person[$j];
+ $this->floor = $j;
+ } else {
+ //否则第i层的结果已经最小,故不需要计算第i+1层
+ break;
+ }
+ }
+ return $this->floor;
+ }
+
+ public function computeTwo()
+ {
+ $min = 6553;//存储最小值 ;
+ for ($i = 1; $i <= $this->n; $i++) { //表示第i楼层电梯停靠
+ $this->time = 0;
+ for ($j = 1; $j < $this->n; $j++) {
+ $this->time += abs(($i - $j)) * $this->person[$j];
+ }
+ if ($min > $this->time) {
+ $min = $this->time;
+ $this->floor = $i;
+ }
+ }
+ return $this->floor;
+ }
+
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
+$obj = new ElevatorDispatch();
+var_dump($obj->compute());
+var_dump($obj->computeTwo());
\ No newline at end of file
diff --git a/src/Other/Encryption.php b/src/Other/Encryption.php
new file mode 100644
index 0000000..22e5eee
--- /dev/null
+++ b/src/Other/Encryption.php
@@ -0,0 +1,78 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 位运算进行加密
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * 加密函数
+ *
+ * @param $txt
+ * @param $key
+ * @return string
+ */
+function passport_encrypt($txt, $key)
+{
+ $encrypt_key = md5(rand(0, 32000));
+ $ctr = 0;
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
+ $tmp .= $encrypt_key[$ctr] . ($txt[$i] ^ $encrypt_key[$ctr++]);
+ }
+ return base64_encode(passport_key($tmp, $key));
+}
+
+/**
+ * 解密函数
+ *
+ * @param $txt
+ * @param $key
+ * @return string
+ */
+function passport_decrypt($txt, $key)
+{
+ $txt = passport_key(base64_decode($txt), $key);
+
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ $md5 = $txt[$i];
+ $tmp .= $txt[++$i] ^ $md5;
+ }
+ return $tmp;
+}
+
+/**
+ * passport_key
+ *
+ * @param $txt
+ * @param $encrypt_key
+ * @return string
+ */
+function passport_key($txt, $encrypt_key)
+{
+ $encrypt_key = md5($encrypt_key);
+ $ctr = 0;
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
+ $tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
+ }
+ return $tmp;
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
diff --git a/src/Other/Factorial.php b/src/Other/Factorial.php
new file mode 100644
index 0000000..ccd2869
--- /dev/null
+++ b/src/Other/Factorial.php
@@ -0,0 +1,44 @@
+
+ * @date 2017/8/25
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:
+ * -------------------------------------------------------------
+ * 斐波那契数列(Fibonacci Sequence)又称黄金分割数列 兔子数列
+ * 指的是这样一个数列:1、1、2、3、5、8、13、21
+ * 在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+/**
+ * 递归方式
+ *
+ * @param $n
+ * @return mixed
+ */
+function FibonacciRecursive($n)
+{
+ if ($n <= 1) {
+ return $n;
+ }
+ return Fibonacci($n - 1) + Fibonacci($n - 2);
+}
+
+/**
+ * 非递归方式
+ *
+ * @param $n
+ * @return mixed
+ */
+function Fibonacci($n)
+{
+ if ($n <= 1) {
+ return $n;
+ }
+ for ($fib = [0, 1], $i = 2; $i <= $n; $i++) {
+ $fib[$i] = $fib[$i - 1] + $fib[$i - 2];
+ }
+ return $fib[$n];
+}
+
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+echo Fibonacci(10);
+echo FibonacciRecursive(10);
diff --git a/src/Other/GetCattle.php b/src/Other/GetCattle.php
new file mode 100644
index 0000000..0997ac0
--- /dev/null
+++ b/src/Other/GetCattle.php
@@ -0,0 +1,60 @@
+
+ * @date 2017/8/24
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:见下方注释
+ * -------------------------------------------------------------
+ *
+ * 牛年求牛:
+ * 有一母牛,到4岁可生育,每年一头,所生均是一样的母牛
+ * 15岁绝育,不再能生,
+ * 20岁死亡,问n年后有多少头牛。
+ *
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * getCattle
+ *
+ * @param $n
+ * @return int
+ */
+function getCattle($n)
+{
+ static $num = 1;
+ for ($i = 1; $i <= $n; $i++) {
+ if ($i == 20) {
+ $num--; //死亡需减一
+ } else if ($i >= 4 && $i < 15) {
+ $num++; //生小母牛(这里有小母牛)
+ getCattle($n - $i); //小母牛生小母牛(这里不包含小母牛)
+ }
+ }
+ return $num;
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+echo '牛年共有:' . getCattle(10);
+
+/*
+123456789
+ 123456
+ 123
+ 12
+9 - 11
+
+---
+
+ */
\ No newline at end of file
diff --git a/src/Other/HanoiGames.php b/src/Other/HanoiGames.php
new file mode 100644
index 0000000..83b1b51
--- /dev/null
+++ b/src/Other/HanoiGames.php
@@ -0,0 +1,63 @@
+
+ * @date 2017/8/26
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:
+ * -------------------------------------------------------------
+ * 汉诺塔(又称河内塔)问题是印度的一个古老的传说。
+ * 开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,
+ * 第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,
+ * 庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,
+ * 但每次只能搬一个,而且大的不能放在小的上面。
+ * 面对庞大的数字(移动圆片的次数)18446744073709551615,看来,众僧们耗尽毕生精力也不可能完成金片的移动。
+ * 后来,这个传说就演变为汉诺塔游戏:
+ * 1.有三根杆子A,B,C。A杆上有若干碟子
+ * 2.每次移动一块碟子,小的只能叠在大的上面
+ * 3.把所有碟子从A杆全部移到C杆上
+ * 经过研究发现,汉诺塔的破解很简单,就是按照移动规则向一个方向移动金片:
+ * 如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
+ * 此外,汉诺塔问题也是程序设计中的经典递归问题。
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * HanoiGames
+ *
+ * @param $n
+ * @param $x
+ * @param $y
+ * @param $z
+ */
+function HanoiGames($n, $x, $y, $z)
+{
+ if ($n == 1) {
+ echo 'move disk 1 from ' . $x . ' to ' . $z . "\n";
+ } else {
+ HanoiGames($n - 1, $x, $z, $y);
+ echo 'move disk ' . $n . ' from ' . $x . ' to ' . $z . "\n";
+ HanoiGames($n - 1, $y, $x, $z);
+ }
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+HanoiGames(3, 'A', 'B', 'C');
+
+// move disk 1 from A to C
+// move disk 2 from A to B
+// move disk 1 from C to B
+// move disk 3 from A to C
+// move disk 1 from B to A
+// move disk 2 from B to C
+// move disk 1 from A to C
diff --git a/src/Other/HashTable.php b/src/Other/HashTable.php
new file mode 100644
index 0000000..cdd6b10
--- /dev/null
+++ b/src/Other/HashTable.php
@@ -0,0 +1,130 @@
+
+ * @date 2019/5/9
+ * @license MIT
+ * -------------------------------------------------------------
+ * HashTable
+ */
+
+
+define('TABLE_SIZE', 100);
+
+class KeyValue
+{
+ public $key;
+ public $value;
+
+ public function __construct($key, $value)
+ {
+ $this->key = $key;
+ $this->value = $value;
+ }
+}
+
+class HashTable
+{
+ public $size = 0;
+ public $data = [];
+}
+
+function create_table($size = TABLE_SIZE)
+{
+ $table = new HashTable();
+ for ($i = 0; $i < $size; ++$i) {
+ $table->data[$i] = null;
+ }
+ $table->size = 100;
+
+ return $table;
+}
+
+function destroy_table(&$table)
+{
+ unset($table);
+}
+
+function hash_key($key, $size = TABLE_SIZE)
+{
+ $len = strlen($key);
+ $hash = 0;
+ for ($i = 0; $i < $len; ++$i) {
+ $hash = $hash * 31 + ord($key[$i]);
+ }
+
+ return abs($hash % $size);
+}
+
+function print_debug($table)
+{
+ for ($i = 0; $i < $table->size; ++$i) {
+ if (null === $table->data[$i]) {
+ echo $i, "\n";
+ } else {
+ echo $i, ' key=', $table->data[$i]->key, ', value=', $table->data[$i]->value , "\n";
+ }
+ }
+}
+
+function exists(&$table, $key)
+{
+ $index = hash_key($key);
+ if (null === $table->data[$index]) {
+ return false;
+ }
+
+ if (0 === strcmp($key, $table->data[$index]->key)) {
+ return true;
+ }
+
+ return false;
+}
+
+function add(&$table, $key, KeyValue $object)
+{
+ $index = hash_key($key);
+ $table->data[$index] = $object;
+}
+
+function get(&$table, $key)
+{
+ $index = hash_key($key);
+ if (0 === strcmp($key, $table->data[$index]->key)) {
+ return $table->data[$index]->value;
+ }
+}
+
+function delete(&$table, $key)
+{
+ $index = hash_key($key);
+ if (null === $table->data[$index]) {
+ return;
+ }
+ if (0 === strcmp($key, $table->data[$index]->key)) {
+ return $table->data[$index] = null;
+ }
+}
+
+$hash_table = create_table();
+print_debug($hash_table);
+
+add($hash_table, 'Wang', new KeyValue('Wang', '50'));
+add($hash_table, 'Li', new KeyValue('Li', '20'));
+add($hash_table, 'Chow', new KeyValue('Chow', '23'));
+print_debug($hash_table);
+
+//get
+echo "----------get-------------- \n";
+var_dump(get($hash_table, 'Wang'));
+
+//delete
+echo "----------delete-------------- \n";
+delete($hash_table, 'Wang');
+var_dump(delete($hash_table, 'Wang'));
+
+//exists
+echo "----------exists-------------- \n";
+var_dump(exists($hash_table, 'Wang'));
+var_dump(exists($hash_table, 'Li'));
\ No newline at end of file
diff --git a/src/Other/Interval.php b/src/Other/Interval.php
new file mode 100644
index 0000000..0b840c2
--- /dev/null
+++ b/src/Other/Interval.php
@@ -0,0 +1,95 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ *
+ * 不同概率的抽奖原理就是把0到*(比重总数)的区间分块
+ * 分块的依据是物品占整个的比重,再根据随机数种子来产生0-* 中的某个数
+ * 判断这个数是落在哪个区间上,区间对应的就是抽到的那个物品。
+ * 随机数理论上是概率均等的,那么相应的区间所含数的多少就体现了抽奖物品概率的不同。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * get_rand
+ *
+ * @param $proArr
+ * @return array
+ */
+function get_rand($proArr)
+{
+ $result = array();
+ foreach ($proArr as $key => $val) {
+ $arr[$key] = $val['v'];
+ }
+ $proSum = array_sum($arr); // 计算总权重
+ $randNum = mt_rand(1, $proSum);
+ $d1 = 0;
+ $d2 = 0;
+ for ($i = 0; $i < count($arr); $i++) {
+ $d2 += $arr[$i];
+ if ($i == 0) {
+ $d1 = 0;
+ } else {
+ $d1 += $arr[$i - 1];
+ }
+ if ($randNum >= $d1 && $randNum <= $d2) {
+ $result = $proArr[$i];
+ }
+ }
+ unset ($arr);
+ return $result;
+}
+
+/**
+ * 使用较多的为这个方法
+ *
+ * @param $proArr
+ * @return array
+ */
+function get_rand1($proArr)
+{
+ $result = array();
+ foreach ($proArr as $key => $val) {
+ $arr[$key] = $val['v'];
+ }
+ // 概率数组的总概率
+ $proSum = array_sum($arr);
+ asort($arr);
+ // 概率数组循环
+ foreach ($arr as $k => $v) {
+ $randNum = mt_rand(1, $proSum);
+ if ($randNum <= $v) {
+ $result = $proArr[$k];
+ break;
+ } else {
+ $proSum -= $v;
+ }
+ }
+ return $result;
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+$arr = array(
+ array('id' => 1, 'name' => '特等奖', 'v' => 1),
+ array('id' => 2, 'name' => '一等奖', 'v' => 5),
+ array('id' => 3, 'name' => '二等奖', 'v' => 10),
+ array('id' => 4, 'name' => '三等奖', 'v' => 12),
+ array('id' => 5, 'name' => '四等奖', 'v' => 22),
+ array('id' => 6, 'name' => '没中奖', 'v' => 50)
+);
+
+var_dump(get_rand($arr));
+
diff --git a/src/Other/Judge.php b/src/Other/Judge.php
new file mode 100644
index 0000000..a69ef43
--- /dev/null
+++ b/src/Other/Judge.php
@@ -0,0 +1,69 @@
+weight = $weight;
+ $this->value = $value;
+ $this->total_weight = $total_weight;
+ }
+
+ # 贪心算法去算最佳的物品
+ public function bag()
+ {
+ $product = [];
+ foreach ($this->weight as $k => $v) {
+ $product[] = ['weight' => $v, 'value' => $this->value[$k], 'pj_value' => ($this->value[$k] / $v)];
+ }
+
+ $total_value = 0;
+ //按价值比去排序
+ $sorted_product = $this->sortByPj_value($product);
+ //print_r($sorted_product);
+ $total = 0;
+ foreach ($sorted_product as $k => $v) {
+ if ($total + $v['weight'] <= $this->total_weight) {
+
+ $total_value += $v['value'];
+
+ $total += $v['weight'];
+ } elseif ($total < $this->total_weight) {
+
+ for ($j = $k + 1; $j < count($sorted_product); $j++) {
+ if (($sorted_product[$j]['weight'] + $total) <= 150) {
+ $total_value += $sorted_product[$j]['value'];
+ $total += $sorted_product[$j]['weight'];
+ }
+ }
+
+ break;
+
+ }else{
+
+ break;
+ }
+ }
+
+ return [$total ,$total_value ];
+
+ }
+
+ private function sortByPj_value($product)
+ {
+ for ($i = 0; $i < count($product); $i++) {
+ for ($j = $i + 1; $j < count($product); $j++) {
+ if ($product[$i]['pj_value'] < $product[$j]['pj_value']) {
+ $temp = $product[$i];
+ $product[$i] = $product[$j];
+ $product[$j] = $temp;
+ }
+ }
+
+ }
+ return $product;
+ }
+}
+
+$obj = new Knapsack([35, 30, 60, 50, 40, 15, 10],[10, 40, 30, 50, 35, 40, 30],150);
+var_dump($obj->bag());
+
+
+
diff --git a/src/Other/Maze.php b/src/Other/Maze.php
new file mode 100644
index 0000000..1efd0a0
--- /dev/null
+++ b/src/Other/Maze.php
@@ -0,0 +1,288 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 构造迷宫二维数组
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+//迷宫一
+for ($l = 0; $l <= 5; $l++) {
+ for ($m = 0; $m <= 5; $m++) {
+ if ($l == 1 && $m <= 3)
+ $arr[$l][$m] = 0;
+ elseif ($l == 2 && ($m == 1 || $m == 3 || $m == 4))
+ $arr[$l][$m] = 0;
+ elseif ($l == 3 && $m <= 4 && $m != 0 && $m != 3)
+ $arr[$l][$m] = 0;
+ elseif ($l == 4 && ($m == 1 || $m >= 4))
+ $arr[$l][$m] = 0;
+ else
+ $arr[$l][$m] = 1;
+
+ echo $arr[$l][$m] . ' ';
+ }
+ echo '
';
+}
+echo '
寻地址算法的实现:
';
+
+/**
+ * findPath
+ *
+ * @param $i
+ * @param $j
+ * @param $dir
+ * @param $arr
+ * @param $iline
+ * @param $jline
+ * @param $dirline
+ * @return int
+ */
+function findPath($i, $j, $dir, $arr, $iline, $jline, $dirline)
+{
+
+ //判断是否结束
+ if ($i == 4 && $j == 5) return 1;
+ $ifdirs = 0;
+ $newdir = $dir;
+ $lastdir = $dir;
+
+
+ //如果该点为0,则前进
+ if ($arr[$i][$j] == 0) {
+ //判断方向增量
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+
+ //判断是否路口
+ for ($n = 1; $n <= 4; $n++) {
+ switch ($newdir) {
+ case 0:
+ $aa = 0;
+ $bb = 1;
+ break;
+ case 1:
+ $aa = 1;
+ $bb = 0;
+ break;
+ case 2:
+ $aa = 0;
+ $bb = -1;
+ break;
+ case 3:
+ $aa = -1;
+ $bb = 0;
+ break;
+ }
+ if ($arr[($i + $aa)][($j + $bb)] == 0) {
+ $ifdirs++;
+ }
+ $newdir = ($newdir + 1) % 4;
+ }
+
+ //判断是否路口,是则记录位置和方向
+ if ($ifdirs > 2) {
+
+ if (in_array($i, $iline) && in_array($j, $jline)) {
+ } else {
+ echo "该点是路口:|$i,$j,$dir|
";
+ $iline[] = $i;
+ $jline[] = $j;
+ $dirline[] = $dir;
+ }
+ }
+
+ if ($ifdirs > 1) {
+ //不是死路,前进
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ //方向不变,可以前进
+ $i += $ii;
+ $j += $jj;
+ echo "方向不变,可以前进:|$i,$j,$dir|
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ } else {
+ //方向改变,试探
+ if ($ifdirs > 2) {
+ //该点是路口,取来时方向为路口记录方向
+ $lastdir = $dirline[(count($dirline) - 1)];
+ } else {
+ //不是路口,则在改变方向前记录方向
+ $lastdir = $dir;
+ }
+
+ //判断来时方向,不能走回头路
+ switch ($lastdir) {
+ case 0:
+ $errdir = 2;
+ break;
+ case 1:
+ $errdir = 3;
+ break;
+ case 2:
+ $errdir = 0;
+ break;
+ case 3:
+ $errdir = 1;
+ break;
+ }
+ //改变方向
+ $dir = ($dir + 1) % 4;
+
+ //判断改变后方向是否为来时方向
+ echo "不能走回头路:err:$errdir,dir:$dir
";
+ if ($dir != $errdir) {
+ echo "turn:($i,$j,$dir)
";
+ switch ($dir) {
+ case 0:
+ $mm = 0;
+ $nn = 1;
+ break;
+ case 1:
+ $mm = 1;
+ $nn = 0;
+ break;
+ case 2:
+ $mm = 0;
+ $nn = -1;
+ break;
+ case 3:
+ $mm = -1;
+ $nn = 0;
+ break;
+ }
+ if ($arr[($i + $mm)][($j + $nn)] == 0) {
+ $i += $mm;
+ $j += $nn;
+ echo "可以前进:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ } else {
+ $dir = ($dir + 1) % 4;
+ echo "再改变方向,试探:$i,$j,$dir
";
+ if ($dir != $errdir) {
+ echo "turn:($i,$j,$dir)
";
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ $i += $ii;
+ $j += $jj;
+ echo "可以前进:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ }
+ } else {
+ $dir = ($dir + 1) % 4;
+ echo "再改变方向,试探:$i,$j,$dir
";
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ $i += $ii;
+ $j += $jj;
+ echo "OK:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ }
+
+ }
+ }
+
+ } else {
+ $dir = ($dir + 1) % 4;
+ echo "不能回头,再改变方向,试探:$i,$j,$dir
";
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ $i += $ii;
+ $j += $jj;
+ echo "可以前进:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ }
+ }
+ }
+ } else {
+ //是死路,需要返回到上个路口,改变方向,试探
+ $dir = $dirline[(count($dirline) - 1)];
+ $i = $iline[(count($iline) - 1)];
+ $j = $jline[(count($jline) - 1)];
+ echo "是死路,返回到上个路口,记录为:#$i,$j,$dir#
";
+ $dir = ($dir + 1) % 4;
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+
+ }
+
+ }
+}
+
+$a[] = $b[] = $c[] = 0;
+echo '初始值=>节点:($i=1,$j=1),方向:($dir=0).
';
+findPath(1, 1, 0, $arr, $a, $b, $c);
\ No newline at end of file
diff --git a/src/Other/MonkeyKing.php b/src/Other/MonkeyKing.php
new file mode 100644
index 0000000..8e25abd
--- /dev/null
+++ b/src/Other/MonkeyKing.php
@@ -0,0 +1,125 @@
+
+ * @date 2017/8/23
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:约瑟夫环问题
+ * -------------------------------------------------------------
+ * 有M个monkey ,转成一圈,第一个开始数数,数到第N个出圈,下一个再从1开始数,再数到第N个出圈,直到圈里只剩最后一个就是大王
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+class MonkeyKing
+{
+ protected $next;
+ protected $name;
+
+ /**
+ * MonkeyKing constructor.
+ *
+ * @param $name
+ */
+ public function __construct($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * whoIsKing
+ *
+ * @static
+ * @param $count
+ * @param $num
+ * @return mixed
+ */
+ public static function whoIsKing($count, $num)
+ {
+ // 构造单向循环链表
+ $current = $first = new MonkeyKing(1);
+ for ($i = 2; $i <= $count; $i++) {
+ $current->next = new MonkeyKing($i);
+ $current = $current->next;
+ }
+ // 最后一个指向第一个
+ $current->next = $first;
+ // 指向第一个
+ $current = $first;
+ // 定义一个数字
+ $cn = 1;
+ while ($current !== $current->next) {
+ $cn++;
+ if ($cn == $num) {
+ $current->next = $current->next->next;
+ $cn = 1;
+ }
+ $current = $current->next;
+ }
+ // 返回猴子姓名
+ return $current->name;
+ }
+}
+
+/**
+ * whoIsKing
+ *
+ * @param $n
+ * @param $m
+ * @return int
+ */
+function whoIsKing($n, $m)
+{
+ $r = 0;
+ for ($i = 2; $i <= $n; $i++) {
+ $r = ($r + $m) % $i;
+ }
+ return $r + 1;
+}
+
+/**
+ * king
+ *
+ * @param $n
+ * @param $m
+ * @return mixed
+ */
+function king($n, $m)
+{
+ $monkeys = range(1, $n);
+ $i = 0;
+ $k = $n;
+ while (count($monkeys) > 1) {
+ if (($i + 1) % $m == 0) {
+ unset($monkeys[$i]);
+ } else {
+ array_push($monkeys, $monkeys[$i]);
+ unset($monkeys[$i]);
+ }
+ $i++;
+ }
+ return current($monkeys);
+}
+
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
+// 共10个猴子每3个出圈
+var_dump(MonkeyKing::whoIsKing(10, 3));
+
+
+var_dump(whoIsKing(10, 3));
+
+
+$a = king(10, 3);
+var_dump($a);
\ No newline at end of file
diff --git a/src/Other/NQueen.php b/src/Other/NQueen.php
new file mode 100644
index 0000000..5b16798
--- /dev/null
+++ b/src/Other/NQueen.php
@@ -0,0 +1,89 @@
+
+ * @date 2023/12/06
+ * @license MIT
+ */
+/*
+|--------------------------------------------------------------------------
+| NQueen Algorithm
+|--------------------------------------------------------------------------
+|
+| Arrange N queens on an NxN chessboard without attacking each other diagonally,
+| horizontally, or vertically—a classic problem in combinatorial optimization and
+| recursion.
+|
+*/
+
+class NQueen
+{
+
+ //Variable to store the dimensions of the chessboard
+ protected int $n;
+
+ //Chessboard represented as an array
+ protected array $board;
+
+ //Constructor to initialize the chessboard dimensions and fill it with zeros
+ public function __construct(int $n)
+ {
+ $this->n = $n;
+ $this->board = array_fill(0, $this->n, array_fill(0, $this->n, 0));
+ }
+
+ public function solve_n_queen($col = 0): void
+ {
+ if ($col >= $this->n) {
+ $this->print_result();
+ }
+
+ //Iterating through each row in the current column
+ for ($row = 0; $row < $this->n; $row++) {
+ if ($this->move_is_promising($row, $col)) {
+ //Placing the queen at the current position
+ $this->board[$row][$col] = 1;
+ //Recursively solving for the next column
+ $this->solve_n_queen($col + 1);
+ //Backtracking by removing the queen from the current position
+ $this->board[$row][$col] = 0;
+ }
+ }
+ }
+
+ public function move_is_promising($row, $col): bool
+ {
+ //Checking if there is no queen in the same row
+ for ($index = 0; $index < $col; $index++)
+ if ($this->board[$row][$index])
+ return false;
+
+ //Checking if there is no queen on the upper-left diagonal
+ for ($i = $row, $j = $col; $i >= 0 && $j >= 0; $i--, $j--)
+ if ($this->board[$i][$j])
+ return false;
+
+ //Checking if there is no queen on the lower-left diagonal
+ for ($i = $row, $j = $col; $i < $this->n && $j >= 0; $i++, $j--)
+ if ($this->board[$i][$j])
+ return false;
+
+ //If no conflicts are found, the move is promising
+ return true;
+ }
+
+ public function print_result(): void
+ {
+ for ($i = 0; $i < $this->n; $i++) {
+ for ($j = 0; $j < $this->n; $j++)
+ echo $this->board[$i][$j];
+ echo "\n";
+ }
+ echo "\n";
+ }
+}
+
+$dimensions = 4;
+(new NQueen($dimensions))->solve_n_queen();
diff --git a/src/Other/OnlyNumbers.php b/src/Other/OnlyNumbers.php
new file mode 100644
index 0000000..f076a9d
--- /dev/null
+++ b/src/Other/OnlyNumbers.php
@@ -0,0 +1,86 @@
+
+ * @date 2017/8/30
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:快排同时做唯一标示
+ * -------------------------------------------------------------
+ * 一个数组里只有唯一一个元素是不同于别的元素,其余元素是两两相等如何得到这个元素
+ *
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+
+/**
+ * OnlyNumbers
+ *
+ * @param array $container
+ * @return array|bool
+ */
+function OnlyNumbers(array $container)
+{
+ $count = count($container);
+ if ($count <= 1) {
+ return $container;
+ }
+ $exist = [];
+ for ($i = 0; $i < $count; $i++) {
+ if (isset($exist[$container[$i]])) {
+ unset($exist[$container[$i]]);
+ continue;
+ }
+ $exist[$container[$i]] = true;
+ }
+ return !empty($exist) ? array_keys($exist)[0] : false;
+}
+
+// +----------------------------------------------------------------------
+// | 方法二
+// +----------------------------------------------------------------------
+/**
+ * @author Openset ';
+ print_r($this->c[$mst[$minid]] ."到" . $this->c[$minid] . " 权值:" . $min);
+ echo '
';
+
+ $sum += $min;
+ $this->lowcost[$minid] = 0;
+
+ for ($j = 1; $j < $n; $j++) {
+ if ($graph[$minid][$j] < $this->lowcost[$j]) {
+ $this->lowcost[$j] = $graph[$minid][$j];
+ $mst[$j] = $minid;
+ }
+ }
+ }
+ print_r("sum:" . $sum);
+ }
+
+ public function main()
+ {
+ $map = [
+ [0, 10, 65535, 65535, 65535, 11, 65535, 65535, 65535],
+ [10, 0, 18, 65535, 65535, 65535, 16, 65535, 12],
+ [65535, 65535, 0, 22, 65535, 65535, 65535, 65535, 8],
+ [65535, 65535, 22, 0, 20, 65535, 65535, 16, 21],
+ [65535, 65535, 65535, 20, 0, 26, 65535, 7, 65535],
+ [11, 65535, 65535, 65535, 26, 0, 17, 65535, 65535],
+ [65535, 16, 65535, 65535, 65535, 17, 0, 19, 65535],
+ [65535, 65535, 65535, 16, 7, 65535, 19, 0, 65535],
+ [65535, 12, 8, 21, 65535, 65535, 65535, 65535, 0]
+ ];
+ $this->prim_main($map, count($map));
+ }
+}
+
+$obj = new Prim();
+$obj->main();
diff --git a/src/Other/Rectangle.php b/src/Other/Rectangle.php
new file mode 100644
index 0000000..725a951
--- /dev/null
+++ b/src/Other/Rectangle.php
@@ -0,0 +1,88 @@
+$value) {
+ $x = abs($value[0]-$one[0]);
+ $y = abs($value[1]-$one[1]);
+ $data[$key] = sqrt(pow($x,2)+pow($y,2));
+ }
+
+ asort($data);
+ $keys = array_keys($data);
+ $maxKey = array_pop($keys);//对焦点
+ $length0 = $data[$maxKey];//对角线长度
+
+ //左右两点 key
+ $left = $keys[0];
+ $right = $keys[1];
+
+ //算第二条对角线长度
+ $x = abs($array[$left][0]-$array[$right][0]);
+ $y = abs($array[$left][1]-$array[$right][1]);
+ $length = sqrt(pow($x,2)+pow($y,2));
+
+ if(!floatEq($length,$length0)) {
+ return false;
+ }
+
+ //算直角
+ $vertical = sqrt(pow($data[$left],2)+pow($data[$right],2));
+
+ if(!floatEq($length,$vertical)) {
+ return false;
+ }
+
+ return true;
+
+}
+
+var_dump(rectangle([0,0],[0,1],[1,1],[1,0])); //true
+var_dump(rectangle([1,2],[0,1],[1,1],[1,0])); //false
+
+/**
+ * 判断两个浮点数是不是相等
+ *
+ * @param $a float
+ * @param $b float
+ * @return bool
+ */
+function floatEq($floatNumber1,$floatNumber2)
+{
+ if(!$floatNumber1 || !$floatNumber2) {
+ return false;
+ }
+ //精度
+ $epsilon = 0.00001;
+
+ if(abs($floatNumber1-$floatNumber2) < $epsilon) {
+ return true;
+ }
+ return false;
+}
diff --git a/src/Other/RotateSort.php b/src/Other/RotateSort.php
new file mode 100644
index 0000000..2fefd3c
--- /dev/null
+++ b/src/Other/RotateSort.php
@@ -0,0 +1,166 @@
+ |
+ * | Date: 2019/10/11 |
+ * | Time: 下午2:56 |
+ * ----------------------------------------
+ * | _____ ______ _ _ |
+ * | | __ \| ____(_) | | |
+ * | | |__) | |__ _ _ __ __ _| | |
+ * | | ___/| __| | | '_ \ / _` | | |
+ * | | | | | | | | | | (_| | | |
+ * | |_| |_| |_|_| |_|\__,_|_| |
+ * ----------------------------------------
+ * 说明: 面试遇到一个写一个函数 让输出效果 如风车一样旋转 如下
+ * foo(4) 逆时针
+ * 16,15,14,13
+ * 5, 4, 3, 12
+ * 6, 1, 2, 11
+ * 7, 8, 9, 10
+ * foo(4) 顺顺时针
+ * 7, 8, 9, 10
+ * 6, 1, 2, 11
+ * 5, 4, 3, 12
+ * 16,15, 14,13
+ *
+ */
+
+ $num = 4;
+ $arr = foo($num);
+ for ($i = 0; $i < $num; $i++) {
+ echo implode(',', $arr[$i])."
";
+ }
+
+ /**
+ * @param $num
+ * @param int $direction 方向 1 为 顺时针旋转 2 为逆时针旋转
+ * @return mixed
+ */
+ function foo($num, $direction = 1)
+ {
+ //填充map
+ $data = new stdClass();
+ $data->x = 1;
+ if ($direction == 1) {
+ $data->y = $num;
+ } elseif ($direction == 2) {
+ $data->y = 1;
+ }
+ $data->num = $num;
+ $data->len = $num * $num;
+ $data->tmp_data = [];
+ $data->rate = 1;//方向
+ $data->struct = create_struct($num);
+ for ($i = $data->len; $i >= 1; $i--) {
+ $data->i = $i;
+ $key = change_key($data, $direction);
+ $data->tmp_data[$key] = $i;
+ unset($data->struct[$key]);
+ }
+
+ //根据y坐标分组
+ $data->struct = create_struct($num);
+ foreach ($data->tmp_data as $key => $value) {
+ $data->struct[$key] = $value;
+ }
+ for ($i = 1; $i <= $data->num; $i++) {
+ $start = ($i - 1) * $data->num;
+ $end = $data->num;
+ $slice = array_slice($data->struct, $start, $end);
+ $data->slice[] = $slice;
+ }
+
+ return $data->slice;
+ }
+
+ function create_struct($num)
+ {
+ $struct = [];
+ for ($i = 1; $i <= $num; $i++) {
+ //嵌套
+ for ($m = 1; $m <= $num; $m++) {
+ $key = $m.','.$i;
+ $struct[$key] = '';
+ }
+ }
+
+ return $struct;
+ }
+
+ function change_key($data, $direction)
+ {
+ $key = $data->x.','.$data->y;
+ if (isset($data->struct[$key])) {
+ return $key;
+ }
+ switch ($data->rate) {
+ // LEFT 方向
+ case 1:
+ $data->tmp_x = $data->x + 1;
+ $key = $data->tmp_x.','.$data->y;
+ if (isset($data->struct[$key])) {
+ $data->x = $data->tmp_x;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 4;
+ } elseif ($direction = 2) {
+ $data->rate = 2;
+ }
+ }
+ break;
+ // DOWN 方向
+ case 2:
+ $data->tmp_y = $data->y + 1;
+ $key = $data->x.','.$data->tmp_y;
+ if (isset($data->struct[$key])) {
+ $data->y = $data->tmp_y;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 1;
+ } elseif ($direction = 2) {
+ $data->rate = 3;
+ }
+ }
+ break;
+ // RIGHT 方向
+ case 3:
+ $data->tmp_x = $data->x - 1;
+ $key = $data->tmp_x.','.$data->y;
+ if (isset($data->struct[$key])) {
+ $data->x = $data->tmp_x;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 2;
+ } elseif ($direction = 2) {
+ $data->rate = 4;
+ }
+ }
+ break;
+ // UP 方向
+ case 4:
+ $data->tmp_y = $data->y - 1;
+ $key = $data->x.','.$data->tmp_y;
+ if (isset($data->struct[$key])) {
+ $data->y = $data->tmp_y;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 3;
+ } elseif ($direction = 2) {
+ $data->rate = 1;
+ }
+ }
+ break;
+ }
+
+ return change_key($data, $direction);
+ }
\ No newline at end of file
diff --git a/src/Other/RotationSort.php b/src/Other/RotationSort.php
new file mode 100644
index 0000000..48d538a
--- /dev/null
+++ b/src/Other/RotationSort.php
@@ -0,0 +1,76 @@
+row = $row;
+ $this->col =$col;
+ $this->start = $start;
+ $this->print_matrix();
+ }
+
+ private function print_matrix()
+ {
+ //当前遍历层数
+ $small =$this->col < $this->row ?$this->col : $this->row;
+
+ $count = ceil($small / 2);
+
+ for($i=0; $i < $count; $i++)
+ {
+ $maxRight = $this->col -1 - $i; //右边最大坐标
+ $maxBottom = $this->row -1 - $i; //下面最大坐标
+
+ for($j=$i; $j<=$maxRight; $j++)
+ {
+ $this->res[$i][$j] = $this->start++;
+ }
+ for($j=$i; $j<$maxBottom; $j++)
+ {
+ $this->res[$j+1][$maxRight] = $this->start++;
+ }
+ for($j=$maxRight-1;$j>=$i; $j--)
+ {
+ if(isset($this->res[$maxBottom][$j])) break;
+ $this->res[$maxBottom][$j] = $this->start++;
+ }
+ for($j=$maxBottom-1;$j>$i;$j--)
+ {
+ if(isset($this->res[$j][$i])) break;
+ $this->res[$j][$i] = $this->start++;
+ }
+ }
+ }
+
+ /**
+ * @return string
+ * 输出回旋形状
+ */
+ public function print_table()
+ {
+ $str = '';
+ for ($i = 0; $i < $this->row; $i++) {
+ $str .='
';
+ return $str;
+ }
+}
+
+$obj = new RotationSort(7, 8);
+echo $obj->print_table();
\ No newline at end of file
diff --git a/src/Other/Solution.php b/src/Other/Solution.php
new file mode 100644
index 0000000..27aca0c
--- /dev/null
+++ b/src/Other/Solution.php
@@ -0,0 +1,63 @@
+grid = $grid;
+ $this->islandPerimeter();
+ }
+
+ public function islandPerimeter()
+ {
+ if (empty($this->grid) || empty($this->grid[0])) return 0;
+
+ foreach ($this->grid as $key => $val) {
+
+ foreach ($this->grid[0] as $k => $v) {
+ if ($this->grid[$key][$k] == 0) continue;
+ $this->result += 4;
+
+ if ($key > 0 && $this->grid[$key - 1][$k] == 1) {
+ $this->result -= 2;
+ }
+ if ($k > 0 && $this->grid[$key][$k - 1] == 1) {
+ $this->result -= 2;
+ }
+ }
+ }
+ }
+}
+
+$arr = [
+ [0,1,0,0],
+ [1,1,1,0],
+ [0,1,0,0],
+ [1,1,0,0]
+];
+
+$result = new Solution($arr);
+var_dump($result->result);
\ No newline at end of file
diff --git a/src/Other/Square.php b/src/Other/Square.php
new file mode 100644
index 0000000..0566953
--- /dev/null
+++ b/src/Other/Square.php
@@ -0,0 +1,43 @@
+point = $point;
+ }
+
+ public function check()
+ {
+ $result = [];
+ if (count($this->point) != 4) return false;
+ for ($i = 0; $i < 4; $i++) {
+ for ($j = $i + 1; $j < 4; $j++) {
+ $result[]=$this->_calculation($i,$j);
+ }
+ }
+ sort($result);
+ if ($result[0] == $result[1] && $result[4] == $result[5] && $result[4] > $result[1]) {
+ return true;
+ }
+ return false;
+
+ }
+
+ private function _calculation($i, $j)
+ {
+ return pow($this->point[$i][0] - $this->point[$j][0],2) + pow($this->point[$i][1] - $this->point[$j][1] ,2);
+ }
+}
+
+$obj = new Square([[0, 0], [1, 0], [1, 1], [0, 1]]);
+var_dump($obj->check());
diff --git a/src/Other/StealingApples.php b/src/Other/StealingApples.php
new file mode 100644
index 0000000..5d821a3
--- /dev/null
+++ b/src/Other/StealingApples.php
@@ -0,0 +1,81 @@
+
+ * @date 2017/8/26
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:
+ * -------------------------------------------------------------
+ * 有5个人偷了一堆苹果,准备在第二天分赃。
+ * 晚上,有一人遛出来,把所有苹果分成5份,但是多了一个,顺手把这个扔给树上的猴了,自己先拿1/5藏了。
+ * 没想到其他四人也都是这么想的,都如第一个人一样分成5份把多的那一个扔给了猴,偷走了1/5。
+ * 第二天,大家分赃,也是分成5份多一个扔给猴了。最后一人分了一份。
+ * 问:共有多少苹果?N 个人呢?
+ * -------------------------------------------------------------
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+$i = 1;
+while (true) {
+ if ($i % 5 == 1) {
+ //第一个人取五分之一,还剩$t
+ $t = $i - round($i / 5) - 1;
+ if ($t % 5 == 1) {
+ //第二个人取五分之一,还剩$r
+ $r = $t - round($t / 5) - 1;
+ if ($r % 5 == 1) {
+ //第三个人取五分之一,还剩$s
+ $s = $r - round($r / 5) - 1;
+ if ($s % 5 == 1) {
+ //第四个人取五分之一,还剩$x
+ $x = $s - round($s / 5) - 1;
+ if ($x % 5 == 1) {
+ //第五个人取五分之一,还剩$y
+ $y = $x - round($x / 5) - 1;
+ if ($y % 5 == 1) {
+ echo $i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ $i++;
+}
+
+// +----------------------------------------------------------------------
+// | 方法二
+// +----------------------------------------------------------------------
+/**
+ * @author Openset ';
+ for ($j = 0; $j < $this->col; $j++) {
+ $str .=' ";
+ }
+ $str .=''.$this->res[$i][$j] . " ";
+ }
+ $str .="