双11购物的凑单问题与财务凑数问题

news2024/11/25 20:21:56


📢作者: 小小明-代码实体

📢博客主页:https://blog.csdn.net/as604049322

📢欢迎点赞 👍 收藏 ⭐留言 📝 欢迎讨论!

📢本文链接:https://xxmdmst.blog.csdn.net/article/details/128437285

凑单问题

对于各类凑单问题,最经典的就是淘宝双十一的满减促销活动,比如“满 200 元减 50 元”。假设你的购物车中有 n 个(n>100)想买的商品,希望从里面选几个,在凑够满减条件的前提下,让选出来的商品价格总和最大程度地接近满减条件(200 元),如何编程解决这个问题?

动态规划解决

使用传统的编程思路就是使用动态规划,思路如下:

购物车中有 n 个商品,针对每个商品都决策是否购买。每次决策之后,对应不同的状态集合。用一个二维数组 s t a t e s [ n ] [ x ] states[n][x] states[n][x],来记录每次决策之后所有可达的状态。

python实现代码为:

def double11advance(items_info: list, w: int):
    """
    动态规划解决双11凑单问题
    :param items_info: 每个商品价格
    :param w: 满减条件,比如 200
    :return:
    """
    n = len(items_info)
    # 超过 3 倍就没有薅羊毛的价值了
    states = [[False] * (3 * w + 1) for i in range(n)]
    states[0][0] = True
    states[0][items_info[0]] = True
    for i in range(1, n):
        for j in range(3 * w + 1):
            if states[i - 1][j]:
                # 不购买第i个商品
                states[i][j] = states[i - 1][j]
                # 购买第i个商品
                nw = j + items_info[i]
                if nw <= 3 * w:
                    states[i][nw] = True
    j = w
    while j < 3 * w + 1 and not states[n - 1][j]:
        j += 1
    # j是大于等于 w 的最小值
    if j == 3 * w + 1:
        return  # 没有可行解
    idx = []
    for i in range(n - 1, 0, -1):
        if j - items_info[i] >= 0 and states[i - 1][j - items_info[i]]:
            idx.append(i)
            j -= items_info[i]
    if j != 0:
        idx.append(0)
    return sorted(idx)

假设,我们的购物车中每件商品的价格为:

48, 30, 19, 36, 36, 27, 42, 42, 36, 24,  40, 70, 32

我们执行代码:

import numpy as np
items_info = np.array([48, 30, 19, 36, 36, 27, 42, 42, 36, 24,  40, 70, 32])

idx = double11advance(items_info, 200)
print("选中商品的索引:", idx)
print("选中商品的价格:", items_info[idx])
print("总价格:", sum(items_info[idx]))
选中商品的索引: [1, 4, 7, 8, 9, 12]
选中商品的价格: [30 36 42 36 24 32]
总价格: 200

可以看到程序完美的找到了一组可行解。

除了动态规划,我们还可以使用回溯算法解决,参考代码就不公布了,接下来我们直接使用优化算法解决这个问题。

优化算法解决

在前面的文章《OR-Tools官档中文用法大全(CP、LP、VRP、Flows等)》中的 背包与装箱问题 一章中,我演示了使用SCIP求解器解决该问题。

不过SCIP求解器速度较慢,而且想获取多个可行解实现起来较为麻烦,所以这里我演示使用ortools的cp_model求解器来解决该问题。

cp_model求解器相对于前面的SCIP求解器的缺点在于只能处理整数。

代码如下:

from ortools.sat.python import cp_model
import numpy as np

model = cp_model.CpModel()
items_info = np.array([48, 30, 19, 36, 36, 27, 42, 42, 36, 24,  40, 70, 32])
items = np.arange(items_info.shape[0])
x = [model.NewBoolVar(f'x_{i}') for i in range(len(items_info))]
obj = (x*items_info).sum()
model.Add(obj >=200)
model.Minimize(obj)
solver = cp_model.CpSolver()
status = solver.Solve(model)
result = [bool(solver.Value(i)) for i in x]
print("选中商品的索引:", items[result])
print("选中商品的价格:", items_info[result])
print("总价格:", items_info[result].sum())
选中商品的索引: [ 1  4  7  8  9 12]
选中商品的价格: [30 36 42 36 24 32]
总价格: 200

可以看到 ortools 库得到了与前面动态规划一致的结果。

ortools获取多个可行解

下面我们考虑使用cp_model求解器获取多个可行解,前面我们已经可行解的最小值为200,下面我们可以限制总价格等于200:

from ortools.sat.python import cp_model
import numpy as np


class MyCpSolver(cp_model.CpSolverSolutionCallback):
    def __init__(self, x):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self.x = x
        self.num = 0

    def on_solution_callback(self):
        self.num += 1
        print(f"第{self.num}个解")
        result = [bool(self.Value(i)) for i in self.x]
        print("选中商品的索引:", items[result])
        print("选中商品的价格:", items_info[result])
        print("总价格:", items_info[result].sum())


model = cp_model.CpModel()
items_info = np.array([48, 30, 19, 36, 36, 27, 42, 42, 36, 24,  40, 70, 32])
items = np.arange(items_info.shape[0])
x = [model.NewBoolVar(f'x_{i}') for i in range(len(items_info))]
obj = (x*items_info).sum()
model.Add(obj == 200)
solver = cp_model.CpSolver()
myCpSolver = MyCpSolver(x)
solver.parameters.enumerate_all_solutions = True
status = solver.Solve(model, myCpSolver)
print(solver.StatusName(status))
print("解的个数:", myCpSolver.num)

最终得到了30个可行解:

image-20221225161243648

如此多的可行解是因为36出现了三次,导致可行解的个数也被翻了3倍,实际可行解就只有10个。下面我们改进一下上面代码,让其获取唯一的可行解:

from collections import Counter
from ortools.sat.python import cp_model
import numpy as np


class MyCpSolver(cp_model.CpSolverSolutionCallback):
    def __init__(self, x):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self.x = x
        self.num = 0

    def on_solution_callback(self):
        self.num += 1
        print(f"第{self.num}个解")
        idx = []
        result = []
        for i, xi in enumerate(self.x):
            v = self.Value(xi)
            if v == 0:
                continue
            idx.append(i)
            result.extend([items_info[i]]*v)
        print("选中商品的索引:", idx)
        print("选中商品的价格:", result)
        print("总价格:", sum(result))


arr = [48, 30, 19, 36, 36, 27, 42, 42, 36, 24,  40, 70, 32]

model = cp_model.CpModel()
items_info = []
x = []
for i, (k, v) in enumerate(Counter(arr).items(), 1):
    items_info.append(k)
    x.append(model.NewIntVar(0, v, f"x{i}"))
items_info = np.array(items_info)
obj = (items_info*x).sum()
model.Add(obj == 200)
solver = cp_model.CpSolver()
myCpSolver = MyCpSolver(x)
solver.parameters.enumerate_all_solutions = True
status = solver.Solve(model, myCpSolver)
print(solver.StatusName(status))
print("解的个数:", myCpSolver.num)
第1个解
选中商品的索引: [1, 2, 4, 5, 7]
选中商品的价格: [30, 19, 27, 42, 42, 40]
总价格: 200
第2个解
选中商品的索引: [2, 3, 4, 5, 7]
选中商品的价格: [19, 36, 36, 27, 42, 40]
总价格: 200
第3个解
选中商品的索引: [2, 4, 5, 8]
选中商品的价格: [19, 27, 42, 42, 70]
总价格: 200
第4个解
选中商品的索引: [0, 2, 3, 4, 8]
选中商品的价格: [48, 19, 36, 27, 70]
总价格: 200
第5个解
选中商品的索引: [0, 2, 4, 5, 6, 7]
选中商品的价格: [48, 19, 27, 42, 24, 40]
总价格: 200
第6个解
选中商品的索引: [0, 1, 2, 3, 4, 7]
选中商品的价格: [48, 30, 19, 36, 27, 40]
总价格: 200
第7个解
选中商品的索引: [0, 5, 7, 8]
选中商品的价格: [48, 42, 40, 70]
总价格: 200
第8个解
选中商品的索引: [1, 3, 6, 7, 8]
选中商品的价格: [30, 36, 24, 40, 70]
总价格: 200
第9个解
选中商品的索引: [1, 3, 5, 6, 9]
选中商品的价格: [30, 36, 36, 42, 24, 32]
总价格: 200
第10个解
选中商品的索引: [0, 3, 5, 9]
选中商品的价格: [48, 36, 42, 42, 32]
总价格: 200
OPTIMAL
解的个数: 10

可以看到顺利的获取到唯一解。

财务凑数问题

财务凑数问题与前面的问题模型一致,区别在于存在小数,例如从一大批金额中找出能够合并出指定金额的组合。

假设我们要查找的金额列表如下:

7750.0, 50000.0, 94693.0, 89159.18, 59000.0, 19634.94, 27000.0, 37770.17, 55631.64, 23800.0,
20000.0, 20000.0, 20000.0, 72985.45, 48000.0, 48000.0, 58750.0, 22000.0, 11219.61, 45600.0,
90500.0, 84288.0, 930.0, 1352.0, 120.0, 750.0, 22880.0, 45678.0, 49555.0, 17181.54, 1925.0,
1500.0, 83325.0, 500.0, 1298.5, 36936.34, 91933.67, 5205.0, 20195.0, 20550.0, 10600.0, 3200.0,
6400.0, 6900.0, 9900.0, 9750.0, 9600.0, 7200.0, 15208.41, 10550.0, 21077.02, 75437.51, 73515.11,
3140.0, 85128.6, 87095.74, 22806.24, 961.72, 13285.47, 28980.0, 67997.62, 35955.33, 12890.27, 15459.47,
20124.58, 25246.66, 13216.11, 89400.0, 89400.0, 26800.0, 11365.0, 16457.0, 50000.0, 54309.0, 12000.0,
39000.0, 70569.5, 45231.5, 56400.0, 86400.0, 86400.0, 86400.0, 86400.0, 12000.0, 390.0, 2500.0, 38109.79,
5968.63, 14862.6, 45038.91, 63189.17, 80784.86, 37664.87, 4981.44, 50000.0, 50000.0, 32323.01, 567.73, 66056.88, 26400.0

我们需要找到95984的组合。

SCIP求解器直接计算

如果使用SCIP求解器可以直接计算结果,编码如下:

from ortools.linear_solver import pywraplp
import numpy as np

arr = [7750.0, 50000.0, 94693.0, 89159.18, 59000.0, 19634.94, 27000.0, 37770.17, 55631.64, 23800.0,
       20000.0, 20000.0, 20000.0, 72985.45, 48000.0, 48000.0, 58750.0, 22000.0, 11219.61, 45600.0,
       90500.0, 84288.0, 930.0, 1352.0, 120.0, 750.0, 22880.0, 45678.0, 49555.0, 17181.54, 1925.0,
       1500.0, 83325.0, 500.0, 1298.5, 36936.34, 91933.67, 5205.0, 20195.0, 20550.0, 10600.0, 3200.0,
       6400.0, 6900.0, 9900.0, 9750.0, 9600.0, 7200.0, 15208.41, 10550.0, 21077.02, 75437.51, 73515.11,
       3140.0, 85128.6, 87095.74, 22806.24, 961.72, 13285.47, 28980.0, 67997.62, 35955.33, 12890.27, 15459.47,
       20124.58, 25246.66, 13216.11, 89400.0, 89400.0, 26800.0, 11365.0, 16457.0, 50000.0, 54309.0, 12000.0,
       39000.0, 70569.5, 45231.5, 56400.0, 86400.0, 86400.0, 86400.0, 86400.0, 12000.0, 390.0, 2500.0, 38109.79,
       5968.63, 14862.6, 45038.91, 63189.17, 80784.86, 37664.87, 4981.44, 50000.0, 50000.0, 32323.01, 567.73, 66056.88, 26400.0]

items_info = np.array(arr)
items = np.arange(items_info.shape[0])
solver = pywraplp.Solver.CreateSolver('SCIP')
x = [solver.BoolVar(f'x_{i}') for i in range(len(items_info))]
obj = (x*items_info).sum()
solver.Add(obj >= 95984)
solver.Minimize(obj)
status = solver.Solve()
print("总重量:", obj.solution_value())
result = np.frompyfunc(lambda x: x.solution_value(), 1, 1)(x).astype(bool)
print("选中商品的索引:", items[result])
print("选中商品的价值:", items_info[result])
print("总价值:", items_info[result].sum())
总重量: 95984.3
选中商品的索引: [22 24 33 34 38 40 41 44 58 61]
选中商品的价值: [  930.     120.     500.    1298.5  20195.   10600.    3200.    9900.
 13285.47 35955.33]
总价值: 95984.3

不过这并不是真正的最优解,如果我们把约束设置为必须为目标值:

solver = pywraplp.Solver.CreateSolver('SCIP')
x = [solver.BoolVar(f'x_{i}') for i in range(len(items_info))]
obj = (x*items_info).sum()
solver.Add(obj == 95984)
status = solver.Solve()
print("总重量:", obj.solution_value())
result = np.frompyfunc(lambda x: x.solution_value(), 1, 1)(x).astype(bool)
print("选中商品的索引:", items[result])
print("选中商品的价值:", items_info[result])
print("总价值:", items_info[result].sum())
总重量: 95984.0
选中商品的索引: [ 5 18 25 30 38 39 43 45 53 57 84 97]
选中商品的价值: [19634.94 11219.61   750.    1925.   20195.   20550.    6900.    9750.
  3140.     961.72   390.     567.73]
总价值: 95984.0

可惜耗时接近10秒。

cp_model求解器

cp_model求解器只能处理整数,为了能够处理小数,我们可以将其乘以100后转换为整数:

from ortools.sat.python import cp_model
import numpy as np

arr = [7750.0, 50000.0, 94693.0, 89159.18, 59000.0, 19634.94, 27000.0, 37770.17, 55631.64, 23800.0,
       20000.0, 20000.0, 20000.0, 72985.45, 48000.0, 48000.0, 58750.0, 22000.0, 11219.61, 45600.0,
       90500.0, 84288.0, 930.0, 1352.0, 120.0, 750.0, 22880.0, 45678.0, 49555.0, 17181.54, 1925.0,
       1500.0, 83325.0, 500.0, 1298.5, 36936.34, 91933.67, 5205.0, 20195.0, 20550.0, 10600.0, 3200.0,
       6400.0, 6900.0, 9900.0, 9750.0, 9600.0, 7200.0, 15208.41, 10550.0, 21077.02, 75437.51, 73515.11,
       3140.0, 85128.6, 87095.74, 22806.24, 961.72, 13285.47, 28980.0, 67997.62, 35955.33, 12890.27, 15459.47,
       20124.58, 25246.66, 13216.11, 89400.0, 89400.0, 26800.0, 11365.0, 16457.0, 50000.0, 54309.0, 12000.0,
       39000.0, 70569.5, 45231.5, 56400.0, 86400.0, 86400.0, 86400.0, 86400.0, 12000.0, 390.0, 2500.0, 38109.79,
       5968.63, 14862.6, 45038.91, 63189.17, 80784.86, 37664.87, 4981.44, 50000.0, 50000.0, 32323.01, 567.73, 66056.88, 26400.0]
model = cp_model.CpModel()
items_info = (np.array(arr)*100).astype(int)
items = np.arange(items_info.shape[0])
x = [model.NewBoolVar(f'x_{i}') for i in range(len(items_info))]
obj = (x*items_info).sum()
model.Add(obj == 95984*100)
solver = cp_model.CpSolver()
status = solver.Solve(model)
print(solver.StatusName(status))
result = [bool(solver.Value(i)) for i in x]
print("选中商品的索引:", items[result])
print("选中商品的价格:", items_info[result]/100)
print("总价格:", items_info[result].sum()/100)
OPTIMAL
选中商品的索引: [ 0 23 24 41 42 47 53 70 71 75]
选中商品的价格: [ 7750.  1352.   120.  3200.  6400.  7200.  3140. 11365. 16457. 39000.]
总价格: 95984.0

获取多个可行解

可以看到财务的金额数据存在大量重复,所以必须先进行计数处理,最终代码为:

from collections import Counter
from ortools.sat.python import cp_model
import numpy as np


class MyCpSolver(cp_model.CpSolverSolutionCallback):
    def __init__(self, x):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self.x = x
        self.num = 0

    def on_solution_callback(self):
        self.num += 1
        print(f"第{self.num}个解")
        idx = []
        result = []
        for i, xi in enumerate(self.x):
            v = self.Value(xi)
            if v == 0:
                continue
            idx.append(i)
            result.extend([items_info[i]/100]*v)
        print("选中商品的索引:", idx)
        print("选中商品的价格:", result)
        print("总价格:", sum(result))


arr = [7750.0, 50000.0, 94693.0, 89159.18, 59000.0, 19634.94, 27000.0, 37770.17, 55631.64, 23800.0,
       20000.0, 20000.0, 20000.0, 72985.45, 48000.0, 48000.0, 58750.0, 22000.0, 11219.61, 45600.0,
       90500.0, 84288.0, 930.0, 1352.0, 120.0, 750.0, 22880.0, 45678.0, 49555.0, 17181.54, 1925.0,
       1500.0, 83325.0, 500.0, 1298.5, 36936.34, 91933.67, 5205.0, 20195.0, 20550.0, 10600.0, 3200.0,
       6400.0, 6900.0, 9900.0, 9750.0, 9600.0, 7200.0, 15208.41, 10550.0, 21077.02, 75437.51, 73515.11,
       3140.0, 85128.6, 87095.74, 22806.24, 961.72, 13285.47, 28980.0, 67997.62, 35955.33, 12890.27, 15459.47,
       20124.58, 25246.66, 13216.11, 89400.0, 89400.0, 26800.0, 11365.0, 16457.0, 50000.0, 54309.0, 12000.0,
       39000.0, 70569.5, 45231.5, 56400.0, 86400.0, 86400.0, 86400.0, 86400.0, 12000.0, 390.0, 2500.0, 38109.79,
       5968.63, 14862.6, 45038.91, 63189.17, 80784.86, 37664.87, 4981.44, 50000.0, 50000.0, 32323.01, 567.73, 66056.88, 26400.0]

model = cp_model.CpModel()
items_info = []
x = []
for i, (k, v) in enumerate(Counter(arr).items(), 1):
    items_info.append(k)
    x.append(model.NewIntVar(0, v, f"x{i}"))
items_info = (np.array(items_info)*100).astype(int)
obj = (items_info*x).sum()
model.Add(obj == 95984*100)
solver = cp_model.CpSolver()
myCpSolver = MyCpSolver(x)
solver.parameters.enumerate_all_solutions = True
status = solver.Solve(model, myCpSolver)
print(solver.StatusName(status))
print("解的个数:", myCpSolver.num)

最终再经过一小时的等待后,并未找出全部的可行解,程序还在运行中,1小时找到一千多个可行解:

image-20221225185130100

为了避免计算时间过长,我们可以设置最大执行时间,例如设置30秒:

solver.parameters.max_time_in_seconds = 30

可以看到30秒内能够找到45个解:

image-20221225185604004

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Chapter3 P-N Junction

3-2 热平衡状态 电流只在一个方向很容易通过&#xff0c;正方向很容易通过电流&#xff0c;负方向很不容易 正电压加在Ptype上才会有电流 就会产生如图b的现象 electron 一定要从high concentration移动到low concentration 所以两个的移动方向如图所示 靠近junction附近&…

C#中window窗体和控件

C#中window窗体和控件 布局与事件–界面的基本问题 布局 就是拉动窗体的时候&#xff0c;按钮也在跟着变动。 事件 //简单的计算器 using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; namespa…

Web API事件高级部分

1、注册事件&#xff08;2种方式&#xff09; 给元素添加事件&#xff0c;称为 注册事件 或者 绑定事件 注册事件有两种方式&#xff1a;传统方式 和 监听注册方式 传统注册方式&#xff1a; 利用on开头的事件 onclick<button οnclick"alert(hi~)"></b…

供应化学试剂mPEG-Biotin,甲氧基-聚乙二醇-生物素

一&#xff1a;产品描述 1、名称 英文&#xff1a;mPEG-Biotin 中文&#xff1a;甲氧基-聚乙二醇-生物素 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a;Biotin PEG Methoxy PEG 4、分子量&#xff1a;可定制1k、2k、3.4k、10k、20k、5k 5、质量控制&#xff1a;95…

shell脚本四剑客--sed的应用

sed的介绍 sed是Linux下一款功能强大的非交互流式文本编辑器&#xff0c;可以对文本文件进行增、删、改、查等操作&#xff0c;支持按行、按字段、按正则匹配文本内容&#xff0c;灵活方便&#xff0c;特别适合于大文件的编辑 sed在处理文本时是逐行读取文件内容&#xff0c;…

TCP协议中的几个核心特性

目录 引言 TCP协议 &#x1f351;TCP 与 UDP 的 区别 &#x1f351;TCP客户端和服务器建立连接的三次握手 &#x1f351;TCP客户端和服务器断开连接的四次挥手 &#x1f351;滑动窗口 &#x1f351;流量控制 &#x1f351;拥塞控制 引言 还记得那个经典的图吗&#x…

TCP最大连接数调优

文章目录1、单机最大TCP连接数1.1、如何标识一个TCP连接1.2、client最大tcp连接数1.3、server最大tcp连接数1.3.1、理论连接数1.3.2、实际连接数1.4、单台服务器支撑的最大TCP并发连接数1.4.1、进程限制句柄限制查看进程句柄数限制临时修改重启后失效的修改&#xff08;不过我在…

IIC 通信协议 (二)

目录 引言 子模块设计 思路 单字节 IIC 发送模块 思路 Verilog 源码 多字节发送控制模块 思路 Verilog 源码 仿真 思路 test bench 仿真结果 参考声明 引言 本篇博文承接前文&#xff0c;继续做 IIC 通信协议 FPGA实现相关的内容。用Verilog 编写一个 IIC 通信控…

【折腾服务器 1】妖板 Intel N5105 + i226 主板安装 ESXi 7.0 教程

Catch Up 今年年初&#xff0c;开始搭建个人服务器&#xff0c;用的是一台 Dell 7010 SFF 主机&#xff0c;在上面部署了一些应用&#xff0c;例如&#xff1a;Calibre &#xff0c;Blogs &#xff0c;Minecraft Server 等。使用的是 frp 做的网络代理&#xff0c;有一台服务器…

cubeIDE开发, UART的CubeMX及HAL库实现原理及底层分析

一、UART通信协议 UART通用异步收发器(Universal Asynchronous Receiver and Transmitter)是STM32 上常用的串行通信外设&#xff0c;可以灵活地与外部设备进行全双工数据交换&#xff0c;需要注意区别&#xff1a; 【1】USART-通用同步异步收发器(Universal Synchronous Async…

<Linux线程互斥与死锁>——《Linux》

目录 1. Linux线程互斥 进程线程间的互斥相关背景概念 互斥量mutex 互斥量的接口 初始化互斥量 销毁互斥量 互斥量加锁和解锁 互斥量实现原理探究 可重入VS线程安全 概念 常见的线程不安全的情况 常见的线程安全的情况 常见不可重入的情况 常见可重入的情况 可重…

K. Lonely Numbers(线性筛 + 差分)

Problem - 1423K - Codeforces 在数字世界中&#xff0c;如果两个不同的数字有很多共同点&#xff0c;而且每个数字都有独特的好处&#xff0c;那么它们就是朋友。 更确切地说&#xff0c;如果gcd(a,b), agcd(a,b), bgcd(a,b)能组成一个三角形的边&#xff0c;那么两个不同的数…

六、应用层(四)电子邮件

目录 4.1 电子邮件系统的组成结构 4.2 简单邮件传输协议&#xff08;SMTP&#xff09; 4.3 电子邮件格式 4.4 多用途网际邮件扩充&#xff08;MIME&#xff09; 4.5 邮局协议&#xff08;POP3&#xff09;和因特网报文存取协议&#xff08;IMAP&#xff09; 4.6 基…

小黑下午第一场面试被鸽,一切遇见随缘,继续第二场的leetcode之旅:654. 最大二叉树

小黑代码 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def constructMaximumBinaryTree(self, nums: Li…

SAP UI5 应用里 FlexBox 控件的设计原理

sap.m.FlexBox 控件为 flexible box layout 构建容器。VBox 控件为垂直的框布局(vertical flexible box layout)构建容器。 VBox 是一种使用的控件&#xff0c;因为它只是一个定制化的 FlexBox 控件。 VBox 包含 items 聚合&#xff0c;从 FlexBox 继承而来。 HBox 控件为水平…

字符串函数

注意&#xff1a;MySQL中&#xff0c;字符串的位置是从1开始的。 ASCII(S) 返回字符串S中的第一个字符的ASCII码值. 与第一个字符后面的其他字符无关。 SELECTASCII(Abcdfsf) FROM DUAL;CHAR_LENGTH(s) 返回字符串s的字符数。作用与CHARACTER_LENGTH(s)相同。 SELECTCHAR_LEN…

生信基础知识

1.生物数据库分类 &#xff08;1&#xff09;核酸数据库&#xff08;2&#xff09;蛋白质数据库&#xff08;3&#xff09;专用数据库 核酸数据库分为一级核酸数据库和二级核酸数据库 蛋白质数据库分为一级蛋白质数据库和二级蛋白质数据库 一级蛋白质数据库又分为蛋白质序列…

【Redis】应用问题解决

一、缓存击穿 1、什么叫缓存击穿 系统中某个查询次数很多的热点key&#xff0c;在某个时刻过期&#xff0c;而此时又正好有大量并发请求查询这个key&#xff0c;但是缓存的重建还没有完成&#xff0c;这样&#xff0c;就会有大量请求涌向后端数据库&#xff0c;使得其压力骤增…

爱了,阿里P9开源分享内部Java核心开发手册(2022版)覆盖P5到P8

这个世界唯一不变的就是变化&#xff0c; IT圈子不外如是。计算机领域一直在改变&#xff0c;从基础框架到计算设备&#xff0c;还有几乎每天都涌现出的新技术。因此&#xff0c;作为一名程序开发人员&#xff0c;我们要通过不断的学习来提高自己的技能。 所以持续学习的脚步自…

基于C++11实现的阻塞队列(BlockQueue)

思路&#xff1a; 生产者消费者模型如图&#xff0c;多个生产者线程和多个消费者线程共享同一固定大小的缓冲区&#xff0c;它们的生产和消费符合以下规则&#xff1a; 生产者不会在缓冲区满的时候继续向缓冲区放入数据&#xff0c;而消费者也不会在缓冲区空的时候&#xff0c…