leecode更新
This commit is contained in:
parent
4032d74f99
commit
69049a5e86
|
|
@ -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<Integer> num_set = new HashSet<Integer>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Integer> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String> 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<String> 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<String> 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<String> 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<String> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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;//没有相遇
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue