思路很牛B!既然我们要得到最长的consecutive序列,那其实逆向思维,任何一个连续序列,只要选中了上面的一个点,一直往左还是往右延伸都可以得到这个序列的长度,所以可以随意选择。那么先构建一个set存放所有值,而且 即使不存放duplicate也不影响最后结果。
最好要注意的是,set和 iterator的基本用法:
Set.isEmpty() (这个和list.isEmpty() 一样啊,都是继承自父类的)
Set.contains(); // 也是和list.contains(); 一样继承自父类。
然后有专门的一个类Iterator,这个类是可以通过具体的 collections类型来定的,直接call这个类的iterator()方法就可以得到实例化的 iter了。
有了iter,就相当于c++的指针指向array/list的起始地址!!是地址不是元素。所以通过iter.next()就可以得到下一个元素的object。然后要将这个类进行强制转型。
具体代码如下:
class Solution {
public int longestConsecutive(int[] nums) {
if(nums.length==0) return 0;
HashSet<Integer> numberSet = new HashSet<Integer>();
for(int num: nums) numberSet.add(num);
int longestLen=1;
while(!numberSet.isEmpty()){
Iterator iterator=numberSet.iterator();
int currLen=1;
int startNum= (Integer)iterator.next(); // contains(), NOT has()
numberSet.remove(startNum);
int goingSmaller=startNum;
while(numberSet.contains(goingSmaller-1)){
numberSet.remove(goingSmaller-1);
goingSmaller--;
currLen++;
}
int goingLarger=startNum;
while(numberSet.contains(goingLarger+1)){
numberSet.remove(goingLarger+1);
goingLarger++;
currLen++;
}
longestLen=Math.max(longestLen, currLen);
}
return longestLen;
}
}
// bug: Line 10: error: incompatible types: Object cannot be converted to int
// 反应了自己对iterator的不熟练,用iterator遍历无序set,就靠iterator,要进行遍历操作,就要进行几个基本操作:
// 1, 通过call实例化的set的iterator()方法得到iterator: Iterator iterator = mySet.iterator();
// 2, 通过iterator来进行遍历,结合两个方法: hasNext(), next(),
// while(iterator.hasNext()) { Object obj = iterator.next(); } // 注意了!!这个时候 next() 返回的是Object这个顶端父类,要想得到具体的Integer或String,要进行向下转型,因此要在前面加上 parse的方法。(Integer)iterator.next();就解决了Line10的问题。 同时next() 不仅返回了Object,而且还自己把iterator移动到下一个object,这跟iterator的具体实现有关,就不深究了。
// 总之,这里就是用空间换时间。使用了set来存储所有的数字,然后只需要向左向右连续查询看是否存在既可。其实也没有什么算法,或者说通过set这种问题的转变来带来算法上时间的改进。
// TODO: N*logN 排序后,怎么遍历一次得到最长串呢?如果处理duplicate的问题呢? 上面这个算法成功避免了duplicates问题,直接查寻下一个目标,而不是访问下一个,看是否符合期望。前者是主动的,后者是被动的。这样也许更容易记住这个问题。