128. 最长连续序列
一、题目
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
二、思路
所有在一个连续区间的元素都会在一个连通分量中,且该连通分量的根节点为该连续区间中的最大值
- 遍历数组,如果nums[i]+1存在,将nums[i]加入nums[i]+1所在的连通分量中
- 重新遍历数组,通过
find
函数找到nums[i]所在分量的根节点,也就是其所在连续区间的最大值,从而求出连续区间的长度
三、代码
class UnionFind { /** * 记录每个节点的父节点 */ private Map<Integer, Integer> parent; public UnionFind(int[] nums) { parent = new HashMap<>(); for (int num : nums) { // 初始化父节点为自身 parent.put(num, num); } } /** * 寻找x的父节点,实际上也就是x的最远连续右边界,也就是其所在连续区间的最大值 * @param x * @return */ public Integer find(int x) { if (!parent.containsKey(x)) { return null; } while (x != parent.get(x)) { // 路径压缩 parent.put(x, parent.get(parent.get(x))); x = parent.get(x); } return x; } /** * 合并两个连通分量,在本题中只用来将num并入到num+1的连续区间中 * @param x * @param y */ public void union(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX == rootY) { return ; } // 将num所在树的根节点设置为num+1所在树的根节点 parent.put(rootX, rootY); } } class Solution { public int longestConsecutive(int[] nums) { UnionFind uf = new UnionFind(nums); int ans = 0; for (int num : nums) { // 当num+1存在,将num合并到num+1所在集合中 if (uf.find(num + 1) != null) { uf.union(num, num + 1); } } for (int num : nums) { // 找到num的最远连续右边界,也就是其所在连续区间的最大值 int right = uf.find(num); ans = Math.max(ans, right - num + 1); } return ans; } }
四、分析
- 时间复杂度:O(n),路径压缩后的并查集时间复杂度近似为O(1)
- 空间复杂度:O(n)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了