← 返回博客列表
Atlassian

🚨 Atlassian 2026 面試真題:CI 流水線區間合併 —— 經典區間問題,為何還有人掛?

2026-01-19

製造焦慮:打破幻覺

最近 Atlassian 的面試題在北美求職圈火了。

很多人看到題目第一反應:「LeetCode 56 原題啊,秒了!」

但真的是這樣嗎?

如果你只是背模板默寫一遍,面試官會立刻追問:

我們 oavoservice 團隊拿到這道題後,發現它雖然是經典題,但 Atlassian 的考察角度非常工程化


題目拆解:展示專業

🔍 原題描述

Problem – Merge Overlapping CI Intervals

Atlassian runs many CI pipelines, and we want to generate reports on usage to find cost-optimization patterns.

Each CI pipeline starts at time X and ends at time Y. We are given a list of pipeline time windows: [[X₁, Y₁], [X₂, Y₂], ...]

Objective: Find the list of non-overlapping time intervals that cover all times when at least one CI pipeline is running.

In other words, merge all overlapping intervals and return the minimal set of disjoint intervals.

📝 中文翻譯

Atlassian 運行大量 CI 流水線,我們需要生成使用報告來發現成本優化模式。

每個 CI 流水線在時間 X 開始,時間 Y 結束。給定一個流水線時間窗口列表: [[X₁, Y₁], [X₂, Y₂], ...]

目標:找出所有至少有一個 CI 流水線在運行的時間區間,合併所有重疊區間,返回最小的不相交區間集合。

🎯 範例分析

Example:

Input:  [[2, 5], [12, 15], [4, 8]]
Output: [[2, 8], [12, 15]]

解釋:


深度複盤:建立信任

🧠 題目本質分析

這道題考察的核心能力:

考點 具體內容
排序思維 為什麼要按起點排序?
貪心策略 如何判斷重疊?如何合併?
邊界處理 相鄰區間 [1,2], [2,3] 算重疊嗎?
工程思維 如何處理大數據量?串流輸入?

📊 關鍵洞察

為什麼按起點排序?

排序後,對於相鄰的兩個區間 [s1, e1][s2, e2],一定有 s1 ≤ s2

判斷重疊只需檢查:s2 ≤ e1

Case 1: 重疊 (s2 <= e1)
[s1=====e1]
    [s2=====e2]
合併: [s1, max(e1, e2)]

Case 2: 不重疊 (s2 > e1)
[s1===e1]
           [s2===e2]
不合併,分別保留

方案引入:核心演算法

標準解法:排序 + 線性掃描

def merge_intervals(intervals):
    """
    Atlassian CI 區間合併
    
    Args:
        intervals: List[List[int]] - 區間列表 [[start, end], ...]
    
    Returns:
        List[List[int]] - 合併後的不重疊區間
    """
    if not intervals:
        return []
    
    # Step 1: 按起點升序排序
    intervals.sort(key=lambda x: x[0])
    
    # Step 2: 初始化結果,放入第一個區間
    result = [intervals[0][:]]  # 複製,避免修改原陣列
    
    # Step 3: 線性掃描合併
    for i in range(1, len(intervals)):
        current_start, current_end = intervals[i]
        last_end = result[-1][1]
        
        if current_start <= last_end:
            # 重疊,合併:更新結束時間
            result[-1][1] = max(last_end, current_end)
        else:
            # 不重疊,直接添加新區間
            result.append([current_start, current_end])
    
    return result

🧪 測試用例

# Test 1: 基本情況
print(merge_intervals([[2, 5], [12, 15], [4, 8]]))
# Expected: [[2, 8], [12, 15]]

# Test 2: 完全包含
print(merge_intervals([[1, 10], [2, 5], [3, 7]]))
# Expected: [[1, 10]]

# Test 3: 無重疊
print(merge_intervals([[1, 2], [5, 6], [9, 10]]))
# Expected: [[1, 2], [5, 6], [9, 10]]

# Test 4: 全部重疊
print(merge_intervals([[1, 4], [2, 5], [3, 6], [4, 7]]))
# Expected: [[1, 7]]

# Test 5: 邊界相鄰(相等算重疊)
print(merge_intervals([[1, 2], [2, 3], [3, 4]]))
# Expected: [[1, 4]]

# Test 6: 單個區間
print(merge_intervals([[1, 5]]))
# Expected: [[1, 5]]

# Test 7: 空輸入
print(merge_intervals([]))
# Expected: []

# Test 8: 亂序輸入
print(merge_intervals([[5, 8], [1, 3], [2, 6], [10, 12]]))
# Expected: [[1, 8], [10, 12]]

複雜度分析

操作 時間複雜度 說明
排序 O(n log n) Python Timsort
掃描合併 O(n) 線性遍歷
總計 O(n log n) 排序主導
空間複雜度 說明
O(n) 最壞情況所有區間都不重疊
O(1) 如果原地修改(不推薦)

🤯 面試官的 Followup 陷阱

Followup 1: 如果區間是開區間怎麼辦?

問題(2, 5)(5, 8) 算重疊嗎?

答案:不算!開區間 (2, 5) 不包含端點 5。

def merge_open_intervals(intervals):
    """開區間合併:(start, end) 不包含端點"""
    if not intervals:
        return []
    
    intervals.sort(key=lambda x: x[0])
    result = [intervals[0][:]]
    
    for i in range(1, len(intervals)):
        current_start, current_end = intervals[i]
        last_end = result[-1][1]
        
        # 開區間:嚴格小於才算重疊
        if current_start < last_end:
            result[-1][1] = max(last_end, current_end)
        else:
            result.append([current_start, current_end])
    
    return result

Followup 2: 如果數據量是 10^8 怎麼辦?

考點:外部排序 / 分散式處理

# 偽代碼:分散式思路
def distributed_merge(partitions):
    """
    1. 每個分區獨立排序和合併
    2. 將各分區結果再合併
    """
    local_results = [merge_intervals(p) for p in partitions]
    # 合併所有局部結果
    all_intervals = []
    for r in local_results:
        all_intervals.extend(r)
    return merge_intervals(all_intervals)

Followup 3: 如果需要即時合併串流資料?

考點:資料結構選擇

使用 平衡二元搜尋樹(如 TreeMap)或 跳表 維護有序區間。

from sortedcontainers import SortedList

class StreamingIntervalMerger:
    def __init__(self):
        self.intervals = SortedList(key=lambda x: x[0])
    
    def add_interval(self, start, end):
        """添加新區間並合併"""
        # 找到所有與 [start, end] 重疊的區間
        to_merge = []
        new_start, new_end = start, end
        
        for interval in self.intervals:
            if interval[1] < start:
                continue
            if interval[0] > end:
                break
            # 重疊
            to_merge.append(interval)
            new_start = min(new_start, interval[0])
            new_end = max(new_end, interval[1])
        
        # 刪除被合併的區間
        for interval in to_merge:
            self.intervals.remove(interval)
        
        # 添加新區間
        self.intervals.add([new_start, new_end])
    
    def get_intervals(self):
        return list(self.intervals)

Followup 4: 如果需要返回每個時刻有多少個 CI 在運行?

考點:掃描線演算法 / 差分陣列

def count_concurrent_pipelines(intervals):
    """返回每個時刻運行的 CI 數量"""
    events = []
    for start, end in intervals:
        events.append((start, 1))   # 開始事件
        events.append((end, -1))    # 結束事件
    
    events.sort(key=lambda x: (x[0], x[1]))
    
    result = []
    current_count = 0
    
    for time, delta in events:
        current_count += delta
        result.append((time, current_count))
    
    return result

🔥 為什麼大多數人會掛?

常見錯誤 正確做法
忘記排序 合併前必須按起點排序
邊界判斷錯誤 s2 <= e1 才算重疊(閉區間)
忘記更新 end 合併時取 max(e1, e2)
修改原陣列 面試時最好複製,避免副作用
沒考慮空輸入 開頭檢查 if not intervals

程式碼模板(可直接使用)

def merge(intervals: list[list[int]]) -> list[list[int]]:
    """
    LeetCode 56 / Atlassian CI Intervals
    合併所有重疊區間
    """
    if not intervals:
        return []
    
    # 按起點排序
    intervals.sort(key=lambda x: x[0])
    
    merged = [intervals[0]]
    
    for current in intervals[1:]:
        if current[0] <= merged[-1][1]:
            # 重疊,合併
            merged[-1][1] = max(merged[-1][1], current[1])
        else:
            # 不重疊,添加新區間
            merged.append(current)
    
    return merged

📞 oavoservice 服務

區間合併看似簡單,但 Atlassian 考察的是工程思維擴展能力

如果你在面試中遇到類似題目,我們可以提供:


👉 立即添加微信:Coding0201

不要讓一道區間合併題,毀掉你的 Atlassian Offer。


本文由 oavoservice 團隊原創,轉載請註明出處。