Leetcode:区间题型

238 阅读2分钟

56. 合并区间

public int[][] merge(int[][] intervals) {
    // 排序
    Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);
    List<int[]> result = new ArrayList<>();

    for (int[] currInterval : intervals) {
        if (result.isEmpty()) {
            result.add(currInterval);
            continue;
        }

        int[] lastInterval = result.get(result.size() - 1);
        if (lastInterval[1] >= currInterval[0]) {
            lastInterval[1] = Math.max(lastInterval[1], currInterval[1]);
        } else {
            result.add(currInterval);
        }
    }

    return result.toArray(new int[result.size()][2]);

}

57. 插入区间

public:
    vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
         vector<vector<int>> result;
            for (auto currInterval: intervals) {
                if (currInterval[1] < newInterval[0]) {
                    result.push_back(currInterval);
                    continue;
                }
                // 开始合并区间
                if (currInterval[0] > newInterval[1]) {
                    result.push_back(newInterval);
                    newInterval = currInterval;
                    continue;
                }
                if (currInterval[1] >= newInterval[0] ||
                    currInterval[0] <= newInterval[1]) {
                    // 替换开始时间
                    newInterval[0] = min(currInterval[0], newInterval[0]);
                    newInterval[1] = max(newInterval[1], currInterval[1]);
                    continue;
                }

            }

            result.push_back(newInterval);
            return result;
    }

252会议室

  • 会员题目

  • 题目描述:给定一个会议时间安排的数组,每个会议时间都会包括开始和结束的时间 [[s1,e1],[s2,e2],…] (si < ei),请你判断一个人是否能够参加这里面的全部会议

  • 示例

Input: [[0,30],[5,10],[15,20]]
Output: false

Input: [[7,10],[2,4]]
Output: true

public boolean canAttendMeetings(int[][] intervals) {
    // 按照会议的开始时间,从小到大排序
    Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
    for (int i = 1; i < intervals.length; i++) {
        // 上一个会议时间
        int[] pre = intervals[i - 1];
        // 当前会议的时间
        int[] curr = intervals[i];
        // 当前会议的开始时间,小于上一个会议的结束时间,就表明有重合
        if (curr[0] < pre[1]) {
            return false;
        }
    }
    return true;
}

253会议室 II

  • 用优先级队构建最小堆 和 栈
/**
* 最少会议室
*
* @param interval
* @return
*/
public int minMeetRooms(int[][] interval) {
  Arrays.sort(interval, Comparator.comparingInt(a -> a[0]));
  PriorityQueue<Integer> minHeap = new PriorityQueue<>();
  // add the first meeting end time;
  minHeap.add(interval[0][1]);
  for (int i = 1; i < interval.length; i++) {
      if (interval[i][0] >= minHeap.peek()) {
          minHeap.poll();
      }
      minHeap.add(interval[i][1]);
  }
  return minHeap.size();
}

495. 提莫攻击

public int findPoisonedDuration(int[] timeSeries, int duration) {
    int count = 0;
    // 当前被攻击的持续时间
    int currAttackInterval = timeSeries[0] + duration - 1;
    int len = timeSeries.length;

    for (int i = 1; i < len; i++) {
        // 没有覆盖,在中毒之后,才出现新的攻击
        if (timeSeries[i] > currAttackInterval) {
            count += duration;
            currAttackInterval = timeSeries[i] + duration - 1;
            continue;

        }
        // 在中毒时候,又被攻击了;
        // case 1: 更新被攻击的持续时间
        currAttackInterval = timeSeries[i] + duration - 1;
        // 去掉重置的中毒时间,然后做累加
        count += timeSeries[i] - timeSeries[i - 1];
    }
    // 因为我们统计的是上次「中毒」维持的时间,不要忘记最后一次中毒将维持 duration秒。所以在遍历结束的时候,结果需要加上 duration。
    // 是不是有点像 dp[i]?
    count += duration;
    return count;
}

763. 划分字母区间

  • 有点滑动窗口的感觉
public List<Integer> partitionLabels(String s) {
    // 所有字符的最大下标
    int[] allIndex = new int[128];
    for (int i = 0; i < s.length(); i++) {
        allIndex[s.charAt(i)] = i;
    }
    List<Integer> res = new ArrayList<>();
    int left = 0;
    int right = 0;
    for (int i = 0; i < s.length(); i++) {
        char currChar = s.charAt(i);
        // 当前字符的最大下标
        right = Math.max(right, allIndex[currChar]);
        // 遍历到最大下标位置
        // 可以做长度截取
        if (i == right) {
            res.add(right - left + 1);
            // 更新left 下标位置,便于下次做截取
            left = i + 1;
        }
    }
    return res;
}

986. 区间列表的交集

public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {
    int len1 = firstList.length;
    int len2 = secondList.length;

    if (len1 == 0 || len2 == 0) {
        return new int[0][];
    }
    List<int[]> res = new ArrayList<>();
    int i = 0;
    int j = 0;
    while (i < len1 && j < len2) {
        int maxLeft = Math.max(firstList[i][0], secondList[j][0]);
        int minRight = Math.min(firstList[i][1], secondList[j][1]);
        if (maxLeft <= minRight) {
            res.add(new int[]{maxLeft, minRight});
        }

        if (firstList[i][1] < secondList[j][1]) {
            i++;
        } else {
            j++;
        }

    }
    return res.toArray(new int[res.size()][2]);
}

最后

  • 感谢各位大佬的题解教程,谢谢你们
  • 主要是为了个人刷题,做个总结,侵权的话,我删除链接;
  • 一键直达code;