Insert Interval
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1:
Given intervals [1,3],[6,9]
, insert and merge [2,5]
in as [1,5],[6,9]
.
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16]
, insert and merge [4,9]
in as [1,2],[3,10],[12,16]
.
先使用二分查找找到newInterval的start和end的位置,然后重新逐一填充intervals;逐个push_back的方式比先erase再insert的方式要快一些。
//binary search of insert position
void findInsertPos(vector<Interval>& intervals, int target, int startInt, int endInt, int& newBound, int& rmIndex, bool findEnd){
int left = startInt;
int right = endInt;
if(left == intervals.size()){
newBound = target;
rmIndex = left;
return;
}
while(left < right){
int half = (left + right) / 2;
if(intervals[half].end > target) right = half;
else if(intervals[half].end == target){
left = half;
break;
}
else left = half + 1;
}
if(findEnd){ //if find end
if(target < intervals[left].start){ //target in leftside of interval
rmIndex = left;
newBound = target;
}
else{
rmIndex = left + 1;
newBound = max(intervals[left].end, target);
}
}else{
if(target <= intervals[left].end){
rmIndex = left;
newBound = max(intervals[left].start, target);
}
else{
newBound = target;
rmIndex = left + 1;
}
}
}
vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
vector<Interval> rst;
if(intervals.size() == 0) intervals.insert(intervals.begin(), newInterval);
else{
int newStart, newEnd; //start and end of new interval
int rmStart, rmEnd; //interval to remove
findInsertPos(intervals, newInterval.start, 0, intervals.size()-1, newStart, rmStart, false);
findInsertPos(intervals, newInterval.end, rmStart, intervals.size()-1, newEnd, rmEnd, true);
newInterval.start = newStart;
newInterval.end = newEnd;
int i = 0;
while (i < rmStart) rst.push_back(intervals[i++]);
rst.push_back(newInterval);
i = rmEnd;
while (i < intervals.size()) rst.push_back(intervals[i++]);
return rst;
// if(rmStart < rmEnd)
// intervals.erase(intervals.begin()+rmStart, intervals.begin()+rmEnd);
// intervals.insert(intervals.begin()+rmStart, newInterval);
}
return intervals;
}
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]
.
先将intervals按start的大小排序,如果下一interval的start小于上一interval的end,则代表可以进行merge
class Solution {
public:
struct interval_comp
{
bool operator() (const Interval& interv1, const Interval& interv2)
{
return (interv1.start < interv2.start);
}
};
vector<Interval> merge(vector<Interval>& intervals) {
vector<Interval> rst;
sort(intervals.begin(), intervals.end(), interval_comp());
if(intervals.size() < 2) return intervals;
int start = intervals[0].start;
int lastEnd = intervals[0].end;
for(int i = 1; i < intervals.size(); i++){
if(intervals[i].start <= lastEnd) lastEnd = max(intervals[i].end, lastEnd); //can merge
else{
Interval tmp(start, lastEnd);
rst.push_back(tmp);
start = intervals[i].start;
lastEnd = intervals[i].end;
}
if(i == intervals.size() - 1){
Interval tmp(start, lastEnd);
rst.push_back(tmp);
}
}
return rst;
}
};
Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1]
, return 6
.
int trap(vector<int>& height) {
int left = 0;
int right = height.size() - 1;
int maxLeft = 0, maxRight = 0;
int water = 0;
while(left < right){
if(height[left] < height[right]){
if(height[left] < maxLeft) water += maxLeft - height[left];
else maxLeft = height[left];
left++;
}else{
if(height[right] < maxRight) water += maxRight - height[right];
else maxRight = height[right];
right--;
}
}
return water;
}
Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
首先找到需要增加的位,如1,2,4,3,2,1 需要增加的位是2。增加某位需保证增加的幅度最小,即某位之后序列需是最小序列。因此将2后面的序列进行翻转,得到1,2,3,4;然后在这序列中找到大于2的最小的数,即3,将2,3交换,得到1,3,1,2,2,4
即使是同样的思路,实现方式不同也会导致性能差异。在减少一些赋值和比较操作之后,速度有提升。
void nextPermutation(vector<int>& nums) {
int i = nums.size() - 1;
while(i > 0 && nums[i] <= nums[i-1]) i--;
if(i > 0){
reverse(nums.begin()+i, nums.end());
int left = i, right = nums.size()-1;
while(left < right){
int half = (left+right) / 2;
if(nums[half] < nums[i-1]) left = half + 1;
else if(nums[half] == nums[i-1]){
while(nums[half] == nums[i-1]) half++;
left = half;
}
else right = half;
}
swap(nums[left], nums[i-1]);
}
else reverse(nums.begin(), nums.end());
}