// 活动选择问题(区间调度)
function maxActivities(intervals) {
intervals.sort((a,b) => a[1] - b[1]); // 按结束时间排序
let count = 0, end = -Infinity;
for (const [s, e] of intervals) {
if (s >= end) { count++; end = e; }
}
return count;
}
【反例警示】:背包问题(0/1)不满足贪心性质,必须用DP
⚡ 双指针技巧
核心思想:利用单调性减少状态空间;常见模式:快慢指针、对撞指针、滑动窗口。
// 接雨水(LeetCode 42)
function trap(height) {
let left = 0, right = height.length-1;
let leftMax = 0, rightMax = 0, res = 0;
while (left < right) {
if (height[left] < height[right]) {
height[left] >= leftMax ? leftMax = height[left] : res += leftMax - height[left];
left++;
} else {
height[right] >= rightMax ? rightMax = height[right] : res += rightMax - height[right];
right--;
}
}
return res;
}
【思维提升】:双指针本质是**状态压缩**——用O(1)空间代替O(n)数组
四、操作系统与网络:高频考点与原理深挖
〔进程与线程〕并发模型的本质差异
维度
进程
线程
内存空间
独立(隔离性好)
共享(通信高效)
切换开销
高(需保存/恢复页表)
低(仅寄存器)
通信方式
管道/消息队列/共享内存
直接读写共享变量
异常影响
独立崩溃不影响其他进程
线程崩溃导致进程退出
常见误区:认为“线程越多性能越好” → 实际受CPU核心数与上下文切换开销制约。
// 线程池核心参数(Java示例)
ThreadPoolExecutor pool = new ThreadPoolExecutor(
4, // corePoolSize
8, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
new ThreadPoolExecutor.CallerRunsPolicy()
);
-- SQL优化实战:避免索引失效
-- ❌ 错误写法:函数/计算导致索引失效
SELECT * FROM orders WHERE YEAR(create_time) = 2023;
-- ✅ 正确写法:范围查询
SELECT * FROM orders WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';