128. Longest Consecutive Sequence
Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
For example,
Given [100, 4, 200, 1, 3, 2]
,
The longest consecutive elements sequence is [1, 2, 3, 4]
. Return its length: 4
.
Your algorithm should run in O(n) complexity.
思路一:In this method, it iterates through the array while maintaining a HashMap whose key is the distinct numbers in input array and value is so far the longest consecutive subsequence starting at the number in key. We only update non-duplicate numbers and the newly added number joints its left consecutive subsequence and right consecutive subsequence to update the maximum length.
class Solution {
public int longestConsecutive(int[] nums) {
int result = 0;
HashMap<Integer,Integer> map = new HashMap<Integer,Integer> ();
for(int num : nums) {
if(!map.containsKey(num)) {
int left = 0, right = 0, sum = 0;
if(map.containsKey(num - 1)) left = map.get(num - 1);
if(map.containsKey(num + 1)) right = map.get(num + 1);
sum = left + right + 1;
map.put(num, 1);
result = Math.max(result, sum);
map.put(num - left, sum); //update both ends
map.put(num + right, sum);
}else
continue; //only care about non-duplicate elements
}
return result;
}
}
思路二:this method uses HashSet and has less interaction with the hash structure, making it a little bit faster. It firstly iterates through the array and store all distinct numbers in HashSet and then iterates the array again to remove all consecutive subsequence while updating the longest length.
class Solution {
public int longestConsecutive(int[] nums) {
int res = 0;
Set<Integer> s = new HashSet<Integer>();
for (int num : nums) s.add(num);
for (int num : nums) {
if (s.remove(num)) {
int pre = num - 1, next = num + 1;
while (s.remove(pre)) --pre;
while (s.remove(next)) ++next;
res = Math.max(res, next - pre - 1);
}
}
return res;
}
}
经验教训: 由于之前做过很多用到假哈希表(int[ ] map)的题,第一反应是创建一个数组map存储所有出现过的元素,但是码完发现这个方法根本无法应对数组长度越界的问题:在java中,array的最大长度在Integer.MAX_VALUE附近,因此若原题中未出现对数据范围的限定,数组map一般是不可以使用的。此外,在实现这两个方法时,有些边界问题十分容易出错,后来发现在纸上写写画画一些小规模的问题十分有助于梳理整个过程。
56. Merge Intervals
Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18]
,
return [1,6],[8,10],[15,18]
.
思路一:重写Comparator中的compare方法,再利用Collections.sort(<T>,comparator<T>) 对ADT进行排序,排序后依次融合所有交叠区间。
public List<Interval> merge(List<Interval> intervals) {
if(intervals.size() <= 1) return intervals;
List<Interval> result = new ArrayList<>();
Comparator comp = new Comparator<Interval>() { //overwrite the compare() method and instantiate a comparator obj
public int compare(Interval o1, Interval o2) {
return o1.start - o2.start;
}
};
Collections.sort(intervals, comp);
int maxReach = intervals.get(0).end, curPos = intervals.get(0).start;
for(int i = 0; i < intervals.size(); i ++) {
if(maxReach >= intervals.get(i).start) {
maxReach = Math.max(maxReach,intervals.get(i).end);
}
else {
result.add(new Interval(curPos,maxReach));
curPos = intervals.get(i).start;
maxReach = intervals.get(i).end;
}
}
result.add(new Interval(curPos,maxReach));
return result;
}
public boolean validPalindrome(String s) {
char [] chars = s.toCharArray();
int left = 0 , right = chars.length - 1 ;
while (left < right) {
if (chars[left] != chars[right]) {
return isPalindrome(chars, left + 1 , right) || isPalindrome(chars, left, right - 1 );
}
left++;
right--;
}
return true ;
}
public boolean isPalindrome(char[] chars, int start, int end) {
while (start < end) {
if (chars[start] != chars[end]) {
return false ;
}
start++;
end--;
}
return true ;
}
}
287.Find the Duplicate Number
思路一:这个是一道linkedlist有环如何找entry point的题:快指针每次走两步,慢指针每次走一步,等他们相遇时一定在环内。此时,立刻从起点再发一个慢指针,新旧慢指针下一的相遇即在环的entry point.题目的思考角度很新颖,但这个用linkedlist解array题的思路有很多限制条件,普适性较差。
class Solution {
public int findDuplicate(int[] nums) {
if(nums.length > 1) {
int slow = nums[0];
int fast = nums[nums[0]];
while(slow != fast) {
slow = nums[slow];
fast = nums[nums[fast]];
}
int meeter = 0;
while(meeter != slow) {
slow = nums[slow];
meeter = nums[meeter];
}
return slow;
}else
return -1;
}
}