《数位DP》Numehehaaaaaa(解题报告)

HTTP 代理服务器的设计与实现 HTTP 代理服务器的设计与实现 首先当然是最重要的代码:github地址 1) 实验目的 熟悉并掌握 Socket 网络编程的过程与技术;深入理解 HTTP 协议,掌握 HTTP 代理服 务器的基本工作原理;掌握 HTTP 代理服务器设计与编程实现的基本技能。 2) 实验内容 基于 java 实现了基本功能与全部附加功能,并增加了 https 的支持 (1) 设计并实现一个基本 HTTP 代理服... 阅读详情

零、题目描述

题目链接:Numehehaaaaaa
题目要求:
输入 t 组测试用例,每组给定一个整数 n,请输出大于等于 n 的最小整数,使得该整数的十进制表示中包含子串“114514”(即“114514”作为连续字符出现)。

示例(假设):

  • 若输入 n = 114513,输出 114514(直接包含模式串);
  • 若输入 n = 114515,输出 1000000 + 114514 = 1114514(需找下一个包含模式串的数)。

一、算法概述

本题采用 “数位动态规划(数位DP)+ 状态机 + 二分查找” 的组合算法,核心思路如下:

  1. 数位DP + 状态机:设计数位DP统计“0到x中包含子串‘114514’的数的个数”。其中,状态机用于追踪当前数位匹配模式串的进度,确保高效识别模式串;
  2. 二分查找:利用“0到x中符合条件的数的个数”的单调性(x越大,个数越多),通过二分查找找到“大于等于n的最小x”,使得x是第一个包含“114514”的数。

该算法的优势在于:

  • 数位DP解决了“大数字范围计数”的问题(避免直接枚举导致的超时);
  • 状态机精准追踪模式串匹配进度,确保不遗漏符合条件的数;
  • 二分查找将“找最小数”转化为“验证计数差”,效率极高。

二、算法思路

2.1 核心问题拆解

本题的核心是两个子问题:

  • 子问题1:如何快速计算 f(x) = 0到x中包含“114514”的数的个数?
  • 子问题2:如何基于 f(x) 找到大于等于n的最小x,使得 f(x) - f(n-1) = 1(即x是n之后第一个包含模式串的数)?

2.2 子问题1:数位DP + 状态机实现 f(x)

2.2.1 状态机设计(模式串匹配核心)

目标是匹配子串“114514”,需设计状态机追踪当前匹配进度:

  • 状态定义:用 data0 表示当前匹配到模式串的第 k 个字符(k ∈ 0~6):
    • 0:初始状态(未匹配任何字符);
    • 1:匹配到第1个字符“1”;
    • 2:匹配到第2个字符“1”(即“11”);
    • 3:匹配到第3个字符“4”(即“114”);
    • 4:匹配到第4个字符“5”(即“1145”);
    • 5:匹配到第5个字符“1”(即“11451”);
    • 6:完全匹配(即“114514”,终止状态)。
  • 转移规则:用二维数组 mat[7][10] 存储状态转移,mat[cur_state][digit] 表示“当前状态为 cur_state 时,输入数字 digit 后转移到的新状态”。例如:
    • mat[0][1] = 1(初始状态遇“1”,匹配第1个字符);
    • mat[5][4] = 6(匹配到“11451”后遇“4”,完全匹配);
    • mat[6][d] = 1(完全匹配后,遇任何数字均回到“匹配第1个‘1’”的状态,不影响后续计数)。
2.2.2 数位DP状态设计

数位DP的递归状态需包含以下信息:

  • depth:当前枚举到的数位位置(从高位到低位);
  • is_leadingzero:是否存在前导零(如“00123”的前导零不影响实际数值);
  • is_limit:当前数位是否受原数 x 的限制(如 x=123,枚举到百位为1时,十位最多为2;若百位为0,十位无限制);
  • dpdata:自定义状态(含 data0 状态机进度、data1 是否已找到模式串)。
2.2.3 数位DP流程
  1. 初始化:dpdata 初始化为 data0=0(未匹配)、data1=0(未找到模式串);
  2. 递归出口:当枚举完所有数位(depth == num.size()),返回 data1(1表示找到模式串,0表示未找到);
  3. 记忆化剪枝:若当前状态已计算过,直接返回缓存结果(避免重复计算);
  4. 枚举数位:根据 is_limit 确定当前数位的最大值,遍历所有可能的数字;
  5. 状态转移:根据当前数字更新 is_leadingzero、is_limit 和 dpdata(通过 getNextDpData 函数更新状态机进度和 data1);
  6. 递归累加:累加所有子状态的结果,存入缓存并返回。

2.3 子问题2:二分查找找最小x

由于 f(x) 是单调递增函数(x越大,包含模式串的数越多),可通过二分查找定位最小x:

  • 二分范围:
    • 左边界 l = n(从n开始找);
    • 右边界 r = (n/1e6 + 1)*1e6 + 114514(保守上界,确保包含至少一个符合条件的数);
  • 二分逻辑:
    1. 计算 lans = f(n)(0到n中符合条件的数的个数);
    2. 取中点 mid = (l + r) / 2,计算 cnt = f(mid) - lans;
    3. 若 cnt >= 1:说明 mid 及左侧存在符合条件的数,调整 r = mid;
    4. 若 cnt < 1:说明 mid 左侧无符合条件的数,调整 l = mid;
    5. 当 l + 1 < r 时重复,最终 r 即为最小x。

三、代码实现

代码分为 模板框架 和 自定义逻辑 两部分,核心自定义逻辑集中在状态机和状态转移。

3.1 宏定义与结构体

#include <iostream>
#include <map>
#include <cstring>
#include <string>
using namespace std;

#define ll long long
#define maxd 65          // 最大数位(十进制65位足够覆盖大整数)
#define MEMORY_USE_MAP   // 启用map记忆化(灵活处理状态,避免数组大小限制)

// 自定义DP状态:存储状态机进度和是否找到模式串
struct DpData {
    ll data0;  // 状态机进度(0~6,对应匹配模式串的0~6个字符)
    ll data1;  // 是否已找到模式串(1=是,0=否)
    static ll K;    // 预留参数(本题未用)
    static ll base; // 进制(十进制=10)

    // 构造函数
    DpData(): data0(0), data1(0) { init(); }
    DpData(ll d0, ll d1): data0(d0), data1(d1) {}

    // map排序需要的比较运算符
    bool operator<(const DpData& d) const {
        return data0 != d.data0 ? data0 < d.data0 : data1 < d.data1;
    }

    // 自定义逻辑:初始化DP状态
    void init() { data0 = 0; data1 = 0; }
    // 自定义逻辑:递归出口返回值
    ll dfsReturn(bool is_leadingzero) const {
        return is_leadingzero ? 0 : data1; // 前导零视为无意义,返回0
    }
    // 自定义逻辑:状态转移
    DpData getNextDpData(bool is_leadingzero, int digit) const;
};

// 静态成员初始化
ll DpData::K = 0;
ll DpData::base = 10;

3.2 状态机转移表与核心函数

// 状态机转移表:mat[当前状态][输入数字] = 下一状态
int mat[7][10] = {
    {0,1,0,0,0,0,0,0,0,0}, // 状态0(初始):遇1→1,其他→0
    {0,2,0,0,0,0,0,0,0,0}, // 状态1(匹配"1"):遇1→2,其他→0/1
    {0,2,0,0,3,0,0,0,0,0}, // 状态2(匹配"11"):遇4→3,其他→0/1
    {0,1,0,0,0,4,0,0,0,0}, // 状态3(匹配"114"):遇5→4,其他→0/1
    {0,5,0,0,0,0,0,0,0,0}, // 状态4(匹配"1145"):遇1→5,其他→0/1
    {0,2,0,0,6,0,0,0,0,0}, // 状态5(匹配"11451"):遇4→6,其他→0/1
    {0,1,0,0,0,0,0,0,0,0}  // 状态6(匹配"114514"):遇任何→1(已找到,不影响)
};

// 状态转移实现:根据当前状态和数字更新DP状态
DpData DpData::getNextDpData(bool is_leadingzero, int digit) const {
    DpData ret = *this;
    if (is_leadingzero) {
        if (digit == 0) {
            // 前导零+当前为0:保持前导零,状态机不变
            ret.data0 = 0;
        } else {
            // 前导零+当前非0:取消前导零,更新状态机
            ret.data0 = mat[0][digit];
        }
    } else {
        // 无中导零:直接按状态机转移
        ret.data0 = mat[ret.data0][digit];
    }
    // 若已找到模式串(data1=1),则保持1;否则检查是否刚匹配成功
    ret.data1 = ret.data1 || (ret.data0 == 6);
    return ret;
}

3.3 数位DP模板(dfs与getans)

// 记忆化数组/Map:dp[深度][前导零][限制][DP状态] = 计数
#ifdef MEMORY_USE_MAP
map<DpData, ll> dp[maxd][2][2];
#else
#define data0_max 7  // 状态机最多7个状态(0~6)
#define data1_max 2  // data1只有0/1
ll dp[maxd][2][2][data0_max][data1_max];
#endif

// 数位DP递归函数
ll dfs(const string& num, int depth, bool is_leadingzero, bool is_limit, DpData dpdata) {
    // 1. 递归出口:枚举完所有数位
    if (depth == num.size()) {
        return dpdata.dfsReturn(is_leadingzero);
    }

    // 2. 记忆化返回
#ifdef MEMORY_USE_MAP
    map<DpData, ll>& memo = dp[depth][is_leadingzero][is_limit];
    auto it = memo.find(dpdata);
    if (it != memo.end()) return it->second;
#else
    ll& ans = dp[depth][is_leadingzero][is_limit][dpdata.data0][dpdata.data1];
    if (ans != -1) return ans;
#endif

    // 3. 枚举当前数位的可能值
    ll ans = 0;
    int max_digit = is_limit ? (num[depth] - '0') : (DpData::base - 1); // 数位上限
    for (int digit = 0; digit <= max_digit; ++digit) {
        // 更新子状态
        bool new_leadingzero = is_leadingzero && (digit == 0);
        bool new_limit = is_limit && (digit == max_digit);
        DpData new_dpdata = dpdata.getNextDpData(is_leadingzero, digit);

        // 递归累加子状态结果
        ans += dfs(num, depth + 1, new_leadingzero, new_limit, new_dpdata);
    }

    // 4. 记忆化存储
#ifdef MEMORY_USE_MAP
    memo[dpdata] = ans;
#endif
    return ans;
}

// 计算[0, n]中包含模式串的数的个数
ll getans(ll n) {
    // 初始化记忆化
#ifdef MEMORY_USE_MAP
    for (int i = 0; i < maxd; ++i)
        for (int j = 0; j < 2; ++j)
            for (int k = 0; k < 2; ++k)
                dp[i][j][k].clear();
#else
    memset(dp, -1, sizeof(dp));
#endif

    // 数字转字符串(高位在前)
    string s;
    if (n == 0) s = "0";
    else {
        int a[maxd], asize = 0;
        while (n) { a[asize++] = n % 10; n /= 10; }
        for (int i = asize - 1; i >= 0; --i) s.push_back('0' + a[i]);
    }

    // 启动数位DP
    DpData dpd;
    return dfs(s, 0, true, false, dpd);
}

// 计算[l, r]中包含模式串的数的个数
ll getans(ll l, ll r) {
    return getans(r) - getans(l - 1);
}

3.4 主函数(二分查找逻辑)

int main() {
    int t;
    cin >> t;
    while (t--) {
        ll n;
        scanf("%lld", &n);

        // 二分查找边界:右边界确保包含答案
        ll lans = getans(n);
        ll l = n, r = (n / 1000000 + 1) * 1000000 + 114514;

        // 二分查找最小x
        while (l + 1 < r) {
            ll mid = (l + r) >> 1;
            if (getans(mid) - lans >= 1) {
                r = mid; // mid左侧可能有答案
            } else {
                l = mid; // mid左侧无答案
            }
        }

        printf("%lld\n", r);
    }
    return 0;
}

四、算法解释

4.1 状态机核心逻辑

状态机是本题识别模式串的关键,mat 数组的设计直接决定匹配准确性:

  • 例如,当处于状态5(已匹配“11451”)时,若当前数字是4,mat[5][4] = 6,data1 设为1(标记找到模式串);
  • 若已找到模式串(data1=1),后续状态转移不改变 data1,确保即使后续数位不匹配,也不会“忘记”已找到的模式串。

4.2 前导零处理

前导零不影响实际数值(如“00114514”等价于“114514”),因此:

  • 若存在前导零且当前数字为0,is_leadingzero 保持为true,data0 仍为0(未开始匹配);
  • 若当前数字非0,is_leadingzero 设为false,开始按状态机匹配模式串。

4.3 记忆化的作用

数位DP的状态空间较小(maxd×2×2×7×2 ≈ 3.6×10³),记忆化可避免重复计算相同状态,将时间复杂度从“指数级”降至“多项式级”,确保处理大数字时不超时。

4.4 二分查找的合理性

f(x) 单调递增的证明:对任意 x1 < x2,[0, x1] 是 [0, x2] 的子集,因此 f(x1) ≤ f(x2)。基于单调性,二分查找可高效定位最小x。

五、复杂度分析

5.1 时间复杂度

  1. 数位DP单次计算(getans(x)):

    • 状态总数:depth × is_leadingzero × is_limit × data0 × data1 = 65 × 2 × 2 × 7 × 2 ≈ 3.6×10³;
    • 每个状态枚举10个数字(十进制),因此单次 getans(x) 时间为 O(3.6×10³ × 10) = O(3.6×10⁴)。
  2. 二分查找:

    • 二分次数:log2(r - l),其中 r 最多为 n + 1e6,因此次数约为 20;
    • 单次测试用例时间:O(20 × 3.6×10⁴) = O(7.2×10⁵)。
  3. 多组测试用例:若 t ≤ 100,总时间为 O(100 × 7.2×10⁵) = O(7.2×10⁷),远低于时间限制。

5.2 空间复杂度

  • 记忆化空间:
    • 若用Map:存储所有状态,空间为 O(3.6×10³)(每个状态的Map条目);
    • 若用数组:dp[65][2][2][7][2],总大小约 65×2×2×7×2 = 3640 个 ll,仅占 3640×8 ≈ 29KB,空间开销极小。
皮肤病识别 - 使用DenseNet或EfficientNet模型在ISIC数据集上进行皮肤病识别任务 在本篇博客中,我们探讨了如何使用 DenseNet 和 EfficientNet 模型在 ISIC 数据集上进行皮肤病识别任务。我们加载了数据集,并进行了预处理。然后我们使用 Keras 构建了两个不同的模型,并训练和评估了它们。最后,我们使用训练好的模型对新的皮肤病图像进行了预测。 阅读详情

相关推荐

告别重复劳动:用Python+pywinauto打造你的微信个人助理(自动回复/收款/定时发消息)

本文介绍如何利用Python和pywinauto库构建微信个人助手,实现自动回复、定时消息、智能收款等功能,告别重复劳动。通过详细的代码示例和配置指南,帮助开发者快速掌握微信自动化技术,提升工作效率。

weixin_42568801的博客 328

深度干货 | 万字长文详解数位dp,超详细题集汇总

史上最通俗易懂,最简单,最全面的数位dp习题集,帮你扫清各种数位dp难题,背诵一套模板秒杀各种数位dp!!!

qq_45832461的博客 1176

华为交换机密码策略配置避坑指南:明文/密文、长度、复杂度,一个命令就出错

本文详细解析华为交换机密码策略配置的关键要点,包括密码长度、复杂度及等保合规要求。通过实战案例揭示常见配置误区,如明文/密文密码格式差异、复杂度检查联动机制等,帮助网络工程师避免安全漏洞。特别针对等保二级和三级要求,提供可直接落地的安全加固方案。

weixin_30879169的博客 367

数位dp详解,记忆化搜索,递推,OJ精讲

数位dp要学会总结出一套模板

EQUINOX1的博客 3189

基于RYU+Mininet的SDN校园网络实战:从零搭建虚拟化实验环境

本文详细介绍了如何利用RYU控制器和Mininet搭建SDN校园网络实验环境,从Ubuntu虚拟机准备到网络拓扑设计,再到关键网络功能实现。通过实战案例展示SDN在校园网络中的应用优势,包括简化配置、提升效率等,为网络工程师和学生提供了一套完整的虚拟化实验方案。

weixin_30872499的博客 455

别再手动连线了!用Tessent IJTAG的SIB和TDR,5分钟搞定复杂芯片的DFT网络分区

本文探讨了如何利用Tessent IJTAG的SIB(Segment Insertion Bit)和TDR(Test Data Register)技术,高效解决复杂芯片DFT网络分区问题。通过智能化的扫描链管理和声明式定义,显著降低连接复杂度,提升测试覆盖率和良率,适用于超大规模SoC设计。

weixin_29251131的博客 300

《数位DP》题集

本文整理了作者英雄哪里出来在抖音算法课程中的配套数位DP题集,分为模板题、课内题和课后题三部分。模板题和课内题作为必做题包含二进制处理、相邻数位差、模式匹配等基础题型,均有视频讲解;课后题则按数位个数统计、相邻数位差、模式匹配、数位和/乘积等分类扩展了近百道经典题目,覆盖HDOJ、蓝桥、洛谷和力扣平台。作者建议先独立完成必做题,选做题则可根据竞赛需求酌情练习,以提升模板熟练度和题型识别能力。该题集系统性地构建了数位DP的知识体系,适合算法竞赛选手循序渐进地训练。

英雄哪里出来 1169

从零学懂车载 TSN(二):802.1AS、Qbv、Qbu 是如何让 Ethernet “按时发送”的?

假设有两台设备: ECU A 认为: 但 Switch B 认为: 如果我们规定: 问题就来了。ECU:Switch:整个调度立即失效。因此 TSN 要做时间调度,第一件事就是:这就是:IEEE 802.1AS 定义时间敏感网络里的:工程中通常会看到:gPTP也就是:generalized Precision Time Protocol可以先简单理解成: 核心表达:所有 TSN 节点使用共同时间。后面抓包时你会经常遇到: 刚入门时不用急着研究每个 bit。先搞清楚它们解决什么问题。两个设备连接: A 需要知

struggle_22_58的博客 47

【数据结构】基于比较的排序算法 - 交换排序

本文介绍交换排序中的冒泡排序与快速排序。冒泡排序通过相邻元素比较交换,实现升序,时间复杂度最坏为O(N²),空间复杂度O(1),稳定且适合小规模有序数据。快速排序采用分治思想,以基准值划分区间,平均时间复杂度O(N log N),空间复杂度O(log N),但不稳定,实际应用中性能优异,可通过随机基准、小区间优化等提升效率。

careathers的博客 316

2025年7月5日全国青少年信息素养大赛Python编程初中组复赛真题+答案解析

2025年7月5日全国青少年信息素养大赛Python编程初中组复赛真题+答案解析

伶俐角少儿编程 464

【eclipse】win 10:eclipse 4.9 下载、安装和汉化(支持中英切换)

目录 一、eclipse下载 二、eclipse安装 三、eclipse在线汉化 四、eclipse离线汉化(推荐) 一、eclipse下载 ①官网下载地址(收费):https://www.eclipse.org/downloads/点击前往下载 ②【推荐】我的百度网盘下载地址(包括离线汉化包):点击下载 提取码:0nfw ③eclipse4.9其他地址下载:http...

顾三殇 —— 博客空间(软件测试) 1万+

pandas 深度入门:从数据结构到一份真实销售报表

本文系统讲解Pandas核心应用,从三分钟安装到完整月度报表生成,涵盖数据读取、清洗、筛选、分组聚合、表连接、透视表与时间序列等13个关键环节。强调“先看数据再动手”,掌握Series/DataFrame/Index结构本质,熟练运用loc/iloc、merge校验、agg/transform区别,通过真实案例实现高效报表自动化,告别手动Excel操作。最后提供性能优化与高频报错解决方案,助力读者快速上手,真正实现“写二十行代码,跑三秒出结果”。

信息安全领域优质创作者|操作系统领域专家 238

导数与微分在 FPS 射击游戏中的实际应用:把“手感”算出来

摘要:射击游戏开发中,单线程适用于简单小游戏(如单机打靶),所有任务由主线程顺序处理,代码简单但效率较低;多线程则适合复杂场景(如多人在线3D大作),通过渲染、逻辑、网络、音效等线程分工协作,确保画面流畅、响应迅速和实时同步。选择依据取决于游戏复杂度、联网需求和性能要求,小型游戏用单线程,大型高要求项目必须采用多线程架构。(149字)

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 3278

工单系统的数据结构化:故障分类体系设计与报表可用性

很多团队上完工单系统半年,会发现一个尴尬的事实:单子照常在走,报表却始终出不来。导出的 Excel 几千行,看不出趋势、算不出口径、答不了"哪类故障占大头"。问题几乎都不在系统,而在数据模型的第一层——。这篇文章把这件事拆开讲:自由文本为什么会失效、分类体系怎么分层、表怎么建、老数据怎么迁、上线前怎么验收。

ITyunwei0987的博客 266

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【Linux进程(二)】深入 Linux 内核:进程状态切换与底层数据结构的秘密

本文从操作系统理论与Linux内核源码双重视角,深入解析进程状态的底层机制。通过“侵入式链表”与“偏移量计算”揭示task_struct如何同时存在于多类数据结构中,实现高效调度与管理。结合ps命令与实战代码,详解R、S、T、Z、X等状态的成因与行为,涵盖前后台切换、暂停/恢复、僵尸进程、孤儿进程等典型场景,揭示进程生命周期的完整图景,实现“知其然更知其所以然”。

wacsii的博客 289

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

数据结构:9.Map和Set

有的讲解会说这里key是标识作用,这种说法其实没有太大意义,就算知道了他是标识value的作用又如何,在实际的使用过程中,我们只会根据具体的效果选择使用的方法等,不会执着于“标识”这种说法。2.由于哈希函数的设计原则太过理论,它仅仅是在认为:这些通过关键码算出来的index不同 的情况下设计的,然而这种理论化的设计原则在遇到冲突时,恰恰就出现了问题,而我们能做的,就是降低冲突率。虽然哈希表的使用过程中存在冲突,但是在实际的使用过程中,哈希表的冲突率是不高的,冲突的个数是可控的。

2602_95646088的博客 183

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

[C++高阶数据结构·图论下] 最短路径:为什么“挑最小的”一定正确?

本文系统对比最小生成树与最短路径的核心差异,聚焦三类最短路算法:Dijkstra(非负权、贪心确认)、Bellman-Ford(可负权、反复松弛)、Floyd(全源、分层中转)。核心区别在于:MST 关注“连通所有点”的最小代价(边数固定),而最短路关注“两点间路径最短”(边数可变)。关键反直觉点是:负权对 MST 无害,却使 Dijkstra 失效——因“绕远更近”破坏贪心前提。算法本质反映三种处理不确定性的策略:确认式(Dijkstra)、迭代修正(Bellman-Ford)、分层逼近(Floyd)。强

Tairitsu_青云 497

[C++高阶数据结构·图论上] 最小生成树:为什么“选边”和“选点”是两条路?

本文系统讲解最小生成树(MST)的核心思想与两大算法:Kruskal与Prim。强调MST目标是用最小权值总和连接所有顶点形成一棵树,而非单边最小。通过三条构造准则(用图中边、恰n-1条边、无环)统一框架。Kruskal按边贪心,依赖并查集判环,适合稀疏图;Prim按点扩张,利用割集特性天然避免成环,需起点,适合稠密图。两算法本质差异在于“判环”机制与数据结构选择,且与最短路径问题在连通性、负权处理上截然相反,需分篇厘清。

Tairitsu_青云 204

Vue3 低代码移动表单设计器实战(二):缩放画布下的拖拽系统与树状级联数据结构

本文深入剖析Vue3低代码表单设计器在缩放画布下的拖拽失效问题,揭示SortableJS在CSS Transform下坐标崩溃的数学根源。通过自研独立视觉克隆壳层与逆向几何补偿算法,实现精准拖拽;采用扁平数据存储+运行时树状计算结构,解决级联依赖与深克隆难题,确保逻辑一致性与性能优化,为复杂低代码系统提供可复用的工程范式。

NanChen的博客 330

排序算法深度笔记(上):比较类排序的思想演进与代码实现

与。本文聚焦前者 —— 也就是通过元素间两两比较来确定相对顺序的排序算法,从最朴素的 O (n²) 基础排序,到工业级主流的 O (nlogn) 进阶排序,逐层拆解设计思想、带注释的代码实现与边界细节。当我们理解了比较排序的性能边界,也就自然引出了非比较排序的存在意义。所有代码均遵循统一的实现规范:入口函数前置空数组与单元素边界校验,基于数组原地修改,主函数附带可直接运行的测试用例,与练习代码风格完全对齐。

2401_87069538的博客 474

【数据结构】静态 & 动态顺序表

顺序存储来实现线性表:链式存储实现线性表:存放在一段,数据元素之间的逻辑关系由物理存储关系体现:存储在,数据元素之间的逻辑关系用来表示:且大小固定()的数组:可以自动调节大小()的数组。

2301_80694580的博客 183

数据结构:双向链表实现,链表与顺序表的对比

本节讲解数据结构双向链表,链表和顺序表的特点对比,顺便解释了一下什么是CPU缓存和内存碎片

lei_jiale的博客 363

【数据结构-3】算法美学之降复杂度

在while循环的循环体内,首先用临时变量保存最后一个位置的数据,再通过for循环把所有元素往后移动一位,最后把tmp中保存的值放到下标为0的位置上去。方法二的思路是:创建新数组,让原数组中后k个数据移动到新数组中前面的位置,让原数组中前numsSize-k个数据移动到新数组中后面的位置,这。这段代码的思路是:三次逆置,第一次逆置前numsSize-k个数据,第二次逆置后k个数据,最后整体逆置。这篇博文分享一道解法不一的算法题,求解过程的目的在于降低算法的时间复杂度,题源力扣。,属于空间换时间的操作。

weixin_44218929的博客 77

【数据结构-2】顺序表的实现

线性表是一种数据结构,它分为逻辑结构和物理结构,在逻辑结构上线性表是呈线性的,数据是是连续存储的;在物理结构(物理空间)上,线性表不一定是连续存储的。线性表的实现,主要分为数组和链式结构。顺序表是线性表的一种实现方式,顺序表在逻辑结构和物理结构上都是连续的。顺序表的底层实现是数组。

weixin_44218929的博客 201

数据结构(2)

不同点顺序表链表(单链表)存储空间上物理上一定连续逻辑上连续,但物理上不一定连续随机访问支持:O(1)不支持:O(N)任意位置插入或删除元素可能需要搬移元素,效率低 O(N)只需修改指针指向插入动态顺序表,空间不够时需要扩容和空间浪费没有容量的概念,按需申请释放,不存在空间浪费应用场景元素高效存储 + 频繁访问任意位置高效插入和删除。

likexuec的博客 116

数据结构—B树

一棵m(m>2)阶的B树,是一棵平衡的M路平衡树,可以说空树或满足以下6点。1.根节点至少有两个孩子2.每个分支节点都包含k-1个关键字和k个孩子,ceil(m/2)<=k<=m;孩子比关键字多一个ceil向上取整3.每个叶子节点都包含k-1个关键字,ceil(m/2)<=k<=m;4.所有的叶子节点在同一层。5.每个节点中的关键字从小到大排列,节点当中k-1个元素正好是k个孩子包含元素的值域划分。6.节点的结构是{n,A0,K1,A1,K2,........Kn,An};

fish_xk的博客 122
上一篇: 迷茫,985大三,考研还是找工作?
下一篇: 由豆包编程生成的挂机升级游戏
英雄哪里出来
英雄哪里出来 2021年博客之星Top1 2021年博客之星Top1 领域专家: 系统编程技术领域 领域专家: 系统编程技术领域
博客等级 码龄17年 30万+粉丝 1016原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄哪里出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值