leecode更新

This commit is contained in:
markilue 2023-03-12 13:27:37 +08:00
parent 4032d74f99
commit 69049a5e86
5 changed files with 345 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;//没有相遇
}
}