├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ └── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── tinytongtong │ │ │ │ └── leetcodetest │ │ │ │ ├── test │ │ │ │ └── MainTest.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── classify │ │ │ │ ├── sort │ │ │ │ │ ├── SwapTest.java │ │ │ │ │ ├── SelectionSort.java │ │ │ │ │ ├── InsertionSort.java │ │ │ │ │ ├── BubbleSort.java │ │ │ │ │ ├── MergeSort.java │ │ │ │ │ └── QuickSort.java │ │ │ │ ├── fibonacci │ │ │ │ │ ├── RectCover.java │ │ │ │ │ └── FrogJumpStep.java │ │ │ │ └── print_list_reverse │ │ │ │ │ └── PrintListReverse.java │ │ │ │ ├── targetoffer │ │ │ │ ├── question15 │ │ │ │ │ ├── JudgeMultipleOfTwo.java │ │ │ │ │ ├── ModifyBits.java │ │ │ │ │ └── NumberOfOne.java │ │ │ │ ├── question65 │ │ │ │ │ └── AddNotByArithmetic.java │ │ │ │ ├── question63 │ │ │ │ │ └── StockMaxProfit.java │ │ │ │ ├── question66 │ │ │ │ │ └── ConstructProductArray.java │ │ │ │ ├── question53 │ │ │ │ │ ├── FindSameIndexNumber.java │ │ │ │ │ ├── FindMissingNumber.java │ │ │ │ │ └── FindNumberInSortedArray.java │ │ │ │ ├── question42 │ │ │ │ │ └── MaxSubArray.java │ │ │ │ ├── question57 │ │ │ │ │ ├── FindTwoNumbersWithSum.java │ │ │ │ │ └── FindContinuousSequence.java │ │ │ │ ├── question48 │ │ │ │ │ └── LongestSubstringWithoutDup.java │ │ │ │ ├── question64 │ │ │ │ │ └── Sum1ToN.java │ │ │ │ ├── question11 │ │ │ │ │ ├── SortAges.java │ │ │ │ │ ├── MinNumberInRotatedArray.java │ │ │ │ │ └── QuickSort.java │ │ │ │ ├── question56 │ │ │ │ │ ├── FindNumberAppearingOnce.java │ │ │ │ │ └── TwoSingleNumbers.java │ │ │ │ ├── question50 │ │ │ │ │ ├── FirstUniqueChar.java │ │ │ │ │ └── FirstUniqueCharInSequence.java │ │ │ │ ├── question21 │ │ │ │ │ └── ExchangeOrder.java │ │ │ │ ├── question58 │ │ │ │ │ ├── ReverseLeftWords.java │ │ │ │ │ └── ReverseWords.java │ │ │ │ ├── question61 │ │ │ │ │ └── PlayingCardsIsStraight.java │ │ │ │ ├── question16 │ │ │ │ │ └── Power.java │ │ │ │ ├── question30 │ │ │ │ │ └── MinStack.java │ │ │ │ ├── question05 │ │ │ │ │ └── ReplaceSpace.java │ │ │ │ ├── question10 │ │ │ │ │ └── Fibonacci.java │ │ │ │ ├── question06 │ │ │ │ │ └── ReversePrintLinked.java │ │ │ │ ├── question38 │ │ │ │ │ ├── StringCombination.java │ │ │ │ │ ├── StringPermutation.java │ │ │ │ │ ├── VerifyCubeVertexSum.java │ │ │ │ │ ├── EightQueen.java │ │ │ │ │ └── NQueen.java │ │ │ │ ├── question55 │ │ │ │ │ ├── BinaryTreeDepth.java │ │ │ │ │ └── IsBalancedTree.java │ │ │ │ ├── question22 │ │ │ │ │ └── KthNodeToTail.java │ │ │ │ ├── question62 │ │ │ │ │ └── CircleLastRemaining.java │ │ │ │ ├── question19 │ │ │ │ │ └── PatternMatch.java │ │ │ │ ├── question03 │ │ │ │ │ └── MaxSwapCountTest.java │ │ │ │ ├── question20 │ │ │ │ │ └── JudgeStringIsNumeric.java │ │ │ │ ├── question43 │ │ │ │ │ └── CountDigitOne.java │ │ │ │ ├── question33 │ │ │ │ │ └── VerifySequenceOfBST.java │ │ │ │ ├── question44 │ │ │ │ │ └── FindNthDigit.java │ │ │ │ ├── question51 │ │ │ │ │ └── ReversePairsCount.java │ │ │ │ ├── question54 │ │ │ │ │ └── kthLargestNode.java │ │ │ │ ├── question67 │ │ │ │ │ └── StrToInt.java │ │ │ │ ├── question04 │ │ │ │ │ └── FindInTwoDimensionalArray.java │ │ │ │ ├── question13 │ │ │ │ │ └── RobotMovingCount.java │ │ │ │ ├── question31 │ │ │ │ │ └── ValidateStackSequence.java │ │ │ │ ├── question59 │ │ │ │ │ ├── MaxQueue.java │ │ │ │ │ └── MaxSlidingWindow.java │ │ │ │ ├── question09 │ │ │ │ │ └── ImplQueueByTwoStack.java │ │ │ │ ├── question68 │ │ │ │ │ ├── LowestCommonAncestorBinarySearchTree.java │ │ │ │ │ └── LowestCommonAncestorBinaryTree.java │ │ │ │ ├── question14 │ │ │ │ │ └── CutingRope.java │ │ │ │ ├── question29 │ │ │ │ │ └── PrintMatrix.java │ │ │ │ ├── question25 │ │ │ │ │ └── MergeTwoSortedList.java │ │ │ │ ├── question41 │ │ │ │ │ └── MedianFinder.java │ │ │ │ ├── question32 │ │ │ │ │ ├── PrintTreeFromTopToBottom.java │ │ │ │ │ └── PrintTreeFromTopToBottomLevelFirstNode.java │ │ │ │ ├── question35 │ │ │ │ │ └── CopyComplexListNode.java │ │ │ │ ├── question12 │ │ │ │ │ └── MatrixHasPath.java │ │ │ │ ├── question47 │ │ │ │ │ └── MaxValueOfGift.java │ │ │ │ ├── question49 │ │ │ │ │ └── UglyNumber.java │ │ │ │ ├── question23 │ │ │ │ │ ├── MeetingNodeInCycle.java │ │ │ │ │ └── MeetingNodeInCycle1.java │ │ │ │ ├── question45 │ │ │ │ │ └── MinNumberInArrays.java │ │ │ │ ├── question18 │ │ │ │ │ └── DeleteNodeO1.java │ │ │ │ ├── question36 │ │ │ │ │ └── TreeToDoublyList.java │ │ │ │ ├── question07 │ │ │ │ │ └── RebuildBinaryTree.java │ │ │ │ └── question27 │ │ │ │ │ └── MirrorBinaryTree.java │ │ │ │ ├── question │ │ │ │ ├── question_0003 │ │ │ │ │ └── LengthOfLongestSubstring.java │ │ │ │ ├── question_0001 │ │ │ │ │ └── TwoSumSolution.java │ │ │ │ ├── question_0011 │ │ │ │ │ └── ContainerWithMostWater.java │ │ │ │ ├── question_0026 │ │ │ │ │ └── RemoveDuplicatesFromSortedArray.java │ │ │ │ ├── question_0074 │ │ │ │ │ └── SearchA2DMatrix.java │ │ │ │ ├── question_0144 │ │ │ │ │ └── BinaryTreePreorderTraversal.java │ │ │ │ ├── question_0155 │ │ │ │ │ └── MinStack.java │ │ │ │ ├── question_0232 │ │ │ │ │ └── ImplementQueueUsingStacks.java │ │ │ │ ├── question_0589 │ │ │ │ │ └── NAryTreePreorderTraversal.java │ │ │ │ ├── question_0002 │ │ │ │ │ └── AddTwoNumbers.java │ │ │ │ ├── question_0629 │ │ │ │ │ └── InversePairs.java │ │ │ │ ├── question_0104 │ │ │ │ │ └── MaximumDepthOfBinaryTree.java │ │ │ │ └── question_0105 │ │ │ │ │ └── BuildTreeFromPreOrderAndInOrder.java │ │ │ │ └── lcof │ │ │ │ ├── lcof_05_replace_space │ │ │ │ └── ReplaceSpace.java │ │ │ │ └── lcof_33_verify_postorder │ │ │ │ └── VerifyPostorder.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── tinytongtong │ │ │ └── leetcodetest │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── tinytongtong │ │ └── leetcodetest │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── README.md └── gradlew.bat /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name='LeetCodeTest' 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LeetCodeTest 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyvampirepudge/LeetCodeTest/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Feb 05 10:12:16 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/test/MainTest.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.test; 2 | 3 | /** 4 | * @Description: TODO 5 | * @Author wangjianzhou 6 | * @Date 2020/11/26 11:22 AM 7 | * @Version TODO 8 | */ 9 | public class MainTest { 10 | public static void main(String[] args) { 11 | System.out.println("猫了个咪"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | 7 | public class MainActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_main); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/test/java/com/tinytongtong/leetcodetest/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/sort/SwapTest.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.sort; 2 | 3 | /** 4 | * @Description: swap交换小技巧 5 | * @Author wangjianzhou 6 | * @Date 2/17/22 8:55 AM 7 | * @Version 8 | */ 9 | public class SwapTest { 10 | 11 | public static void main(String[] args) { 12 | int a = 5; 13 | int b = 12; 14 | a ^= b; 15 | b ^= a; 16 | a ^= b; 17 | System.out.println(a); 18 | System.out.println(b); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question15/JudgeMultipleOfTwo.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question15; 2 | 3 | /** 4 | * @Description: 用一条语句判断一个整数是不是2的整数次方 5 | * @Author tinytongtong 6 | * @Date 2020/9/6 8:32 PM 7 | * @Version 8 | */ 9 | public class JudgeMultipleOfTwo { 10 | private static boolean judgeMultipleOfTwo(int n) { 11 | if (n <= 0) { 12 | return false; 13 | } 14 | return (n & (n - 1)) == 0; 15 | } 16 | 17 | public static void main(String[] args) { 18 | int n = 65536; 19 | System.out.println(judgeMultipleOfTwo(n)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question65/AddNotByArithmetic.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question65; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/ 5 | * 剑指 Offer 65. 不用加减乘除做加法 6 | * @Author tinytongtong 7 | * @Date 2020/9/18 9:20 PM 8 | * @Version 9 | */ 10 | public class AddNotByArithmetic { 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 | public static void main(String[] args) { 24 | System.out.println(add(10, 20)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question15/ModifyBits.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question15; 2 | 3 | /** 4 | * @Description: 输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。 5 | * @Author tinytongtong 6 | * @Date 2020/9/6 9:11 PM 7 | * @Version 8 | */ 9 | public class ModifyBits { 10 | private static int modifyBits(int m, int n) { 11 | if (m == n) { 12 | return 0; 13 | } 14 | int count = 0; 15 | /** 16 | * 我们可以分为两步解决这个问题:第一步求这两个数的异或;第二步统计异或结果中1的位数 17 | */ 18 | int r = m ^ n; 19 | while (r != 0) { 20 | count++; 21 | r = r & (r - 1); 22 | } 23 | return count; 24 | } 25 | 26 | public static void main(String[] args) { 27 | int m = 0b11011; 28 | int n = 0b10100; 29 | System.out.println(modifyBits(m, n)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/tinytongtong/leetcodetest/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.tinytongtong.leetcodetest", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.0" 6 | defaultConfig { 7 | applicationId "com.tinytongtong.leetcodetest" 8 | minSdkVersion 19 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation 'androidx.appcompat:appcompat:1.1.0' 25 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'androidx.test.ext:junit:1.1.0' 28 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question63/StockMaxProfit.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question63; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/gu-piao-de-zui-da-li-run-lcof/ 5 | * 剑指 Offer 63. 股票的最大利润 6 | * @Author tinytongtong 7 | * @Date 2020/9/18 10:07 AM 8 | * @Version 9 | */ 10 | public class StockMaxProfit { 11 | private static int maxProfit(int[] prices) { 12 | if (prices == null || prices.length < 2) { 13 | return 0; 14 | } 15 | int min = prices[0]; 16 | int max = 0; 17 | for (int i = 1; i < prices.length; i++) { 18 | if (prices[i] - min > max) { 19 | max = prices[i] - min; 20 | } 21 | if (prices[i] < min) { 22 | min = prices[i]; 23 | } 24 | } 25 | return max; 26 | } 27 | 28 | public static void main(String[] args) { 29 | int[] prices = new int[]{9, 11, 8, 5, 7, 12, 16, 14}; 30 | System.out.println(maxProfit(prices)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0003/LengthOfLongestSubstring.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0003; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @Description: 3. 无重复字符的最长子串 7 | * https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 8 | * @Author wangjianzhou 9 | * @Date 2022/2/9 10:41 AM 10 | */ 11 | public class LengthOfLongestSubstring { 12 | public static void main(String[] args) { 13 | System.out.println(lengthOfLongestSubstring("abba")); 14 | } 15 | 16 | public static int lengthOfLongestSubstring(String s) { 17 | // 空字符串 18 | if (s == null || s.length() == 0) return 0; 19 | // 滑动窗口解法 20 | int left = 0; // 窗口左侧 21 | int max = 0; // 记录最长子串的长度 22 | HashMap map = new HashMap<>(); 23 | for (int i = 0; i < s.length(); i++) { 24 | if (map.containsKey(s.charAt(i))) left = Math.max(map.get(s.charAt(i)) + 1, left); 25 | map.put(s.charAt(i), i); 26 | max = Math.max(max, i - left + 1); 27 | } 28 | return max; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question66/ConstructProductArray.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question66; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/gou-jian-cheng-ji-shu-zu-lcof/ 7 | * 剑指 Offer 66. 构建乘积数组 8 | * @Author tinytongtong 9 | * @Date 2020/9/18 9:50 PM 10 | * @Version 11 | */ 12 | public class ConstructProductArray { 13 | private static int[] constructArr(int[] a) { 14 | if (a == null || a.length == 0) { 15 | return new int[0]; 16 | } 17 | int[] result = new int[a.length]; 18 | result[0] = 1; 19 | for (int i = 1; i < a.length; i++) { 20 | result[i] = result[i - 1] * a[i - 1]; 21 | } 22 | double temp = 1; 23 | for (int i = a.length - 2; i >= 0; i--) { 24 | temp *= a[i + 1]; 25 | result[i] *= temp; 26 | } 27 | return result; 28 | } 29 | 30 | public static void main(String[] args) { 31 | int[] nums = new int[]{1, 2, 3, 4, 5}; 32 | System.out.println(Arrays.toString(constructArr(nums))); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/sort/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: 选择排序 7 | * @Author wangjianzhou 8 | * @Date 2022/2/13 11:41 PM 9 | * @Version 10 | */ 11 | public class SelectionSort { 12 | public static void main(String[] args) { 13 | int[] array = new int[]{4, 5, 6, 3, 2, 1}; 14 | // int[] array = new int[]{6,5,4,3,2,1}; 15 | int n = 6; 16 | System.out.println(Arrays.toString(array)); 17 | selectionSort(array, n); 18 | System.out.println(Arrays.toString(array)); 19 | } 20 | 21 | /** 22 | * 选择排序 23 | * 24 | * @param a 25 | * @param n 26 | */ 27 | private static void selectionSort(int[] a, int n) { 28 | for (int i = 0; i < n - 1; i++) { 29 | int index = i; 30 | for (int j = i + 1; j < n; j++) { 31 | if (a[j] > a[index]) { 32 | index = j; 33 | } 34 | } 35 | int temp = a[i]; 36 | a[i] = a[index]; 37 | a[index] = temp; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/lcof/lcof_05_replace_space/ReplaceSpace.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.lcof.lcof_05_replace_space; 2 | 3 | /** 4 | * @Description: 替换字符串中的空格 5 | * 剑指 Offer 05. 替换空格 6 | * https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/ 7 | * https://www.nowcoder.com/practice/4060ac7e3e404ad1a894ef3e17650423?tpId=13&tqId=11155&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 8 | * @Author tinytongtong 9 | * @Date 2020-02-08 14:56 10 | * @Version 11 | */ 12 | public class ReplaceSpace { 13 | public static String replaceSpace(StringBuffer str) { 14 | StringBuffer sb = new StringBuffer(); 15 | for (int i = 0; i < str.length(); i++) { 16 | if (' ' == str.charAt(i)) { 17 | sb.append("%20"); 18 | } else { 19 | sb.append(str.charAt(i)); 20 | } 21 | } 22 | return sb.toString(); 23 | } 24 | 25 | public static void main(String[] args) { 26 | StringBuffer sb = new StringBuffer("We Are Happy"); 27 | String result = replaceSpace(sb); 28 | System.out.println(String.format("result:%s", result)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question53/FindSameIndexNumber.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question53; 2 | 3 | /** 4 | * @Description: 数组中数值和下标相等的元素 5 | * 假设一个单调递增的数组里的每个元素都是整数并且是唯一的。 6 | * 请编程实现一个函数,找出数组中任意一个数值等于其下标的元素。 7 | * 例如,在数组{-3, -1, 1, 3, 5}中,数字3和它的下标相等。 8 | * @Author tinytongtong 9 | * @Date 2020/9/14 11:21 PM 10 | * @Version 11 | */ 12 | public class FindSameIndexNumber { 13 | private static int findSameIndexNumber(int[] nums) { 14 | if (nums == null || nums.length == 0) { 15 | return -1; 16 | } 17 | int left = 0, right = nums.length - 1; 18 | while (left <= right) { 19 | int middle = (left + right) >> 1; 20 | if (nums[middle] == middle) { 21 | return middle; 22 | } 23 | if (nums[middle] > middle) { 24 | right = middle - 1; 25 | } else { 26 | left = middle + 1; 27 | } 28 | } 29 | return -1; 30 | } 31 | 32 | public static void main(String[] args) { 33 | int[] nums = new int[]{-3, -1, 1, 3, 4}; 34 | System.out.println(findSameIndexNumber(nums)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0001/TwoSumSolution.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0001; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @Description: 1. 两数之和 8 | * https://leetcode-cn.com/problems/two-sum/ 9 | * @Author tinytongtong 10 | * @Date 2020-02-05 10:15 11 | * @Version 12 | */ 13 | public class TwoSumSolution { 14 | public static int[] twoSum(int[] nums, int target) { 15 | // 存储数据值和对应的角标 16 | Map map = new HashMap<>(); 17 | for (int i = 0; i < nums.length; i++) { 18 | // 算出对应的差值,查找是否已经存在了 19 | int key = target - nums[i]; 20 | // 对应数字已存在于map中,表示匹配成功,退出循环,返回结果 21 | if (map.get(key) != null) { 22 | return new int[]{map.get(key), i}; 23 | } 24 | map.put(nums[i], i); 25 | } 26 | return new int[]{-1, -1}; 27 | } 28 | 29 | public static void main(String[] args) { 30 | int[] nums = new int[]{2, 7, 11, 15}; 31 | int target = 9; 32 | int[] result = twoSum(nums, target); 33 | System.out.println("result:result[0]:" + result[0] + ",result[1]:" + result[1]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question42/MaxSubArray.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question42; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/ 5 | * 剑指 Offer 42. 连续子数组的最大和 6 | * @Author tinytongtong 7 | * @Date 2020/9/11 1:54 PM 8 | * @Version 9 | */ 10 | public class MaxSubArray { 11 | /** 12 | * 迭代解法 13 | * 时间复杂度O(n) 14 | * 空间复杂度O(1) 15 | * 16 | * @param nums 17 | * @return 18 | */ 19 | private static int maxSubArray(int[] nums) { 20 | if (nums == null || nums.length == 0) { 21 | return Integer.MIN_VALUE; 22 | } 23 | int sum = 0; 24 | int max = Integer.MIN_VALUE; 25 | for (int i = 0; i < nums.length; i++) { 26 | if (sum <= 0) { 27 | sum = nums[i]; 28 | } else { 29 | sum += nums[i]; 30 | } 31 | if (sum > max) { 32 | max = sum; 33 | } 34 | } 35 | return max; 36 | } 37 | 38 | public static void main(String[] args) { 39 | int[] nums = new int[]{1, -2, 3, 10, -4, 7, 2, -5}; 40 | System.out.println(maxSubArray(nums)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question57/FindTwoNumbersWithSum.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question57; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof/ 7 | * 剑指 Offer 57. 和为s的两个数字 8 | * @Author tinytongtong 9 | * @Date 2020/9/15 5:06 PM 10 | * @Version 11 | */ 12 | public class FindTwoNumbersWithSum { 13 | private static int[] findTwoNumbersWithSum(int[] nums, int target) { 14 | if (nums == null || nums.length < 2) { 15 | return new int[0]; 16 | } 17 | int index1 = 0; 18 | int index2 = nums.length - 1; 19 | while (index2 > index1) { 20 | if (nums[index1] + nums[index2] == target) { 21 | return new int[]{nums[index1], nums[index2]}; 22 | } else if (nums[index1] + nums[index2] > target) { 23 | index2--; 24 | } else { 25 | index1++; 26 | } 27 | } 28 | return new int[0]; 29 | } 30 | 31 | public static void main(String[] args) { 32 | int[] nums = new int[]{1, 2, 4, 7, 11, 15}; 33 | System.out.println(Arrays.toString(findTwoNumbersWithSum(nums, 15))); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0011/ContainerWithMostWater.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0011; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/container-with-most-water/ 5 | * 11. 盛最多水的容器 6 | * @Author tinytongtong 7 | * @Date 2020/9/1 11:25 AM 8 | * @Version 9 | */ 10 | public class ContainerWithMostWater { 11 | /** 12 | * 双指针、每次移动短边 13 | * 14 | * @param height 15 | * @return 16 | */ 17 | public static int maxArea(int[] height) { 18 | int res = 0; 19 | int left = 0, right = height.length - 1; 20 | while (left < right) { 21 | // 区域要取最大值 22 | res = Math.max(res, (right - left) * Math.min(height[left], height[right])); 23 | // 向中间移动短边 24 | if (height[left] < height[right]) { 25 | left++; 26 | } else { 27 | right--; 28 | } 29 | } 30 | return res; 31 | } 32 | 33 | public static void main(String[] args) { 34 | int[] nums = new int[]{1,8,6,2,5,4,8,3,7}; 35 | int count = maxArea(nums); 36 | System.out.println(count); 37 | System.out.println("------------------------------------"); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/fibonacci/RectCover.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.fibonacci; 2 | 3 | /** 4 | * @Description: 矩形覆盖问题,用2*1的小矩形覆盖2*n的矩形,有多少种方式 5 | * https://www.nowcoder.com/practice/72a5a919508a4251859fb2cfb987a0e6?tpId=13&tqId=11163&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 6 | * 剑指Offer面试题9 7 | * @Author tinytongtong 8 | * @Date 2020-02-09 01:29 9 | * @Version 10 | */ 11 | public class RectCover { 12 | public static int rectCover(int n) { 13 | if (n == 1) { 14 | return 1; 15 | } 16 | if (n == 2) { 17 | return 2; 18 | } 19 | 20 | int valueOne = 1; 21 | int valueTwo = 2; 22 | int valueN = 0; 23 | for (int i = 3; i <= n; i++) { 24 | valueN = valueOne + valueTwo; 25 | valueOne = valueTwo; 26 | valueTwo = valueN; 27 | } 28 | return valueN; 29 | } 30 | 31 | public static void main(String[] args) { 32 | int n = 3; 33 | 34 | long startTime1 = System.nanoTime(); 35 | int result1 = rectCover(n); 36 | long endTime1 = System.nanoTime(); 37 | System.out.println(String.format("矩形覆盖,result1:%d, 耗时:%d", result1, endTime1 - startTime1)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/sort/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: 插入排序 7 | * @Author wangjianzhou 8 | * @Date 2022/2/13 11:06 PM 9 | */ 10 | public class InsertionSort { 11 | public static void main(String[] args) { 12 | int[] array = new int[]{4, 5, 6, 3, 2, 1}; 13 | // int[] array = new int[]{6,5,4,3,2,1}; 14 | int n = 6; 15 | System.out.println(Arrays.toString(array)); 16 | insertionSort(array, n); 17 | System.out.println(Arrays.toString(array)); 18 | } 19 | 20 | /** 21 | * 插入排序 22 | * @param a 23 | * @param n 24 | */ 25 | private static void insertionSort(int[] a, int n) { 26 | if (n <= 1) { 27 | return; 28 | } 29 | // 未排序数组 30 | for (int i = 1; i < n; i++) { 31 | // 从后向前遍历已排序数组 32 | int value = a[i]; 33 | int j = i - 1; // 排序数组最后一个元素 34 | for (; j >= 0; j--) { 35 | if (value > a[j]) { // 移动数据 36 | a[j + 1] = a[j]; 37 | } else { 38 | break; 39 | } 40 | } 41 | a[j + 1] = value; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question48/LongestSubstringWithoutDup.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question48; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @Description: https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/ 8 | * 剑指 Offer 48. 最长不含重复字符的子字符串 9 | * @Author tinytongtong 10 | * @Date 2020/10/20 9:31 PM 11 | * @Version 12 | */ 13 | public class LongestSubstringWithoutDup { 14 | public static int lengthOfLongestSubstring(String s) { 15 | Map dic = new HashMap<>(); 16 | int res = 0, tmp = 0; 17 | for(int j = 0; j < s.length(); j++) { 18 | int i = dic.getOrDefault(s.charAt(j), -1); // 获取索引 i 19 | dic.put(s.charAt(j), j); // 更新哈希表 20 | tmp = tmp < j - i ? tmp + 1 : j - i; // dp[j - 1] -> dp[j] 21 | res = Math.max(res, tmp); // max(dp[j - 1], dp[j]) 22 | } 23 | return res; 24 | } 25 | 26 | public static void main(String[] args) { 27 | System.out.println(lengthOfLongestSubstring("arabcacfrr")); 28 | System.out.println(lengthOfLongestSubstring("abcabcabc")); 29 | System.out.println(lengthOfLongestSubstring("bbbbb")); 30 | System.out.println(lengthOfLongestSubstring("pwwkew")); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question64/Sum1ToN.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question64; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/qiu-12n-lcof/ 5 | * 剑指 Offer 64. 求1+2+…+n 6 | * @Author tinytongtong 7 | * @Date 2020/9/18 5:22 PM 8 | * @Version 9 | */ 10 | public class Sum1ToN { 11 | /** 12 | * 递归实现,从n, n - 1, 一直加到1 13 | * 时间复杂度O(n) 14 | * 空间复杂度O(n) 15 | * 16 | * @param n 17 | * @return 18 | */ 19 | private static int sumNumsByRecursive(int n) { 20 | boolean flag = n > 1 && (n = n + sumNumsByRecursive(n - 1)) > 0; 21 | return n; 22 | } 23 | 24 | /** 25 | * 递归实现,n*(n + 1)/2 26 | * 使用俄罗斯农名算法模拟乘法n*(n + 1) 27 | * 28 | * @param n 29 | * @return 30 | */ 31 | private static int sumNumsByRecursive1(int n) { 32 | return sumNumsByRecursiveCore(n, n + 1, 0) >> 1; 33 | } 34 | 35 | private static int sumNumsByRecursiveCore(int n, int k, int sum) { 36 | boolean s = (k & 1) == 1 && (sum += n) > 0; 37 | boolean flag = k > 0 && (sum = sumNumsByRecursiveCore(n << 1, k >> 1, sum)) > 0; 38 | return sum; 39 | } 40 | 41 | public static void main(String[] args) { 42 | System.out.println(sumNumsByRecursive(4)); 43 | System.out.println(sumNumsByRecursive1(4)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question11/SortAges.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question11; 2 | 3 | import java.util.Arrays; 4 | import java.util.Random; 5 | 6 | /** 7 | * @Description: 请实现一个排序算法,时间复杂度为O(n); 8 | * 对公司所有员工的年龄排序,公司有几万名员工。也就是说数字的大小在一定范围内。 9 | * 可以使用常量大小的辅助空间,不能超过O(n) 10 | * @Author tinytongtong 11 | * @Date 2020/9/5 5:48 PM 12 | * @Version 13 | */ 14 | public class SortAges { 15 | private static void sortAges(int[] ages) { 16 | if (ages == null || ages.length == 0) { 17 | return; 18 | } 19 | int maxAge = 99; 20 | int timesOfAge[] = new int[maxAge + 1]; 21 | for (int i = 0; i < ages.length; i++) { 22 | timesOfAge[ages[i]]++; 23 | } 24 | int index = 0; 25 | for (int i = 0; i <= maxAge; i++) { 26 | for (int j = 0; j < timesOfAge[i]; j++) { 27 | ages[index] = i; 28 | index++; 29 | } 30 | } 31 | } 32 | 33 | public static void main(String[] args) { 34 | int maxSize = 1000; 35 | int ages[] = new int[maxSize]; 36 | for (int i = 0; i < maxSize; i++) { 37 | ages[i] = new Random().nextInt(99); 38 | } 39 | System.out.println(Arrays.toString(ages)); 40 | sortAges(ages); 41 | System.out.println(Arrays.toString(ages)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question56/FindNumberAppearingOnce.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question56; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/ 5 | * 剑指 Offer 56 - II. 数组中数字出现的次数 II 6 | * @Author tinytongtong 7 | * @Date 2020/9/15 2:41 PM 8 | * @Version 9 | */ 10 | public class FindNumberAppearingOnce { 11 | private static int findNumberAppearingOnce(int[] nums) { 12 | if (nums == null || nums.length <= 0) { 13 | throw new RuntimeException("Invalid input."); 14 | } 15 | int[] bitSum = new int[32]; 16 | for (int i = 0; i < nums.length; i++) { 17 | int bitMask = 1; 18 | for (int j = 31; j >= 0; j--) { 19 | int bit = nums[i] & bitMask; 20 | if (bit != 0) { 21 | bitSum[j]++; 22 | } 23 | bitMask = bitMask << 1; 24 | } 25 | } 26 | 27 | int result = 0; 28 | for (int i = 0; i < 32; i++) { 29 | result = result << 1; 30 | result += bitSum[i] % 3; 31 | } 32 | return result; 33 | } 34 | 35 | public static void main(String[] args) { 36 | int[] nums = new int[]{9, 1, 7, 9, 7, 9, 7}; 37 | System.out.println(findNumberAppearingOnce(nums)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question50/FirstUniqueChar.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question50; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/ 7 | * 剑指 Offer 50. 第一个只出现一次的字符 8 | * @Author tinytongtong 9 | * @Date 2020/9/14 9:23 AM 10 | * @Version 11 | */ 12 | public class FirstUniqueChar { 13 | /** 14 | * 借助辅助空间 15 | * 时间复杂度O(n) 16 | * 空间复杂度O(n) 17 | * @param s 18 | * @return 19 | */ 20 | private static char firstUniqueChar(String s) { 21 | if (s == null || s.length() == 0) { 22 | return ' '; 23 | } 24 | HashMap map = new HashMap<>(); 25 | for (int i = 0; i < s.length(); i++) { 26 | if (map.get(s.charAt(i)) == null) { 27 | map.put(s.charAt(i), 1); 28 | } else { 29 | map.put(s.charAt(i), map.get(s.charAt(i)) + 1); 30 | } 31 | } 32 | for (int i = 0; i < s.length(); i++) { 33 | if (map.get(s.charAt(i)) != null && map.get(s.charAt(i)) == 1) { 34 | return s.charAt(i); 35 | } 36 | } 37 | return ' '; 38 | } 39 | 40 | public static void main(String[] args) { 41 | System.out.println(firstUniqueChar("abaccdeff")); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/fibonacci/FrogJumpStep.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.fibonacci; 2 | 3 | /** 4 | * @Description: 青蛙跳台阶问题,每次可以调一级,也可以调两级 5 | * 剑指Offer面试题9 6 | * https://www.nowcoder.com/practice/8c82a5b80378478f9484d87d1c5f12a4?tpId=13&tqId=11161&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 7 | * @Author tinytongtong 8 | * @Date 2020-02-09 01:04 9 | * @Version 10 | */ 11 | public class FrogJumpStep { 12 | 13 | /** 14 | * 从上往下计算 15 | * 16 | * @param n 17 | * @return 18 | */ 19 | public static int jumpFloor(int n) { 20 | if (n == 1) { 21 | return 1; 22 | } 23 | if (n == 2) { 24 | return 2; 25 | } 26 | 27 | int valueOne = 1; 28 | int valueTwo = 2; 29 | int valueN = 0; 30 | 31 | for (int i = 3; i <= n; i++) { 32 | valueN = valueOne + valueTwo; 33 | valueOne = valueTwo; 34 | valueTwo = valueN; 35 | } 36 | return valueN; 37 | } 38 | 39 | public static void main(String[] args) { 40 | int n = 3; 41 | 42 | long startTime1 = System.nanoTime(); 43 | int result1 = jumpFloor(n); 44 | long endTime1 = System.nanoTime(); 45 | System.out.println(String.format("青蛙跳台阶,result1:%d, 耗时:%d", result1, endTime1 - startTime1)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question53/FindMissingNumber.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question53; 2 | 3 | /** 4 | * @Description: 找到0~n-1中缺失的数字 5 | * 一个长度为 n-1 的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围 0~n-1 之内。 6 | * @Author tinytongtong 7 | * @Date 2020/9/14 10:48 PM 8 | * @Version 9 | */ 10 | public class FindMissingNumber { 11 | 12 | private static int missingNumber(int[] nums) { 13 | if (nums == null || nums.length == 0) { 14 | return -1; 15 | } 16 | int left = 0; 17 | int right = nums.length - 1; 18 | while (left <= right) { 19 | int middle = (left + right) >> 1; 20 | if (nums[middle] != middle) { 21 | if (middle == 0 || nums[middle - 1] == middle - 1) { 22 | return middle; 23 | } 24 | right = middle - 1; 25 | } else { 26 | left = middle + 1; 27 | } 28 | } 29 | if (left == right) { 30 | return left; 31 | } 32 | 33 | if (left == nums.length) { 34 | return left; 35 | } 36 | return -1; 37 | } 38 | 39 | 40 | public static void main(String[] args) { 41 | int[] nums = new int[]{0, 1, 2, 4, 5, 6, 7, 8, 9}; 42 | // int[] nums = new int[]{0}; 43 | System.out.println(missingNumber(nums)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | 18 | # Gradle files 19 | .gradle/ 20 | build/ 21 | gradle-app.setting 22 | !gradle-wrapper.jar 23 | gradle.properties 24 | 25 | # Local configuration file (sdk path, etc) 26 | local.properties 27 | 28 | # Proguard folder generated by Eclipse 29 | proguard/ 30 | 31 | # Log Files 32 | *.log 33 | 34 | # Android Studio Navigation editor temp files 35 | .navigation/ 36 | 37 | # Android Studio captures folder 38 | captures/ 39 | 40 | # IntelliJ 41 | *.iml 42 | .idea/ 43 | *.ipr 44 | *.iws 45 | 46 | # Keystore files 47 | # Uncomment the following line if you do not want to check your keystore files in. 48 | #*.jks 49 | #*.keystore 50 | 51 | # External native build folder generated in Android Studio 2.2 and later 52 | .externalNativeBuild 53 | .cxx/ 54 | 55 | # Google Services (e.g. APIs or Firebase) 56 | google-services.json 57 | 58 | # Freeline 59 | freeline.py 60 | freeline/ 61 | freeline_project_description.json 62 | 63 | # fastlane 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | fastlane/readme.md 69 | 70 | # Version control 71 | vcs.xml 72 | 73 | # lint 74 | lint/intermediates/ 75 | lint/generated/ 76 | lint/outputs/ 77 | lint/tmp/ 78 | # lint/reports/ 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: 冒泡排序 7 | * @Author wangjianzhou 8 | * @Date 2022/2/13 12:36 PM 9 | * @Version 10 | */ 11 | public class BubbleSort { 12 | public static void main(String[] args) { 13 | int[] array = new int[]{4, 5, 6, 3, 2, 1}; 14 | // int[] array = new int[]{6,5,4,3,2,1}; 15 | int n = 6; 16 | System.out.println(Arrays.toString(array)); 17 | bubbleSort(array, n); 18 | System.out.println(Arrays.toString(array)); 19 | } 20 | 21 | /** 22 | * 冒泡排序-将较大的数放到后面。 23 | * 24 | * @param a 25 | * @param n 26 | */ 27 | private static void bubbleSort(int[] a, int n) { 28 | if (a == null || n <= 1) { 29 | return; 30 | } 31 | for (int i = 0; i < n - 1; i++) { 32 | // 提前退出冒泡排序的标记位,当数据全部有序时,就不再需要排序了。 33 | boolean flag = false; 34 | for (int j = 0; j < n - i - 1; j++) { 35 | if (a[j] > a[j + 1]) { // swap 36 | int temp = a[j]; 37 | a[j] = a[j + 1]; 38 | a[j + 1] = temp; 39 | flag = true; 40 | } 41 | } 42 | if (!flag) { // 数据已全部有序,不再需要排序了。 43 | break; 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question21/ExchangeOrder.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question21; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/ 7 | * 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 8 | * @Author tinytongtong 9 | * @Date 2020/9/7 9:40 PM 10 | * @Version 11 | */ 12 | public class ExchangeOrder { 13 | private static int[] exchange(int[] nums) { 14 | if (nums == null || nums.length <= 1) { 15 | return nums; 16 | } 17 | int start = 0; 18 | int end = nums.length - 1; 19 | 20 | while (start < end) { 21 | // 奇数 22 | while (start < nums.length - 1 && (nums[start] & 1) == 1) { 23 | start++; 24 | } 25 | // 偶数 26 | while (end > 0 && (nums[end] & 1) == 0) { 27 | end--; 28 | } 29 | // swap 30 | if (start < end) { 31 | nums[start] ^= nums[end]; 32 | nums[end] ^= nums[start]; 33 | nums[start] ^= nums[end]; 34 | } 35 | } 36 | 37 | return nums; 38 | } 39 | 40 | public static void main(String[] args) { 41 | int[] nums = new int[]{1}; 42 | int[] result = exchange(nums); 43 | System.out.println(Arrays.toString(result)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question58/ReverseLeftWords.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question58; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/ 5 | * 剑指 Offer 58 - II. 左旋转字符串 6 | * @Author tinytongtong 7 | * @Date 2020/9/16 1:28 PM 8 | * @Version 9 | */ 10 | public class ReverseLeftWords { 11 | private static String reverseLeftWords(String s, int n) { 12 | if (s == null || n >= s.length() || n < 1) { 13 | return s; 14 | } 15 | char[] chars = s.toCharArray(); 16 | reverseChars(chars, 0, n - 1); 17 | reverseChars(chars, n, chars.length - 1); 18 | reverseChars(chars, 0, chars.length - 1); 19 | StringBuilder sb = new StringBuilder(); 20 | for (char item : chars) { 21 | sb.append(item); 22 | } 23 | return sb.toString(); 24 | } 25 | 26 | private static void reverseChars(char[] chars, int start, int end) { 27 | if (chars == null || end >= chars.length) { 28 | return; 29 | } 30 | char temp = '0'; 31 | while (start < end) { 32 | temp = chars[start]; 33 | chars[start] = chars[end]; 34 | chars[end] = temp; 35 | start++; 36 | end--; 37 | } 38 | } 39 | 40 | public static void main(String[] args) { 41 | System.out.println(reverseLeftWords("abcdefg", 2)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question61/PlayingCardsIsStraight.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question61; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/ 7 | * 剑指 Offer 61. 扑克牌中的顺子 8 | * @Author tinytongtong 9 | * @Date 2020/9/17 10:55 PM 10 | * @Version 11 | */ 12 | public class PlayingCardsIsStraight { 13 | private static boolean isStraight(int[] nums) { 14 | if (nums == null || nums.length < 1) { 15 | return false; 16 | } 17 | // 先把数据排序 18 | Arrays.sort(nums); 19 | // 其次统计数组中0的个数 20 | int zeroCount = 0; 21 | for (int i = 0; i < nums.length; i++) { 22 | if (nums[i] == 0) { 23 | zeroCount++; 24 | } 25 | } 26 | // 最后统计排序之后的数组中,相邻两个数字之间的空缺总数 27 | int gapCount = 0; 28 | for (int i = 0; i < nums.length - 1; i++) { 29 | if (nums[i] > 0) { 30 | if (nums[i + 1] == nums[i]) { 31 | return false; 32 | } 33 | gapCount += nums[i + 1] - nums[i] - 1; 34 | } 35 | } 36 | return zeroCount >= gapCount; 37 | } 38 | 39 | public static void main(String[] args) { 40 | // int[] nums = new int[]{5, 4, 3, 2, 1}; 41 | int[] nums = new int[]{0, 0, 2, 2, 5}; 42 | System.out.println(isStraight(nums)); 43 | System.out.println(Arrays.toString(nums)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question16/Power.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question16; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/ 5 | * 剑指 Offer 16. 数值的整数次方 6 | * @Author tinytongtong 7 | * @Date 2020/9/6 9:54 PM 8 | * @Version 9 | */ 10 | public class Power { 11 | 12 | private static double power(double base, int exponent) { 13 | // 底数为0 14 | if (base == 0) { 15 | return 0; 16 | } 17 | long absLongExp = exponent; 18 | double res = 1.0; 19 | if (absLongExp < 0) { 20 | base = 1 / base; 21 | absLongExp = -absLongExp; 22 | } 23 | while (absLongExp > 0) { 24 | // 基数 25 | if ((absLongExp & 1) == 1) { 26 | res *= base; 27 | } 28 | base *= base; 29 | absLongExp = absLongExp >> 1; 30 | } 31 | return res; 32 | } 33 | 34 | public static void main(String[] args) { 35 | double base = 2.00000; 36 | int exponent = 10; 37 | double result = power(base, exponent); 38 | System.out.println(result); 39 | 40 | double base1 = 2.10000; 41 | int exponent1 = 3; 42 | double result1 = power(base1, exponent1); 43 | System.out.println(result1); 44 | 45 | double base2 = 2.00000; 46 | int exponent2 = -2; 47 | double result2 = power(base2, exponent2); 48 | System.out.println(result2); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question30/MinStack.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question30; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/ 7 | * 剑指 Offer 30. 包含min函数的栈 8 | * @Author tinytongtong 9 | * @Date 2020/9/8 10:42 PM 10 | * @Version 11 | */ 12 | public class MinStack { 13 | Stack stack; 14 | Stack stackMin; 15 | 16 | public MinStack() { 17 | stack = new Stack<>(); 18 | stackMin = new Stack<>(); 19 | } 20 | 21 | public void push(int x) { 22 | stack.push(x); 23 | if (!stackMin.isEmpty()) { 24 | int num = stackMin.peek(); 25 | if (x < num) { 26 | stackMin.push(x); 27 | } else { 28 | stackMin.push(num); 29 | } 30 | } else { 31 | stackMin.push(x); 32 | } 33 | } 34 | 35 | public void pop() { 36 | stack.pop(); 37 | stackMin.pop(); 38 | } 39 | 40 | public int top() { 41 | return stack.peek(); 42 | } 43 | 44 | public int min() { 45 | return stackMin.peek(); 46 | } 47 | 48 | public static void main(String[] args) { 49 | MinStack minStack = new MinStack(); 50 | minStack.push(-2); 51 | minStack.push(0); 52 | minStack.push(-3); 53 | System.out.println(minStack.min()); 54 | minStack.pop(); 55 | System.out.println(minStack.top()); 56 | System.out.println(minStack.min()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question05/ReplaceSpace.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question05; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/ 5 | * 剑指 Offer 05. 替换空格 6 | * @Author tinytongtong 7 | * @Date 2020/9/3 11:30 PM 8 | * @Version 9 | */ 10 | public class ReplaceSpace { 11 | /** 12 | * 先查找出空格的个数,根据这个个数计算出 13 | * 14 | * @param s 15 | * @return 16 | */ 17 | private static String replaceSpace(String s) { 18 | if (s == null) { 19 | return s; 20 | } 21 | char[] chars = s.toCharArray(); 22 | int count = 0; 23 | for (int i = 0; i < chars.length; i++) { 24 | if (chars[i] == ' ') { 25 | count++; 26 | } 27 | } 28 | char[] newChars = new char[chars.length + count * 2]; 29 | for (int i = chars.length - 1, j = newChars.length - 1; i >= 0; i--, j--) { 30 | if (' ' == chars[i]) { 31 | newChars[j--] = '0'; 32 | newChars[j--] = '2'; 33 | newChars[j] = '%'; 34 | } else { 35 | newChars[j] = chars[i]; 36 | } 37 | } 38 | StringBuilder sb = new StringBuilder(); 39 | for (int i = 0; i < newChars.length; i++) { 40 | sb.append(newChars[i]); 41 | } 42 | return sb.toString(); 43 | } 44 | 45 | public static void main(String[] args) { 46 | String s = "We are happy."; 47 | String result = replaceSpace(s); 48 | System.out.println(result); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0026/RemoveDuplicatesFromSortedArray.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0026; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ 5 | * 26. 删除排序数组中的重复项 6 | * @Author tinytongtong 7 | * @Date 2020/9/1 9:45 AM 8 | * @Version 9 | */ 10 | public class RemoveDuplicatesFromSortedArray { 11 | 12 | /** 13 | * 快慢指针 14 | * 15 | * @param nums 16 | * @return 17 | */ 18 | public static int removeDuplicates(int[] nums) { 19 | if (nums.length == 0) { 20 | return 0; 21 | } 22 | int slow = 0; 23 | for (int fast = 1; fast < nums.length; fast++) { 24 | if (nums[slow] != nums[fast]) { 25 | slow++; 26 | nums[slow] = nums[fast]; 27 | } 28 | } 29 | return slow + 1; 30 | } 31 | 32 | public static void main(String[] args) { 33 | int[] nums = new int[]{0, 0, 1, 1, 1, 2, 2, 3, 3, 4}; 34 | int count = removeDuplicates(nums); 35 | for (int i = 0; i < count; i++) { 36 | System.out.print(nums[i] + ", "); 37 | } 38 | System.out.println(); 39 | System.out.println("------------------------------------"); 40 | 41 | int[] nums1 = new int[]{1, 1, 2}; 42 | int count1 = removeDuplicates(nums1); 43 | for (int i = 0; i < count1; i++) { 44 | System.out.print(nums1[i] + ", "); 45 | } 46 | System.out.println(); 47 | System.out.println("------------------------------------"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question10/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question10; 2 | 3 | /** 4 | * @Description: 剑指 Offer 10. 斐波那契数列 5 | * @Author tinytongtong 6 | * @Date 2020/9/5 3:46 PM 7 | * @Version 8 | */ 9 | public class Fibonacci { 10 | /** 11 | * 递归实现fibonacci数列 12 | * 存在大量重复计算 13 | * 14 | * @param n 15 | * @return 16 | */ 17 | private static int fibonacciByRecursion(int n) { 18 | if (n < 0) { 19 | return 0; 20 | } 21 | if (n == 0) { 22 | return 0; 23 | } 24 | if (n == 1) { 25 | return 1; 26 | } 27 | return fibonacciByRecursion(n - 1) + fibonacciByRecursion(n - 2); 28 | } 29 | 30 | /** 31 | * 迭代实现fibonacci数列 32 | * 从下往上计算 33 | * 34 | * @param n 35 | * @return 36 | */ 37 | private static int fibonacciByIteration(int n) { 38 | if (n <= 0) { 39 | return 0; 40 | } 41 | if (n == 1) { 42 | return 1; 43 | } 44 | int result = 0; 45 | int index = 2; 46 | int one = 0; 47 | int two = 1; 48 | while (index <= n) { 49 | result = two + one; 50 | one = two; 51 | two = result; 52 | index++; 53 | } 54 | return result; 55 | } 56 | 57 | public static void main(String[] args) { 58 | int result = fibonacciByRecursion(9); 59 | System.out.println(result); 60 | 61 | int result1 = fibonacciByIteration(9); 62 | System.out.println(result1); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0074/SearchA2DMatrix.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0074; 2 | 3 | /** 4 | * @Description: 74. 搜索二维矩阵 5 | * 二位数组的查找 6 | * https://leetcode-cn.com/problems/search-a-2d-matrix/ 7 | * https://www.nowcoder.com/practice/abc3fe2ce8e146608e868a70efebf62e?tpId=13&tqId=11154&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 8 | * 剑指offer第三题 9 | * @Author tinytongtong 10 | * @Date 2020-02-08 13:34 11 | * @Version 12 | */ 13 | public class SearchA2DMatrix { 14 | public static boolean searchMatrix(int[][] matrix, int target) { 15 | if (matrix == null || matrix.length <= 0 || matrix[0] == null || matrix[0].length <= 0) { 16 | return false; 17 | } 18 | 19 | int rowIndex = 0; 20 | int columnIndex = matrix[0].length - 1; 21 | while (rowIndex < matrix.length && columnIndex >= 0) { 22 | if (matrix[rowIndex][columnIndex] == target) { 23 | return true; 24 | } else if (matrix[rowIndex][columnIndex] > target) { 25 | columnIndex--; 26 | } else if (matrix[rowIndex][columnIndex] < target) { 27 | rowIndex++; 28 | } 29 | } 30 | return false; 31 | } 32 | 33 | public static void main(String[] args) { 34 | int[][] matrix = new int[][]{ 35 | {1, 3, 5, 7}, 36 | {10, 11, 16, 20}, 37 | {23, 30, 34, 50} 38 | }; 39 | int target = -1; 40 | boolean result = searchMatrix(matrix, target); 41 | System.out.println(String.format("target:%s, result:%b", target, result)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question06/ReversePrintLinked.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question06; 2 | 3 | import java.util.Arrays; 4 | import java.util.Stack; 5 | 6 | /** 7 | * @Description: https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/ 8 | * 剑指 Offer 06. 从尾到头打印链表 9 | * @Author tinytongtong 10 | * @Date 2020/9/4 9:18 AM 11 | * @Version 12 | */ 13 | public class ReversePrintLinked { 14 | private static class ListNode { 15 | int val; 16 | ListNode next; 17 | 18 | public ListNode(int val) { 19 | this.val = val; 20 | } 21 | } 22 | 23 | /** 24 | * 用栈实现 25 | * 时间复杂度O(n) 26 | * 空间复杂度O(n) 27 | * 28 | * @param head 29 | * @return 30 | */ 31 | private static int[] reversePrint(ListNode head) { 32 | if (head == null) { 33 | return new int[0]; 34 | } 35 | Stack stack = new Stack<>(); 36 | while (head != null) { 37 | stack.add(head.val); 38 | head = head.next; 39 | } 40 | int[] result = new int[stack.size()]; 41 | for (int i = 0; i < result.length; i++) { 42 | result[i] = stack.pop(); 43 | } 44 | return result; 45 | } 46 | 47 | public static void main(String[] args) { 48 | ListNode head = new ListNode(1); 49 | ListNode temp = head; 50 | for (int i = 2; i < 10; i++) { 51 | ListNode node = new ListNode(i); 52 | temp.next = node; 53 | temp = node; 54 | } 55 | 56 | int[] result = reversePrint(head); 57 | System.out.println(Arrays.toString(result)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question56/TwoSingleNumbers.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question56; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/ 7 | * 剑指 Offer 56 - I. 数组中数字出现的次数 8 | * @Author tinytongtong 9 | * @Date 2020/9/15 10:52 AM 10 | * @Version 11 | */ 12 | public class TwoSingleNumbers { 13 | private static int[] singleNumbers(int[] nums) { 14 | if (nums == null || nums.length < 2) { 15 | return new int[0]; 16 | } 17 | // 求出所有的异或结果 18 | int sum = 0; 19 | for (int i = 0; i < nums.length; i++) { 20 | sum ^= nums[i]; 21 | } 22 | int indexBit = findFirstBitIs1(sum); 23 | // 根据最右侧的1,将数组分成两部分,然后各自异或的结果就是要查找的数据 24 | int num1 = 0, num2 = 0; 25 | for (int i = 0; i < nums.length; i++) { 26 | if (isBit1(nums[i], indexBit)) { 27 | num1 ^= nums[i]; 28 | } else { 29 | num2 ^= nums[i]; 30 | } 31 | } 32 | return new int[]{num1, num2}; 33 | } 34 | 35 | private static int findFirstBitIs1(int num) { 36 | int indexBit = 0; 37 | while ((num & 1) == 0) { 38 | num = num >> 1; 39 | indexBit++; 40 | } 41 | return indexBit; 42 | } 43 | 44 | private static boolean isBit1(int num, int indexBit) { 45 | num = num >> indexBit; 46 | return (num & 1) == 1; 47 | } 48 | 49 | public static void main(String[] args) { 50 | int[] nums = new int[]{2, 3, 4, 6, 3, 2, 5, 5}; 51 | System.out.println(Arrays.toString(singleNumbers(nums))); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/print_list_reverse/PrintListReverse.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.print_list_reverse; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Stack; 5 | 6 | /** 7 | * @Description: 反转打印链表,不破坏原有链表结构 8 | * 剑指offer第五题 9 | * https://www.nowcoder.com/practice/d0267f7f55b3412ba93bd35cfa8e8035?tpId=13&tqId=11156&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 10 | * @Author tinytongtong 11 | * @Date 2020-02-08 15:51 12 | * @Version 13 | */ 14 | public class PrintListReverse { 15 | private static class ListNode { 16 | int val; 17 | ListNode next = null; 18 | 19 | ListNode(int val) { 20 | this.val = val; 21 | } 22 | } 23 | 24 | public static ArrayList printListFromTailToHead(ListNode listNode) { 25 | // 使用栈来反转链表的顺序 26 | Stack stack = new Stack<>(); 27 | while (listNode != null) { 28 | stack.push(listNode.val); 29 | listNode = listNode.next; 30 | } 31 | 32 | ArrayList result = new ArrayList<>(); 33 | while (!stack.isEmpty()) { 34 | result.add(stack.pop()); 35 | } 36 | return result; 37 | } 38 | 39 | public static void main(String[] args) { 40 | ListNode originNode = new ListNode(0); 41 | int i = 1; 42 | ListNode node = originNode; 43 | while (i < 10) { 44 | ListNode listNode = new ListNode(i); 45 | node.next = listNode; 46 | node = listNode; 47 | i++; 48 | } 49 | 50 | ArrayList result = printListFromTailToHead(originNode); 51 | System.out.println(String.format("result:%s", result.toString())); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question38/StringCombination.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @Description: 求字符的所有组合 9 | * 输入三个字符a、b、c,则他们的组合有a、b、c、ab、ac、bc、abc。 10 | * 当交换字符串中的两个字符时,虽然能得到两个不同的排列,但却是同一个组合。 11 | * 比如ab和ba是不同的排列,但只算一个组合。 12 | * @Author tinytongtong 13 | * @Date 2020/9/10 3:31 PM 14 | * @Version 15 | */ 16 | public class StringCombination { 17 | private static String[] getStringCombination(String str) { 18 | if (str == null || str.length() == 0) { 19 | return new String[0]; 20 | } 21 | List list = new ArrayList<>(); 22 | StringBuilder sb = new StringBuilder(); 23 | int m = 1; 24 | while (m <= str.length()) { 25 | combinationCore(str, list, sb, m); 26 | m++; 27 | } 28 | String[] result = new String[list.size()]; 29 | return list.toArray(result); 30 | } 31 | 32 | private static void combinationCore(String str, List list, StringBuilder sb, int m) { 33 | if (m == 0) { 34 | list.add(sb.toString()); 35 | return; 36 | } 37 | if (str.length() > 0) { 38 | sb.append(str.charAt(0)); 39 | // 从剩余的n-1中选择m-1个 40 | combinationCore(str.substring(1), list, sb, m - 1); 41 | sb.deleteCharAt(sb.length() - 1); 42 | // 从剩余的n-1中选择m个 43 | combinationCore(str.substring(1), list, sb, m); 44 | } 45 | } 46 | 47 | public static void main(String[] args) { 48 | String data = "abcd"; 49 | String[] result = getStringCombination(data); 50 | System.out.println(Arrays.toString(result)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0144/BinaryTreePreorderTraversal.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0144; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Description: https://leetcode-cn.com/problems/binary-tree-preorder-traversal/ 8 | * 144. 二叉树的前序遍历 9 | * @Author tinytongtong 10 | * @Date 2020/9/1 3:27 PM 11 | * @Version 12 | */ 13 | public class BinaryTreePreorderTraversal { 14 | private static class TreeNode { 15 | int val; 16 | TreeNode left; 17 | TreeNode right; 18 | 19 | public TreeNode(int val) { 20 | this.val = val; 21 | } 22 | } 23 | 24 | private static List preorderTraversal(TreeNode root) { 25 | LinkedList nodes = new LinkedList<>(); 26 | LinkedList result = new LinkedList<>(); 27 | if (root == null) { 28 | return result; 29 | } 30 | nodes.add(root); 31 | while (!nodes.isEmpty()) { 32 | TreeNode node = nodes.pollLast(); 33 | if (node == null) { 34 | return result; 35 | } 36 | result.add(node.val); 37 | if (node.right != null) { 38 | nodes.add(node.right); 39 | } 40 | if (node.left != null) { 41 | nodes.add(node.left); 42 | } 43 | } 44 | return result; 45 | } 46 | 47 | public static void main(String[] args) { 48 | TreeNode node3 = new TreeNode(3); 49 | TreeNode node2 = new TreeNode(2); 50 | node2.left = node3; 51 | TreeNode root = new TreeNode(1); 52 | root.right = node2; 53 | 54 | List result = preorderTraversal(root); 55 | System.out.println(result); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question50/FirstUniqueCharInSequence.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question50; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedHashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * @Description: 字符流中第一个只出现一次的字符 9 | * 请实现一个函数,用来找出字符流中第一个只出现一次的字符。 10 | * 例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是'g'; 11 | * 当从该字符流中读出前6个字符"google"时,第一个只出现一次的字符是'l'。 12 | * @Author tinytongtong 13 | * @Date 2020/9/14 10:23 AM 14 | * @Version 15 | */ 16 | public class FirstUniqueCharInSequence { 17 | LinkedHashMap map; 18 | 19 | public FirstUniqueCharInSequence() { 20 | map = new LinkedHashMap<>(); 21 | } 22 | 23 | public void insert(char ch) { 24 | if (map.get(ch) == null) { 25 | map.put(ch, 1); 26 | } else { 27 | map.put(ch, map.get(ch) + 1); 28 | } 29 | } 30 | 31 | public char firstAppearingOnce() { 32 | for (Map.Entry item : map.entrySet()) { 33 | if (item.getValue() != null && item.getValue() == 1) { 34 | return item.getKey(); 35 | } 36 | } 37 | return ' '; 38 | } 39 | 40 | public static void main(String[] args) { 41 | FirstUniqueCharInSequence firstUniqueCharInSequence = new FirstUniqueCharInSequence(); 42 | firstUniqueCharInSequence.insert('g'); 43 | firstUniqueCharInSequence.insert('o'); 44 | System.out.println(firstUniqueCharInSequence.firstAppearingOnce()); 45 | firstUniqueCharInSequence.insert('o'); 46 | firstUniqueCharInSequence.insert('g'); 47 | firstUniqueCharInSequence.insert('l'); 48 | firstUniqueCharInSequence.insert('e'); 49 | System.out.println(firstUniqueCharInSequence.firstAppearingOnce()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question38/StringPermutation.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question38; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | 6 | /** 7 | * @Description: https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/ 8 | * 剑指 Offer 38. 字符串的排列 9 | * 全排列的数量是 n! 10 | * @Author tinytongtong 11 | * @Date 2020/9/10 10:42 AM 12 | * @Version 13 | */ 14 | public class StringPermutation { 15 | private static String[] permutation(String pStr) { 16 | if (pStr == null || pStr.length() == 0) { 17 | return new String[0]; 18 | } 19 | HashSet list = new HashSet<>(); 20 | char[] chars = pStr.toCharArray(); 21 | permutationCore(chars, list, 0); 22 | String[] result = new String[list.size()]; 23 | return list.toArray(result); 24 | } 25 | 26 | private static void permutationCore(char[] chars, HashSet list, int start) { 27 | if (start == chars.length) { 28 | StringBuilder sb = new StringBuilder(); 29 | for (char item : chars) { 30 | sb.append(item); 31 | } 32 | list.add(sb.toString()); 33 | } else { 34 | for (int i = start; i < chars.length; i++) { 35 | swap(chars, i, start); 36 | permutationCore(chars, list, start + 1); 37 | swap(chars, i, start); 38 | } 39 | } 40 | } 41 | 42 | private static void swap(char[] chars, int index1, int index2) { 43 | char temp = chars[index1]; 44 | chars[index1] = chars[index2]; 45 | chars[index2] = temp; 46 | } 47 | 48 | public static void main(String[] args) { 49 | String data = "abc"; 50 | String[] result = permutation(data); 51 | System.out.println(Arrays.toString(result)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question57/FindContinuousSequence.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question57; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @Description: https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/ 9 | * 剑指 Offer 57 - II. 和为s的连续正数序列 10 | * @Author tinytongtong 11 | * @Date 2020/9/15 9:01 PM 12 | * @Version 13 | */ 14 | public class FindContinuousSequence { 15 | 16 | private static int[][] findContinuousSequence(int target) { 17 | if (target < 2) { 18 | return new int[0][0]; 19 | } 20 | List> lists = new ArrayList<>(); 21 | int small = 1; 22 | int big = 2; 23 | while (small < (target + 1) >> 1) { 24 | int sum = (big + small) * (big - small + 1) / 2; 25 | if (sum == target) { 26 | List list = new ArrayList<>(); 27 | for (int i = small; i <= big; i++) { 28 | list.add(i); 29 | } 30 | lists.add(list); 31 | big++; 32 | } else if (sum > target) { 33 | small++; 34 | } else { 35 | big++; 36 | } 37 | } 38 | int[][] result = new int[lists.size()][]; 39 | for (int i = 0; i < lists.size(); i++) { 40 | List list = lists.get(i); 41 | result[i] = new int[list.size()]; 42 | for (int j = 0; j < list.size(); j++) { 43 | result[i][j] = list.get(j); 44 | } 45 | } 46 | return result; 47 | } 48 | 49 | public static void main(String[] args) { 50 | int[][] result = findContinuousSequence(9); 51 | for (int i = 0; i < result.length; i++) { 52 | System.out.println(Arrays.toString(result[i])); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0155/MinStack.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0155; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Description: 155. 最小栈 7 | * https://leetcode-cn.com/problems/min-stack/ 8 | * 剑指offer第21题 9 | * @Author tinytongtong 10 | * @Date 2020-02-05 16:15 11 | * @Version 12 | */ 13 | public class MinStack { 14 | Stack stack; 15 | Stack assistStack; 16 | 17 | public MinStack() { 18 | stack = new Stack<>(); 19 | assistStack = new Stack<>(); 20 | } 21 | 22 | /** 23 | * 添加元素 24 | * 25 | * @param x 26 | */ 27 | public void push(int x) { 28 | stack.push(x); 29 | if (!assistStack.isEmpty() && assistStack.peek() < x) { 30 | assistStack.push(assistStack.peek()); 31 | } else { 32 | assistStack.push(x); 33 | } 34 | } 35 | 36 | /** 37 | * 移除顶部元素 38 | */ 39 | public void pop() { 40 | stack.pop(); 41 | assistStack.pop(); 42 | } 43 | 44 | /** 45 | * 获取栈顶的值 46 | * 47 | * @return 48 | */ 49 | public int top() { 50 | return stack.peek(); 51 | } 52 | 53 | /** 54 | * 获取当前栈中的最小值 55 | * 56 | * @return 57 | */ 58 | public int getMin() { 59 | if (!assistStack.isEmpty()) { 60 | return assistStack.peek(); 61 | } 62 | return -1; 63 | } 64 | 65 | public static void main(String[] args) { 66 | MinStack minStack = new MinStack(); 67 | minStack.push(-2); 68 | minStack.push(0); 69 | minStack.push(-3); 70 | System.out.println("minStack.getMin():" + minStack.getMin()); // --> 返回 -3. 71 | minStack.pop(); 72 | System.out.println("minStack.top():" + minStack.top()); // --> 返回 0. 73 | System.out.println("minStack.getMin():" + minStack.getMin()); // --> 返回 -2. 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question58/ReverseWords.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question58; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/ 5 | * 剑指 Offer 58 - I. 翻转单词顺序 6 | * @Author tinytongtong 7 | * @Date 2020/9/16 9:24 AM 8 | * @Version 9 | */ 10 | public class ReverseWords { 11 | private static String reverseWords(String s) { 12 | if (s == null) { 13 | return s; 14 | } 15 | char[] chars = s.toCharArray(); 16 | // 整体反转 17 | reverseChars(chars, 0, chars.length - 1); 18 | // 单词反转 19 | int index1 = 0; 20 | int index2 = 0; 21 | while (index1 < chars.length && index2 < chars.length) { 22 | while (index1 < chars.length && chars[index1] == ' ') { 23 | index1++; 24 | } 25 | index2 = index1; 26 | while (index2 < chars.length && chars[index2] != ' ') { 27 | index2++; 28 | } 29 | reverseChars(chars, index1, index2 - 1); 30 | index1 = index2; 31 | } 32 | StringBuilder sb = new StringBuilder(); 33 | for (char item : chars) { 34 | sb.append(item); 35 | } 36 | return sb.toString(); 37 | } 38 | 39 | private static void reverseChars(char[] chars, int start, int end) { 40 | if (chars == null || end >= chars.length) { 41 | return; 42 | } 43 | char temp = '0'; 44 | while (start < end) { 45 | temp = chars[start]; 46 | chars[start] = chars[end]; 47 | chars[end] = temp; 48 | start++; 49 | end--; 50 | } 51 | } 52 | 53 | public static void main(String[] args) { 54 | // String str = "we are student."; 55 | String str = " hello world! "; 56 | System.out.println(reverseWords(str)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question55/BinaryTreeDepth.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question55; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-cha-shu-de-shen-du-lcof/ 5 | * 剑指 Offer 55 - I. 二叉树的深度 6 | * @Author tinytongtong 7 | * @Date 2020/9/15 10:23 AM 8 | * @Version 9 | */ 10 | public class BinaryTreeDepth { 11 | private static class TreeNode { 12 | int val; 13 | TreeNode left; 14 | TreeNode right; 15 | 16 | public TreeNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "TreeNode{" + 23 | "val=" + val + 24 | ", left=" + left + 25 | ", right=" + right + 26 | '}'; 27 | } 28 | } 29 | 30 | /** 31 | * 从下往上遍历 32 | * 33 | * @param root 34 | * @return 35 | */ 36 | private static int maxDepth(TreeNode root) { 37 | if (root == null) { 38 | return 0; 39 | } 40 | int left = maxDepth(root.left); 41 | int right = maxDepth(root.right); 42 | return left > right ? left + 1 : right + 1; 43 | } 44 | 45 | public static void main(String[] args) { 46 | TreeNode root = new TreeNode(1); 47 | TreeNode node11 = new TreeNode(2); 48 | TreeNode node12 = new TreeNode(3); 49 | root.left = node11; 50 | root.right = node12; 51 | 52 | TreeNode node21 = new TreeNode(4); 53 | TreeNode node22 = new TreeNode(5); 54 | TreeNode node23 = new TreeNode(6); 55 | node11.left = node21; 56 | node11.right = node22; 57 | node12.right = node23; 58 | 59 | TreeNode node31 = new TreeNode(7); 60 | node22.left = node31; 61 | 62 | System.out.println(root); 63 | 64 | System.out.println(maxDepth(root)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question22/KthNodeToTail.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question22; 2 | 3 | 4 | /** 5 | * @Description: https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/ 6 | * 剑指 Offer 22. 链表中倒数第k个节点 7 | * @Author tinytongtong 8 | * @Date 2020/9/8 7:55 AM 9 | * @Version 10 | */ 11 | public class KthNodeToTail { 12 | private static class ListNode { 13 | int val; 14 | ListNode next; 15 | 16 | public ListNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "ListNode{" + 23 | "val=" + val + 24 | ", next=" + next + 25 | '}'; 26 | } 27 | } 28 | 29 | private static ListNode getKthFromEnd(ListNode head, int k) { 30 | if (head == null || k <= 0) { 31 | return null; 32 | } 33 | int index = 0; 34 | ListNode node1 = head; 35 | ListNode node2 = head; 36 | while (index < k) { 37 | if (node1 == null) { 38 | return null; 39 | } 40 | node1 = node1.next; 41 | index++; 42 | } 43 | while (node1 != null) { 44 | node1 = node1.next; 45 | node2 = node2.next; 46 | } 47 | return node2; 48 | } 49 | 50 | public static void main(String[] args) { 51 | ListNode pHead = new ListNode(1); 52 | ListNode pNode2 = new ListNode(2); 53 | ListNode pNode3 = new ListNode(3); 54 | ListNode pNode4 = new ListNode(4); 55 | ListNode pNode5 = new ListNode(5); 56 | pHead.next = pNode2; 57 | pNode2.next = pNode3; 58 | pNode3.next = pNode4; 59 | pNode4.next = pNode5; 60 | System.out.println(pHead); 61 | 62 | System.out.println(getKthFromEnd(pHead, 1)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question62/CircleLastRemaining.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question62; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/ 7 | * 剑指 Offer 62. 圆圈中最后剩下的数字 8 | * 约瑟夫环问题 9 | * @Author tinytongtong 10 | * @Date 2020/9/17 11:37 PM 11 | * @Version 12 | */ 13 | public class CircleLastRemaining { 14 | 15 | /** 16 | * 使用环形链表解决 17 | * 18 | * @param n 19 | * @param m 20 | * @return 21 | */ 22 | private static int lastRemainingByCycleLinked(int n, int m) { 23 | if (n < 1 || m < 1) { 24 | return -1; 25 | } 26 | LinkedList list = new LinkedList<>(); 27 | for (int i = 0; i < n; i++) { 28 | list.add(i); 29 | } 30 | int index = 0; 31 | while (list.size() > 1) { 32 | for (int i = 1; i < m; i++) { 33 | if (index + 1 < list.size()) { 34 | index++; 35 | } else { 36 | index = 0; 37 | } 38 | } 39 | list.remove(index); 40 | if (index > list.size() - 1) { 41 | index = 0; 42 | } 43 | } 44 | return !list.isEmpty() ? list.peekFirst() : -1; 45 | } 46 | 47 | /** 48 | * 公式解法 49 | * 50 | * @param n 51 | * @param m 52 | * @return 53 | */ 54 | private static int lastRemaining(int n, int m) { 55 | if (n < 1 || m < 1) { 56 | return -1; 57 | } 58 | int last = 0; 59 | for (int i = 2; i <= n; i++) { 60 | last = (last + m) % i; 61 | } 62 | return last; 63 | } 64 | 65 | public static void main(String[] args) { 66 | System.out.println(lastRemainingByCycleLinked(5, 2)); 67 | System.out.println(lastRemaining(5, 2)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question19/PatternMatch.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question19; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof/ 5 | * 剑指 Offer 19. 正则表达式匹配 6 | * @Author tinytongtong 7 | * @Date 2020/9/7 5:18 PM 8 | * @Version 9 | */ 10 | public class PatternMatch { 11 | private static boolean isMatch(String s, String p) { 12 | if (s == null || p == null) { 13 | return false; 14 | } 15 | int n = s.length(); 16 | int m = p.length(); 17 | boolean[][] f = new boolean[n + 1][m + 1]; 18 | 19 | 20 | for (int i = 0; i <= n; i++) { 21 | for (int j = 0; j <= m; j++) { 22 | // 分为 空正则 和 非空正则 两种 23 | if (j == 0) { 24 | f[i][j] = i == 0; 25 | } else { 26 | // 非空正则分为两种情况, * 和 非* 27 | if (p.charAt(j - 1) != '*') { 28 | if (i > 0 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.')) { 29 | f[i][j] = f[i - 1][j - 1]; 30 | } 31 | } else { 32 | // 碰到 * 了,分为看和不来看两种情况 33 | // 不看 34 | if (j >= 2) { 35 | f[i][j] |= f[i][j - 2]; 36 | } 37 | // 看 38 | if (i >= 1 && j >= 2 && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.')) { 39 | f[i][j] |= f[i - 1][j]; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | 46 | return f[n][m]; 47 | } 48 | 49 | public static void main(String[] args) { 50 | String s = "aa"; 51 | String p = "a*"; 52 | boolean result = isMatch(s, p); 53 | System.out.println(result); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question03/MaxSwapCountTest.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question03; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | 6 | /** 7 | * @Description: https://github.com/zhedahht/CodingInterviewChinese2/issues/63 8 | * 0~(n-1)这个n个数字在没有重复数字的情况下最多需要交换n-1次就可以让所有数字找到自己的位置:最大次数应该是n 9 | * 验证这个结论 10 | * @Author tinytongtong 11 | * @Date 2020/9/3 5:35 PM 12 | * @Version 13 | */ 14 | public class MaxSwapCountTest { 15 | /** 16 | * https://github.com/zhedahht/CodingInterviewChinese2/issues/63 17 | * 18 | * 验证方法 19 | * 20 | * @param nums 21 | * @return 22 | */ 23 | private static int verifyTest(int[] nums) { 24 | if (nums == null) { 25 | return -1; 26 | } 27 | int swapCount = 0; 28 | int temp = 0; 29 | for (int i = 0; i < nums.length; i++) { 30 | while (nums[i] != i) { 31 | // 交换元素 32 | temp = nums[i]; 33 | nums[i] = i; 34 | i = temp; 35 | swapCount++; 36 | } 37 | } 38 | return swapCount; 39 | } 40 | 41 | public static void main(String[] args) { 42 | /** 43 | * 0~(n-1)这个n个数字在没有重复数字的情况下最多需要交换n-1次就可以让所有数字找到自己的位置 44 | */ 45 | // 测试10遍 46 | for (int m = 0; m < 10; m++) { 47 | int[] nums1 = new int[100000]; 48 | ArrayList list = new ArrayList<>(); 49 | for (int i = 0; i < nums1.length; i++) { 50 | nums1[i] = i; 51 | list.add(i); 52 | } 53 | // 列表乱序 54 | Collections.shuffle(list); 55 | for (int i = 0; i < nums1.length; i++) { 56 | nums1[i] = list.get(i); 57 | } 58 | // 获取交换次数 59 | int swapCount = verifyTest(nums1); 60 | System.out.println("swapCount:" + swapCount); 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0232/ImplementQueueUsingStacks.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0232; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Description: 232. 用栈实现队列 7 | * 用栈是先链表 8 | * 剑指Offer面试题7 9 | * https://leetcode-cn.com/problems/implement-queue-using-stacks/ 10 | * https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6?tpId=13&tqId=11158&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 11 | * @Author tinytongtong 12 | * @Date 2020-02-08 21:20 13 | * @Version 14 | */ 15 | public class ImplementQueueUsingStacks { 16 | /** 17 | * push操作:直接放入stack1 18 | * pop操作: 19 | * ————如果stack2不为空,直接stack2.pop(); 20 | * ————如果stack2为空,则先将stack1的所有数据依次压入stack2, 然后stack2.pop(); 21 | */ 22 | Stack stack1 = new Stack(); 23 | Stack stack2 = new Stack(); 24 | 25 | /** 26 | * Initialize your data structure here. 27 | */ 28 | public ImplementQueueUsingStacks() { 29 | 30 | } 31 | 32 | /** 33 | * Push element x to the back of queue. 34 | */ 35 | public void push(int x) { 36 | stack1.push(x); 37 | } 38 | 39 | /** 40 | * Removes the element from in front of queue and returns that element. 41 | */ 42 | public int pop() { 43 | if (stack2.isEmpty()) { 44 | while (!stack1.isEmpty()) { 45 | stack2.push(stack1.pop()); 46 | } 47 | } 48 | return stack2.pop(); 49 | } 50 | 51 | /** 52 | * Get the front element. 53 | */ 54 | public int peek() { 55 | if (stack2.isEmpty()) { 56 | while (!stack1.isEmpty()) { 57 | stack2.push(stack1.pop()); 58 | } 59 | } 60 | return stack2.peek(); 61 | } 62 | 63 | /** 64 | * Returns whether the queue is empty. 65 | */ 66 | public boolean empty() { 67 | return stack1.isEmpty() && stack2.isEmpty(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LeetCodeTest 2 | LeetCode题目练习,Java版本 3 | 4 | ### 1、剑指offer第二版Java代码,参考对应的LeetCode题目:具体代码请看[targetoffer](https://github.com/tinyvampirepudge/LeetCodeTest/tree/master/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer)目录。 5 | 6 | 具体来说有如下几个特点: 7 | #### 1、完整的完成剑指offer上所有的题目,从`第3题到第68题`。 8 | ![1](https://img-blog.csdnimg.cn/20201021171807766.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2Mjg3NDM1,size_16,color_FFFFFF,t_70#pic_center) 9 | ![1](https://img-blog.csdnimg.cn/20201021171807740.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2Mjg3NDM1,size_16,color_FFFFFF,t_70#pic_center) 10 | 11 | #### 2、尽可能的将题目与[LeetCode](https://leetcode-cn.com/problemset/all/)上的题目对应起来。 12 | ![2](https://img-blog.csdnimg.cn/20201021171807996.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2Mjg3NDM1,size_16,color_FFFFFF,t_70#pic_center) 13 | 14 | #### 3、每个题目均附有`完整的测试用例`。 15 | ![3](https://img-blog.csdnimg.cn/20201021171808196.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2Mjg3NDM1,size_16,color_FFFFFF,t_70#pic_center) 16 | 17 | #### 4、针对剑指offer上的`题目变形和附加题`,也一一做了解答。 18 | ![4](https://img-blog.csdnimg.cn/20201021171808454.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2Mjg3NDM1,size_16,color_FFFFFF,t_70#pic_center) 19 | 20 | #### 5、对某些解题过程中用到的`定理或者结论`,也进行了验证。 21 | ![5](https://img-blog.csdnimg.cn/20201021171808801.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2Mjg3NDM1,size_16,color_FFFFFF,t_70#pic_center) 22 | 23 | #### 6、各个题目间的`数据结构相互隔离`,互不影响。 24 | 25 | ![6](https://img-blog.csdnimg.cn/20201021171808769.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2Mjg3NDM1,size_16,color_FFFFFF,t_70#pic_center) 26 | 27 | 需要的同学可以自行使用,希望能帮助到大家,可以的话点个star。 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question20/JudgeStringIsNumeric.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question20; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/ 5 | * 剑指 Offer 20. 表示数值的字符串 6 | * @Author tinytongtong 7 | * @Date 2020/9/7 6:12 PM 8 | * @Version 9 | */ 10 | public class JudgeStringIsNumeric { 11 | 12 | private static boolean isNumber(String s) { 13 | if (s == null) { 14 | return false; 15 | } 16 | int[] index = new int[1]; 17 | boolean numeric = scanInteger(s, index); 18 | 19 | // 小数部分 20 | if (index[0] < s.length() && s.charAt(index[0]) == '.') { 21 | index[0]++; 22 | numeric = scanUnsignedInteger(s, index) || numeric; 23 | } 24 | if (index[0] < s.length() && (s.charAt(index[0]) == 'e' || s.charAt(index[0]) == 'E')) { 25 | index[0]++; 26 | numeric = numeric && scanInteger(s, index); 27 | } 28 | return numeric && index[0] == s.length(); 29 | } 30 | 31 | /** 32 | * 扫描可能表示正负的'+'或者'-'起始的0~9的数位 33 | * 34 | * @param s 35 | * @param index 36 | * @return 37 | */ 38 | private static boolean scanInteger(String s, int[] index) { 39 | if (index[0] < s.length() && (s.charAt(index[0]) == '+' || s.charAt(index[0]) == '-')) { 40 | index[0]++; 41 | } 42 | return scanUnsignedInteger(s, index); 43 | } 44 | 45 | /** 46 | * 扫描字符串中0~9的数位 47 | * 48 | * @param s 49 | * @param index 50 | * @return 51 | */ 52 | private static boolean scanUnsignedInteger(String s, int[] index) { 53 | int before = index[0]; 54 | while (index[0] < s.length() && s.charAt(index[0]) >= '0' && s.charAt(index[0]) <= '9') { 55 | index[0]++; 56 | } 57 | return index[0] > before; 58 | } 59 | 60 | public static void main(String[] args) { 61 | String s = "1"; 62 | boolean result = isNumber(s); 63 | System.out.println(result); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question43/CountDigitOne.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question43; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/ 5 | * 剑指 Offer 43. 1~n整数中1出现的次数 6 | * @Author tinytongtong 7 | * @Date 2020/9/11 3:41 PM 8 | * @Version 9 | */ 10 | public class CountDigitOne { 11 | /** 12 | * @param x 13 | * @return 14 | */ 15 | private static int countDigitOne(int x) { 16 | if (x <= 0) { 17 | return 0; 18 | } 19 | return countCore(x); 20 | } 21 | 22 | /** 23 | * 将数字分为两部分 24 | * 25 | * @param x 26 | * @return 27 | */ 28 | private static int countCore(int x) { 29 | if (x == 0) { 30 | return 0; 31 | } 32 | if (x < 10) { 33 | return 1; 34 | } 35 | int sum = 0; 36 | // 获取数字的位数 37 | int m = getHighDigit(x); 38 | // 获取高位的值 39 | int n = getHighNum(x, m); 40 | // 获取地位的余数 41 | int delta = (int) (x % Math.pow(10, m - 1)); 42 | // 1在最高位上出现的次数 43 | if (n > 1) { 44 | sum += Math.pow(10, m - 1); 45 | } else { 46 | sum += delta + 1; 47 | } 48 | // 1在除了最高位上出现的次数 49 | sum += n * Math.pow(10, m - 2) * (m - 1); 50 | // 计算低位所有数字的个数 51 | sum += countCore(delta); 52 | return sum; 53 | } 54 | 55 | /** 56 | * 获取数字的位数 57 | * 58 | * @param n 59 | * @return 60 | */ 61 | private static int getHighDigit(int n) { 62 | int count = 0; 63 | while (n > 0) { 64 | n /= 10; 65 | count++; 66 | } 67 | return count; 68 | } 69 | 70 | /** 71 | * 获取最高位的数字 72 | * 73 | * @param n 74 | * @return 75 | */ 76 | private static int getHighNum(int n, int highDigit) { 77 | return (int) (n / Math.pow(10, highDigit - 1)); 78 | } 79 | 80 | public static void main(String[] args) { 81 | System.out.println(countDigitOne(10));// 2 82 | System.out.println(countDigitOne(20));// 14 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question33/VerifySequenceOfBST.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question33; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/ 5 | * 剑指 Offer 33. 二叉搜索树的后序遍历序列 6 | * @Author tinytongtong 7 | * @Date 2020/9/9 3:33 PM 8 | * @Version 9 | */ 10 | public class VerifySequenceOfBST { 11 | 12 | private static boolean verify(int[] postorder) { 13 | if (postorder == null) { 14 | return false; 15 | } 16 | return verifyCore(postorder, 0, postorder.length - 1); 17 | } 18 | 19 | private static boolean verifyCore(int[] postorder, int start, int end) { 20 | if (start == end) { 21 | return true; 22 | } 23 | // 确定左子树的范围 24 | int leftCount = 0; 25 | for (int i = start; i <= end - 1; i++) { 26 | if (postorder[i] > postorder[end]) { 27 | break; 28 | } 29 | leftCount++; 30 | } 31 | int leftStart = start; 32 | int leftEnd = start + leftCount - 1; 33 | int rightStart = start + leftCount; 34 | int rightEnd = end - 1; 35 | 36 | // 验证右子树数据 37 | if (rightEnd > rightStart) { 38 | for (int i = rightStart; i <= rightEnd; i++) { 39 | if (postorder[i] < postorder[end]) { 40 | return false; 41 | } 42 | } 43 | } 44 | boolean leftResult = true; 45 | if (leftEnd > leftStart) { 46 | leftResult = verifyCore(postorder, leftStart, leftEnd); 47 | } 48 | boolean rightResult = true; 49 | if (rightStart < rightEnd) { 50 | rightResult = verifyCore(postorder, rightStart, rightEnd); 51 | } 52 | return leftResult && rightResult; 53 | } 54 | 55 | public static void main(String[] args) { 56 | // int[] postorder = new int[]{1, 2, 3, 6, 5}; 57 | // int[] postorder = new int[]{1, 6, 3, 2, 5}; 58 | int[] postorder = new int[]{1, 2, 5, 10, 6, 9, 4, 3}; 59 | boolean result = verify(postorder); 60 | System.out.println(result); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question44/FindNthDigit.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question44; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/ 5 | * 剑指 Offer 44. 数字序列中某一位的数字 6 | * @Author tinytongtong 7 | * @Date 2020/9/11 4:57 PM 8 | * @Version 9 | */ 10 | public class FindNthDigit { 11 | private static int findNthDigit(int n) { 12 | if (n < 10) { 13 | return n; 14 | } 15 | int result = 0; 16 | result = findNthDigitCore(n, 9, 1); 17 | return result; 18 | } 19 | 20 | private static int findNthDigitCore(int n, int sum, int digit) { 21 | int delta = 0; 22 | int start = 0; 23 | do { 24 | start = sum + 1; 25 | digit++; 26 | delta = (int) (digit * 9 * Math.pow(10, digit - 1)); 27 | sum += delta; 28 | } while (n > sum); 29 | 30 | // 在[start, end]区间内查找对应位数 31 | int nDelta = n - start + 1; 32 | // 第几个数,从0开始 33 | int j = (nDelta - 1) / digit; 34 | // 数字的第几位 35 | int k = (nDelta - 1) % digit; 36 | int nStart = (int) Math.pow(10, digit - 1); 37 | return getIntAtIndex(nStart + j, k, digit); 38 | } 39 | 40 | /** 41 | * 获取第n位的数字,从左到右,从0开始 42 | * 43 | * @param n 44 | * @param index 45 | * @return 46 | */ 47 | private static int getIntAtIndex(int n, int index, int digit) { 48 | int count = 0; 49 | while (count < index) { 50 | n %= Math.pow(10, digit - 1 - count); 51 | count++; 52 | } 53 | int result = (int) (n / Math.pow(10, digit - 1 - count)); 54 | return result; 55 | } 56 | 57 | public static void main(String[] args) { 58 | System.out.println(findNthDigit(10)); 59 | System.out.println(findNthDigit(11)); 60 | System.out.println(findNthDigit(12)); 61 | System.out.println(findNthDigit(13)); 62 | System.out.println(findNthDigit(14)); 63 | System.out.println(findNthDigit(15)); 64 | System.out.println(findNthDigit(16)); 65 | System.out.println(findNthDigit(17)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question11/MinNumberInRotatedArray.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question11; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/ 5 | * 剑指 Offer 11. 旋转数组的最小数字 6 | * @Author tinytongtong 7 | * @Date 2020/9/5 6:23 PM 8 | * @Version 9 | */ 10 | public class MinNumberInRotatedArray { 11 | 12 | private static int minArray(int[] numbers) { 13 | if (numbers == null) { 14 | return -1; 15 | } 16 | int index1 = 0; 17 | int index2 = numbers.length - 1; 18 | int indexMid = index1; 19 | while (numbers[index1] >= numbers[index2]) { 20 | if (index2 - index1 == 1) { 21 | indexMid = index2; 22 | break; 23 | } 24 | indexMid = (index1 + index2) / 2; 25 | // 如果index1、index2和indexMid三个位置的数据相等,则只能顺序查找了 26 | if (numbers[index1] == numbers[index2] && numbers[index2] == numbers[indexMid]) { 27 | return minInOrder(numbers, index1, index2); 28 | } 29 | 30 | if (numbers[indexMid] >= numbers[index1]) { 31 | index1 = indexMid; 32 | } else if (numbers[indexMid] <= numbers[index2]) { 33 | index2 = indexMid; 34 | } 35 | } 36 | return numbers[indexMid]; 37 | } 38 | 39 | private static int minInOrder(int[] numbers, int start, int end) { 40 | int result = numbers[start]; 41 | for (int i = start + 1; i <= end; i++) { 42 | if (result > numbers[i]) { 43 | result = numbers[i]; 44 | } 45 | } 46 | return result; 47 | } 48 | 49 | public static void main(String[] args) { 50 | int[] arrays = new int[]{3, 4, 5, 1, 2}; 51 | System.out.println(minArray(arrays)); 52 | 53 | int[] arrays1 = new int[]{2, 2, 2, 0, 1}; 54 | System.out.println(minArray(arrays1)); 55 | 56 | int[] arrays2 = new int[]{1, 0, 1, 1, 1}; 57 | System.out.println(minArray(arrays2)); 58 | 59 | int[] arrays3 = new int[]{1, 1, 1, 0, 1}; 60 | System.out.println(minArray(arrays3)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question51/ReversePairsCount.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question51; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/ 5 | * 剑指 Offer 51. 数组中的逆序对 6 | * @Author tinytongtong 7 | * @Date 2020/9/14 10:37 AM 8 | * @Version 9 | */ 10 | public class ReversePairsCount { 11 | /** 12 | * 递归解法 13 | * 时间复杂度O(nlogn) 14 | * 空间复杂度O(n) 15 | * 16 | * @param nums 17 | * @return 18 | */ 19 | private static int reversePairs(int[] nums) { 20 | if (nums == null || nums.length == 0) { 21 | return 0; 22 | } 23 | int[] arrays = new int[nums.length]; 24 | System.arraycopy(nums, 0, arrays, 0, nums.length); 25 | int result = reversePairsCore(nums, arrays, 0, nums.length - 1); 26 | return result; 27 | } 28 | 29 | private static int reversePairsCore(int[] nums, int[] arrays, int start, int end) { 30 | if (start == end) { 31 | arrays[start] = nums[start]; 32 | return 0; 33 | } 34 | int length = (end - start) >> 1; 35 | int left = reversePairsCore(arrays, nums, start, start + length); 36 | int right = reversePairsCore(arrays, nums, start + length + 1, end); 37 | // i 初始化为前半段最后一个数字的角标 38 | int i = start + length; 39 | // j 初始化为后半段最后一个数值的角标 40 | int j = end; 41 | int indexCopy = end; 42 | int count = 0; 43 | while (i >= start && j >= start + length + 1) { 44 | if (nums[i] > nums[j]) { 45 | arrays[indexCopy--] = nums[i--]; 46 | count += j - start - length; 47 | } else { 48 | arrays[indexCopy--] = nums[j--]; 49 | } 50 | } 51 | while (i >= start) { 52 | arrays[indexCopy--] = nums[i--]; 53 | } 54 | while (j >= start + length + 1) { 55 | arrays[indexCopy--] = nums[j--]; 56 | } 57 | return left + right + count; 58 | } 59 | 60 | public static void main(String[] args) { 61 | int[] nums = new int[]{7, 5, 6, 4}; 62 | System.out.println(reversePairs(nums)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question54/kthLargestNode.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question54; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/ 5 | * 剑指 Offer 54. 二叉搜索树的第k大节点 6 | * @Author tinytongtong 7 | * @Date 2020/9/15 9:05 AM 8 | * @Version 9 | */ 10 | public class kthLargestNode { 11 | private static class TreeNode { 12 | int val; 13 | TreeNode left; 14 | TreeNode right; 15 | 16 | public TreeNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "TreeNode{" + 23 | "val=" + val + 24 | ", left=" + left + 25 | ", right=" + right + 26 | '}'; 27 | } 28 | } 29 | 30 | /** 31 | * 中序遍历,就是从小到大排序 32 | * 反向中序遍历,就是从大到小排序 33 | * 34 | * @param root 35 | * @param k 36 | * @return 37 | */ 38 | private static int kthLargest(TreeNode root, int k) { 39 | if (root == null || k <= 0) { 40 | return -1; 41 | } 42 | int[] result = new int[1]; 43 | int[] index = new int[1]; 44 | index[0] = 1; 45 | kthLargestCore(root, k, result, index); 46 | return result[0]; 47 | } 48 | 49 | private static void kthLargestCore(TreeNode root, int k, int[] result, int[] index) { 50 | if (root == null) { 51 | return; 52 | } 53 | kthLargestCore(root.right, k, result, index); 54 | if (index[0] == k) { 55 | result[0] = root.val; 56 | } 57 | index[0]++; 58 | kthLargestCore(root.left, k, result, index); 59 | } 60 | 61 | 62 | public static void main(String[] args) { 63 | TreeNode root = new TreeNode(3); 64 | TreeNode node11 = new TreeNode(1); 65 | TreeNode node12 = new TreeNode(4); 66 | root.left = node11; 67 | root.right = node12; 68 | TreeNode node21 = new TreeNode(2); 69 | node11.right = node21; 70 | 71 | System.out.println(root); 72 | 73 | System.out.println(kthLargest(root, 1)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question67/StrToInt.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question67; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | 10 | /** 11 | * @Description: https://leetcode-cn.com/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/ 12 | * 剑指 Offer 67. 把字符串转换成整数 13 | * @Author tinytongtong 14 | * @Date 2020/9/20 4:05 PM 15 | * @Version 16 | */ 17 | public class StrToInt { 18 | private static int strToInt(String str) { 19 | int result = 0, boundary = Integer.MAX_VALUE / 10; 20 | int i = 0, sign = 1, length = str.length(); 21 | if (length == 0) { 22 | return 0; 23 | } 24 | // 去除首部空格 25 | while (i < length && str.charAt(i) == ' ') i++; 26 | if (i >= length) return 0; 27 | // 获取符号 28 | if (str.charAt(i) == '-') { 29 | sign = -1; 30 | } 31 | if (str.charAt(i) == '-' || str.charAt(i) == '+') { 32 | i++; 33 | } 34 | // 拼接数字 35 | for (int j = i; j < length; j++) { 36 | // 非法字符 37 | if (str.charAt(j) < '0' || str.charAt(j) > '9') { 38 | break; 39 | } 40 | // 越界处理 41 | if (result > boundary || (result == boundary && str.charAt(j) > '7')) { 42 | return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; 43 | } 44 | // 拼接数据 45 | result = result * 10 + (str.charAt(j) - '0'); 46 | } 47 | return sign * result; 48 | } 49 | 50 | public static void main(String[] args) { 51 | System.out.println(Integer.MAX_VALUE); 52 | System.out.println(Integer.MIN_VALUE); 53 | System.out.println(Integer.MAX_VALUE / 10); 54 | System.out.println(strToInt("42")); 55 | System.out.println(strToInt(" -42")); 56 | System.out.println(strToInt("4193 with words")); 57 | System.out.println(strToInt("words with 987")); 58 | System.out.println(strToInt("-91283472332")); 59 | System.out.println(strToInt(" ")); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question15/NumberOfOne.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question15; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/ 5 | * 剑指 Offer 15. 二进制中1的个数 6 | * @Author tinytongtong 7 | * @Date 2020/9/6 7:48 PM 8 | * @Version 9 | */ 10 | public class NumberOfOne { 11 | /** 12 | * 首先把n和1做与运算,判断n的最低位是不是1; 13 | * 接着把1左移一位得到2,再和n的最低位做与运算,就能判断n的次低位是不是1…… 14 | * 这样反复左移,每次都能判断n的其中一位是不是1. 15 | * 时间复杂度O(1):因为int类型是32位,所以就是32次。 16 | * 空间复杂度O(1) 17 | * 18 | * @param n 19 | * @return 20 | */ 21 | private static int hammingWeight(int n) { 22 | int limit = 0; 23 | int count = 0; 24 | // 负数的符号位也需要计入,但是在左移过程中,符号位是不参与移位运算的。 25 | if (n < 0) { 26 | count++; 27 | } 28 | int flag = 1; 29 | while (limit <= 32) { 30 | if ((n & flag) > 0) { 31 | count++; 32 | } 33 | flag = flag << 1; 34 | limit++; 35 | } 36 | return count; 37 | } 38 | 39 | public int hammingWeight0(int n) { 40 | int res = 0; 41 | while (n != 0) { 42 | res++; 43 | n &= n - 1; 44 | } 45 | return res; 46 | } 47 | 48 | private static int hammingWeight1(int n) { 49 | int count = 0; 50 | while (n != 0) { 51 | count++; 52 | n = (n - 1) & n; 53 | } 54 | return count; 55 | } 56 | 57 | public static void main(String[] args) { 58 | test(0); 59 | test(1); 60 | test(0x7FFFFFFF); 61 | test(0x80000000); 62 | test(0xfFFFFFFF); 63 | } 64 | 65 | private static void test(int number) { 66 | boolean isPositive = number >= 0; 67 | System.out.println(String.format("--------------%s---------------", isPositive ? "正数" : "负数")); 68 | System.out.println("二进制表示:" + Integer.toBinaryString(number)); 69 | int result = hammingWeight(number); 70 | System.out.println(result); 71 | int result1 = hammingWeight1(number); 72 | System.out.println(result1); 73 | System.out.println("-----------------------------"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/lcof/lcof_33_verify_postorder/VerifyPostorder.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.lcof.lcof_33_verify_postorder; 2 | 3 | /** 4 | * @Description: 剑指 Offer 33. 二叉搜索树的后序遍历序列 5 | * https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/ 6 | * @Author wangjianzhou 7 | * @Date 2/23/22 10:19 PM 8 | * @Version 9 | */ 10 | public class VerifyPostorder { 11 | 12 | public static void main(String[] args) { 13 | VerifyPostorder verifyPostorder = new VerifyPostorder(); 14 | int[] postorder = new int[]{1, 2, 5, 10, 6, 9, 4, 3}; 15 | boolean result = verifyPostorder.verifyPostorder(postorder); 16 | System.out.println(result); 17 | } 18 | 19 | public boolean verifyPostorder(int[] postorder) { 20 | if (postorder == null) { 21 | return false; 22 | } 23 | return verifyCore(postorder, 0, postorder.length - 1); 24 | } 25 | 26 | public boolean verifyCore(int[] postorder, int start, int end) { 27 | // 只有一个元素,返回true 28 | if (start == end) { 29 | return true; 30 | } 31 | // 找到左子节点的个数 32 | int leftCount = 0; 33 | for (int i = start; i < end; i++) { 34 | if (postorder[i] > postorder[end]) { 35 | break; 36 | } 37 | leftCount++; 38 | } 39 | // 确定左右节点的范围 40 | int leftStart = start; 41 | int leftEnd = leftStart + leftCount - 1; 42 | int rightStart = leftEnd + 1; 43 | int rightEnd = end - 1; 44 | // 默认返回true,只有在有效范围内,且数据不合规,才返回false 45 | if (rightStart < rightEnd) { 46 | for (int i = rightStart; i <= rightEnd; i++) { 47 | if (postorder[i] < postorder[end]) { 48 | return false; 49 | } 50 | } 51 | } 52 | // 左子树递归判断 53 | boolean leftValid = true; 54 | if (leftStart < leftEnd) { 55 | leftValid = verifyCore(postorder, leftStart, leftEnd); 56 | } 57 | // 右子树递归判断 58 | boolean rightValid = true; 59 | if (rightStart < rightEnd) { 60 | rightValid = verifyCore(postorder, rightStart, rightEnd); 61 | } 62 | return leftValid && rightValid; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question11/QuickSort.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question11; 2 | 3 | import java.util.Arrays; 4 | import java.util.Random; 5 | 6 | /** 7 | * @Description: 快速排序,随机选择 pivot 8 | * @Author tinytongtong 9 | * @Date 2020/9/5 4:36 PM 10 | * @Version 11 | */ 12 | public class QuickSort { 13 | /** 14 | * 快速排序 15 | * 最坏时间复杂度O(n²) 16 | * 平均时间复杂度O(nlogn) 17 | * 18 | * @param data 19 | * @param start 20 | * @param end 21 | */ 22 | private static int partition(int[] data, int start, int end) { 23 | if (data == null || data.length == 0 || start < 0 || end >= data.length || end < start) { 24 | return -1; 25 | } 26 | // 随机获取角标 27 | int randomIndex = new Random().nextInt(end - start) + start; 28 | // swap,将随机选择的数字放到end角标上 29 | int temp = data[randomIndex]; 30 | data[randomIndex] = data[end]; 31 | data[end] = temp; 32 | 33 | // small 表示交换到前面的元素,最后一个元素的角标 34 | int small = start - 1; 35 | for (int i = start; i < end; i++) { 36 | if (data[i] < data[end]) { 37 | small++; 38 | if (small != i) { 39 | // swap,将small和i位置的元素进行互换 40 | temp = data[small]; 41 | data[small] = data[i]; 42 | data[i] = temp; 43 | } 44 | } 45 | } 46 | small++; 47 | // 还原位置 48 | temp = data[small]; 49 | data[small] = data[end]; 50 | data[end] = temp; 51 | return small; 52 | } 53 | 54 | private static void quickSort(int[] data, int start, int end) { 55 | if (data == null || start == end) { 56 | return; 57 | } 58 | int index = partition(data, start, end); 59 | if (index > start) { 60 | quickSort(data, start, index - 1); 61 | } 62 | if (index < end) { 63 | quickSort(data, index + 1, end); 64 | } 65 | } 66 | 67 | public static void main(String[] args) { 68 | int[] data = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 69 | quickSort(data, 0, data.length - 1); 70 | System.out.println(Arrays.toString(data)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: 归并排序 7 | * @Author wangjianzhou@qding.me 8 | * @Date 2/15/22 8:31 AM 9 | * @Version 10 | */ 11 | public class MergeSort { 12 | public static void main(String[] args) { 13 | int[] array = new int[]{4, 5, 6, 3, 2, 1}; 14 | // int[] array = new int[]{6,5,4,3,2,1}; 15 | int n = 6; 16 | System.out.println(Arrays.toString(array)); 17 | mergeSort(array, n); 18 | System.out.println(Arrays.toString(array)); 19 | } 20 | 21 | /** 22 | * 归并排序 23 | * 归并排序的核心思想还是蛮简单的。如果要排序一个数组,我们先把数组从中间分成前后两部分, 24 | * 然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。 25 | * 26 | * @param a 27 | * @param n 28 | */ 29 | private static void mergeSort(int[] a, int n) { 30 | if (n <= 1) { 31 | return; 32 | } 33 | mergeCore(a, 0, n - 1); 34 | } 35 | 36 | private static void mergeCore(int[] a, int p, int r) { 37 | // 递归终止条件 38 | if (p >= r) { 39 | return; 40 | } 41 | // 分为前后两部分 42 | int q = (p + r) / 2; 43 | mergeCore(a, p, q); 44 | mergeCore(a, q + 1, r); 45 | // 合并 46 | merge(a, p, q, r); 47 | } 48 | 49 | /** 50 | * 合并有序数组[p,q]和[q+1,r] 51 | * 52 | * @param a 数组 53 | * @param p 54 | * @param q 55 | * @param r 56 | */ 57 | private static void merge(int[] a, int p, int q, int r) { 58 | int[] tmp = new int[r - p + 1]; 59 | int i = p, j = q + 1, k = 0; 60 | // 一个数组中的数据取完了就先停止。 61 | while (i <= q && j <= r) { 62 | if (a[i] > a[j]) { 63 | tmp[k++] = a[i++]; 64 | } else { 65 | tmp[k++] = a[j++]; 66 | } 67 | } 68 | // 找到没copy完的数组 69 | int start = i, end = q; 70 | if (j <= r) { 71 | start = j; 72 | end = r; 73 | } 74 | // 将剩余的数据copy到临时数组中 75 | while (start <= end) { 76 | tmp[k++] = a[start++]; 77 | } 78 | // 将tmp中的数组copy回数组a中 79 | for (int m = p; m <= r; m++) { 80 | a[m] = tmp[m - p]; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question04/FindInTwoDimensionalArray.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question04; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/ 5 | * 剑指 Offer 04. 二维数组中的查找 6 | * n*m数组,每一行从左到右递增,每一列从上到下递增。 7 | * 判断二维数组中是否包含某个整数 8 | * @Author tinytongtong 9 | * @Date 2020/9/3 9:43 PM 10 | * @Version 11 | */ 12 | public class FindInTwoDimensionalArray { 13 | private static boolean findNumberIn2DArray(int[][] arrays, int target) { 14 | if (arrays == null || arrays.length == 0) { 15 | return false; 16 | } 17 | 18 | int rows = arrays.length; 19 | int columns = arrays[0].length; 20 | // 从右上角开始 21 | int row = 0, column = columns - 1; 22 | while (row < rows && column >= 0) { 23 | if (arrays[row][column] == target) { 24 | return true; 25 | } else if (arrays[row][column] < target) { 26 | row++; 27 | } else { 28 | column--; 29 | } 30 | } 31 | return false; 32 | } 33 | 34 | public static void main(String[] args) { 35 | int[][] arrays = { 36 | {1, 4, 7, 11, 15}, 37 | {2, 5, 8, 12, 19}, 38 | {3, 6, 9, 16, 22}, 39 | {10, 13, 14, 17, 24}, 40 | {18, 21, 23, 26, 30} 41 | }; 42 | boolean result = findNumberIn2DArray(arrays, 5); 43 | System.out.println(result); 44 | 45 | boolean result1 = findNumberIn2DArray(arrays, 1); 46 | System.out.println(result1); 47 | 48 | boolean result2 = findNumberIn2DArray(arrays, 15); 49 | System.out.println(result2); 50 | 51 | boolean result3 = findNumberIn2DArray(arrays, 18); 52 | System.out.println(result3); 53 | 54 | boolean result4 = findNumberIn2DArray(arrays, 30); 55 | System.out.println(result4); 56 | 57 | boolean result5 = findNumberIn2DArray(arrays, 0); 58 | System.out.println(result5); 59 | 60 | boolean result6 = findNumberIn2DArray(arrays, 31); 61 | System.out.println(result6); 62 | 63 | boolean result7 = findNumberIn2DArray(arrays, 20); 64 | System.out.println(result7); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0589/NAryTreePreorderTraversal.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0589; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * @Description: https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/ 10 | * 589. N叉树的前序遍历 11 | * @Author tinytongtong 12 | * @Date 2020/9/1 1:36 PM 13 | * @Version 14 | */ 15 | public class NAryTreePreorderTraversal { 16 | 17 | /** 18 | * Definition for a Node. 19 | */ 20 | private static class Node { 21 | public int val; 22 | public List children; 23 | 24 | public Node() { 25 | } 26 | 27 | public Node(int val) { 28 | this.val = val; 29 | } 30 | 31 | public Node(int val, List children) { 32 | this.val = val; 33 | this.children = children; 34 | } 35 | } 36 | 37 | /** 38 | * 迭代解法 39 | * 40 | * @param root 41 | * @return 42 | */ 43 | public static List preorder(Node root) { 44 | LinkedList nodes = new LinkedList<>(); 45 | LinkedList result = new LinkedList<>(); 46 | if (root == null) { 47 | return result; 48 | } 49 | nodes.add(root); 50 | while (!nodes.isEmpty()) { 51 | // 拿尾部的元素 52 | Node node = nodes.pollLast(); 53 | if (node == null) { 54 | return result; 55 | } 56 | result.add(node.val); 57 | if (node.children != null && node.children.size() > 0) { 58 | // 精髓 59 | Collections.reverse(node.children); 60 | nodes.addAll(node.children); 61 | } 62 | } 63 | return result; 64 | } 65 | 66 | public static void main(String[] args) { 67 | Node child111 = new Node(5); 68 | Node child112 = new Node(6); 69 | Node child11 = new Node(3, Arrays.asList(child111, child112)); 70 | Node child12 = new Node(2); 71 | Node child13 = new Node(4); 72 | Node root = new Node(1, Arrays.asList(child11, child12, child13)); 73 | 74 | List list = preorder(root); 75 | System.out.println(list); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question13/RobotMovingCount.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question13; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/ 5 | * 剑指 Offer 13. 机器人的运动范围 6 | * @Author tinytongtong 7 | * @Date 2020/9/6 12:44 PM 8 | * @Version 9 | */ 10 | public class RobotMovingCount { 11 | 12 | private static int movingCount(int threshold, int rows, int cols) { 13 | if (threshold < 0 || rows <= 0 || cols <= 0) { 14 | return 0; 15 | } 16 | boolean[][] visited = new boolean[rows][cols]; 17 | int count = movingCountCore(threshold, rows, cols, 0, 0, visited); 18 | return count; 19 | } 20 | 21 | private static int movingCountCore(int threshold, int rows, int cols, int row, int col, boolean[][] visited) { 22 | int count = 0; 23 | if (check(threshold, rows, cols, row, col, visited)) { 24 | visited[row][col] = true; 25 | count = 1 26 | + movingCountCore(threshold, rows, cols, row, col - 1, visited) 27 | + movingCountCore(threshold, rows, cols, row - 1, col, visited) 28 | + movingCountCore(threshold, rows, cols, row, col + 1, visited) 29 | + movingCountCore(threshold, rows, cols, row + 1, col, visited); 30 | } 31 | return count; 32 | } 33 | 34 | /** 35 | * 判断机器人能否进入坐标为[row,col] 36 | * 37 | * @param threshold 38 | * @param rows 39 | * @param cols 40 | * @param row 41 | * @param col 42 | * @param visited 43 | * @return 44 | */ 45 | private static boolean check(int threshold, int rows, int cols, int row, int col, boolean[][] visited) { 46 | if (row >= 0 && col >= 0 && row < rows && col < cols && getDigitSum(row) + getDigitSum(col) <= threshold && !visited[row][col]) { 47 | return true; 48 | } 49 | return false; 50 | } 51 | 52 | private static int getDigitSum(int number) { 53 | int sum = 0; 54 | while (number > 0) { 55 | sum += number % 10; 56 | number /= 10; 57 | } 58 | return sum; 59 | } 60 | 61 | public static void main(String[] args) { 62 | int result = movingCount(5, 30, 40); 63 | System.out.println(result); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question38/VerifyCubeVertexSum.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @Description: 输入一个含有8个数字的数组,判断有没有可能把这8个数字分别放到正方体的8个顶点上,使得正方体上三组相对的面上的4个顶点的和都相等 9 | * a1 + a2 + a3 + a4 = a5 + a6 + a7 + a8 10 | * a1 + a3 + a5 + a7 = a2 + a4 + a6 + a8 11 | * a1 + a2 + a5 + a6 = a3 + a4 + a7 + a8 12 | * @Author tinytongtong 13 | * @Date 2020/9/10 4:22 PM 14 | * @Version 15 | */ 16 | public class VerifyCubeVertexSum { 17 | private static boolean verify(int[] nums) { 18 | if (nums == null || nums.length < 8) { 19 | return false; 20 | } 21 | List list = new ArrayList<>(); 22 | permutationCore(nums, list, 0); 23 | for (int[] item : list) { 24 | if (verifyArrays(item)) { 25 | return true; 26 | } 27 | } 28 | return false; 29 | } 30 | 31 | private static void permutationCore(int[] nums, List list, int start) { 32 | if (start == nums.length) { 33 | list.add(Arrays.copyOfRange(nums, 0, nums.length)); 34 | } else { 35 | for (int i = start; i < nums.length; i++) { 36 | swap(nums, i, start); 37 | permutationCore(nums, list, start + 1); 38 | swap(nums, i, start); 39 | } 40 | } 41 | } 42 | 43 | private static void swap(int[] nums, int index1, int index2) { 44 | int temp = nums[index1]; 45 | nums[index1] = nums[index2]; 46 | nums[index2] = temp; 47 | } 48 | 49 | private static boolean verifyArrays(int[] nums) { 50 | if (nums == null || nums.length < 8) { 51 | return false; 52 | } 53 | boolean result = nums[0] + nums[1] + nums[2] + nums[3] == nums[4] + nums[5] + nums[6] + nums[7] 54 | || nums[0] + nums[2] + nums[4] + nums[6] == nums[1] + nums[3] + nums[5] + nums[7] 55 | || nums[0] + nums[1] + nums[4] + nums[5] == nums[2] + nums[3] + nums[6] + nums[7]; 56 | return result; 57 | } 58 | 59 | public static void main(String[] args) { 60 | int[] nums = new int[]{2, 2, 3, 4, 5, 6, 7, 9}; 61 | boolean result = verify(nums); 62 | System.out.println(result); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question31/ValidateStackSequence.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question31; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/zhan-de-ya-ru-dan-chu-xu-lie-lcof/ 7 | * 剑指 Offer 31. 栈的压入、弹出序列 8 | * @Author tinytongtong 9 | * @Date 2020/9/9 9:56 AM 10 | * @Version 11 | */ 12 | public class ValidateStackSequence { 13 | /** 14 | * 验证入栈序列和出栈序列 15 | * ①如果下一个弹出的数字刚好是栈顶数字,那么直接弹出; 16 | * ②如果下一个弹出的数字不在栈顶,则把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止; 17 | * ③如果所有数字都压入栈后,仍然没有找到下一个弹出的序列,那么该序列不可能是一个弹出序列。 18 | * 19 | * @param pushed 20 | * @param popped 21 | * @return 22 | */ 23 | private static boolean validate(int[] pushed, int[] popped) { 24 | if (pushed == null || popped == null || pushed.length != popped.length) { 25 | return false; 26 | } 27 | boolean result = false; 28 | Stack stack = new Stack<>(); 29 | int pushIndex = 0; 30 | int popIndex = 0; 31 | while (popIndex <= popped.length && pushIndex <= pushed.length) { 32 | if (pushIndex == pushed.length && popIndex == popped.length) { 33 | result = true; 34 | break; 35 | } 36 | if (!stack.isEmpty() && stack.peek() == popped[popIndex]) { 37 | // 直接弹出栈顶元素 38 | stack.pop(); 39 | popIndex++; 40 | } else { 41 | // add to stack 42 | while (pushIndex < pushed.length) { 43 | stack.push(pushed[pushIndex]); 44 | if (stack.peek() == popped[popIndex]) { 45 | pushIndex++; 46 | break; 47 | } 48 | pushIndex++; 49 | } 50 | if (!stack.isEmpty() && stack.peek() == popped[popIndex]) { 51 | stack.pop(); 52 | popIndex++; 53 | } else { 54 | return false; 55 | } 56 | } 57 | } 58 | return result; 59 | } 60 | 61 | public static void main(String[] args) { 62 | int[] pushed = new int[]{1, 2, 3, 4, 5}; 63 | int[] popped = new int[]{4, 5, 3, 1, 2}; 64 | boolean result = validate(pushed, popped); 65 | System.out.println(result); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question38/EightQueen.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @Description: 8皇后问题 9 | * 使用一维数组降维 10 | * @Author tinytongtong 11 | * @Date 2020/9/10 4:50 PM 12 | * @Version 13 | */ 14 | public class EightQueen { 15 | 16 | private static List getQueenResult() { 17 | List list = new ArrayList<>(); 18 | List result = new ArrayList<>(); 19 | int[] nums = new int[]{0, 1, 2, 3, 4, 5, 6, 7}; 20 | permutationCore(nums, list, 0); 21 | System.out.println("全排列的数量:" + list.size());// 全排列的数量是n! 22 | for (int[] item : list) { 23 | if (verifyQueue(item)) { 24 | result.add(item); 25 | } 26 | } 27 | return result; 28 | } 29 | 30 | private static void permutationCore(int[] nums, List list, int start) { 31 | if (start == nums.length) { 32 | list.add(Arrays.copyOf(nums, nums.length)); 33 | } else { 34 | for (int i = start; i < nums.length; i++) { 35 | swap(nums, i, start); 36 | permutationCore(nums, list, start + 1); 37 | swap(nums, i, start); 38 | } 39 | } 40 | } 41 | 42 | private static void swap(int[] nums, int index1, int index2) { 43 | int temp = nums[index1]; 44 | nums[index1] = nums[index2]; 45 | nums[index2] = temp; 46 | } 47 | 48 | /** 49 | * 判断是否在同一个对角线上 50 | * 51 | * @param nums 52 | * @return true不在同一个对角线上,false表示在。 53 | */ 54 | private static boolean verifyQueue(int[] nums) { 55 | for (int i = 0; i < nums.length; i++) { 56 | for (int j = 0; j < nums.length; j++) { 57 | if (i != j) { 58 | // 是对角线 59 | if (j - i == nums[j] - nums[i] || i - j == nums[j] - nums[i]) { 60 | return false; 61 | } 62 | } 63 | } 64 | } 65 | return true; 66 | } 67 | 68 | public static void main(String[] args) { 69 | List result = getQueenResult(); 70 | System.out.println(result.size()); 71 | for (int[] item : result) { 72 | System.out.println(Arrays.toString(item)); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question55/IsBalancedTree.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question55; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof/ 5 | * 剑指 Offer 55 - II. 平衡二叉树 6 | * @Author tinytongtong 7 | * @Date 2020/9/15 10:35 AM 8 | * @Version 9 | */ 10 | public class IsBalancedTree { 11 | private static class TreeNode { 12 | int val; 13 | TreeNode left; 14 | TreeNode right; 15 | 16 | public TreeNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "TreeNode{" + 23 | "val=" + val + 24 | ", left=" + left + 25 | ", right=" + right + 26 | '}'; 27 | } 28 | } 29 | 30 | private static boolean isBalanced(TreeNode root) { 31 | if (root == null) { 32 | return false; 33 | } 34 | int[] depth = new int[1]; 35 | return isBalancedCore(root, depth); 36 | } 37 | 38 | private static boolean isBalancedCore(TreeNode root, int[] depth) { 39 | if (root == null) { 40 | depth[0] = 0; 41 | return true; 42 | } 43 | int[] left = new int[1], right = new int[1]; 44 | if (isBalancedCore(root.left, left) && isBalancedCore(root.right, right)) { 45 | int diff = left[0] - right[0]; 46 | if (diff >= -1 && diff <= 1) { 47 | depth[0] = 1 + (left[0] > right[0] ? left[0] : right[0]); 48 | return true; 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | public static void main(String[] args) { 55 | TreeNode root = new TreeNode(1); 56 | TreeNode node11 = new TreeNode(2); 57 | TreeNode node12 = new TreeNode(3); 58 | root.left = node11; 59 | root.right = node12; 60 | 61 | TreeNode node21 = new TreeNode(4); 62 | TreeNode node22 = new TreeNode(5); 63 | TreeNode node23 = new TreeNode(6); 64 | node11.left = node21; 65 | node11.right = node22; 66 | node12.right = node23; 67 | 68 | TreeNode node31 = new TreeNode(7); 69 | node22.left = node31; 70 | node31.left = new TreeNode(8); 71 | 72 | System.out.println(root); 73 | 74 | System.out.println(isBalanced(root)); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question59/MaxQueue.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question59; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/ 7 | * 剑指 Offer 59 - II. 队列的最大值 8 | * @Author tinytongtong 9 | * @Date 2020/9/17 1:38 PM 10 | * @Version 11 | */ 12 | public class MaxQueue { 13 | private LinkedList maxDeque; 14 | private LinkedList list; 15 | 16 | public MaxQueue() { 17 | maxDeque = new LinkedList<>(); 18 | list = new LinkedList<>(); 19 | } 20 | 21 | public int max_value() { 22 | return maxDeque.peekFirst(); 23 | } 24 | 25 | public void push_back(int value) { 26 | while (!maxDeque.isEmpty() && value >= maxDeque.peekLast()) { 27 | maxDeque.pollLast(); 28 | } 29 | list.addLast(value); 30 | maxDeque.addLast(value); 31 | } 32 | 33 | public int pop_front() { 34 | if (!maxDeque.isEmpty() && maxDeque.peekFirst().equals(list.peekFirst())) { 35 | maxDeque.pollFirst(); 36 | } 37 | return list.pollFirst(); 38 | } 39 | 40 | public static void main(String[] args) { 41 | MaxQueue maxQueue = new MaxQueue(); 42 | maxQueue.push_back(2); 43 | System.out.println("max_value:" + maxQueue.max_value()); 44 | maxQueue.push_back(3); 45 | System.out.println("max_value:" + maxQueue.max_value()); 46 | maxQueue.push_back(4); 47 | System.out.println("max_value:" + maxQueue.max_value()); 48 | maxQueue.push_back(2); 49 | System.out.println("pop_front:" + maxQueue.pop_front()); 50 | System.out.println("max_value:" + maxQueue.max_value()); 51 | maxQueue.push_back(6); 52 | System.out.println("pop_front:" + maxQueue.pop_front()); 53 | System.out.println("max_value:" + maxQueue.max_value()); 54 | maxQueue.push_back(2); 55 | System.out.println("pop_front:" + maxQueue.pop_front()); 56 | System.out.println("max_value:" + maxQueue.max_value()); 57 | maxQueue.push_back(5); 58 | System.out.println("pop_front:" + maxQueue.pop_front()); 59 | System.out.println("max_value:" + maxQueue.max_value()); 60 | maxQueue.push_back(1); 61 | System.out.println("pop_front:" + maxQueue.pop_front()); 62 | System.out.println("max_value:" + maxQueue.max_value()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question09/ImplQueueByTwoStack.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question09; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/ 7 | * 剑指 Offer 09. 用两个栈实现队列 8 | * @Author tinytongtong 9 | * @Date 2020/9/4 6:05 PM 10 | * @Version 11 | */ 12 | public class ImplQueueByTwoStack { 13 | 14 | /** 15 | * 实现思路: 16 | * ①stackAdd用来添加 17 | * ②stackRemove用来获取 18 | * ③如果stackRemove为空时,就把stackAdd中的元素依次出栈再加入到stackRemove中,然后从stackRemove中获取元素。 19 | */ 20 | private static class CQueue { 21 | private Stack stackAdd; 22 | private Stack stackRemove; 23 | 24 | public CQueue() { 25 | stackAdd = new Stack<>(); 26 | stackRemove = new Stack<>(); 27 | } 28 | 29 | public void appendTail(int value) { 30 | stackAdd.add(value); 31 | } 32 | 33 | public int deleteHead() { 34 | if (stackRemove.isEmpty()) { 35 | while (!stackAdd.isEmpty()) { 36 | stackRemove.add(stackAdd.pop()); 37 | } 38 | } 39 | return !stackRemove.isEmpty() ? stackRemove.pop() : -1; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "CQueue{" + 45 | "stackAdd=" + stackAdd + 46 | ", stackRemove=" + stackRemove + 47 | '}'; 48 | } 49 | } 50 | 51 | public static void main(String[] args) { 52 | CQueue obj = new CQueue(); 53 | obj.appendTail(1); 54 | obj.appendTail(2); 55 | obj.appendTail(3); 56 | System.out.println(obj); 57 | System.out.println(obj.deleteHead()); 58 | System.out.println(obj); 59 | System.out.println(obj.deleteHead()); 60 | obj.appendTail(4); 61 | obj.appendTail(5); 62 | obj.appendTail(6); 63 | System.out.println(obj); 64 | System.out.println(obj.deleteHead()); 65 | System.out.println(obj); 66 | System.out.println(obj.deleteHead()); 67 | System.out.println(obj); 68 | System.out.println(obj.deleteHead()); 69 | System.out.println(obj); 70 | System.out.println(obj.deleteHead()); 71 | // 无数据了 72 | System.out.println(obj); 73 | System.out.println(obj.deleteHead()); 74 | System.out.println(obj); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0002/AddTwoNumbers.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0002; 2 | 3 | /** 4 | * @Description: 2. 两数相加 5 | * https://leetcode-cn.com/problems/add-two-numbers/ 6 | * @Author wangjianzhou 7 | * @Date 2022/2/8 6:23 PM 8 | * @Version 9 | */ 10 | public class AddTwoNumbers { 11 | 12 | private static final class ListNode { 13 | int val; 14 | ListNode next; 15 | 16 | ListNode() { 17 | } 18 | 19 | ListNode(int val) { 20 | this.val = val; 21 | } 22 | 23 | ListNode(int val, ListNode next) { 24 | this.val = val; 25 | this.next = next; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "ListNode{" + 31 | "val=" + val + 32 | ", next=" + next + 33 | '}'; 34 | } 35 | } 36 | 37 | public static void main(String[] args) { 38 | ListNode l1 = new ListNode(2); 39 | ListNode l12 = new ListNode(4); 40 | ListNode l13 = new ListNode(3); 41 | l1.next = l12; 42 | l12.next = l13; 43 | 44 | System.out.println(l1); 45 | 46 | ListNode l2 = new ListNode(5); 47 | ListNode l22 = new ListNode(6); 48 | ListNode l23 = new ListNode(4); 49 | l2.next = l22; 50 | l22.next = l23; 51 | 52 | System.out.println(l2); 53 | 54 | ListNode ln = addTwoNumbers(l1, l2); 55 | System.out.println(ln); 56 | } 57 | 58 | public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { 59 | // 遍历l1和l2 60 | int extra = 0; // 进位 61 | ListNode dummy = new ListNode(); 62 | ListNode head = dummy; 63 | while (l1 != null || l2 != null || extra > 0) { 64 | // 构建新的node 65 | ListNode ln = new ListNode(); 66 | // val相加 67 | if (l1 != null) ln.val += l1.val; 68 | if (l2 != null) ln.val += l2.val; 69 | // 累加extra的值 70 | if (extra > 0) { 71 | ln.val += extra; 72 | } 73 | // 重新计算extra的值 74 | extra = Math.max(ln.val / 10, 0); 75 | ln.val %= 10; 76 | // 组成新的链表 77 | head.next = ln; 78 | head = head.next; 79 | // 指向下一个指针 80 | if (l1 != null) l1 = l1.next; 81 | if (l2 != null) l2 = l2.next; 82 | } 83 | return dummy.next; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question53/FindNumberInSortedArray.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question53; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/ 5 | * 剑指 Offer 53 - I. 在排序数组中查找数字 I 6 | * 统计一个数字在排序数组中出现的次数。 7 | * @Author tinytongtong 8 | * @Date 2020/9/14 6:10 PM 9 | * @Version 10 | */ 11 | public class FindNumberInSortedArray { 12 | 13 | /** 14 | * 基于二分查找,分别查找第一次出现的位置和最后一次出现的位置 15 | * 16 | * @param nums 17 | * @param target 18 | * @return 19 | */ 20 | private static int search(int[] nums, int target) { 21 | if (nums == null || nums.length == 0) { 22 | return 0; 23 | } 24 | int number = 0; 25 | int firstK = getFirstK(nums, target, 0, nums.length - 1); 26 | int lastK = getLastK(nums, target, 0, nums.length - 1); 27 | if (firstK > -1 && lastK > -1) { 28 | number = lastK - firstK + 1; 29 | } 30 | return number; 31 | } 32 | 33 | private static int getFirstK(int[] nums, int target, int start, int end) { 34 | if (start > end) { 35 | return -1; 36 | } 37 | int middle = (start + end) >> 1; 38 | if (nums[middle] == target) { 39 | if ((middle > 0 && nums[middle - 1] != target) || middle == 0) { 40 | return middle; 41 | } else { 42 | end = middle - 1; 43 | } 44 | } else if (nums[middle] > target) { 45 | end = middle - 1; 46 | } else { 47 | start = middle + 1; 48 | } 49 | return getFirstK(nums, target, start, end); 50 | } 51 | 52 | private static int getLastK(int[] nums, int target, int start, int end) { 53 | if (start > end) { 54 | return -1; 55 | } 56 | int middle = (start + end) >> 1; 57 | if (nums[middle] == target) { 58 | if ((middle < nums.length - 1 && nums[middle + 1] != target) || middle == nums.length - 1) { 59 | return middle; 60 | } else { 61 | start = middle + 1; 62 | } 63 | } else if (nums[middle] > target) { 64 | end = middle - 1; 65 | } else { 66 | start = middle + 1; 67 | } 68 | return getLastK(nums, target, start, end); 69 | } 70 | 71 | public static void main(String[] args) { 72 | int[] nums = new int[]{1, 2, 3, 3, 3, 3, 4, 5}; 73 | System.out.println(search(nums, 3)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question68/LowestCommonAncestorBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question68; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof/ 5 | * 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 6 | * @Author tinytongtong 7 | * @Date 2020/10/20 1:31 PM 8 | * @Version 9 | */ 10 | public class LowestCommonAncestorBinarySearchTree { 11 | private static class TreeNode { 12 | int val; 13 | TreeNode left; 14 | TreeNode right; 15 | 16 | public TreeNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "TreeNode{" + 23 | "val=" + val + 24 | ", left=" + left + 25 | ", right=" + right + 26 | '}'; 27 | } 28 | } 29 | 30 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 31 | if (root == null || p == null || q == null) { 32 | return null; 33 | } 34 | while (root != null) { 35 | if (root.val > p.val && root.val > q.val) { 36 | root = root.left; 37 | } else if (root.val < p.val && root.val < q.val) { 38 | root = root.right; 39 | } else { 40 | return root; 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | public static void main(String[] args) { 47 | LowestCommonAncestorBinarySearchTree lca = new LowestCommonAncestorBinarySearchTree(); 48 | TreeNode root = new TreeNode(6); 49 | TreeNode node11 = new TreeNode(2); 50 | TreeNode node12 = new TreeNode(8); 51 | root.left = node11; 52 | root.right = node12; 53 | 54 | TreeNode node21 = new TreeNode(0); 55 | TreeNode node22 = new TreeNode(4); 56 | node11.left = node21; 57 | node11.right = node22; 58 | 59 | TreeNode node23 = new TreeNode(7); 60 | TreeNode node24 = new TreeNode(9); 61 | node12.left = node23; 62 | node12.right = node24; 63 | 64 | TreeNode node31 = new TreeNode(3); 65 | TreeNode node32 = new TreeNode(5); 66 | node22.left = node31; 67 | node22.right = node32; 68 | 69 | TreeNode p = new TreeNode(0); 70 | TreeNode q = new TreeNode(3); 71 | TreeNode result = lca.lowestCommonAncestor(root, p, q); 72 | System.out.println(result != null ? result.toString() : "null"); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question14/CutingRope.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question14; 2 | 3 | /** 4 | * @Description: 剑指 Offer 14. 剪绳子 5 | * @Author tinytongtong 6 | * @Date 2020/9/6 6:13 PM 7 | * @Version 8 | */ 9 | public class CutingRope { 10 | /** 11 | * 动态规划 12 | * 时间复杂度O(n²) 13 | * 空间复杂度O(n) 14 | * 15 | * @param length 16 | * @return 17 | */ 18 | private static int maxProductAfterCutting(int length) { 19 | if (length < 2) { 20 | return 0; 21 | } 22 | if (length == 2) { 23 | return 1; 24 | } 25 | if (length == 3) { 26 | return 2; 27 | } 28 | 29 | int[] products = new int[length + 1]; 30 | products[0] = 0;// 这个没用 31 | // 这三个长度是不剪的,是基本单位 32 | products[1] = 1; 33 | products[2] = 2; 34 | products[3] = 3; 35 | 36 | int max = 0; 37 | // 从下到上计算 38 | for (int i = 4; i <= length; i++) { 39 | max = 0; 40 | for (int j = 1; j <= i / 2; j++) { 41 | int product = products[j] * products[i - j]; 42 | if (max < product) { 43 | max = product; 44 | } 45 | products[i] = max; 46 | } 47 | } 48 | max = products[length]; 49 | return max; 50 | } 51 | 52 | /** 53 | * 贪婪算法 54 | * 时间复杂度O(1) 55 | * 空间复杂度O(1) 56 | * 57 | * @param length 58 | * @return 59 | */ 60 | private static int maxProductAfterCutting1(int length) { 61 | if (length < 2) { 62 | return 0; 63 | } 64 | if (length == 2) { 65 | return 1; 66 | } 67 | if (length == 3) { 68 | return 2; 69 | } 70 | 71 | // 尽可能多地减去长度为3的绳子端 72 | int timeOf3 = length / 3; 73 | // 当绳子最后剩下的长度是4的时候,不能再减去长度为3的绳子段, 74 | // 此时更好地方式是把绳子剪成长度为2的两端,因为2 * 2 > 3 * 1 75 | if (length % 3 == 1) { 76 | timeOf3--; 77 | } 78 | int timeOf2 = (length - timeOf3 * 3) / 2; 79 | System.out.println(String.format("timeOf3:%d, timeOf2:%d", timeOf3, timeOf2)); 80 | return (int) (Math.pow(3, timeOf3) * Math.pow(2, timeOf2)); 81 | } 82 | 83 | public static void main(String[] args) { 84 | int length = 7; 85 | 86 | int result = maxProductAfterCutting(length); 87 | System.out.println(result); 88 | 89 | int result1 = maxProductAfterCutting1(length); 90 | System.out.println(result1); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question29/PrintMatrix.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question29; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/ 7 | * 剑指 Offer 29. 顺时针打印矩阵 8 | * @Author tinytongtong 9 | * @Date 2020/9/8 9:29 PM 10 | * @Version 11 | */ 12 | public class PrintMatrix { 13 | private static int[] spiralOrder(int[][] matrix) { 14 | if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { 15 | return new int[0]; 16 | } 17 | int rows = matrix.length; 18 | int columns = matrix[0].length; 19 | int[] result = new int[rows * columns]; 20 | int[] index = new int[1]; 21 | int start = 0; 22 | while (rows > start * 2 && columns > start * 2) { 23 | printMatrixInCircle(matrix, start, result, index); 24 | start++; 25 | } 26 | return result; 27 | } 28 | 29 | private static void printMatrixInCircle(int[][] matrix, int start, int[] result, int[] index) { 30 | int rows = matrix.length; 31 | int columns = matrix[0].length; 32 | int endX = columns - 1 - start; 33 | int endY = rows - 1 - start; 34 | // 从左到右打印一行:必须步骤 35 | for (int i = start; i <= endX; i++) { 36 | int number = matrix[start][i]; 37 | result[index[0]++] = number; 38 | } 39 | // 从上到下打印一列:最少两行 40 | if (start < endY) { 41 | for (int i = start + 1; i <= endY; i++) { 42 | int number = matrix[i][endX]; 43 | result[index[0]++] = number; 44 | } 45 | } 46 | // 从右到左打印一行:最少两行两列 47 | if (start < endX && start < endY) { 48 | for (int i = endX - 1; i >= start; i--) { 49 | int number = matrix[endY][i]; 50 | result[index[0]++] = number; 51 | } 52 | } 53 | // 从下到上打印一列:最少三行两列 54 | if (start < endX && start < endY - 1) { 55 | for (int i = endY - 1; i >= start + 1; i--) { 56 | int number = matrix[i][start]; 57 | result[index[0]++] = number; 58 | } 59 | } 60 | } 61 | 62 | public static void main(String[] args) { 63 | int[][] matrix = new int[][]{ 64 | {1, 2, 3, 4}, 65 | {5, 6, 7, 8}, 66 | {9, 10, 11, 12}, 67 | {13, 14, 15, 16}, 68 | {17, 18, 19, 20} 69 | }; 70 | int[] result = spiralOrder(matrix); 71 | System.out.println(Arrays.toString(result)); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/classify/sort/QuickSort.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.classify.sort; 2 | 3 | import java.util.Arrays; 4 | import java.util.Random; 5 | 6 | /** 7 | * @Description: 快速排序 8 | * {@link com.tinytongtong.leetcodetest.targetoffer.question11.QuickSort} 9 | * @Author wangjianzhou 10 | * @Date 2/16/22 10:22 PM 11 | * @Version 12 | */ 13 | public class QuickSort { 14 | 15 | public static void main(String[] args) { 16 | // int[] array = new int[]{4, 5, 6, 3, 2, 1}; 17 | int[] array = new int[]{6, 5, 4, 3, 2, 1}; 18 | // int[] array = new int[]{4, 2, 1}; 19 | int n = 6; 20 | System.out.println(Arrays.toString(array)); 21 | quickSort(array, n); 22 | System.out.println(Arrays.toString(array)); 23 | } 24 | 25 | private static void quickSort(int[] a, int n) { 26 | if (a == null || n <= 1) { 27 | return; 28 | } 29 | quickSortCore(a, 0, n - 1); 30 | } 31 | 32 | private static void quickSortCore(int[] a, int start, int end) { 33 | if (start >= end) { 34 | return; 35 | } 36 | // 获取分区点,并将 37 | int pivot = partition(a, start, end); 38 | quickSortCore(a, start, pivot - 1); 39 | quickSortCore(a, pivot + 1, end); 40 | } 41 | 42 | /** 43 | * 随机选择一个pivot,小于它的数据在左侧,大于它的数据在右侧。 44 | * 执行完毕后,这意味着pivot对应的数据在正确的位置。 45 | * 46 | * @return 返回pivot的角标。 47 | */ 48 | private static int partition(int[] a, int start, int end) { 49 | if (a == null || a.length <= 0 || start < 0 || end >= a.length) { 50 | throw new IllegalArgumentException("invalid params in partition"); 51 | } 52 | // 获取所及的pivot 53 | int randomIndex = new Random().nextInt(end - start) + start; 54 | // randomIndex 跟最后一个元素交换位置 55 | if (end != randomIndex) { 56 | a[end] ^= a[randomIndex]; 57 | a[randomIndex] ^= a[end]; 58 | a[end] ^= a[randomIndex]; 59 | } 60 | 61 | // 从前到后遍历,将小于pivot的数交换到前面。 62 | int index = start; 63 | for (int i = start; i < end; i++) { 64 | if (a[i] < a[end]) { 65 | if (i != index) { 66 | a[index] ^= a[i]; 67 | a[i] ^= a[index]; 68 | a[index] ^= a[i]; 69 | } 70 | 71 | index++; 72 | } 73 | } 74 | // 将 randomIndex 交换到小于它的数的后面 75 | if (index != end) { 76 | a[index] ^= a[end]; 77 | a[end] ^= a[index]; 78 | a[index] ^= a[end]; 79 | } 80 | 81 | return index; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question25/MergeTwoSortedList.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question25; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof/ 5 | * 剑指 Offer 25. 合并两个排序的链表 6 | * @Author tinytongtong 7 | * @Date 2020/9/8 2:14 PM 8 | * @Version 9 | */ 10 | public class MergeTwoSortedList { 11 | 12 | private static class ListNode { 13 | int val; 14 | ListNode next; 15 | 16 | public ListNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "ListNode{" + 23 | "val=" + val + 24 | ", next=" + next + 25 | '}'; 26 | } 27 | } 28 | 29 | private static ListNode mergeTwoLists(ListNode p1, ListNode p2) { 30 | if (p1 == null) { 31 | return p2; 32 | } 33 | if (p2 == null) { 34 | return p1; 35 | } 36 | 37 | ListNode dummy = new ListNode(0); 38 | ListNode pNode = dummy; 39 | while (p1 != null && p2 != null) { 40 | if (p1.val < p2.val) { 41 | pNode.next = p1; 42 | p1 = p1.next; 43 | } else { 44 | pNode.next = p2; 45 | p2 = p2.next; 46 | } 47 | pNode = pNode.next; 48 | pNode.next = null;// 删除额外的结点 49 | } 50 | if (p1 != null) { 51 | pNode.next = p1; 52 | } 53 | if (p2 != null) { 54 | pNode.next = p2; 55 | } 56 | return dummy.next; 57 | } 58 | 59 | public static void main(String[] args) { 60 | ListNode pHead = new ListNode(1); 61 | ListNode pNode2 = new ListNode(3); 62 | ListNode pNode3 = new ListNode(5); 63 | ListNode pNode4 = new ListNode(7); 64 | ListNode pNode5 = new ListNode(9); 65 | pHead.next = pNode2; 66 | pNode2.next = pNode3; 67 | pNode3.next = pNode4; 68 | pNode4.next = pNode5; 69 | System.out.println(pHead); 70 | 71 | ListNode p1Head = new ListNode(2); 72 | ListNode p1Node2 = new ListNode(4); 73 | ListNode p1Node3 = new ListNode(6); 74 | ListNode p1Node4 = new ListNode(8); 75 | ListNode p1Node5 = new ListNode(10); 76 | p1Head.next = p1Node2; 77 | p1Node2.next = p1Node3; 78 | p1Node3.next = p1Node4; 79 | p1Node4.next = p1Node5; 80 | System.out.println(p1Head); 81 | 82 | ListNode result = mergeTwoLists(pHead, p1Head); 83 | System.out.println(result); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question41/MedianFinder.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question41; 2 | 3 | import android.annotation.SuppressLint; 4 | 5 | import java.util.Comparator; 6 | import java.util.PriorityQueue; 7 | 8 | /** 9 | * @Description: https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/ 10 | * 剑指 Offer 41. 数据流中的中位数 11 | * 把数据分成两部分,左侧使用最大堆,右侧使用最小堆,左右的数量相差最大为1。 12 | * 为了实现平均分配,数据的总数目为偶数时把新数据插入最小堆,否则插入最大堆。 13 | * @Author tinytongtong 14 | * @Date 2020/9/11 10:05 AM 15 | * @Version 16 | */ 17 | public class MedianFinder { 18 | private PriorityQueue queueMax; 19 | private PriorityQueue queueMin; 20 | private int count = 0; 21 | 22 | @SuppressLint("NewApi") 23 | public MedianFinder() { 24 | queueMax = new PriorityQueue<>(new Comparator() { 25 | @Override 26 | public int compare(Integer o1, Integer o2) { 27 | return o2 - o1; 28 | } 29 | }); 30 | queueMin = new PriorityQueue<>(); 31 | } 32 | 33 | public void addNum(int num) { 34 | if ((count & 1) == 0) { // 添加进右侧的最小堆 35 | if (!queueMax.isEmpty() && num < queueMax.peek()) { 36 | queueMax.add(num); 37 | num=queueMax.poll(); 38 | } 39 | queueMin.add(num); 40 | } else {// 添加进左侧的最大堆 41 | if (!queueMin.isEmpty() && num > queueMin.peek()) { 42 | queueMin.add(num); 43 | num = queueMin.poll(); 44 | } 45 | queueMax.add(num); 46 | } 47 | count++; 48 | } 49 | 50 | public double findMedian() { 51 | if (count > 0) { 52 | if ((count & 1) == 1) { 53 | return queueMin.peek(); 54 | } else { 55 | if (!queueMax.isEmpty() && !queueMin.isEmpty()) { 56 | return (queueMax.peek() + queueMin.peek()) / 2.0; 57 | } 58 | if (!queueMax.isEmpty()) { 59 | return queueMax.peek(); 60 | } 61 | if (!queueMin.isEmpty()) { 62 | return queueMin.peek(); 63 | } 64 | } 65 | } 66 | return 0; 67 | } 68 | 69 | public static void main(String[] args) { 70 | MedianFinder medianFinder = new MedianFinder(); 71 | medianFinder.addNum(4); 72 | System.out.println(medianFinder.findMedian()); 73 | medianFinder.addNum(3); 74 | System.out.println(medianFinder.findMedian()); 75 | medianFinder.addNum(2); 76 | System.out.println(medianFinder.findMedian()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question32/PrintTreeFromTopToBottom.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question32; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import java.util.Queue; 8 | 9 | /** 10 | * @Description: https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/ 11 | * 剑指 Offer 32 - I. 从上到下打印二叉树 12 | * @Author tinytongtong 13 | * @Date 2020/9/9 11:16 AM 14 | * @Version 15 | */ 16 | public class PrintTreeFromTopToBottom { 17 | private static class TreeNode { 18 | int val; 19 | TreeNode left; 20 | TreeNode right; 21 | 22 | public TreeNode(int val) { 23 | this.val = val; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "TreeNode{" + 29 | "val=" + val + 30 | ", left=" + left + 31 | ", right=" + right + 32 | '}'; 33 | } 34 | } 35 | 36 | /** 37 | * 从上到下打印二叉树 38 | * 借助队列,先入先出 39 | * 40 | * @return 41 | */ 42 | private static int[] printTree(TreeNode root) { 43 | if (root == null) { 44 | return new int[0]; 45 | } 46 | List list = new ArrayList<>(); 47 | Queue queue = new LinkedList<>(); 48 | queue.add(root); 49 | while (!queue.isEmpty()) { 50 | TreeNode node = queue.poll(); 51 | list.add(node.val); 52 | if (node.left != null) { 53 | queue.add(node.left); 54 | } 55 | if (node.right != null) { 56 | queue.add(node.right); 57 | } 58 | } 59 | int[] result = new int[list.size()]; 60 | for (int i = 0; i < list.size(); i++) { 61 | result[i] = list.get(i); 62 | } 63 | return result; 64 | } 65 | 66 | public static void main(String[] args) { 67 | TreeNode pRoot1 = new TreeNode(1); 68 | TreeNode pNode11 = new TreeNode(2); 69 | TreeNode pRoot12 = new TreeNode(3); 70 | pRoot1.left = pNode11; 71 | pRoot1.right = pRoot12; 72 | 73 | TreeNode pNode21 = new TreeNode(4); 74 | TreeNode pRoot22 = new TreeNode(5); 75 | pNode11.left = pNode21; 76 | pNode11.right = pRoot22; 77 | 78 | TreeNode pNode23 = new TreeNode(6); 79 | TreeNode pRoot24 = new TreeNode(7); 80 | pRoot12.left = pNode23; 81 | pRoot12.right = pRoot24; 82 | System.out.println(pRoot1); 83 | 84 | int[] result = printTree(pRoot1); 85 | System.out.println(Arrays.toString(result)); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question35/CopyComplexListNode.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question35; 2 | 3 | import org.w3c.dom.Node; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/ 7 | * 剑指 Offer 35. 复杂链表的复制 8 | * @Author tinytongtong 9 | * @Date 2020/9/9 6:00 PM 10 | * @Version 11 | */ 12 | public class CopyComplexListNode { 13 | private static class Node { 14 | int val; 15 | Node next; 16 | Node random; 17 | 18 | public Node(int val) { 19 | this.val = val; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "ComplexTreeNode{" + 25 | "val=" + val + 26 | ", next=" + next + 27 | '}'; 28 | } 29 | } 30 | 31 | /** 32 | * 分三步:克隆、链接、删除原节点 33 | * 34 | * @param head 35 | * @return 36 | */ 37 | private static Node cloneComplexNode(Node head) { 38 | if (head == null) { 39 | return null; 40 | } 41 | copyNode(head); 42 | linkNode(head); 43 | return reLinkNode(head); 44 | } 45 | 46 | private static void copyNode(Node head) { 47 | while (head != null) { 48 | Node node = new Node(head.val); 49 | node.next = head.next; 50 | head.next = node; 51 | head = node.next; 52 | } 53 | } 54 | 55 | private static void linkNode(Node head) { 56 | while (head != null) { 57 | Node node = head.next; 58 | if (head.random !=null) { 59 | node.random = head.random.next; 60 | } 61 | head = node.next; 62 | } 63 | } 64 | 65 | private static Node reLinkNode(Node head) { 66 | Node result = head.next; 67 | head = head.next; 68 | while (head != null && head.next !=null) { 69 | Node node = head.next; 70 | head.next = node.next; 71 | head = node.next; 72 | } 73 | return result; 74 | } 75 | 76 | public static void main(String[] args) { 77 | Node pRoot1 = new Node(7); 78 | 79 | Node pNode2 = new Node(13); 80 | pRoot1.next = pNode2; 81 | 82 | Node pNode3 = new Node(11); 83 | pNode2.next = pNode3; 84 | 85 | Node pNode4 = new Node(10); 86 | pNode3.next = pNode4; 87 | 88 | Node pNode5 = new Node(1); 89 | pNode4.next = pNode5; 90 | 91 | pNode2.random = pRoot1; 92 | pNode3.random = pNode5; 93 | pNode4.random = pNode3; 94 | pNode5.random = pRoot1; 95 | 96 | System.out.println(cloneComplexNode(pRoot1)); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question68/LowestCommonAncestorBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question68; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/ 5 | * 剑指 Offer 68 - II. 二叉树的最近公共祖先 6 | * @Author tinytongtong 7 | * @Date 2020/10/20 1:47 PM 8 | * @Version 9 | */ 10 | public class LowestCommonAncestorBinaryTree { 11 | private static class TreeNode { 12 | int val; 13 | TreeNode left; 14 | TreeNode right; 15 | 16 | public TreeNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "TreeNode{" + 23 | "val=" + val + 24 | ", left=" + left + 25 | ", right=" + right + 26 | '}'; 27 | } 28 | } 29 | 30 | /** 31 | * 递归解法 32 | * https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-ii-er-cha-shu-de-zui-jin-gong-gon-7/ 33 | * 34 | * @param root 35 | * @param p 36 | * @param q 37 | * @return 38 | */ 39 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 40 | if(root == null || root.val == p.val || root.val == q.val) return root; 41 | TreeNode left = lowestCommonAncestor(root.left, p, q); 42 | TreeNode right = lowestCommonAncestor(root.right, p, q); 43 | if(left == null) return right; 44 | if(right == null) return left; 45 | return root; 46 | } 47 | 48 | public static void main(String[] args) { 49 | LowestCommonAncestorBinaryTree lca = new LowestCommonAncestorBinaryTree(); 50 | TreeNode root = new TreeNode(3); 51 | TreeNode node11 = new TreeNode(5); 52 | TreeNode node12 = new TreeNode(1); 53 | root.left = node11; 54 | root.right = node12; 55 | 56 | TreeNode node21 = new TreeNode(6); 57 | TreeNode node22 = new TreeNode(2); 58 | node11.left = node21; 59 | node11.right = node22; 60 | 61 | TreeNode node23 = new TreeNode(0); 62 | TreeNode node24 = new TreeNode(8); 63 | node12.left = node23; 64 | node12.right = node24; 65 | 66 | TreeNode node31 = new TreeNode(7); 67 | TreeNode node32 = new TreeNode(4); 68 | node22.left = node31; 69 | node22.right = node32; 70 | 71 | TreeNode p = new TreeNode(5); 72 | TreeNode q = new TreeNode(1); 73 | System.out.println(root); 74 | TreeNode result = lca.lowestCommonAncestor(root, p, q); 75 | System.out.println(result != null ? result.toString() : "null"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0629/InversePairs.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0629; 2 | 3 | /** 4 | * @Description: 629. K个逆序对数组 5 | * 逆序对 6 | * 剑指Offer第36题 7 | * LeetCode第629题 8 | * https://leetcode-cn.com/problems/k-inverse-pairs-array/ 9 | * @Author tinytongtong 10 | * @Date 2020-02-06 16:06 11 | * @Version 12 | */ 13 | public class InversePairs { 14 | public static int inversePairs(int[] data, int length) { 15 | if (data == null || length < 0) { 16 | return 0; 17 | } 18 | 19 | int[] copy = new int[length]; 20 | for (int i = 0; i < length; i++) { 21 | copy[i] = data[i]; 22 | } 23 | 24 | int count = inversesPairsCore(data, copy, 0, length - 1); 25 | return count; 26 | } 27 | 28 | /** 29 | * 递归调用的方法 30 | * 返回start-end之间数据的逆序对 31 | * 先进行升序排序,再进行比对 32 | * 33 | * @param data 原数据 34 | * @param copy 辅助数组,用来承装排好序的数据 35 | * @param start 起始角标 36 | * @param end 结束角标 37 | * @return 38 | */ 39 | public static int inversesPairsCore(int[] data, int[] copy, int start, int end) { 40 | if (start == end) { 41 | copy[start] = data[start]; 42 | return 0; 43 | } 44 | 45 | // 将数组分为两部分,这个是第一部分的长度 46 | int length = (end - start) / 2; 47 | 48 | // 获取左右子数组的逆序对数,递归调用 49 | // 这里需要格外注意,依次传入的是copy和data,不是data和copy 50 | int left = inversesPairsCore(copy, data, start, start + length); 51 | int right = inversesPairsCore(copy, data, start + length + 1, end); 52 | 53 | // i初始化为前半段最后一个数字的下标 54 | int i = start + length; 55 | // j初始化为后半段最后一个数字的下标 56 | int j = end; 57 | // 辅助数组从右向左复制,这个是起点 58 | int indexCopy = end; 59 | // 左右数组之间的的逆序对数 60 | int count = 0; 61 | // 开始复制 62 | while (i >= start && j >= start + length + 1) { 63 | if (data[i] > data[j]) { 64 | copy[indexCopy--] = data[i--]; 65 | // 右侧数组当前的数字全部小于左侧的数字,所以都是逆序对 66 | count += j - start - length; 67 | } else { 68 | copy[indexCopy--] = data[j--]; 69 | } 70 | } 71 | 72 | // 将剩下的数据copy进辅助数组 73 | for (; i >= start; --i) { 74 | copy[indexCopy--] = data[i]; 75 | } 76 | 77 | for (; j >= start + length + 1; --j) { 78 | copy[indexCopy--] = data[j]; 79 | } 80 | 81 | return left + right + count; 82 | } 83 | 84 | public static void main(String[] args) { 85 | int[] data = new int[]{7, 5, 6, 4}; 86 | int count = inversePairs(data, data.length); 87 | System.out.println("count:" + count); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question12/MatrixHasPath.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question12; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/ 5 | * 剑指 Offer 12. 矩阵中的路径 6 | * @Author tinytongtong 7 | * @Date 2020/9/5 9:44 PM 8 | * @Version 9 | */ 10 | public class MatrixHasPath { 11 | private static boolean hasPath(char[][] matrix, String str) { 12 | if (matrix == null || matrix.length < 1 || matrix[0].length < 1 || str == null) { 13 | return false; 14 | } 15 | int rows = matrix.length; 16 | int cols = matrix[0].length; 17 | boolean[][] visited = new boolean[rows][cols]; 18 | int[] pathLength = new int[1]; 19 | for (int i = 0; i < rows; i++) { 20 | for (int j = 0; j < cols; j++) { 21 | if (hasPathCore(matrix, i, j, str, pathLength, visited)) { 22 | return true; 23 | } 24 | } 25 | } 26 | return false; 27 | } 28 | 29 | private static boolean hasPathCore(char[][] matrix, int row, int col, String str, int[] pathLength, boolean[][] visited) { 30 | if (pathLength[0] == str.length()) { 31 | return true; 32 | } 33 | int rows = matrix.length; 34 | int cols = matrix[0].length; 35 | boolean hasPath = false; 36 | if (row >= 0 && row < rows && col >= 0 && col < cols && matrix[row][col] == str.charAt(pathLength[0]) && !visited[row][col]) { 37 | pathLength[0]++; 38 | visited[row][col] = true; 39 | hasPath = hasPathCore(matrix, row, col - 1, str, pathLength, visited) 40 | || hasPathCore(matrix, row - 1, col, str, pathLength, visited) 41 | || hasPathCore(matrix, row, col + 1, str, pathLength, visited) 42 | || hasPathCore(matrix, row + 1, col, str, pathLength, visited); 43 | if (!hasPath) { 44 | --pathLength[0]; 45 | visited[row][col] = false; 46 | } 47 | } 48 | return hasPath; 49 | } 50 | 51 | public static void main(String[] args) { 52 | char[][] matrix = new char[][]{ 53 | {'A', 'B', 'C', 'E'}, 54 | {'S', 'F', 'C', 'S'}, 55 | {'A', 'D', 'E', 'E'} 56 | }; 57 | String str = "ABCCED"; 58 | boolean result = hasPath(matrix, str); 59 | System.out.println(result); 60 | 61 | char[][] matrix1 = new char[][]{ 62 | {'a', 'b'}, 63 | {'c', 'd'} 64 | }; 65 | String str1 = "ABCCED"; 66 | boolean result1 = hasPath(matrix1, str1); 67 | System.out.println(result1); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question47/MaxValueOfGift.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question47; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/ 5 | * 剑指 Offer 47. 礼物的最大价值 6 | * @Author tinytongtong 7 | * @Date 2020/9/13 10:38 AM 8 | * @Version 9 | */ 10 | public class MaxValueOfGift { 11 | /** 12 | * 迭代解法:需要同等大小的辅助数组 13 | * 时间复杂度O(mn) 14 | * 空间复杂度O(mn) 15 | * 16 | * @param grid 17 | * @return 18 | */ 19 | private static int maxValue(int[][] grid) { 20 | if (grid == null || grid.length == 0 || grid[0].length == 0) { 21 | return 0; 22 | } 23 | int rows = grid.length; 24 | int columns = grid[0].length; 25 | int[][] values = new int[rows][columns]; 26 | for (int i = 0; i < rows; i++) { 27 | for (int j = 0; j < columns; j++) { 28 | int up = 0; 29 | int left = 0; 30 | if (i > 0) { 31 | up = values[i - 1][j]; 32 | } 33 | if (j > 0) { 34 | left = values[i][j - 1]; 35 | } 36 | int max = up > left ? up : left; 37 | values[i][j] = grid[i][j] + max; 38 | } 39 | } 40 | return values[rows - 1][columns - 1]; 41 | } 42 | 43 | /** 44 | * 迭代解法:需要一个大小为列数的一维数组 45 | * 时间复杂度O(mn) 46 | * 空间复杂度O(n) 47 | * 48 | * @param grid 49 | * @return 50 | */ 51 | private static int maxValue1(int[][] grid) { 52 | if (grid == null || grid.length == 0 || grid[0].length == 0) { 53 | return 0; 54 | } 55 | int rows = grid.length; 56 | int columns = grid[0].length; 57 | int[] values = new int[columns]; 58 | for (int i = 0; i < rows; i++) { 59 | for (int j = 0; j < columns; j++) { 60 | int up = 0; 61 | int left = 0; 62 | if (i > 0) { 63 | up = values[j]; 64 | } 65 | if (j > 0) { 66 | left = values[j - 1]; 67 | } 68 | int max = up > left ? up : left; 69 | values[j] = grid[i][j] + max; 70 | } 71 | } 72 | return values[columns - 1]; 73 | } 74 | 75 | public static void main(String[] args) { 76 | int[][] grid = new int[][]{ 77 | {1, 10, 3, 8}, 78 | {12, 2, 9, 6}, 79 | {5, 7, 4, 11}, 80 | {3, 7, 16, 5} 81 | }; 82 | int result = maxValue(grid); 83 | System.out.println(result); 84 | System.out.println(maxValue1(grid)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question49/UglyNumber.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question49; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/chou-shu-lcof/ 5 | * 剑指 Offer 49. 丑数 6 | * @Author tinytongtong 7 | * @Date 2020/9/13 9:07 PM 8 | * @Version 9 | */ 10 | public class UglyNumber { 11 | /** 12 | * 暴力解法 13 | * @param n 14 | * @return 15 | */ 16 | private static int nthUglyNumber(int n) { 17 | if (n <= 0) { 18 | return 0; 19 | } 20 | int number = 0; 21 | int uglyFound = 0; 22 | while (uglyFound < n) { 23 | ++number; 24 | if (isUgly(number)) { 25 | uglyFound++; 26 | } 27 | } 28 | return number; 29 | } 30 | 31 | /** 32 | * @param number 33 | * @return 34 | */ 35 | private static boolean isUgly(int number) { 36 | while (number % 2 == 0) { 37 | number /= 2; 38 | } 39 | while (number % 3 == 0) { 40 | number /= 3; 41 | } 42 | while (number % 5 == 0) { 43 | number /= 5; 44 | } 45 | return number == 1; 46 | } 47 | 48 | /** 49 | * 只找丑数 50 | * @param n 51 | * @return 52 | */ 53 | private static int nthUglyNumber1(int n) { 54 | if (n <= 0) { 55 | return 0; 56 | } 57 | int[] uglyNumbers = new int[n]; 58 | uglyNumbers[0] = 1; 59 | int nextUglyIndex = 1; 60 | int[] multiply2 = uglyNumbers; 61 | int index2 = 0; 62 | int[] multiply3 = uglyNumbers; 63 | int index3 = 0; 64 | int[] multiply5 = uglyNumbers; 65 | int index5 = 0; 66 | 67 | while (nextUglyIndex < n) { 68 | int min = min(multiply2[index2] * 2, multiply3[index3] * 3, multiply5[index5] * 5); 69 | uglyNumbers[nextUglyIndex] = min; 70 | while (multiply2[index2] * 2 <= uglyNumbers[nextUglyIndex]) { 71 | index2++; 72 | } 73 | while (multiply3[index3] * 3 <= uglyNumbers[nextUglyIndex]) { 74 | index3++; 75 | } 76 | while (multiply5[index5] * 5 <= uglyNumbers[nextUglyIndex]) { 77 | index5++; 78 | } 79 | nextUglyIndex++; 80 | } 81 | 82 | int number = uglyNumbers[nextUglyIndex - 1]; 83 | return number; 84 | } 85 | 86 | private static int min(int number2, int number3, int number5) { 87 | int min = number2 < number3 ? number2 : number3; 88 | min = min < number5 ? min : number5; 89 | return min; 90 | } 91 | 92 | 93 | public static void main(String[] args) { 94 | System.out.println(nthUglyNumber(7)); 95 | System.out.println(nthUglyNumber1(8)); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0104/MaximumDepthOfBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0104; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * @Description: https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/ 8 | * 104. 二叉树的最大深度 9 | * @Author tinytongtong 10 | * @Date 2020/9/2 11:36 AM 11 | * @Version 12 | */ 13 | public class MaximumDepthOfBinaryTree { 14 | 15 | private static class TreeNode { 16 | int val; 17 | TreeNode left; 18 | TreeNode right; 19 | 20 | public TreeNode(int val) { 21 | this.val = val; 22 | } 23 | } 24 | 25 | /** 26 | * 递归 DFS 27 | * 时间复杂度:O(n),其中 nn 为二叉树节点的个数。每个节点在递归中只被遍历一次。 28 | * 空间复杂度:O(height),其中 height 表示二叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于二叉树的高度。 29 | *

30 | * 作者:LeetCode-Solution 31 | * 链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/solution/er-cha-shu-de-zui-da-shen-du-by-leetcode-solution/ 32 | * 来源:力扣(LeetCode) 33 | * 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 34 | * 35 | * @param root 36 | * @return 37 | */ 38 | private static int maxDepth(TreeNode root) { 39 | if (root == null) { 40 | return 0; 41 | } 42 | return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; 43 | } 44 | 45 | /** 46 | * 迭代 BFS 47 | * 48 | * @param root 49 | * @return 50 | */ 51 | private static int maxDepthBFS(TreeNode root) { 52 | if (root == null) { 53 | return 0; 54 | } 55 | Queue queue = new LinkedList<>(); 56 | queue.offer(root); 57 | int result = 0; 58 | // 循环拿出本层所有的节点 59 | while (!queue.isEmpty()) { 60 | // 把每层所有节点都加入到队列中 61 | int size = queue.size(); 62 | while (size > 0) { 63 | TreeNode node = queue.poll(); 64 | if (node.left != null) { 65 | queue.offer(node.left); 66 | } 67 | if (node.right != null) { 68 | queue.offer(node.right); 69 | } 70 | size--; 71 | } 72 | result++; 73 | } 74 | return result; 75 | } 76 | 77 | public static void main(String[] args) { 78 | TreeNode root = new TreeNode(3); 79 | TreeNode node11 = new TreeNode(9); 80 | root.left = node11; 81 | TreeNode node12 = new TreeNode(20); 82 | root.right = node12; 83 | TreeNode node21 = new TreeNode(15); 84 | TreeNode node22 = new TreeNode(7); 85 | node12.left = node21; 86 | node12.right = node22; 87 | 88 | int result = maxDepth(root); 89 | System.out.println(result); 90 | 91 | int result1 = maxDepthBFS(root); 92 | System.out.println(result1); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question59/MaxSlidingWindow.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question59; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Arrays; 5 | import java.util.Deque; 6 | import java.util.LinkedList; 7 | 8 | /** 9 | * @Description: https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/ 10 | * 剑指 Offer 59 - I. 滑动窗口的最大值 11 | * @Author tinytongtong 12 | * @Date 2020/9/17 9:40 AM 13 | * @Version 14 | */ 15 | public class MaxSlidingWindow { 16 | 17 | private static int[] maxSlidingWindow(int[] nums, int k) { 18 | if (nums == null || nums.length <= 0 || k > nums.length) { 19 | return new int[0]; 20 | } 21 | int[] result = new int[nums.length - k + 1]; 22 | Deque deque = new ArrayDeque<>(); 23 | // 获取前k个数的最大值。 24 | for (int i = 0; i < k; i++) { 25 | while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) { 26 | deque.pollLast(); 27 | } 28 | deque.addLast(i); 29 | } 30 | // 移动窗口,获取最大值 31 | for (int i = k; i < nums.length; i++) { 32 | result[i - k] = nums[deque.peekFirst()]; 33 | while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) { 34 | deque.pollLast(); 35 | } 36 | if (!deque.isEmpty() && deque.peekFirst() <= (i - k)) { 37 | deque.pollFirst(); 38 | } 39 | deque.addLast(i); 40 | } 41 | result[result.length - 1] = nums[deque.peekFirst()]; 42 | return result; 43 | } 44 | 45 | private static int[] maxSlidingWindow1(int[] nums, int k) { 46 | // 异常数据校验 47 | if (nums == null || nums.length <= 0 || k > nums.length) { 48 | return new int[0]; 49 | } 50 | 51 | int[] result = new int[nums.length - k + 1]; 52 | Deque deque = new LinkedList<>(); 53 | // m表示窗口的起点,n表示当前的元素角标 54 | // m大于等于0,表示窗口的数据满了,符合移动的条件了 55 | for (int m = 1 - k, n = 0; n < nums.length; m++, n++) { 56 | // 先删除超出窗口边界的元素。m=0表示第一个窗口,m>0表示移动后的窗口。 57 | if (m > 0 && deque.peekFirst() == nums[m - 1]) { 58 | deque.removeFirst(); 59 | } 60 | // 比较新加入的元素跟现有元素的大小,保证最大值在左侧,同时要保证队列递减 61 | while (!deque.isEmpty() && deque.peekLast() < nums[n]) { 62 | deque.removeLast(); 63 | } 64 | deque.addLast(nums[n]); 65 | if (m >= 0) { 66 | result[m] = deque.peekFirst(); 67 | } 68 | } 69 | return result; 70 | } 71 | 72 | public static void main(String[] args) { 73 | int[] nums = new int[]{2, 3, 4, 2, 6, 2, 5, 1}; 74 | System.out.println(Arrays.toString(maxSlidingWindow(nums, 3))); 75 | System.out.println(Arrays.toString(maxSlidingWindow1(nums, 3))); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question23/MeetingNodeInCycle.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question23; 2 | 3 | 4 | /** 5 | * @Description: 剑指 Offer 23. 链表中环的入口节点 6 | * @Author tinytongtong 7 | * @Date 2020/9/8 9:20 AM 8 | * @Version 9 | */ 10 | public class MeetingNodeInCycle { 11 | private static class ListNode { 12 | int val; 13 | ListNode next; 14 | 15 | public ListNode(int val) { 16 | this.val = val; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "ListNode{" + 22 | "val=" + val + 23 | '}'; 24 | } 25 | } 26 | 27 | /** 28 | * 第一步确定是否有环 29 | * 快慢指针,找到环中任意一个节点 30 | * 31 | * @param head 32 | * @return 33 | */ 34 | private static ListNode meetingNode(ListNode head) { 35 | if (head == null) { 36 | return null; 37 | } 38 | ListNode result = null; 39 | ListNode pFast = head; 40 | ListNode pSlow = head; 41 | while (pFast.next != null && pFast.next.next != null) { 42 | pFast = pFast.next.next; 43 | pSlow = pSlow.next; 44 | if (pFast.val == pSlow.val) { 45 | result = pFast; 46 | break; 47 | } 48 | } 49 | return result; 50 | } 51 | 52 | /** 53 | * 第二步找到环的入口 54 | * 55 | * @param pHead 56 | * @return 57 | */ 58 | private static ListNode entryNodeOfLoop(ListNode pHead) { 59 | ListNode pMeeting = meetingNode(pHead); 60 | if (pMeeting == null) { 61 | return null; 62 | } 63 | // 先得到环节点的数目 64 | int count = 1; 65 | ListNode pNode = pMeeting.next; 66 | while (pNode.val != pMeeting.val) { 67 | pNode = pNode.next; 68 | count++; 69 | } 70 | ListNode pFast = pHead; 71 | ListNode pSlow = pHead; 72 | // 快慢指针,找到入口节点 73 | while (count > 0) { 74 | pFast = pFast.next; 75 | count--; 76 | } 77 | while (pFast.val != pSlow.val) { 78 | pFast = pFast.next; 79 | pSlow = pSlow.next; 80 | } 81 | return pFast; 82 | } 83 | 84 | public static void main(String[] args) { 85 | ListNode pHead = new ListNode(1); 86 | ListNode pNode2 = new ListNode(2); 87 | ListNode pNode3 = new ListNode(3); 88 | ListNode pNode4 = new ListNode(4); 89 | ListNode pNode5 = new ListNode(5); 90 | pHead.next = pNode2; 91 | pNode2.next = pNode3; 92 | pNode3.next = pNode4; 93 | pNode4.next = pNode5; 94 | pNode5.next = pNode4; 95 | System.out.println(pHead); 96 | 97 | System.out.println(entryNodeOfLoop(pHead)); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question38/NQueen.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @Description: https://leetcode-cn.com/problems/eight-queens-lcci/ 9 | * n皇后问题 10 | * @Author tinytongtong 11 | * @Date 2020/9/10 6:03 PM 12 | * @Version 13 | */ 14 | public class NQueen { 15 | private static List> solveNQueens(int n) { 16 | List> result = new ArrayList<>(); 17 | if (n <= 0) return result; 18 | // 得到全排列 19 | int[] nums = new int[n]; 20 | for (int i = 0; i < n; i++) { 21 | nums[i] = i; 22 | } 23 | List list = new ArrayList<>(); 24 | permutationCore(nums, list, 0); 25 | // 挑选符合规则的数组 26 | List queenList = new ArrayList<>(); 27 | for (int[] item : list) { 28 | if (verifyQueen(item)) queenList.add(item); 29 | } 30 | // 将数组转换成Q字符串 31 | for (int[] item : queenList) { 32 | result.add(convertToQueen(item)); 33 | } 34 | return result; 35 | } 36 | 37 | private static void permutationCore(int[] nums, List list, int start) { 38 | if (start == nums.length) { 39 | list.add(Arrays.copyOf(nums, nums.length)); 40 | } else { 41 | for (int i = start; i < nums.length; i++) { 42 | swap(nums, i, start); 43 | permutationCore(nums, list, start + 1); 44 | swap(nums, i, start); 45 | } 46 | } 47 | } 48 | 49 | private static boolean verifyQueen(int[] nums) { 50 | for (int i = 0; i < nums.length; i++) { 51 | for (int j = 0; j < nums.length; j++) { 52 | if (i != j) { 53 | if (j - i == nums[j] - nums[i] || i - j == nums[j] - nums[i]) return false; 54 | } 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | private static void swap(int[] nums, int index1, int index2) { 61 | int temp = nums[index1]; 62 | nums[index1] = nums[index2]; 63 | nums[index2] = temp; 64 | } 65 | 66 | private static List convertToQueen(int[] nums) { 67 | List strList = new ArrayList<>(); 68 | for (int i = 0; i < nums.length; i++) { 69 | StringBuilder sb = new StringBuilder(); 70 | for (int j = 0; j < nums.length; j++) { 71 | if (nums[i] == j) { 72 | sb.append("Q"); 73 | } else { 74 | sb.append("."); 75 | } 76 | } 77 | strList.add(sb.toString()); 78 | } 79 | return strList; 80 | } 81 | 82 | public static void main(String[] args) { 83 | List> result = solveNQueens(4); 84 | System.out.println(result); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question45/MinNumberInArrays.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question45; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/ 7 | * 剑指 Offer 45. 把数组排成最小的数 8 | * @Author tinytongtong 9 | * @Date 2020/9/11 10:59 PM 10 | * @Version 11 | */ 12 | public class MinNumberInArrays { 13 | 14 | private static String minNumber(int[] nums) { 15 | if (nums == null || nums.length == 0) { 16 | return ""; 17 | } 18 | String[] strs = new String[nums.length]; 19 | for (int i = 0; i < nums.length; i++) { 20 | strs[i] = String.valueOf(nums[i]); 21 | } 22 | quickSort(strs, 0, strs.length - 1); 23 | StringBuilder sb = new StringBuilder(); 24 | for (String item : strs) { 25 | sb.append(item); 26 | } 27 | return sb.toString(); 28 | } 29 | 30 | private static void quickSort(String[] data, int start, int end) { 31 | if (data == null || start == end) { 32 | return; 33 | } 34 | int index = partition(data, start, end); 35 | if (index > start) { 36 | quickSort(data, start, index - 1); 37 | } 38 | if (index < end) { 39 | quickSort(data, index + 1, end); 40 | } 41 | } 42 | 43 | /** 44 | * 快速排序 45 | * 最坏时间复杂度O(n²) 46 | * 平均时间复杂度O(nlogn) 47 | * 48 | * @param data 49 | * @param start 50 | * @param end 51 | */ 52 | private static int partition(String[] data, int start, int end) { 53 | if (data == null || data.length == 0 || start < 0 || end >= data.length || end < start) { 54 | return -1; 55 | } 56 | // 随机获取角标 57 | int randomIndex = new Random().nextInt(end - start) + start; 58 | // swap,将随机选择的数字放到end角标上 59 | String temp = data[randomIndex]; 60 | data[randomIndex] = data[end]; 61 | data[end] = temp; 62 | 63 | // small 表示交换到前面的元素,最后一个元素的角标 64 | int small = start - 1; 65 | for (int i = start; i < end; i++) { 66 | if ((data[i] + data[end]).compareTo(data[end] + data[i]) < 0) { 67 | small++; 68 | if (small != i) { 69 | // swap,将small和i位置的元素进行互换 70 | temp = data[small]; 71 | data[small] = data[i]; 72 | data[i] = temp; 73 | } 74 | } 75 | } 76 | small++; 77 | // 还原位置 78 | temp = data[small]; 79 | data[small] = data[end]; 80 | data[end] = temp; 81 | return small; 82 | } 83 | 84 | public static void main(String[] args) { 85 | // int[] nums = new int[]{10, 2}; 86 | int[] nums = new int[]{3, 30, 34, 5, 9}; 87 | String result = minNumber(nums); 88 | System.out.println(result); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question18/DeleteNodeO1.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question18; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof/ 7 | * 剑指 Offer 18. 在O(1)时间删除链表结点 8 | * @Author tinytongtong 9 | * @Date 2020/9/7 11:26 AM 10 | * @Version 11 | */ 12 | public class DeleteNodeO1 { 13 | /** 14 | * Definition for singly-linked list. 15 | */ 16 | private static class ListNode { 17 | int val; 18 | ListNode next; 19 | 20 | public ListNode(int val) { 21 | this.val = val; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "ListNode{" + 27 | "val=" + val + 28 | ", next=" + next + 29 | '}'; 30 | } 31 | 32 | @Override 33 | public boolean equals(Object o) { 34 | if (this == o) return true; 35 | if (!(o instanceof ListNode)) return false; 36 | ListNode listNode = (ListNode) o; 37 | return val == listNode.val; 38 | } 39 | 40 | @Override 41 | public int hashCode() { 42 | return Objects.hash(val); 43 | } 44 | } 45 | 46 | /** 47 | * 分三种情况: 48 | * ①如果pToBeDelete不是尾节点,就删除它。将它下一个节点的值赋值给pToBeDelete,同时pToBeDelete.next执行pToBeDelete.next.next 49 | * ②如果pToBeDelete是尾节点,则只能从头遍历,找到上一个pToBeDelete的上一个节点 50 | * ③如果pToBeDelete就是pHead,则将pHead置为null即可 51 | * 52 | * @param pHead 53 | * @param pToBeDelete 54 | */ 55 | private static ListNode deleteNode(ListNode pHead, ListNode pToBeDelete) { 56 | if (pHead == null || pToBeDelete == null) { 57 | return null; 58 | } 59 | // 情况① 60 | if (pToBeDelete.next != null) { 61 | ListNode pNext = pToBeDelete.next; 62 | pToBeDelete.val = pNext.val; 63 | pToBeDelete.next = pNext.next; 64 | pNext = null; 65 | } else if (pHead == pToBeDelete) { // 情况③ 66 | pHead = null; 67 | pToBeDelete = null; 68 | } else {// 情况② 69 | ListNode pNode = pHead; 70 | while (pNode.next != pToBeDelete) { 71 | pNode = pNode.next; 72 | } 73 | pNode.next = null; 74 | pToBeDelete = null; 75 | } 76 | return pHead; 77 | } 78 | 79 | public static void main(String[] args) { 80 | ListNode pHead = new ListNode(1); 81 | ListNode pNode2 = new ListNode(2); 82 | ListNode pNode3 = new ListNode(3); 83 | ListNode pNode4 = new ListNode(4); 84 | ListNode pNode5 = new ListNode(5); 85 | pHead.next = pNode2; 86 | pNode2.next = pNode3; 87 | pNode3.next = pNode4; 88 | pNode4.next = pNode5; 89 | System.out.println(pHead); 90 | 91 | System.out.println(deleteNode(pHead, pNode5)); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question32/PrintTreeFromTopToBottomLevelFirstNode.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question32; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * @Description: 头条面试题 8 | * 从上到下打印二叉树,每层的第一个节点 9 | * 分层打印 10 | * @Author tinytongtong 11 | * @Date 2020/11/25 10:11 AM 12 | * @Version 13 | */ 14 | 15 | public class PrintTreeFromTopToBottomLevelFirstNode { 16 | private static class TreeNode { 17 | int val; 18 | TreeNode left; 19 | TreeNode right; 20 | 21 | public TreeNode(int val) { 22 | this.val = val; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "TreeNode{" + 28 | "val=" + val + 29 | ", left=" + left + 30 | ", right=" + right + 31 | '}'; 32 | } 33 | } 34 | 35 | /** 36 | * 打印每层第一个节点 37 | * 38 | * @param root 39 | * @return 40 | */ 41 | private static void printLevelFirstNode(TreeNode root) { 42 | if (root == null) { 43 | return; 44 | } 45 | // 1、分层打印 46 | // 2、打印每层第一个节点 47 | Queue queue = new LinkedList<>(); 48 | queue.add(root); 49 | // 下一层的节点数 50 | int nextLevel = 0; 51 | // 当前层中还没有打印的节点数 52 | int toBePrinted = 1;// 从root节点开始。 53 | // 打印左侧第一个节点 54 | System.out.println(queue.peek().val); 55 | while (!queue.isEmpty()) { 56 | TreeNode node = queue.poll(); 57 | if (node.left != null) { 58 | queue.add(node.left); 59 | nextLevel++; 60 | } 61 | if (node.right != null) { 62 | queue.add(node.right); 63 | nextLevel++; 64 | } 65 | toBePrinted--; 66 | if (toBePrinted == 0) { 67 | // 如果下一层没有结点,就不添加list了 68 | if (nextLevel > 0) { 69 | // 打印左侧第一个节点 70 | System.out.println(queue.peek().val); 71 | } 72 | toBePrinted = nextLevel; 73 | nextLevel = 0; 74 | } 75 | } 76 | } 77 | 78 | public static void main(String[] args) { 79 | TreeNode pRoot1 = new TreeNode(1); 80 | TreeNode pNode11 = new TreeNode(2); 81 | TreeNode pRoot12 = new TreeNode(3); 82 | pRoot1.left = pNode11; 83 | pRoot1.right = pRoot12; 84 | 85 | TreeNode pNode21 = new TreeNode(4); 86 | TreeNode pRoot22 = new TreeNode(5); 87 | pNode11.left = pNode21; 88 | pNode11.right = pRoot22; 89 | 90 | TreeNode pNode23 = new TreeNode(6); 91 | TreeNode pRoot24 = new TreeNode(7); 92 | pRoot12.left = pNode23; 93 | pRoot12.right = pRoot24; 94 | System.out.println(pRoot1); 95 | System.out.println("————————————————————————————"); 96 | printLevelFirstNode(pRoot1); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question36/TreeToDoublyList.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question36; 2 | 3 | /** 4 | * @Description: https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/ 5 | * 剑指 Offer 36. 二叉搜索树与双向链表 6 | * @Author tinytongtong 7 | * @Date 2020/9/9 9:43 PM 8 | * @Version 9 | */ 10 | public class TreeToDoublyList { 11 | private static class Node { 12 | int val; 13 | Node left; 14 | Node right; 15 | 16 | public Node(int val) { 17 | this.val = val; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "Node{" + 23 | "val=" + val + 24 | ", left=" + left + 25 | ", right=" + right + 26 | '}'; 27 | } 28 | } 29 | 30 | private static Node treeToDoublyList(Node root) { 31 | if (root == null) { 32 | return null; 33 | } 34 | // 最后一个节点 35 | Node[] pLast = new Node[1]; 36 | midOrder(root, pLast); 37 | // 获取首节点 38 | while (pLast[0] != null && pLast[0].left != null) { 39 | pLast[0] = pLast[0].left; 40 | } 41 | return pLast[0]; 42 | } 43 | 44 | private static void midOrder(Node root, Node[] pLast) { 45 | if (root == null) { 46 | return; 47 | } 48 | Node pCurrent = root; 49 | // 遍历左子节点 50 | if (pCurrent.left != null) { 51 | midOrder(pCurrent.left, pLast); 52 | } 53 | // 链接左子节点和中间节点 54 | pCurrent.left = pLast[0]; 55 | if (pLast[0] != null) { 56 | pLast[0].right = pCurrent; 57 | } 58 | // 中间节点 59 | System.out.println(pCurrent.val); 60 | // 链接中间节点 61 | pLast[0] = pCurrent; 62 | // 遍历右子节点 63 | if (pCurrent.right != null) { 64 | midOrder(pCurrent.right, pLast); 65 | } 66 | } 67 | 68 | public static void main(String[] args) { 69 | Node root = new Node(10); 70 | Node node11 = new Node(6); 71 | Node node12 = new Node(14); 72 | root.left = node11; 73 | root.right = node12; 74 | Node node21 = new Node(4); 75 | Node node22 = new Node(8); 76 | node11.left = node21; 77 | node11.right = node22; 78 | Node node23 = new Node(12); 79 | Node node24 = new Node(16); 80 | node12.left = node23; 81 | node12.right = node24; 82 | 83 | System.out.println(root); 84 | Node result = treeToDoublyList(root); 85 | System.out.println("从小到大:"); 86 | Node pLast = null; 87 | while (result != null) { 88 | System.out.println(result.val); 89 | pLast = result; 90 | result = result.right; 91 | } 92 | System.out.println("从大到小:"); 93 | while (pLast != null) { 94 | System.out.println(pLast.val); 95 | pLast = pLast.left; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question07/RebuildBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question07; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @Description: https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/ 7 | * 剑指 Offer 07. 重建二叉树 8 | * @Author tinytongtong 9 | * @Date 2020/9/4 10:31 AM 10 | * @Version 11 | */ 12 | public class RebuildBinaryTree { 13 | private static class TreeNode { 14 | int val; 15 | TreeNode left; 16 | TreeNode right; 17 | 18 | public TreeNode(int val) { 19 | this.val = val; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "TreeNode{" + 25 | "val=" + val + 26 | ", left=" + left + 27 | ", right=" + right + 28 | '}'; 29 | } 30 | } 31 | 32 | /** 33 | * 迭代实现 34 | * 时间复杂度O(nlogn) 35 | * 空间复杂度O(n) 36 | * 37 | * @param preorder 38 | * @param inorder 39 | * @return 40 | */ 41 | private static TreeNode rebuildTree(int[] preorder, int[] inorder) { 42 | if (preorder == null || inorder == null) { 43 | return null; 44 | } 45 | // 利用HashMap定位 46 | HashMap map = new HashMap<>(); 47 | for (int i = 0; i < inorder.length; i++) { 48 | map.put(inorder[i], i); 49 | } 50 | 51 | TreeNode root = buildNode(map, preorder, inorder, 0, preorder.length - 1, 0, preorder.length - 1); 52 | return root; 53 | } 54 | 55 | /** 56 | * 构建根节点,构建左子树,构建右子树 57 | * 58 | * @param preorder 59 | * @param inorder 60 | * @param startPre 61 | * @param endPre 62 | * @param startIn 63 | * @param endIn 64 | * @return 65 | */ 66 | private static TreeNode buildNode(HashMap map, int[] preorder, int[] inorder, int startPre, int endPre, int startIn, int endIn) { 67 | if (startPre > endPre || startPre < 0 || endPre >= preorder.length || startIn < 0 || endIn >= preorder.length) { 68 | return null; 69 | } 70 | // 只有一个结点 71 | if (startPre == endPre) { 72 | return new TreeNode(preorder[startPre]); 73 | } 74 | TreeNode root = new TreeNode(preorder[startPre]); 75 | // 或取根节点在中序遍历数组中的角标 76 | int rootIndex = map.get(preorder[startPre]); 77 | int leftCount = rootIndex - startIn; 78 | // 左节点 79 | root.left = buildNode(map, preorder, inorder, startPre + 1, startPre + leftCount, startIn, rootIndex - 1); 80 | // 有节点 81 | root.right = buildNode(map, preorder, inorder, startPre + leftCount + 1, endPre, rootIndex + 1, endIn); 82 | return root; 83 | } 84 | 85 | public static void main(String[] args) { 86 | int[] preorder = new int[]{3, 9, 20, 15, 7}; 87 | int[] inorder = new int[]{9, 3, 15, 20, 7}; 88 | TreeNode result = rebuildTree(preorder, inorder); 89 | System.out.println(result); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question27/MirrorBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question27; 2 | 3 | 4 | import java.util.Stack; 5 | 6 | /** 7 | * @Description: https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/ 8 | * 剑指 Offer 27. 二叉树的镜像 9 | * @Author tinytongtong 10 | * @Date 2020/9/8 5:07 PM 11 | * @Version 12 | */ 13 | public class MirrorBinaryTree { 14 | private static class TreeNode { 15 | int val; 16 | TreeNode left; 17 | TreeNode right; 18 | 19 | public TreeNode(int val) { 20 | this.val = val; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "TreeNode{" + 26 | "val=" + val + 27 | ", left=" + left + 28 | ", right=" + right + 29 | '}'; 30 | } 31 | } 32 | 33 | /** 34 | * 递归解法 35 | * 36 | * @param root 37 | * @return 38 | */ 39 | private static TreeNode mirrorTreeByRecursive(TreeNode root) { 40 | if (root == null) { 41 | return null; 42 | } 43 | TreeNode temp = root.left; 44 | root.left = root.right; 45 | root.right = temp; 46 | mirrorTreeByRecursive(root.left); 47 | mirrorTreeByRecursive(root.right); 48 | return root; 49 | } 50 | 51 | /** 52 | * 迭代解法 53 | * 54 | * @param root 55 | * @return 56 | */ 57 | private static TreeNode mirrorTreeByIteration(TreeNode root) { 58 | if (root == null) { 59 | return null; 60 | } 61 | Stack stack = new Stack<>(); 62 | stack.push(root); 63 | while (!stack.isEmpty()) { 64 | TreeNode node = stack.pop(); 65 | // swap 66 | TreeNode temp = node.left; 67 | node.left = node.right; 68 | node.right = temp; 69 | if (node.left != null) { 70 | stack.push(node.left); 71 | } 72 | if (node.right != null) { 73 | stack.push(node.right); 74 | } 75 | } 76 | return root; 77 | } 78 | 79 | public static void main(String[] args) { 80 | TreeNode pRoot1 = new TreeNode(8); 81 | TreeNode pNode11 = new TreeNode(6); 82 | TreeNode pRoot12 = new TreeNode(10); 83 | pRoot1.left = pNode11; 84 | pRoot1.right = pRoot12; 85 | 86 | TreeNode pNode21 = new TreeNode(5); 87 | TreeNode pRoot22 = new TreeNode(7); 88 | pNode11.left = pNode21; 89 | pNode11.right = pRoot22; 90 | 91 | TreeNode pNode23 = new TreeNode(9); 92 | TreeNode pRoot24 = new TreeNode(11); 93 | pRoot12.left = pNode23; 94 | pRoot12.right = pRoot24; 95 | 96 | System.out.println(pRoot1); 97 | // 递归 98 | // System.out.println(mirrorTreeByRecursive(pRoot1)); 99 | // 迭代 100 | System.out.println(mirrorTreeByIteration(pRoot1)); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/question/question_0105/BuildTreeFromPreOrderAndInOrder.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.question.question_0105; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * @Description: 105. 从前序与中序遍历序列构造二叉树 7 | * https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 8 | * @Author wangjianzhou 9 | * @Date 2022/2/23 5:23 PM 10 | */ 11 | public class BuildTreeFromPreOrderAndInOrder { 12 | 13 | public static void main(String[] args) { 14 | int[] preorder = new int[]{1, 2, 3}; 15 | int[] inorder = new int[]{2, 3, 1}; 16 | BuildTreeFromPreOrderAndInOrder buildTree = new BuildTreeFromPreOrderAndInOrder(); 17 | TreeNode tree = buildTree.buildTree(preorder, inorder); 18 | buildTree.logTree(tree); 19 | } 20 | 21 | private TreeNode buildTree(int[] preorder, int[] inorder) { 22 | return buildNode(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1); 23 | } 24 | 25 | private TreeNode buildNode(int[] preorder, int[] inorder, int preStart, int preEnd, int inStart, int inEnd) { 26 | if (preStart > preEnd || inStart > inEnd || preStart < 0 || preEnd >= preorder.length 27 | || inStart < 0 || inEnd >= inorder.length) return null; 28 | // 查找root的值。前序遍历的第一个数据就是 29 | int midNodeValue = preorder[preStart]; 30 | // 在中序遍历的数组中,找到root值的位置。借此区分出左子树的数据,进而区分右子树的数据。 31 | int midNodeIndex = inStart; 32 | for (int i = inStart; i <= inEnd; i++) { 33 | if (midNodeValue == inorder[i]) { 34 | midNodeIndex = i; 35 | break; 36 | } 37 | } 38 | int leftCount = midNodeIndex - inStart; 39 | TreeNode left = buildNode(preorder, inorder, preStart + 1, preStart + leftCount, inStart, inStart + leftCount - 1); 40 | TreeNode right = buildNode(preorder, inorder, preStart + leftCount + 1, preEnd, inStart + leftCount + 1, inEnd); 41 | TreeNode node = new TreeNode(midNodeValue, left, right); 42 | return node; 43 | } 44 | 45 | private void logTree(TreeNode tree) { 46 | ArrayList result = new ArrayList<>(); 47 | if (tree == null) { 48 | System.out.println(result); 49 | return; 50 | } 51 | logTreeCore(tree, result); 52 | System.out.println(result); 53 | } 54 | 55 | private void logTreeCore(TreeNode tree, ArrayList result) { 56 | if (tree == null) { 57 | result.add(null); 58 | return; 59 | } 60 | result.add(tree.val); 61 | logTreeCore(tree.left, result); 62 | logTreeCore(tree.right, result); 63 | } 64 | 65 | private static final class TreeNode { 66 | int val; 67 | TreeNode left; 68 | TreeNode right; 69 | 70 | TreeNode() { 71 | } 72 | 73 | TreeNode(int val) { 74 | this.val = val; 75 | } 76 | 77 | TreeNode(int val, TreeNode left, TreeNode right) { 78 | this.val = val; 79 | this.left = left; 80 | this.right = right; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question23/MeetingNodeInCycle1.java: -------------------------------------------------------------------------------- 1 | package com.tinytongtong.leetcodetest.targetoffer.question23; 2 | 3 | 4 | /** 5 | * @Description: 美团面试题:找到链表中环的入口节点,如果无环就返回空 6 | * @Author tinytongtong 7 | * @Date 2020/9/8 9:20 AM 8 | * @Version 9 | */ 10 | public class MeetingNodeInCycle1 { 11 | private static class ListNode { 12 | int val; 13 | ListNode next; 14 | 15 | public ListNode(int val) { 16 | this.val = val; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "ListNode{" + 22 | "val=" + val + 23 | '}'; 24 | } 25 | } 26 | 27 | private static ListNode entryNodeOfLoop(ListNode head) { 28 | // 1、先根据快慢指针确定是否有环。如果有环就找到一个环内节点,如果没有就返回null 29 | ListNode cycleNode = findCycleNode(head); 30 | // 无环 31 | if (cycleNode == null) { 32 | return null; 33 | } 34 | // 2、然后确定环的个数n。快慢指针,相遇的时候,慢指针走过的距离 35 | int n = countCycleNodeNum(cycleNode); 36 | // 3、然后两个指针P1和P2,均指向链表头部节点,P1先移动n,然后P1和P2以相同的速度前进,它两相遇的节点就是入口节点。 37 | ListNode p1 = head, p2 = head; 38 | while (n > 0) { 39 | p1 = p1.next; 40 | n--; 41 | } 42 | while (p1.val != p2.val) { 43 | p1 = p1.next; 44 | p2 = p2.next; 45 | } 46 | return p1; 47 | } 48 | 49 | /** 50 | * 判断链表是否有环,如果有,就返回环中的一个node; 51 | * 如果没有就返回null; 52 | * 53 | * @param head 54 | * @return 55 | */ 56 | private static ListNode findCycleNode(ListNode head) { 57 | if (head == null) { 58 | return null; 59 | } 60 | ListNode slow = head, fast = head; 61 | while (slow != null && fast != null) { 62 | slow = slow.next; 63 | if (fast.next != null) { 64 | fast = fast.next.next; 65 | } else { // 无环 66 | return null; 67 | } 68 | if (slow != null && fast != null && slow.val == fast.val) { 69 | return fast; 70 | } 71 | } 72 | return null; 73 | } 74 | 75 | /** 76 | * 统计环形链表中环的个数 77 | * 78 | * @param node 79 | * @return 80 | */ 81 | private static int countCycleNodeNum(ListNode node) { 82 | if (node == null) { 83 | return 0; 84 | } 85 | int n = 1; 86 | ListNode slow = node.next; 87 | ListNode fast = node.next.next; 88 | while (slow.val != fast.val) { 89 | slow = slow.next; 90 | fast = fast.next.next; 91 | n++; 92 | } 93 | return n; 94 | } 95 | 96 | public static void main(String[] args) { 97 | ListNode pHead = new ListNode(1); 98 | ListNode pNode2 = new ListNode(2); 99 | ListNode pNode3 = new ListNode(3); 100 | ListNode pNode4 = new ListNode(4); 101 | ListNode pNode5 = new ListNode(5); 102 | pHead.next = pNode2; 103 | pNode2.next = pNode3; 104 | pNode3.next = pNode4; 105 | pNode4.next = pNode5; 106 | pNode5.next = pNode5; 107 | System.out.println(pHead); 108 | 109 | System.out.println(entryNodeOfLoop(pHead)); 110 | } 111 | } 112 | --------------------------------------------------------------------------------