动态规划二 & 贪心算法 实验三
一、贪心算法和动态规划法解决背包问题。
有一个背包其容积 C = 13。现有表格内的物品可以购买。
商品 |
价格 P |
体积 V |
啤酒 |
24 |
10 |
汽水 |
2 |
3 |
饼干 |
9 |
4 |
面包 |
10 |
5 |
牛奶 |
9 |
4 |
1 用动态规划法解决“0-1背包问题”
(1) 使用模块化开发的方式,把解决问题的过程抽象成三个模块,构造值结构的归并排序MergeSort类模块、处理值问题的背包Knapsack类模块和创建商品的KnapsackItem类模块。
(2) MergeSort类在Knapsack类中,被封装成处理归并排序的回调函数, 定义了最优值,负责在Knapsack类对sortPossibleItemsByWeight函数背包的weight由小到大进行排序,sortPossibleItemsByValue则对value由大到小执行排序,sortPossibleItemsByValuePerWeightRatio是price/weight的性价比,由大到小执行排序。其中Knapsack类又包含了处理购物清单selectedItems的totalValue()、totalWeight()、countCoin()、getLastProcduct()、setLastProcductValue(value)和setLastProcductWeight(weight)的功能函数,实现对购物清单里面的商品进行处理。 KnapsackItem类则实现了创建商品的对象,定义了商品的{value(价格), weight(体积), itemsInStock = 1(数量) ,produce(名称)},实现对单个商品的totalValue()、totalWeight()、valuePerWeightRatio()、setValue(value)、setWeight(weight)和toString()进行商品属性处理的功能函数。
(3)0-1背包问题的solveZeroOneKnapsackProblem函数。
1)首先递归地对value降序排序,然后对weight进行升序排序,定义最优解的值。
2)再运用矩阵链乘法,创建一个子串长度与背包商品n和背包容积的n*m的空矩阵,第一维度的矩阵中每行的数据是用来定义对商品n的价格进行逐个比较的子串。第二维度的矩阵中每行列对应的数据是对每个物品从1至背包最大体积n的逐个价格的组合。从每一行中对价格的子问题进行累加记录,从而解决大问题,计算出最优的价格值。
3)最后通过循环遍历每件商品,用之前所得到最优的价格值矩阵,通过自底向上比较最后一行得到的最优值与上一行的最优值比较。如果两个值相同,则说明最后一行的物品没有被购买,不能选择价格最高者。如果两个值不相同,则说明当前商品被购买,应该加入购物清单。如此反复进行,最终构造购物清单的最优解。
2 核心函数实现代码。
solveZeroOneKnapsackProblem() {
this.sortPossibleItemsByValue();
this.sortPossibleItemsByWeight();
this.selectedItems = [];
const numberOfRows = this.possibleItems.length;
const numberOfColumns = this.weightLimit;
const knapsackMatrix = Array(numberOfRows).fill(null).map(() => {
return Array(numberOfColumns + 1).fill(null);
});
for (let itemIndex = 0; itemIndex < this.possibleItems.length; itemIndex += 1) {
knapsackMatrix[itemIndex][0] = 0;
}
for (let weightIndex = 1; weightIndex <= this.weightLimit; weightIndex += 1) {
const itemIndex = 0;
const itemWeight = this.possibleItems[itemIndex]._weight;
const itemValue = this.possibleItems[itemIndex]._value;
knapsackMatrix[itemIndex][weightIndex] = itemWeight <= weightIndex ? itemValue : 0;
}
for (let itemIndex = 1; itemIndex < this.possibleItems.length; itemIndex += 1) {
for (let weightIndex = 1; weightIndex <= this.weightLimit; weightIndex += 1) {
const currentItemWeight = this.possibleItems[itemIndex]._weight;
const currentItemValue = this.possibleItems[itemIndex]._value;
if (currentItemWeight > weightIndex) {
knapsackMatrix[itemIndex][weightIndex] = knapsackMatrix[itemIndex - 1][weightIndex];
} else {
knapsackMatrix[itemIndex][weightIndex] = Math.max(
currentItemValue + knapsackMatrix[itemIndex - 1][weightIndex - currentItemWeight],
knapsackMatrix[itemIndex - 1][weightIndex],
);
}
}
}
let itemIndex = this.possibleItems.length - 1;
let weightIndex = this.weightLimit;
while (itemIndex > 0) {
const currentItem = this.possibleItems[itemIndex];
const prevItem = this.possibleItems[itemIndex - 1];
if (
knapsackMatrix[itemIndex][weightIndex]
&& knapsackMatrix[itemIndex][weightIndex] === knapsackMatrix[itemIndex - 1][weightIndex]
) {
const prevSumValue = knapsackMatrix[itemIndex - 1][weightIndex];
const prevPrevSumValue = knapsackMatrix[itemIndex - 2][weightIndex];
if (
!prevSumValue
|| (prevSumValue && prevPrevSumValue !== prevSumValue)
) {
this.selectedItems.push(prevItem);
}
} else if (knapsackMatrix[itemIndex - 1][weightIndex - currentItem._weight]) {
this.selectedItems.push(prevItem);
weightIndex -= currentItem._weight;
}
itemIndex -= 1;
}
}
3 背包内物品的组合与价格。
4 贪心算法解决“部分背包问题”的流程步骤。
贪心算法的前1-2步骤和动态规划相同,区别在于核心问题的处理函数。
部分背包问题的solveUnboundedKnapsackProblem函数。
1)首先递归地对value降序排序,然后通过price/weight性价比进行升序排序,定义最优解的值。
2)通过循环,每次选择性价比最高的商品。因为可以部分购买,只需由上往下,购买直至满足背包的最大体积。
5 核心函数实现代码。
solveUnboundedKnapsackProblem() {
this.sortPossibleItemsByValue();
this.sortPossibleItemsByValuePerWeightRatio();
for (let itemIndex = 0; itemIndex < this.possibleItems.length; itemIndex += 1) {
if (this.totalWeight < this.weightLimit) {
const currentItem = this.possibleItems[itemIndex];
const availableWeight = this.weightLimit - this.totalWeight;
const maxPossibleItemsCount = Math.floor(availableWeight / currentItem._weight);
if (maxPossibleItemsCount > currentItem.itemsInStock) {
currentItem.quantity = currentItem.itemsInStock;
} else if (maxPossibleItemsCount) {
currentItem.quantity = maxPossibleItemsCount;
}
this.selectedItems.push(currentItem);
}
}
}
6 背包内物品的组合与价格。
7 两种方法对于背包问题优点与缺点。
(1)动态规划:
优点:
1)可以获得商品价格每个组合的对比,得到全局最优解
2)动态规划方法反映了动态过程演变的联系和特征,在计算时可以利用实际知识和经验提高求解效率。
缺点:
1)空间需求大,需要额外的内存空间,并且一维问题可能需要二维空间。
2)构建解决问题的方法复杂,需要对寻找最优值进行大量处理。
(2)贪心算法:
优点:
1)空间和时间消耗相对比动态规划小
2)构建解决问题的方法简单,只需关注背包的体积
缺点:
1)不能保证求得的最后解是最佳的;
2)不能用来求最大或最小解问题;
3)只能求满足某些约束条件的可行解的范围。
二、 用贪心算法求解“找n分钱的最佳方案”
现在有面值分别为2角5分,1角,5分,1分的硬币,请给出找n分钱的最佳方案(要求找出的硬币数目最少)。
1 贪心算法解决“找n分钱的最佳方案”的流程步骤。
(1)基本定义和第一问动态规划定义1相同,把创建商品的KnapsackItem类换成CoinItem类模块。
(2) 基本定义和第一问动态规划定义2相同。
CoinItem类实现了创建商品的对象,定义了商品的{weight(n分钱), itemsInStock = 10000(存货数量)},实现对单个商品的totalWeight()、setWeight(weight)、set quantity(quantity)和toString()进行硬币规格处理的功能函数。
(3)n分钱问题的solveCoinProblem函数。
1)首先使用sortCoinByWeight递归地对硬币规格降序排序,定义最优解的值。
2)由于硬币已大到小排序,由上往下,遍历n分钱。当this.possibleItems[itemIndex]._weight(当前硬币的规格) <= this.weightLimit(n分钱),通过maxPossibleItemsCount=Math.floor(availableWeight/currentItem._weight)求得凑齐n分钱每个规格的最大可能硬币个数。如果maxPossibleItemsCount
> currentItem.itemsInStock判断最大硬币个数超过定义的存货数量时,把当前存入的列表的硬币实际个数设置成硬币的存货数量,如果maxPossibleItemsCount && maxPossibleItemsCount > 0,判断硬币的最大可能数不能为负数或0,并把硬币实际个数设置最大可能硬币个数。最后如果该硬币的最大可能硬币个数为0,那么该硬币设置数量为0。
2 核心函数实现代码。
solveCoinProblem() {
this.sortCoinByWeight()
for (let itemIndex = 0; itemIndex < this.possibleItems.length; itemIndex += 1) {
if (this.possibleItems[itemIndex]._weight <= this.weightLimit) {
const currentItem = this.possibleItems[itemIndex];
const availableWeight = this.weightLimit - this.totalWeight;
const maxPossibleItemsCount = Math.floor(availableWeight / currentItem._weight);
if (maxPossibleItemsCount > currentItem.itemsInStock) {
currentItem._quantity = currentItem.itemsInStock;
} else if (maxPossibleItemsCount && maxPossibleItemsCount > 0) {
currentItem._quantity = maxPossibleItemsCount;
}
if(!maxPossibleItemsCount){
currentItem._quantity = maxPossibleItemsCount;
}
this.selectedItems.push(currentItem);
}
}
}
3 找5分钱、17分钱、22分钱、35分钱的最佳方案。
完整代码:
class MergeSort{
constructor(originalCallbacks) {
this.callbacks = MergeSort.initSortingCallbacks(originalCallbacks);
this.comparator = this.callbacks.compareCallback || MergeSort.defaultCompareFunction;
}
static initSortingCallbacks(originalCallbacks) {
const callbacks = originalCallbacks || {};
const stubCallback = () => {}; callbacks.compareCallback = callbacks.compareCallback || undefined;
callbacks.visitingCallback = callbacks.visitingCallback || stubCallback; return callbacks;
} sort(originalArray) {
if (originalArray.length <= 1) {
return originalArray;
} const middleIndex = Math.floor(originalArray.length / 2);
const leftArray = originalArray.slice(0, middleIndex);
const rightArray = originalArray.slice(middleIndex, originalArray.length); const leftSortedArray = this.sort(leftArray);
const rightSortedArray = this.sort(rightArray); return this.mergeSortedArrays(leftSortedArray, rightSortedArray);
} lessThan(a, b) {
return this.comparator(a, b) < 0;
} equal(a, b) {
return this.comparator(a, b) === 0;
} lessThanOrEqual(a, b) {
return this.lessThan(a, b) || this.equal(a, b);
} static defaultCompareFunction(a, b) {
if (a === b) {
return 0;
} return a < b ? -1 : 1;
} mergeSortedArrays(leftArray, rightArray) {
const sortedArray = [];
let leftIndex = 0;
let rightIndex = 0; while (leftIndex < leftArray.length && rightIndex < rightArray.length) {
let minElement = null;
if (this.lessThanOrEqual(leftArray[leftIndex], rightArray[rightIndex])) {
minElement = leftArray[leftIndex];
leftIndex += 1;
} else {
minElement = rightArray[rightIndex];
rightIndex += 1;
}
sortedArray.push(minElement);
} return sortedArray
.concat(leftArray.slice(leftIndex))
.concat(rightArray.slice(rightIndex));
}
} const fp = require('lodash/fp');
//背包
class Knapsack { constructor(possibleItems, weightLimit) {
this.selectedItems = [];
this.weightLimit = weightLimit;
this.possibleItems = possibleItems;
} sortPossibleItemsByWeight() {
this.possibleItems = new MergeSort({ compareCallback: (itemA, itemB) => {
if (itemA._weight === itemB._weight) {
return 0;
} return itemA._weight < itemB._weight ? -1 : 1;
},
}).sort(this.possibleItems);
} sortCoinByWeight() {
this.possibleItems = new MergeSort({ compareCallback: (itemA, itemB) => {
if (itemA._weight === itemB._weight) {
return 0;
} return itemA._weight > itemB._weight ? -1 : 1;
},
}).sort(this.possibleItems);
} sortPossibleItemsByValue() {
this.possibleItems = new MergeSort({
compareCallback: (itemA, itemB) => {
if (itemA._value === itemB._value) {
return 0;
} return itemA._value > itemB._value ? -1 : 1;
},
}).sort(this.possibleItems);
} sortPossibleItemsByValuePerWeightRatio() {
this.possibleItems = new MergeSort({
compareCallback: (itemA, itemB) => {
if (itemA.valuePerWeightRatio === itemB.valuePerWeightRatio) {
return 0;
} return itemA.valuePerWeightRatio > itemB.valuePerWeightRatio ? -1 : 1;
},
}).sort(this.possibleItems);
} solveZeroOneKnapsackProblem() {
this.sortPossibleItemsByValue();
this.sortPossibleItemsByWeight();
this.selectedItems = [];
// console.log(this.sortPossibleItemsByValue());
// console.log(this.sortPossibleItemsByWeight());
const numberOfRows = this.possibleItems.length;
const numberOfColumns = this.weightLimit;
console.log(numberOfRows, numberOfColumns)
const knapsackMatrix = Array(numberOfRows).fill(null).map(() => {
return Array(numberOfColumns + 1).fill(null);
});
// console.log(knapsackMatrix) for (let itemIndex = 0; itemIndex < this.possibleItems.length; itemIndex += 1) {
knapsackMatrix[itemIndex][0] = 0;
}
for (let weightIndex = 1; weightIndex <= this.weightLimit; weightIndex += 1) {
const itemIndex = 0;
const itemWeight = this.possibleItems[itemIndex]._weight;
const itemValue = this.possibleItems[itemIndex]._value;
knapsackMatrix[itemIndex][weightIndex] = itemWeight <= weightIndex ? itemValue : 0;
} for (let itemIndex = 1; itemIndex < this.possibleItems.length; itemIndex += 1) {
for (let weightIndex = 1; weightIndex <= this.weightLimit; weightIndex += 1) {
const currentItemWeight = this.possibleItems[itemIndex]._weight;
const currentItemValue = this.possibleItems[itemIndex]._value; if (currentItemWeight > weightIndex) {
knapsackMatrix[itemIndex][weightIndex] = knapsackMatrix[itemIndex - 1][weightIndex];
} else {
knapsackMatrix[itemIndex][weightIndex] = Math.max(
currentItemValue + knapsackMatrix[itemIndex - 1][weightIndex - currentItemWeight],
knapsackMatrix[itemIndex - 1][weightIndex],
);
}
}
}
// console.log(knapsackMatrix) let itemIndex = this.possibleItems.length - 1;
let weightIndex = this.weightLimit;
while (itemIndex > 0) {
const currentItem = this.possibleItems[itemIndex];
const prevItem = this.possibleItems[itemIndex - 1];
console.log('-----',currentItem,'---\n');
if (
knapsackMatrix[itemIndex][weightIndex]
&& knapsackMatrix[itemIndex][weightIndex] === knapsackMatrix[itemIndex - 1][weightIndex]
) {
const prevSumValue = knapsackMatrix[itemIndex - 1][weightIndex];
const prevPrevSumValue = knapsackMatrix[itemIndex - 2][weightIndex];
if (
!prevSumValue
|| (prevSumValue && prevPrevSumValue !== prevSumValue)
) {
this.selectedItems.push(prevItem);
}
} else if (knapsackMatrix[itemIndex - 1][weightIndex - currentItem._weight]) {
// console.log(currentItem._weight, currentItem.weight)
this.selectedItems.push(prevItem);
weightIndex -= currentItem._weight;
}
itemIndex -= 1;
console.log(knapsackMatrix)
} } solveUnboundedKnapsackProblem() {
// this.sortPossibleItemsByValue();
this.sortPossibleItemsByValuePerWeightRatio();
console.log(this.possibleItems);
// console.log(this.sortPossibleItemsByWeight());
for (let itemIndex = 0; itemIndex < this.possibleItems.length; itemIndex += 1) {
if (this.totalWeight < this.weightLimit) {
const currentItem = this.possibleItems[itemIndex]; const availableWeight = this.weightLimit - this.totalWeight; const maxPossibleItemsCount = Math.floor(availableWeight / currentItem._weight); if (maxPossibleItemsCount > currentItem.itemsInStock) { currentItem.quantity = currentItem.itemsInStock;
} else if (maxPossibleItemsCount) {
currentItem.quantity = maxPossibleItemsCount;
} this.selectedItems.push(currentItem);
}
}
}
solveCoinProblem() {
this.sortCoinByWeight() for (let itemIndex = 0; itemIndex < this.possibleItems.length; itemIndex += 1) {
if (this.possibleItems[itemIndex]._weight <= this.weightLimit) { const currentItem = this.possibleItems[itemIndex];
const availableWeight = this.weightLimit - this.totalWeight;
const maxPossibleItemsCount = Math.floor(availableWeight / currentItem._weight); if (maxPossibleItemsCount > currentItem.itemsInStock) {
currentItem._quantity = currentItem.itemsInStock; } else if (maxPossibleItemsCount && maxPossibleItemsCount > 0) {
currentItem._quantity = maxPossibleItemsCount;
} if(!maxPossibleItemsCount){
currentItem._quantity = maxPossibleItemsCount;
} this.selectedItems.push(currentItem);
}
}
}
get totalValue() {
/** @var {KnapsackItem} item */
return this.selectedItems.reduce((accumulator, item) => {
return accumulator + item.totalValue;
}, 0);
} get totalWeight() {
/** @var {KnapsackItem} item */
return this.selectedItems.reduce((accumulator, item) => {
return accumulator + item.totalWeight;
}, 0);
}
get countCoin() {
return this.selectedItems.reduce((accumulator, item) => {
return accumulator + item._quantity;
}, 0);
}
get getLastProcduct() {
// console.log(fp.last(this.selectedItems));
return fp.last(this.selectedItems);
}
set setLastProcductValue(value) {
fp.last(this.selectedItems).value = value;
}
set setLastProcductWeight(weight) {
fp.last(this.selectedItems).weight = weight
}
}
class KnapsackItem { constructor({ value, weight, itemsInStock = 1 ,produce}) {
// this.value = value;
// this.weight = weight;
this._value = value;
this._weight = weight;
this.itemsInStock = itemsInStock;
this.produce = produce;
this.quantity = 1;
} get totalValue() {
return this._value * this.quantity;
} get totalWeight() {
return this._weight * this.quantity;
} get valuePerWeightRatio() {
return this._value / this._weight;
}
set value(value) {
this._value = value;
}
set weight(weight) {
this._weight = weight;
}
toString() { return `购买的物品为:${this.produce} 价格为: ${this._value} 体积为: ${this._weight}`;
} } class CoinItem {
constructor({weight, itemsInStock = 1000}) {
this._weight = weight;
this.itemsInStock = itemsInStock;
this._quantity = 1;
} get totalWeight() {
return this._weight * this._quantity;
} set weight(weight) {
this._weight = weight;
}
set quantity (quantity) {
this._quantity = quantity;
}
toString() {
return `币值为: ${this._weight} 数量为: ${this._quantity}`;
} }
const possibleKnapsackItems = [
new KnapsackItem({produce: '啤酒', value: 24, weight: 10 }),//2.4
new KnapsackItem({produce: '汽水', value: 2, weight: 3 }),//0.6
new KnapsackItem({produce: '饼干', value: 9, weight: 4 }),//2.2
new KnapsackItem({produce: '面包', value: 10, weight: 5 }),//2
new KnapsackItem({produce: '牛奶', value: 9, weight: 4 }),//2.2
]; let maxKnapsackWeight = 13; //动态规划
const dynamicKnapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight);
dynamicKnapsack.solveZeroOneKnapsackProblem();
console.log(`总价格为${dynamicKnapsack.totalValue} 总体积为${dynamicKnapsack.totalWeight}`);
dynamicKnapsack.selectedItems.map(x => console.log(x.toString()));
/*
*/
// maxKnapsackWeight = 13;
/*
//贪心算法
const greedyKnapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight);
greedyKnapsack.solveUnboundedKnapsackProblem();
let lasted = greedyKnapsack .totalWeight - maxKnapsackWeight
if(lasted === 0){
console.log(`总价格为${greedyKnapsack.totalValue} 总体积为${greedyKnapsack .totalWeight}`);
greedyKnapsack.selectedItems.map(x => console.log(x.toString()));
}else{
let lastProduce = greedyKnapsack.getLastProcduct;
let lastValueRatio = lastProduce.valuePerWeightRatio.toFixed(2);
let lastProduceWeight = lastProduce._weight - lasted;
let lastProduceValue = lastValueRatio * lastProduceWeight;
greedyKnapsack.setLastProcductValue = lastProduceValue;
greedyKnapsack.setLastProcductWeight = lastProduceWeight;
// console.log(greedyKnapsack.setLastProcductValue = lastValueRatio)
// console.log(lastProduceWeight, lastProduceValue)
console.log(`总价格为${greedyKnapsack.totalValue} 总体积为${greedyKnapsack.totalWeight}`);
greedyKnapsack.selectedItems.map(x => console.log(x.toString()));
}
*/
/*
//贪心算法找硬币
const coin = [
new CoinItem({ weight: 25 }),//2.4
new CoinItem({ weight: 10 }),//0.6
new CoinItem({ weight: 5 }),//2.2
new CoinItem({ weight: 1 }),//2.2 ];
let searchCoin = [5, 17, 22, 35];
searchCoin.map(x => {
console.log('----------------------------------\n');
console.log(`找 ${x} 分钱的最佳方案为:`)
const greedyCoin = new Knapsack(coin, x);
greedyCoin.solveCoinProblem();
console.log(`总币值为${greedyCoin.totalWeight} 总硬币数目为 ${greedyCoin.countCoin}`);
greedyCoin.selectedItems.filter(x => x._quantity > 0).map(x => console.log(x.toString()));
console.log('\n----------------------------------');
});
*/
// console.log(greedyCoin.selectedItems);
动态规划二 & 贪心算法 实验三的更多相关文章
- JavaScript算法模式——动态规划和贪心算法
动态规划 动态规划(Dynamic Programming,DP)是一种将复杂问题分解成更小的子问题来解决的优化算法.下面有一些用动态规划来解决实际问题的算法: 最少硬币找零 给定一组硬币的面额,以及 ...
- 算法(C#版)动态规划和贪心算法
https://blog.csdn.net/kouzhuanjing1849/article/details/88954811
- 二叉树遍历问题、时间空间复杂度、淘汰策略算法、lru数据结构、动态规划贪心算法
二叉树的前序遍历.中序遍历.后序遍历 前序遍历 遍历顺序规则为[根左右] ABCDEFGHK 中序遍历 遍历顺序规则为[左根右] BDCAEHGKF 后序遍历 遍历顺序规则为[左右根] DCBHKGF ...
- poj_1042 贪心算法
poj 1042 gone fishing 题目要求: 由有n个湖, 按照顺序排列,一个人从第一个湖向最后一个湖行进(方向只能从湖0到湖n-1),途中可以在湖中钓鱼.在每个湖中钓鱼时,开始的5分钟内可 ...
- 20172308 实验三《Java面向对象程序设计 》实验报告
20172308 2017-2018-2 <程序设计与数据结构>实验三报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 周亚杰 学号:20172308 实验教师:王 ...
- 20172319 实验三 《敏捷开发与XP实践》 实验报告
20172319 2018.05.17-30 实验三 <敏捷开发与XP实践> 实验报告 课程名称:<程序设计与数据结构> 学生班级:1723班 学生姓名:唐才铭 学生学号:20 ...
- 201971010110-高杨 实验三 结对项目—《{0-1}KP 实例数据集算法实验平台》项目报告
项目内容 项目 内容 班级博客链接 https://edu.cnblogs.com/campus/xbsf/2019nwnucs 作业要求 https://edu.cnblogs.com/campus ...
- 贪心算法和动态规划[zz]
http://www.cnblogs.com/asuran/archive/2010/01/26/1656399.html 贪心算法 1.贪心选择性质 所谓贪心选择性质是指所求问题的整体最优解可以通过 ...
- 「面试高频」二叉搜索树&双指针&贪心 算法题指北
本文将覆盖 「字符串处理」 + 「动态规划」 方面的面试算法题,文中我将给出: 面试中的题目 解题的思路 特定问题的技巧和注意事项 考察的知识点及其概念 详细的代码和解析 开始之前,我们先看下会有哪些 ...
- leetcode 55 Jump Game 三种方法,回溯、动态规划、贪心
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
随机推荐
- ArcMap手动新建矢量要素的方式
本文介绍在ArcGIS下属ArcMap软件中,新建点.线.面等矢量要素图层,并对新建图层的空间范围加以划定的方法. 首先,在右侧"Catalog"栏中选择需要存放新建立矢量 ...
- 2023-05-27:给你一个只包含小写英文字母的字符串 s 。 每一次 操作 ,你可以选择 s 中两个 相邻 的字符,并将它们交换。 请你返回将 s 变成回文串的 最少操作次数 。 注意 ,输入数据
2023-05-27:给你一个只包含小写英文字母的字符串 s . 每一次 操作 ,你可以选择 s 中两个 相邻 的字符,并将它们交换. 请你返回将 s 变成回文串的 最少操作次数 . 注意 ,输入数据 ...
- 浅谈 ByteHouse Projection 优化实践
预聚合是 OLAP 系统中常用的一种优化手段,在通过在加载数据时就进行部分聚合计算,生成聚合后的中间表或视图,从而在查询时直接使用这些预先计算好的聚合结果,提高查询性能,实现这种预聚合方法大多都使用物 ...
- “古老”编程语言的最新选择!华为云发布CodeArts IDE for C/C++
摘要:华为云CodeArts IDE for C/C++正式上线,欢迎体验. 本文分享自华为云社区<"古老"编程语言的最新选择!华为云发布CodeArts IDE for C ...
- ChatGPT教我用200行代码写一个简版Vue框架 - OpenTiny
AI 是未来最好的老师 最近,我正在准备一份关于 Vue 基础的学习材料.期间我突发奇想:能否利用现在热门的 ChatGPT 帮我创建学习内容?其实 Vue 本身不难学,特别是基础用法,但是,如果你想 ...
- Helm实战案例二:在Kubernetes(k8s)上使用helm安装部署日志管理系统EFK
目录 一.系统环境 二.前言 三.日志管理系统EFK简介 四.helm安装EFK 4.1 helm在线安装EFK 4.2 helm离线安装EFK(推荐) 五.访问kibana 5.1 数据分片 六.卸 ...
- vivo 游戏黑产反作弊实践
作者:vivo 互联网安全团队 - Cai Yifan 在数字化.移动化的浪潮下,游戏产业迅速发展,尤其疫情过后许多游戏公司业务迎来新的增长点. 游戏行业从端游开始一直是黑灰产活跃的重要场景.近年来, ...
- kafka学习笔记02
kafka拥有与其他几个消息队列同样的本事: ①缓冲/削峰:控制和优化数据经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况. 应用场景:双十一秒杀活动,将用户消息写入消息队列中,我 ...
- 跨越HTTP无状态边界:Cookie与Session在Django中的实战应用
本文深入探索了Django中的Cookie和Session,解析了如何应对HTTP协议的无状态性问题,说明其基础概念,分析工作原理,并讨论何时应选择使用Cookie或Session.文章进阶部分,提出 ...
- PerfView专题 (第十四篇): 洞察那些 C# 代码中的短命线程
一:背景 1. 讲故事 这篇文章源自于分析一些疑难dump的思考而产生的灵感,在dump分析中经常要寻找的一个答案就是如何找到死亡线程的生前都做了一些什么?参考如下输出: 0:001> !t T ...