文章目录
概览
LeetCode Hot:最长连续序列、只出现一次的数字、单词拆分、环形链表、环形链表 II
LeetCode Hot
2.46 最长连续序列
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
//使用Hash集合
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int x:nums){
set.add(x);
}
int longest = 0,curNum,curLen = 0;
for(int x:nums){
if(!set.contains(x-1)){ //关键
curNum = x;
curLen = 1;
while(set.contains(curNum+1)){
curNum++;
curLen++;
}
}
longest = Math.max(longest,curLen);
}
return longest;
}
}
2.47 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
//异或
//异或运算满足交换律,a^b^a=a^a^b=b,因此res相当于nums[0]^nums[1]^nums[2]^nums[3]^nums[4]..... 然后再根据交换律把相等的合并到一块儿进行异或(结果为0),然后再与只出现过一次的元素进行异或,这样最后的结果就是,只出现过一次的元素(0^任意值=任意值)
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for(int x:nums){
res ^= x;
}
return res;
}
}
2.48 单词拆分
给你一个字符串 s
和一个字符串列表 wordDict
作为字典。请你判断是否可以利用字典中出现的单词拼接出 s
。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。
//DP
//定义dp[i] 表示字符串s前i个字符组成的字符串 s[0..i−1] 是否能被空格拆分成若干个字典中出现的单词
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
int len = s.length(), maxw = 0;
boolean[] dp = new boolean[len + 1];
dp[0] = true;
Set<String> set = new HashSet();
for(String str : wordDict){
set.add(str);
maxw = Math.max(maxw, str.length());
}
for(int i = 1; i < len + 1; i++){
for(int j = i; j >= 0 && j >= i - maxw; j--){
if(dp[j] && set.contains(s.substring(j, i))){ //dp[i]只需要往前探索到词典里最长的单词即可
dp[i] = true;
break;
}
}
}
return dp[len];
}
}
2.49 环形链表
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
//快慢指针
public boolean hasCycle(ListNode head) {
ListNode fast = head, slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) { // 在指针移动后再比较,排除初始都指向头结点的情况
return true;
}
}
return false;
}
2.50 环形链表 II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
//快慢指针
/*
1.第一次相遇,slow = nb
2.a+nb = 入口点
3.slow再走a = 入口 = head走到入口 = a
4.由3得出,起始距离入口 = 第一次相遇位置 + a
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow = head;
while (true) {
if (fast == null || fast.next == null) return null;
fast = fast.next.next;
slow = slow.next;
if (fast == slow) break;
}
fast = head; //第一次相遇后,slow走了nb步,只需要再走a步即入口,此时让fast移动到head,再次相遇即走了a步
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return fast;
}
}
总结
1.复习前面知识点,总结算法模板框架。