LintCode 1636: Aerial Movie (双指针法典型题)

为缓解乘客飞行途中的无聊感,某航空公司决定在航班上播放两部电影。鉴于起飞和降落期间无法放映,公司需确保所选电影总时长不超过飞行时长减30分钟,并尽可能接近该数值。采用双指针法,从已排序的电影时长数组中高效选出最适配的一对。算法需考虑多种情况,包括总时长精确匹配和最接近但不超时的情况。
  1. Aerial Movie
    In order to prevent passengers from being too bored during the flight, LQ Airlines decided to play two movies during the flight. Since the movie cannot be played during the take-off and landing of the aircraft, LQ Airlines must ensure that the duration of the two movies to be less than or equal to the flight duration minus 30 minutes, and the total length of the two movies should be as long as possible. Now given t ,the flight duration(minutes), and array dur[],the length of movies. Please output the length of the two movies in order of length. If there are multiple groups of the same length, select the one which contains the longest single moive.It is guarantee that there is a least one solution.

Example
Given t=87,dur=[20,25,19,37],return[20,37]

Explanation:
87-30=57
20+25=45,57-45=12
20+19=39,57-39=19
20+37=57,57-57=0
25+19=44,57-44=13
25+37=62,57<62
19+37=56,57-56=1
Givent=67,dur=[20,17,19,18],return[17,20]

Explanation:
67-30=37
17+20=37,18+19=37
The longest movie in the first group is 20,and 19 in the second grouo, so output[17,20]
Notice
30<t<=1000
dur[i]<=1000
1<=len(dur)<=100000

解法:双指针法。

class Solution {
public:
    /**
     * @param t: the length of the flight
     * @param dur: the length of movies 
     * @return: output the lengths of two movies
     */
    vector<int> aerial_Movie(int t, vector<int> &dur) {
        int len = dur.size();
        sort(dur.begin(), dur.end());
        int target = t - 30;
        int p1 = 0, p2 = len - 1;
        int minGap = INT_MAX;
        vector<int> result(2, 0);
        
        while (p1 < p2) {
            int sum = dur[p1] + dur[p2];
            if (sum > target) {
                p2--;
            } else if (sum == target) {
                result[0] = dur[p1];
                result[1] = dur[p2];
                return result;
            } else {
                int gap = target - sum;
                if (minGap > gap) {
                    minGap = gap;
                    result[0] = dur[p1];
                    result[1] = dur[p2];
                }
                p1++;
            }
        } 
        return result;
    }
};

二刷:

class Solution {
public:
    /**
     * @param t: the length of the flight
     * @param dur: the length of movies 
     * @return: output the lengths of two movies
     */
    vector<int> aerialMovie(int t, vector<int> &dur) {
        int n = dur.size();
        sort(dur.begin(), dur.end());
        int target = t - 30;
        int left = 0, right = n - 1;
        int minDiff = INT_MAX, minLeft = -1, minRight = -1;
        while (left < right) {
            int sum = dur[left] + dur[right];
            if (sum < target) {
                int diff = target - sum;
                if (diff < minDiff) {
                    minDiff = diff;
                    minLeft = left;
                    minRight = right;
                } else if (minDiff == diff) {
                    if (right >= minRight) {
                        minLeft = left;
                        minRight = right;
                    }
                }
                left++;
            } else if (sum > target) {
                right--;
            } else {
                if (minDiff > 0) {
                    minDiff = 0;
                    minLeft = left;
                    minRight = right;
                }
                left++;
                right--;
            }
        }
        return {dur[minLeft], dur[minRight]};
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值