209. 长度最小的子数组
leetcode-cn.com/problems/mi…
- 滑动窗口
- 用来解决一些查找满足一定条件的连续区间的性质问题,当区间发生变化时,可以通过旧有的计算结果对搜索空间进行剪枝,减少重复的计算量,降低算法时间复杂度
- 扩张窗口:为了找到一个可行解,找到了就不再扩张
- 收缩窗口:在长度上优化该可行解,直到条件被破坏
- 寻找下一个可行解,然后再优化到不能优化……
/**
* @param {number} s
* @param {number[]} nums
* @return {number}
*/
var minSubArrayLen = function(s, nums) {
let sum = 0
let counter = Number.MAX_SAFE_INTEGER
let left = 0
for(let right=0
sum = sum + nums[right]
while(sum >= s){
counter = Math.min(counter,right-left+1)
sum = sum - nums[left]
left++
}
}
return counter === Number.MAX_SAFE_INTEGER ? 0 : counter
}
实现一个最大堆
- 定义
- 二叉堆是一颗完全二叉树
- 堆中某个节点的值总是不大于其父节点的值(最大堆),相反的定义则是最小堆
- 性质(由数组实现)
- 左子树头节点的 index = 2 * k + 1
- 右子树头节点的 index = 2 * k + 2
- 父亲节点的 index = Math.floor((k - 1) / 2)
- 应用
class MaxHeap {
data = []
constructor(data = []) {
this.data = data
for (let i = this.getParent(this.getSize() - 1); i >= 0; i--) {
this.siftDown(i)
}
}
isEmpty() {
return this.data.length === 0
}
getSize() {
return this.data.length
}
add(e) {
this.data.push(e)
this.siftUp(this.getSize() - 1)
}
findMax() {
return this.data[0]
}
removeMax() {
const max = this.findMax()
this.swap(0, this.getSize() - 1)
this.data.pop()
this.siftDown(0)
return max
}
getParent(k) {
return Math.floor((k - 1) / 2)
}
getLeftChild(k) {
return 2 * k + 1
}
getRightChild(k) {
return 2 * k + 2
}
swap(k1, k2) {
const temp = this.data[k1]
this.data[k1] = this.data[k2]
this.data[k2] = temp
}
siftUp(k) {
while (k > 0 && this.data[k] > this.data[this.getParent(k)]) {
this.swap(k, this.getParent(k))
k = this.getParent(k)
}
}
siftDown(k) {
while (this.getLeftChild(k) < this.getSize()) {
const left = this.getLeftChild(k)
const right = this.getRightChild(k)
let maxIndex = left
if (right < this.getSize() && this.data[left] < this.data[right]) {
maxIndex = right
}
if (this.data[k] > this.data[maxIndex]) {
break
}
this.swap(k, maxIndex)
k = maxIndex
}
}
replace(e) {
const max = this.findMax()
this.data[0] = e
this.siftDown(0)
return max
}
}