2026-09-10:维持亮度的最小总能量。用go语言,有 n 个灯泡排成一行,位置编号从 0 到 n-1。时间按离散单位划分,每个单位时间都可以独立决定每个灯泡是开还是关。一个开启的灯泡会照亮它自己的位置,以及左右相邻的位置,如果这些位置存在的话。一个单位时间内的照明总量,等于至少被一个开启灯泡照到的不同位置数量;同一个位置即使被多个灯泡照亮,也只算一次。

另外给定一个亮度要求 brightness,以及若干个闭时间区间。对于被这些区间中任意一个覆盖到的单位时间,照明总量必须达到或超过 brightness。对于没有被任何区间覆盖的单位时间,没有照明要求,灯泡可以全部关闭。

每开启一个灯泡一个单位时间,就消耗 1 单位能量。目标是在满足所有区间内照明要求的前提下,使总能量消耗尽可能小,并返回这个最小总能量。

1 <= n <= 1000000。

1 <= brightness <= n。

1 <= intervals.length <= 100000。

intervals[i] == [starti, endi]。

0 <= starti <= endi <= 1000000000。

输入: n = 5, brightness = 5, intervals = [[6,12]]。

输出: 14。

解释:

开启位于位置 1 和 4 的灯泡。

当前序列状态:0 1 0 0 1.

全部 5 个位置都被照亮,因此达到了要求的亮度。

有效区间长度为 12 - 6 + 1 = 7,因此总能量为 2 * 7 = 14。

题目来自力扣3951。

代码逻辑分步详解 第1步:排序区间

  • • 输入intervals是若干闭区间[start, end],表示这些时间单位必须满足亮度要求。

  • • 首先按区间的左端点从小到大排序,这是为了后续合并重叠区间。

第2步:合并重叠区间(求总覆盖时间长度)
  • • 因为如果两个区间在时间上有重叠,那么重叠部分只需要满足一次亮度要求即可(但实际照明是连续时间,不需要重复计算)。

  • • 合并规则:

    • • 初始化left=0,right=-1(表示当前合并区间为空)。

    • • 遍历排序后的每个区间[p[0], p[1]]:

      • • 如果当前区间的左端点p[0]≤ 当前合并区间的右端点right,说明有重叠或相邻,可以合并,更新right = max(right, p[1])。

      • • 否则(不相交),则说明当前合并区间结束,将它的长度(right - left + 1)累加到sumLen,然后开始一个新的合并区间left=p[0], right=p[1]。

  • • 遍历结束后,将最后一个合并区间的长度也累加到sumLen。

  • •结果:sumLen是所有必须满足亮度要求的时间单位总数(去重后)。

第3步:计算单时间单位所需最少灯泡数
  • • 一个灯泡最多照亮 3 个位置(自身+左右)。

  • • 要照亮至少brightness个不同位置,最少需要bulbs = ceil(brightness / 3)个灯泡。

  • • 代码中(brightness + 2) / 3就是向上取整。

第4步:计算最小总能量
  • • 每个时间单位需要bulbs个灯泡,共sumLen个时间单位。

  • • 总能量 =bulbs × sumLen。

  • • 返回int64类型,因为结果可能较大。

针对给定示例的模拟计算
  • • 输入:n=5, brightness=5, intervals=[[6,12]]

  • • 排序(只有一个区间,无需合并):

    • •sumLen = 12 - 6 + 1 = 7

  • •bulbs = (5+2)/3 = 7/3 = 2.333... → 2(向上取整)

  • • 总能量 =2 × 7 = 14,与题目输出一致。

时间复杂度分析
  • •排序:O(k log k),其中k = len(intervals),最多 100000。

  • •合并区间遍历:O(k)。

  • • 整体时间复杂度:O(k log k),主要受排序限制。

额外空间复杂度分析
  • • 排序通常需要O(log k)的栈空间(递归深度)或O(1)的原地排序(如 Go 的slices.SortFunc使用快速排序,平均栈空间O(log k))。

  • • 除了输入数组外,只使用了少数几个变量(sumLen,left,right,bulbs),额外空间为O(1)(忽略排序的栈开销)。

  • • 若严格考虑排序辅助空间,可认为是O(log k),但通常描述为O(1)额外空间(不计输入和排序临时空间)。

最终答案总结
  • •过程:排序区间 → 合并求总覆盖时间长度 → 计算所需最少灯泡数 → 乘积得最小总能量。

  • •时间复杂度:O(k log k),k 为区间数量。

  • •额外空间复杂度:O(1)(或O(log k)含排序栈空间,但通常视为常数级)。

Go完整代码如下:

package main

import (
"fmt"
"slices"
)

func minEnergy(_, brightness int, intervals [][]int) int64 {
slices.SortFunc(intervals, func(p, q []int) int { return p[0] - q[0] }) // 按照左端点从小到大排序

// 56. 合并区间(只计算区间长度之和)
sumLen := 0
left, right := 0, -1
for _, p := range intervals {
if p[0] <= right { // 左端点在合并区间内,可以合并
right = max(right, p[1]) // 更新合并区间的右端点
} else { // 不相交,无法合并
sumLen += right - left + 1
left, right = p[0], p[1] // 新的合并区间
}
}
sumLen += right - left + 1

bulbs := (brightness + 2) / 3 // 至少要开启 bulbs 个灯泡
return int64(bulbs * sumLen)
}

func main() {
n := 5
brightness := 5
intervals := [][]int{{6, 12}}
result := minEnergy(n, brightness, intervals)
fmt.Println(result)
}
打开网易新闻 查看精彩图片

Python完整代码如下:

# -*-coding:utf-8-*-

def min_energy(_, brightness: int, intervals: list[list[int]]) -> int:
# 按左端点从小到大排序
intervals.sort(key=lambda x: x[0])

# 合并区间,并计算所有区间的总长度(闭区间长度)
total_len = 0
left, right = 0, -1
for start, end in intervals:
if start <= right: # 当前区间与合并区间重叠
right = max(right, end)
else: # 开始新的合并区间
total_len += right - left + 1
left, right = start, end
total_len += right - left + 1 # 加上最后一个合并区间

# 至少需要开启的灯泡数量:ceil(brightness / 3)
bulbs = (brightness + 2) // 3

return bulbs * total_len

if __name__ == "__main__":
n = 5
brightness = 5
intervals = [[6, 12]]
result = min_energy(n, brightness, intervals)
print(result)
打开网易新闻 查看精彩图片

C++完整代码如下:

  




using namespace std;

long long minEnergy(int /* n 未使用 */, int brightness, vector int >>& intervals) {
// 按左端点从小到大排序
sort(intervals.begin(), intervals.end(),
[]( const vector< int >& a, const vector< int >& b) {
return a[ 0 ] < b[ 0 ];
});

// 合并区间,计算所有区间的总长度(闭区间)
long long sumLen = 0 ;
int left = 0 , right = -1 ;
for ( const auto& p : intervals) {
int start = p[ 0 ], end = p[ 1 ];
if (start <= right) { // 区间重叠或相邻,可以合并
right = max(right, end);
} else { // 开始新的合并区间
sumLen += right - left + 1 ;
left = start;
right = end;
}
}
sumLen += right - left + 1 ; // 加上最后一个合并区间

// 至少需要开启的灯泡数量:ceil(brightness / 3)
long long bulbs = (brightness + 2 ) / 3 ;

return bulbs * sumLen;
}

int main() {
int n = 5 ;
int brightness = 5 ;
vector int >> intervals = {{ 6 , 12 }};

long long result = minEnergy(n, brightness, intervals);
cout << result << endl;

return 0 ;
}
打开网易新闻 查看精彩图片

我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。