From 69049a5e86ab18e71e41be44ea236d0156fdceae Mon Sep 17 00:00:00 2001 From: markilue <745518019@qq.com> Date: Sun, 12 Mar 2023 13:27:37 +0800 Subject: [PATCH] =?UTF-8?q?leecode=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hot100/T50_LongestConsecutive.java | 88 +++++++++++++++ .../leecode/hot100/T51_SingleNumber.java | 58 ++++++++++ .../leecode/hot100/T52_WordBreak.java | 104 ++++++++++++++++++ .../markilue/leecode/hot100/T53_HasCycle.java | 41 +++++++ .../leecode/hot100/T54_DetectCycle.java | 54 +++++++++ 5 files changed, 345 insertions(+) create mode 100644 Leecode/src/main/java/com/markilue/leecode/hot100/T50_LongestConsecutive.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/hot100/T51_SingleNumber.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/hot100/T52_WordBreak.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/hot100/T53_HasCycle.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/hot100/T54_DetectCycle.java diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T50_LongestConsecutive.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T50_LongestConsecutive.java new file mode 100644 index 0000000..ad77eb2 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T50_LongestConsecutive.java @@ -0,0 +1,88 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-03-12 10:58 + *@Description: + * TODO 力扣128题 最长连续序列: + * 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 + * 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 + *@Version: 1.0 + */ +public class T50_LongestConsecutive { + + @Test + public void test() { + int[] nums = {}; + System.out.println(longestConsecutive(nums)); + } + + /** + * 思路:排序后连续,但是时间复杂度O(n) + * 速度击败99.86% 内存击败91.74% 11ms + * @param nums + * @return + */ + public int longestConsecutive(int[] nums) { + if (nums == null || nums.length == 0) return 0; + + Arrays.sort(nums); + + int max = 1; + int cur = 1; + + for (int i = 1; i < nums.length; i++) { + if (nums[i] == nums[i - 1] + 1) { + cur++; + } else if (nums[i] == nums[i - 1]) { + continue; + } else { + cur = 1; + } + if (cur > max) max = cur; + } + + return max; + + } + + + /** + * 官方题解:哈希表 时间复杂度O(n) + * 速度击败78.83% 内存击败28.14% 19ms + * @param nums + * @return + */ + public int longestConsecutive1(int[] nums) { + Set num_set = new HashSet(); + for (int num : nums) { + num_set.add(num); + } + + int longestStreak = 0; + + for (int num : num_set) { + if (!num_set.contains(num - 1)) { + int currentNum = num; + int currentStreak = 1; + + while (num_set.contains(currentNum + 1)) { + currentNum += 1; + currentStreak += 1; + } + + longestStreak = Math.max(longestStreak, currentStreak); + } + } + + return longestStreak; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T51_SingleNumber.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T51_SingleNumber.java new file mode 100644 index 0000000..017c055 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T51_SingleNumber.java @@ -0,0 +1,58 @@ +package com.markilue.leecode.hot100; + +import java.util.HashSet; +import java.util.Set; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-03-12 11:25 + *@Description: + * TODO 力扣136题 只出现一次的数字: + * 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 + * 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 + *@Version: 1.0 + */ +public class T51_SingleNumber { + + /** + * 思路:使用hashset去重,最后还在hashset中的就是剩下的 + * 速度击败19.56% 内存击败46.55% 10ms + * @param nums + * @return + */ + public int singleNumber(int[] nums) { + + Set set = new HashSet<>(); + + for (int num : nums) { + if (set.contains(num)) { + set.remove(num); + } else { + set.add(num); + } + } + int result = 0; + for (Integer integer : set) { + result = integer; + } + return result; + } + + + /** + * 官方思路:位运算去重 + * 速度击败99.99% 内存击败44.28% 1ms + * @param nums + * @return + */ + public int singleNumber1(int[] nums) { + + int singleNumber = 0; + for (int num : nums) { + singleNumber = singleNumber ^ num; + } + return singleNumber; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T52_WordBreak.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T52_WordBreak.java new file mode 100644 index 0000000..5041bb2 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T52_WordBreak.java @@ -0,0 +1,104 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-03-12 11:44 + *@Description: + * TODO 力扣139题 单词拆分: + * 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 + * 注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 + *@Version: 1.0 + */ +public class T52_WordBreak { + + @Test + public void test() { + String s = "leetcode"; + List dict = Arrays.asList("leet", "code"); + System.out.println(wordBreak(s, dict)); + } + + + /** + * 思路:动态规划法,依次判断当前位置能否使用word拼接出来 + * 速度击败88.38% 内存击败89.96% + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak(String s, List wordDict) { + + boolean[] dp = new boolean[s.length() + 1]; + dp[0] = true; + for (int i = 1; i < dp.length; i++) { + for (int j = 0; j < wordDict.size(); j++) { + String word = wordDict.get(j); + int length = word.length(); + if (i >= length) dp[i] |= dp[i - length] && word.equals(s.substring(i - length, i)); + if (dp[i]) break; + } + } + + return dp[s.length()]; + + + } + + + /** + * 以前的一些写法:本质上类似,但是if变简单了,不需要次次都判断了,直接dp[i]=true + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak1(String s, List wordDict) { + boolean[] dp = new boolean[s.length() + 1]; + dp[0] = true; + + for (int i = 1; i <= s.length(); i++) { + for (String word : wordDict) { + int len = word.length(); + if (i >= len && dp[i - len] && word.equals(s.substring(i - len, i))) { + dp[i] = true;// + break; + } + } + } + + return dp[s.length()]; + } + + /** + * 官方最快:回溯+记忆化搜索 + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak2(String s, List wordDict) { + int[] memo = new int[s.length()]; + Arrays.fill(memo, -1); + return check(s, 0, wordDict, memo); + } + + private boolean check(String s, int idx, List wordDict, int[] memo) { + if (idx == s.length()) return true; + if (memo[idx] != -1) return memo[idx] != 0;//记忆化回溯 + for (String word : wordDict) + if (s.startsWith(word, idx) && check(s, idx + word.length(), wordDict, memo)) {//找到了,就check后面行不行 + memo[idx] = 1;//找到了 + return true; + } + //没找到 + memo[idx] = 0; + return false; + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T53_HasCycle.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T53_HasCycle.java new file mode 100644 index 0000000..daa734d --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T53_HasCycle.java @@ -0,0 +1,41 @@ +package com.markilue.leecode.hot100; + +import com.markilue.leecode.listnode.ListNode; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-03-12 12:20 + *@Description: + * TODO 力扣141 环形链表: + * 给你一个链表的头节点 head ,判断链表中是否有环。 + * 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 + * 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 + * 注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。 + * 如果链表中存在环 ,则返回 true 。 否则,返回 false 。 + *@Version: 1.0 + */ +public class T53_HasCycle { + + /** + * 思路:简单题 快慢指针 一个走一步,一个走两步,如果有环则一定相遇 + * 速度击败100% 内存击败74.13% 0ms + * @param head + * @return + */ + public boolean hasCycle(ListNode head) { + + ListNode fast = head; + ListNode slow = head; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + if (fast == slow) return true; + } + + return false; + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T54_DetectCycle.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T54_DetectCycle.java new file mode 100644 index 0000000..115ca28 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T54_DetectCycle.java @@ -0,0 +1,54 @@ +package com.markilue.leecode.hot100; + +import com.markilue.leecode.listnode.ListNode; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-03-12 12:34 + *@Description: + * TODO 力扣142题 环形链表II: + * 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 + * 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 + * 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 + * 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 + * 不允许修改 链表。 + *@Version: 1.0 + */ +public class T54_DetectCycle { + + + /** + * 思路:快慢指针法,先相遇,再让他走x步和从头出发的相遇 + * 速度击败100% 内存击败68.41% + * @param head + * @return + */ + public ListNode detectCycle(ListNode head) { + + ListNode fast = head; + ListNode slow = head; + + while (fast != null && fast.next != null) { + //有环则一定不会等于null + fast = fast.next.next; + slow = slow.next; + + if (fast == slow) { + //两者相遇了 + //从头出发一个,从相遇位置出发一个 + ListNode start = head; + ListNode meet = fast; + while (start != meet) { + start = start.next; + meet = meet.next; + } + return meet; + } + } + + return null;//没有相遇 + + } +}