2024 Huawei OD Computer Test Real Questions [Interval Overlap/Greedy Algorithm] [Java]

Question description

Given a set of line segments on the coordinate axis, the starting point and end point of the line segment are both integers and the length is not less than 1. Please find the minimum number of line segments that can cover all line segments.

Input description
The first line of input is the number of all line segments, not exceeding 10,000. Each subsequent line represents a line segment in the format of "x,y".
x and y represent the starting point and end point respectively, and the value range is [-10^5, 10^5].
Output description

The minimum number of line segments, which is a positive integer.
Input
3
1,4
2,5
3,6
Output
2

Interpretation of the question

First, use an example to understand the meaning of the question : now there are three line segments:

Line segment No. 1: starting point 1, end point 4;

Line segment No. 2: starting point 2, end point 5;

Line segment No. 3: starting point 3, end point 6;

Insert image description here
We need to select several line segments from these three line segments to cover 1~6the entire interval.

For example, we can choose number one, number two, and number three. No. 1 covers 1~4, No. 2 covers 2~5, No. 3 covers 3~6, and the three line segments add up to cover 1~6the entire interval. However, the question requires choosing as few line segments as possible . Therefore, we only need to select No. 1 and No. 3 to cover 1~6the entire range. Therefore, the answer is to select 2line segments (i.e. No. 1, No. 3).

Problem-solving ideas

This is a typical greedy algorithm . The greedy strategy is as follows:

First, sort all the line segments from small to large starting points.

Then traverse the sorted line segments, and each time a line segment is traversed (we call the line segment currently being traversed a line segment), find all the line segmentscurrent in the following line segments whose left endpoint is less than or equal to the currentright endpoint of the line segment (we call it an alternative line segment ) , find the line segment with the largest right endpoint among the candidate line segments . Next traverse .maxLinemaxLine

Repeat the above operations until the entire interval of length m is covered, and the minimum number of line segments can be obtained.

Video explanation

2023 Huawei Computer Test Real Questions [Interval Overlap/Greedy Algorithm]

Sample code (Java version)

import java.util.*;
import java.io.*;

public class Main {
    
    
    
    public static void main(String[] args) throws IOException {
    
    
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        int count = Integer.parseInt(reader.readLine().trim());
        List<int[]> intervals = new ArrayList<>();
        for (int i = 0; i < count; i++) {
    
    
            String[] parts = reader.readLine().split(",");
            intervals.add(new int[] {
    
     Integer.parseInt(parts[0]), Integer.parseInt(parts[1]) });
        }
        intervals.sort((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);

        Stack<int[]> stack = new Stack<>();
        stack.push(intervals.get(0));

        for (int i = 1; i < count; i++) {
    
    
            int[] currentInterval = intervals.get(i);
            int[] topInterval = stack.isEmpty() ? null : stack.peek();

            while (true) {
    
    
                // 如果栈为空,直接加入当前区间
                if (topInterval == null) {
    
    
                    stack.push(currentInterval);
                    break;
                }

                int topStart = topInterval[0];
                int topEnd = topInterval[1];
                int currentStart = currentInterval[0];
                int currentEnd = currentInterval[1];

                // 当前区间在栈顶区间的左侧且没有重叠
                if (currentEnd <= topStart) {
    
    
                    break;
                }
                // 当前区间在栈顶区间的左侧但与其有重叠
                else if (currentStart <= topStart && currentEnd <= topEnd) {
    
    
                    break;
                }
                // 当前区间完全覆盖栈顶区间
                else if (currentStart <= topStart && currentEnd > topEnd) {
    
    
                    stack.pop();
                }
                // 当前区间在栈顶区间内部,但终点超出
                else if (currentStart > topStart && currentEnd > topEnd) {
    
    
                    stack.push(new int[] {
    
    topEnd, currentEnd});
                    break;
                }
                // 当前区间在栈顶区间的右侧且没有重叠
                else {
    
    
                    stack.push(currentInterval);
                    break;
                }

                topInterval = stack.isEmpty() ? null : stack.peek();
            }
        }

        System.out.println(stack.size());
    }
}



Guess you like

Origin blog.csdn.net/wtswts1232/article/details/135190592