Array(10) -- Insert Interval, Merge Intervals, Trapping Rain Water, Next Permutation

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.

首尾双指针,如果左边的比较小, 则先把左边的水灌满,因为左边小于右边,因此左边的水位高度一定是maxLeft, 则当前bar的积水为maxLeft - height[left];右边同理。最后双指针一定会停留在最高的bar处。

    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());
    }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值