0
点赞
收藏
分享

微信扫一扫

【Android春招每日一练】(二十八) LeetCode Hot 5题

q松_松q 2022-02-15 阅读 72

文章目录

概览

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 。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JgkeXYOa-1644888846210)(D:\Typora\img\circularlinkedlist.png)]

输入: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 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E8WqmEG0-1644888846215)(D:\Typora\img\image-20220213150542996.png)]

//快慢指针
/*
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.复习前面知识点,总结算法模板框架。

举报

相关推荐

0 条评论