- 502. IPO">502. IPO
- 881. 救生艇">881. 救生艇
- 1011. 在 D 天内送达包裹的能力">1011. 在 D 天内送达包裹的能力
- 1382. 将二叉搜索树变平衡">1382. 将二叉搜索树变平衡
- 1386. 安排电影院座位">1386. 安排电影院座位
- 1663. 具有给定数值的最小字符串">1663. 具有给定数值的最小字符串
- 1792. 最大平均通过率">1792. 最大平均通过率
- 1846. 减小和重新排列数组后的最大元素">1846. 减小和重新排列数组后的最大元素
- 1877. 数组中最大数对和的最小值">1877. 数组中最大数对和的最小值
- 剑指 Offer 45. 把数组排成最小的数">剑指 Offer 45. 把数组排成最小的数
- 面试题 10.11. 峰与谷">面试题 10.11. 峰与谷
502. IPO
思路:大堆,维护一个收益最大堆
前置条件:
1、合并项目和收益数组,以启动资本降序,收益升序排列项目和启动资本的合并数组;
2、构建一个大堆,队中的排序规则是,收益降序,自动资本升序。
过程:
1、获取不高于当前资本的所有项目入堆;
2、从堆中选择一个项目,k—,并计算资本;
3、返回最终结果。
/*** @param {number} k* @param {number} w* @param {number[]} profits* @param {number[]} capital* @return {number}*/var findMaximizedCapital = function(k, w, profits, capital) {const projects = new Array(profits.length);for (let i = 0; i < profits.length; i++) {projects[i] = {profit: profits[i],capital: capital[i]};}projects.sort((a, b) => {if (a.capital === b.capital) {return a.profit - b.profit;}return b.capital - a.capital;});const hp = new Heap((a, b) => {if (a.profit === b.profit) {return a.capital - b.capital;}return b.profit - a.profit;});let ans = w;while (k) {while (projects.length && projects[projects.length - 1] && projects[projects.length - 1].capital <= ans) {hp.push(projects.pop());}let p;if (!hp.isEmpty()) {p = hp.pop();}if (!p) {// 已有资金不够启动新项目break;}ans += p.profit;k--;}return ans;};function swap(d, i, j) {[d[i], d[j]] = [d[j], d[i]];}function toUpper(d, i, comp) {while (i > 0) {let p = ((i - 1) >>> 1);if (comp(d[p], d[i]) > 0) {swap(d, p, i);}i = p;}}function toBottom(d, i, len, comp) {while (i < len) {let l = 1 + (i << 1);let r = 2 + (i << 1);let m = i;if (l < len && comp(d[l], d[m]) < 0) {m = l;}if (r < len && comp(d[r], d[m]) < 0) {m = r;}if (m === i) {break;}swap(d, m, i);i = m;}}class Heap {constructor(comp) {this.d = [];this.comp = comp;}push(t) {this.d.push(t);toUpper(this.d, this.d.length - 1, this.comp);}pop() {if (this.d.length <= 1) {return this.d.pop();}const r = this.d[0];this.d[0] = this.d.pop();toBottom(this.d, 0, this.d.length, this.comp);return r;}peek() {return this.d[0];}isEmpty() {return this.d.length === 0;}}
881. 救生艇
/**
* @param {number[]} people
* @param {number} limit
* @return {number}
*/
var numRescueBoats = function(people, limit) {
people.sort((a, b) => a- b);
let ans = 0, left = 0, right = people.length - 1;
while (left <= right) {
ans += 1;
if (people[right] + people[left] <= limit) {
left ++;
}
right --;
}
return ans;
};
1011. 在 D 天内送达包裹的能力
/**
* @param {number[]} weights
* @param {number} days
* @return {number}
*/
var shipWithinDays = function(weights, days) {
let bounds = weights.reduce((r, i) => {
r.min = i > r.min ? i : r.min;
r.max += i;
return r;
}, {
min: Number.MIN_SAFE_INTEGER,
max: 0
});
let {min: left, max: right } = bounds;
let ans = right;
while (left < right) {
const mid = left + ((right - left) >> 1);
let r = 1;
let sum = 0;
for (let i = 0; i < weights.length; i++) {
if (sum + weights[i] > mid) {
r += 1;
sum = 0;
}
sum += weights[i];
}
if (r > days) {
left = mid + 1;
} else if (r <= days) {
right = mid;
ans = Math.min(ans, mid);
}
}
return ans;
};
1382. 将二叉搜索树变平衡
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var balanceBST = function(root) {
const r = [];
const traverse = (node) => {
if (node.left) {traverse(node.left); }
r.push(node.val);
if (node.right){traverse(node.right);}
};
traverse(root);
const makeTree = (left, right) => {
if (left > right) return null;
if (left === right) {
return new TreeNode(r[left]);
}
let mid = left + Math.floor((right - left)/2);
const nroot = makeTree(mid, mid);
nroot.left = makeTree(left, mid - 1);
nroot.right = makeTree(mid + 1, right);
return nroot;
};
return makeTree(0, r.length - 1);
};
1386. 安排电影院座位
/**
* @param {number} n
* @param {number[][]} reservedSeats
* @return {number}
*/
var maxNumberOfFamilies = function(n, reservedSeats) {
const rs = new Map();
reservedSeats.reduce((r, item) => {
const [row, c] = item;
// 限定预定的座位在【2,9】之间,确保只会可以安排一个4口之家。
// 在1,10位置预定的,不影响结果计算判断。
if (c >= 2 && c <= 9) {
r.set(row, (r.get(row) || 0) + (1 << (c - 2)));
}
return r;
}, rs);
// left: 2345, right: 4567, mid: 2345
const left = 0b11110000, right = 0b00001111, mid = 0b11000011;
// 不在预定里面的行可以安排两个结果,所以要乘以2;
let ans = (n - rs.size) * 2;
for (let value of rs.values()) {
// 利用或的性质,检测每个家庭的位置是否被占用,如果没有被占用,则这个位置可以安排
if ((value | left) === left || (value | mid) === mid || (value | right) === right) {
ans += 1;
}
}
return ans;
};
1663. 具有给定数值的最小字符串
/**
* @param {number} n
* @param {number} k
* @return {string}
*/
var getSmallestString = function(n, k) {
// 先给每个位置默认填充'a',然后计算剩余的数值的分配
let q = new Array(n).fill('a'), remain = k - n, i = n - 1;
while (remain) {
if (remain > 25) {
remain -= 25;
q[i] = 'z';
i--;
} else {
q[i] = String.fromCharCode(97 + remain);
remain = 0;
}
}
return q.join('');
};
1792. 最大平均通过率
/**
* @param {number[][]} classes
* @param {number} extraStudents
* @return {number}
*/
var maxAverageRatio = function(classes, extraStudents) {
const heap = new MaxPriorityQueue({ priority: (bid) => bid.delta });
classes.forEach(([p, t], index) => {
heap.enqueue({
delta: (p+1)/(t+1) - p/t,
index
});
});
while (extraStudents) {
const top = heap.dequeue().element;
classes[top.index][0]++;
classes[top.index][1]++;
let [p, t] = classes[top.index];
heap.enqueue({
delta: (p + 1)/(t+1) - p/t,
index: top.index
});
extraStudents--;
}
let ans = 0;
for (let i = 0; i < classes.length; i++) {
ans += (classes[i][0]/classes[i][1]);
}
return ans/classes.length;
};
1846. 减小和重新排列数组后的最大元素
/**
* @param {number[]} arr
* @return {number}
*/
var maximumElementAfterDecrementingAndRearranging = function(arr) {
arr.sort((a, b) => a - b);
arr[0] = 1;
for (let i = 1; i < arr.length; i++) {
if (arr[i] - arr[i-1] > 1) {
arr[i] = arr[i-1] + 1;
}
}
return arr[arr.length - 1];
};
1877. 数组中最大数对和的最小值
/**
* @param {number[]} nums
* @return {number}
*/
var minPairSum = function(nums) {
nums.sort((a, b) => a - b);
let l = 0, r = nums.length - 1;
let ans = 0;
while (l < r) {
ans = Math.max(ans, nums[l++] + nums[r--]);
}
return ans;
};
剑指 Offer 45. 把数组排成最小的数
/**
* @param {number[]} nums
* @return {string}
*/
var minNumber = function(nums) {
return nums.sort((a, b) => Number(a + '' + b) - Number(b + '' + a)).join('');
};
面试题 10.11. 峰与谷
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var wiggleSort = function(nums) {
let cmp = [
(a, b) => a > b,
(a, b) => a < b
];
for (let i = 0; i < nums.length; i ++) {
let limit = i;
for (let j = i + 1; j < nums.length; j++) {
if (cmp[i%2](nums[j], nums[limit])){
limit = j;
}
}
const t = nums[i];
nums[i] = nums[limit];
nums[limit] = t;
}
return nums;
};
