每日一题——力扣20. 有效的括号(举一反三+思想解读+逐步优化)


一个认为一切根源都是“自己不够强”的INTJ

个人主页:用哲学编程-CSDN博客
专栏:每日一题——举一反三
Python编程学习
Python内置函数

Python-3.12.0文档解读

目录

我的写法

专业点评

时间复杂度分析

空间复杂度分析

代码优化建议

我要更强

优化方案1:使用动态数组

优化方案2:使用有限状态机

优化方案3:简化逻辑(不使用动态内存分配)

总结

哲学和编程思想

优化方案1:使用动态数组

1. 动态内存管理

2. 抽象

3. 扩展性

4. 资源管理

优化方案2:使用有限状态机

1. 状态化思维

2. 确定性

3. 简化逻辑

优化方案3:简化逻辑(不使用动态内存分配)

1. 预分配

2. 空间时间权衡

3. 极简主义

通用编程思想

举一反三

1. 动态内存管理

2. 抽象与封装

3. 状态化思维与有限状态机

4. 预分配与空间时间权衡

5. 高内聚低耦合

6. 资源管理

总结


https://leetcode.cn/problems/valid-parentheses/description/


我的写法

#include <stdlib.h>


// 检查括号字符串是否有效的函数
bool isValid(char* s) {
    // 定义栈的顶部索引和底部索引
    int top = 0, bottle = 0;
    // 定义栈的大小
    int size = 10000;
    // 动态分配一个整型数组作为栈
    int* stack = (int*)malloc(size * sizeof(int));
    // 定义字符变量ch,用于遍历字符串
    int ch = ' ';


    // 遍历输入字符串
    for (int i = 0; (ch = s[i]) != '\0'; i++) {
        // 打印当前字符(用于调试)
        printf("%c", ch);
        // 如果字符是左括号之一,则将其压入栈中
        if (ch == '(' || ch == '{' || ch == '[') {
            stack[top++] = ch;
        } else {
            // 如果栈为空但遇到了右括号,说明不匹配
            if (top == 0) {
                return false;
            } else {
                // 检查栈顶与当前右括号是否匹配
                if (stack[top - 1] == '(' && ch == ')') {
                    top--; // 匹配则弹出栈顶
                } else if (stack[top - 1] == '{' && ch == '}') {
                    top--; // 匹配则弹出栈顶
                } else if (stack[top - 1] == '[' && ch == ']') {
                    top--; // 匹配则弹出栈顶
                } else {
                    // 不匹配则返回false
                    return false;
                }
            }
        }
    }
    // 遍历结束后,栈应该为空,如果不为空则返回false
    if (top != bottle) {
        return false;
    } else {
        return true; // 栈为空则返回true,表示字符串括号匹配
    }
}


 

这段代码实现了检查括号字符串是否有效的功能。下面是专业的点评和复杂度分析:

专业点评

  1. 代码结构与逻辑
    • 代码结构清晰:函数 isValid 逻辑清晰,分为遍历字符串、检查括号类型、维护栈等部分。
    • 使用栈数据结构合适:对括号匹配的问题,使用栈来解决是非常合适的,符合括号匹配的后进先出(LIFO)特性。
  2. 可能存在的改进点
  • 内存管理:代码中使用了 malloc 动态分配栈空间,但在函数结束时没有释放分配的内存。如果 isValid 函数在大规模使用时会造成内存泄漏问题,应该使用 free(stack) 释放内存。
  • 栈溢出检查:没有对 top 的值进行合法性检查,当字符过多时可能会导致栈溢出。可以通过动态调整栈大小来解决这个问题。
  • 无用的变量:bottle 变量并没有实际用途,可以移除。
  • 打印语句:printf("%c", ch); 用于调试的打印语句应在生产代码中删除,避免不必要的输出开销。

时间复杂度分析

  • 时间复杂度:O(n),其中 n 是字符串 s 的长度。
  • 遍历字符串的每一个字符需要 O(n) 的时间。
  • 每个字符的入栈和出栈操作在均摊情况下都是 O(1) 的时间复杂度,因此总时间复杂度为 O(n)。

空间复杂度分析

  • 空间复杂度:O(n),其中 n 是字符串 s 的长度。
  • 最坏情况下,所有的字符都是左括号(例如字符串全是 ((((((),此时栈的大小会达到字符串的长度。
  • 因此,栈的空间复杂度为 O(n)。

代码优化建议

bool isValid(char* s) {
    int top = 0;
    int size = 10000;
    int* stack = (int*)malloc(size * sizeof(int));
    if (stack == NULL) {
        return false; // 内存分配失败时返回false
    }
    int ch = ' ';
    for (int i = 0; (ch = s[i]) != '\0'; i++) {
        if (ch == '(' || ch == '{' || ch == '[') {
            stack[top++] = ch;
        } else {
            if (top == 0) {
                free(stack); // 释放内存
                return false;
            } else {
                if ((stack[top - 1] == '(' && ch == ')') ||
                    (stack[top - 1] == '{' && ch == '}') ||
                    (stack[top - 1] == '[' && ch == ']')) {
                    top--;
                } else {
                    free(stack); // 释放内存
                    return false;
                }
            }
        }
    }
    bool isValid = (top == 0);
    free(stack); // 释放内存
    return isValid;
}
  1. 内存管理:
  2. 动态调整栈大小(可选):
  • 如果预期字符串长度会很长,可以考虑动态调整栈大小以避免栈溢出。

总结来看,这段代码在逻辑上是正确的,但在内存管理和栈溢出检查方面还有优化空间。时间复杂度为 O(n),空间复杂度为 O(n),在大多数情况下表现良好。


我要更强

在括号匹配问题上,时间复杂度已经是最优的 O(n),因为每个字符都需要检查一次。空间复杂度的优化可能性有限,因为在最坏情况下,所有字符都是左括号或有嵌套括号时,仍然需要 O(n) 的空间来存储这些括号。但是,我们可以考虑一些具体的优化方法:

  1. 使用动态数组(矢量):动态调整栈的大小,以节省空间。
  2. 使用有限状态机:对某些特定情况可以优化,但一般情况下仍然需要 O(n) 的空间。

以下是几个优化方案及其实现代码:

优化方案1:使用动态数组

动态数组可以根据需要调整大小来节省空间。

#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

// 动态数组结构
typedef struct {
    char* data;
    int capacity;
    int size;
} Stack;

// 初始化动态数组
Stack* createStack(int initialCapacity) {
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->data = (char*)malloc(initialCapacity * sizeof(char));
    stack->capacity = initialCapacity;
    stack->size = 0;
    return stack;
}

// 释放动态数组
void freeStack(Stack* stack) {
    free(stack->data);
    free(stack);
}

// 动态数组压入元素
void push(Stack* stack, char value) {
    // 如果容量不足,增加容量
    if (stack->size == stack->capacity) {
        stack->capacity *= 2;
        stack->data = (char*)realloc(stack->data, stack->capacity * sizeof(char));
    }
    stack->data[stack->size++] = value;
}

// 动态数组弹出元素
char pop(Stack* stack) {
    return stack->data[--stack->size];
}

// 检查栈是否为空
bool isEmpty(Stack* stack) {
    return stack->size == 0;
}

// 检查栈顶元素
char top(Stack* stack) {
    return stack->data[stack->size - 1];
}

// 检查括号是否有效
bool isValid(char* s) {
    Stack* stack = createStack(128); // 初始容量设置为128
    for (int i = 0; s[i] != '\0'; i++) {
        char ch = s[i];
        if (ch == '(' || ch == '{' || ch == '[') {
            push(stack, ch);
        } else {
            if (isEmpty(stack)) {
                freeStack(stack);
                return false;
            }
            char topElement = top(stack);
            if ((topElement == '(' && ch == ')') ||
                (topElement == '{' && ch == '}') ||
                (topElement == '[' && ch == ']')) {
                pop(stack);
            } else {
                freeStack(stack);
                return false;
            }
        }
    }
    bool result = isEmpty(stack);
    freeStack(stack);
    return result;
}

优化方案2:使用有限状态机

有限状态机适用于某些特定的字符串匹配场景,但对于括号匹配,效果不如栈明显。不过,以下是使用有限状态机的简单版本:

#include <stdbool.h>

#define MAX_STATES 128

typedef struct {
    int transitions[MAX_STATES][256];
    int currentState;
} StateMachine;

// 初始化状态机
void initStateMachine(StateMachine* sm) {
    sm->currentState = 0;
    for (int i = 0; i < MAX_STATES; i++) {
        for (int j = 0; j < 256; j++) {
            sm->transitions[i][j] = -1;
        }
    }
}

// 设定状态转换
void setTransition(StateMachine* sm, int fromState, char input, int toState) {
    sm->transitions[fromState][(unsigned char)input] = toState;
}

// 处理输入字符
void processInput(StateMachine* sm, char input) {
    int nextState = sm->transitions[sm->currentState][(unsigned char)input];
    if (nextState != -1) {
        sm->currentState = nextState;
    }
}

// 检查括号是否有效
bool isValid(char* s) {
    StateMachine sm;
    initStateMachine(&sm);

    // 定义状态转换
    setTransition(&sm, 0, '(', 1);
    setTransition(&sm, 1, ')', 0);
    setTransition(&sm, 0, '{', 2);
    setTransition(&sm, 2, '}', 0);
    setTransition(&sm, 0, '[', 3);
    setTransition(&sm, 3, ']', 0);

    for (int i = 0; s[i] != '\0'; i++) {
        processInput(&sm, s[i]);
    }

    return sm.currentState == 0;
}

优化方案3:简化逻辑(不使用动态内存分配)

如果预先知道字符串长度不会过长,可以使用固定大小的数组来避免动态内存分配。

#include <stdbool.h>

#define MAX_LENGTH 10000

bool isValid(char* s) {
    char stack[MAX_LENGTH];
    int top = 0;

    for (int i = 0; s[i] != '\0'; i++) {
        char ch = s[i];
        if (ch == '(' || ch == '{' || ch == '[') {
            stack[top++] = ch;
        } else {
            if (top == 0) {
                return false;
            }
            char topElement = stack[top - 1];
            if ((topElement == '(' && ch == ')') ||
                (topElement == '{' && ch == '}') ||
                (topElement == '[' && ch == ']')) {
                top--;
            } else {
                return false;
            }
        }
    }
    return top == 0;
}

总结

上述优化方法中,第一种使用动态数组的方法是最为灵活和常用的,因为它可以根据需要动态调整栈的大小,避免不必要的内存浪费。第三种方法则适用于已知长度限制的场景,可以有效避免动态内存分配的开销。有限状态机的方法在括号匹配问题上不常用,但在某些特定模式匹配问题上可能会有用。


哲学和编程思想

这些优化方法应用了多种哲学和编程思想,具体如下:

优化方案1:使用动态数组

1. 动态内存管理
  • 哲学思想:最小化资源使用和避免浪费。
  • 编程思想:动态内存分配允许程序根据实际需要调整资源使用,避免过度分配。
2. 抽象
  • 哲学思想:抽象化有助于将复杂问题简化。
  • 编程思想:通过创建 Stack 结构体和相关操作函数,使栈的操作更加模块化、易于理解和维护。
3. 扩展性
  • 哲学思想:系统应该能够适应变化和增长。
  • 编程思想:动态调整栈的大小,使程序能够处理不同规模的数据,增强了程序的灵活性和适应性。
4. 资源管理
  • 哲学思想:有效管理和合理利用资源。
  • 编程思想:在使用动态内存时,确保在不再需要时释放内存,防止内存泄漏。

优化方案2:使用有限状态机

1. 状态化思维
  • 哲学思想:将复杂的过程分解为简单的状态和转移。
  • 编程思想:有限状态机通过明确定义状态和状态之间的转换,简化了复杂系统的设计和实现。
2. 确定性
  • 哲学思想:系统的每个输入都有确定的行为。
  • 编程思想:有限状态机确保每个输入在当前状态下的行为是确定的,有助于提高程序的可靠性和可预测性。
3. 简化逻辑
  • 哲学思想:简化逻辑以提高效率和减少错误。
  • 编程思想:通过有限状态机的方式处理输入,避免了复杂的条件判断和嵌套逻辑,使代码更加清晰和可维护。

优化方案3:简化逻辑(不使用动态内存分配)

1. 预分配
  • 哲学思想:在有限资源环境中优化资源的使用。
  • 编程思想:预先分配固定大小的数组,避免了动态内存分配的开销和复杂性,提高了程序的效率。
2. 空间时间权衡
  • 哲学思想:在时间效率和空间效率之间找到平衡。
  • 编程思想:使用固定大小的数组在空间上可能会浪费一些内存,但可以换取更高的时间效率,适用于已知数据规模的场景。
3. 极简主义
  • 哲学思想:以最简单和直接的方式解决问题。
  • 编程思想:通过使用固定大小数组和简单的条件判断,消除了不必要的复杂性,使代码更加简洁和高效。

通用编程思想

  1. 封装
    • 将数据和操作封装在一起,隐藏实现细节,提高代码的模块化和可维护性。例如,Stack 结构体和相关操作函数实现了栈的封装。
  2. 单一职责原则
    • 每个函数或模块只负责一项功能,提高代码的可读性和可维护性。例如,push、pop、isEmpty 等函数各自负责栈的不同操作。
  3. 责任分离
    • 将不同的功能和职责分离,避免模块之间的耦合。例如,状态机将状态转换逻辑和输入处理逻辑分离,提高了代码的灵活性。
  4. 高内聚,低耦合
    • 模块内部的各个部分紧密相关,而不同模块之间尽量松散耦合。例如,栈的操作函数和主逻辑分开实现,提高了代码的可维护性和复用性。
  5. 资源管理
  • 合理管理资源的分配和释放,避免资源泄漏和浪费。例如,动态数组在使用完后需要释放内存。

通过这些哲学和编程思想,可以更好地理解和优化代码,提高其性能、可维护性和扩展性。


举一反三

理解和应用编程哲学和思想可以大大提升你的编程技巧,以下是一些具体的技巧和建议,帮助你在编程时举一反三:

1. 动态内存管理

技巧:

  • 避免硬编码的大小:尽量不要使用硬编码的大小限制,除非你非常确定数据不会超过这个限制。
  • 动态扩展:学习如何使用动态内存分配(如 malloc、realloc 和 free),以便根据需要动态扩展数据结构的大小。
  • 内存管理工具:熟悉和使用内存调试工具(如 Valgrind)来检测内存泄漏和越界访问。

举一反三:

  • 在处理不确定大小的数据(如文件、网络数据流)时,考虑使用动态数组或链表等数据结构。
  • 当需要高效、快速地处理大量数据时,考虑使用哈希表、红黑树等动态数据结构。

2. 抽象与封装

技巧:

  • 模块化设计:将复杂的功能拆分为多个小模块,每个模块只负责一个功能。
  • 接口与实现分离:通过定义接口(如函数原型、类接口)来隐藏实现细节,减少模块之间的依赖。
  • 使用标准库:尽量使用标准库提供的数据结构和算法,避免重复造轮子。

举一反三:

  • 在设计大型系统时,考虑使用设计模式(如工厂模式、单例模式)来提高代码的可维护性和可扩展性。
  • 在团队开发中,制定和遵循接口规范,确保各模块之间的接口一致。

3. 状态化思维与有限状态机

技巧:

  • 状态图:在处理复杂流程时,先画出状态图,明确各个状态和状态之间的转换。
  • 状态机实现:使用二维数组或哈希表来实现状态机的状态转移,确保状态机的实现简洁明了。
  • 测试状态机:通过单元测试,确保状态机在各种输入下都能正确运行。

举一反三:

  • 在处理交互式应用(如游戏、用户界面)时,使用状态机来管理应用的各个状态。
  • 在处理协议解析(如网络协议、文件格式)时,使用状态机来确保解析过程的正确性和可靠性。

4. 预分配与空间时间权衡

技巧:

  • 预估数据规模:在启动时预估数据规模,并进行合理的资源分配,避免频繁的动态内存分配。
  • 缓冲区:在处理流数据时,使用缓冲区来提高数据处理效率。
  • 空间换时间:在对时间效率要求较高的场景中,可以适当增加内存使用,以换取更快的执行速度。

举一反三:

  • 在处理大量数据时,考虑使用批处理和缓冲区技术来减少处理开销。
  • 在实现缓存机制时,考虑使用合适的缓存策略(如 LRU 缓存)来提高系统性能。

5. 高内聚低耦合

技巧:

  • 单一职责原则:确保每个模块或函数只有一个明确的责任,提高代码的可读性和可维护性。
  • 接口隔离:设计良好的接口,确保模块之间的依赖最小化。
  • 依赖注入:通过依赖注入减少模块之间的耦合,提高模块的可测试性和灵活性。

举一反三:

  • 在设计类和模块时,考虑使用面向对象的设计原则(如 SOLID 原则)来提高代码质量。
  • 在大型项目中,使用依赖注入框架(如 Spring)来管理依赖关系,提高代码的灵活性和可维护性。

6. 资源管理

技巧:

  • 使用 RAII(资源获取即初始化):在 C++ 等语言中,通过构造函数获取资源,析构函数释放资源,确保资源的正确释放。
  • 引用计数:使用引用计数技术来管理共享资源,避免资源泄漏和双重释放。
  • 自动垃圾回收:在支持垃圾回收的语言中,尽量使用语言提供的自动垃圾回收机制,减少手动管理内存的复杂性。

举一反三:

  • 在处理文件、网络连接等资源时,确保在使用完后正确关闭和释放资源。
  • 在多线程环境中,使用智能指针或其他线程安全的资源管理技术,确保资源的正确释放和管理。

总结

通过理解这些编程思想和哲学,并在实际编程中应用这些技巧,你可以更高效地解决问题,提高代码的质量和可维护性。同时,保持学习和实践,不断积累经验,能够在各种编程场景中举一反三,灵活应用这些思想和技巧。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

强烈推荐|分享6款小而美的图片美化工具

给大家分享6个我日常用到的图片美化软件&#xff0c;都是免费且好用的&#xff0c;如果大家觉得有用&#xff0c;求一个点赞收藏&#xff0c;如果点赞收藏超过60&#xff0c;后续我会继续分享&#xff0c;谢谢大家&#xff5e; 文字卡片美化&#xff1a; https://www.memocar…

C语言实现贪吃蛇小游戏(控制台)

本篇主要内容是使用C语言在Windows环境的控制台中模拟实现经典小游戏贪吃蛇。 一、准备工作 我们要实现的基本功能有&#xff1a; 地图绘制蛇吃食物的功能&#xff08;上、下、左、右方向键控制蛇的动作&#xff09;蛇撞墙死亡蛇撞自身死亡计算得分蛇身加速、减速暂停游戏 …

数据恢复大革新!EasyRecovery16版本带来UIUX及性能的重大提升

全球领先的数据恢复解决方案提供商Ontrack与其中国区总代理近日共同宣布&#xff0c;其广受欢迎的数据恢复软件EasyRecovery16迎来了重大更新&#xff0c;版本号提升至v16.0.0.5。这一更新为用户带来了一系列值得关注的新功能和改进&#xff0c;进一步巩固了EasyRecovery在数据…

Android 输入法框架流程

输入法框架流程梳理 输入法框架构成 输入法管理端&#xff08;IMMS/InputMethodManagerService&#xff09; 主要负责输入法服务端与客户端的绑定&#xff1b;输入法的切换/显示/隐藏/启用/关闭。输入法服务端&#xff08;IMS/InputMethodService&#xff09; 输入法服务&…

【C++面试50题】

以下是针对C程序员面试可能遇到的一些问题&#xff0c;涵盖了从基础语法、面向对象、STL、内存管理、模板、异常处理、并发编程等多个方面。 ### 基础概念与语法 1. C与C的主要区别是什么&#xff1f; 2. 什么是构造函数和析构函数&#xff1f;它们何时被调用&#xff1f; 3. 什…

JDK版本特性(JDK8\11\17\21版本)

JDK版本特性 Oracle官网https://www.oracle.com/java/technologies/java-se-support-roadmap.html Oracle官网中JDK版本的说明&#xff0c;Java SE 8、11、17和21是LTS版本。也就是长期支持版本。 我们针对这几个版本了解学习下对应版本的新特性。 JDK8版本 正式发布于2014…

XCP协议系列介绍02-基于ASAP2 Tool-Set生成A2l介绍

本文框架 1. 前言2. ASAP2 Tool-Set系统介绍2.1 ASAP2 Creator介绍2.2 ASAP2 Updater介绍2.3 ASAP2 Merger介绍2.4 ASAP2 Comparer及Checker介绍2.5 ASAP2 Modifier介绍2.6 ASAP2 Studio介绍 3. 项目实操说明3.1 项目实操建议3.2 工具下载地址及使用 1. 前言 在XCP观测及标定整…

【自撰写,国际象棋入门】第1课、棋盘和棋子

第1课 棋盘和棋子 一、国际象棋的棋盘 国际象棋的棋盘为一8乘8的黑、白格相间的棋盘&#xff0c;8条竖线的编号分别为A-H&#xff0c;8条横线的编号分别为1-8&#xff0c;在记谱时用竖线编号横线编号的方式表示棋盘上的格子&#xff0c;例如a1格、h8格等.棋盘上有几条重要的大…

抖音 UG 社招一面算法原题

史上最严热点新机制 或许是受到前段时间「巴黎丢作业」的影响&#xff0c;抖音近日&#xff08;5月27日&#xff09;实施了新的热点内容核实机制。 具体来说&#xff0c;若用户在抖音以热点事件当事人身份发声&#xff0c;抖音将联系当事人进行身份认证。 逾期未认证的用户&…

基于springboot实现网络海鲜市场系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现网络海鲜市场系统演示 摘要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔阂给消除…

STM32作业实现(六)闪存保存数据

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

大学生Python自救课程总结

因为一些事情的缘故&#xff0c;我已经几乎没有更新很久了&#xff0c;然后现在快到期末了&#xff0c;不知道各位学习python的同志们慌不慌【坏笑】。 本学期&#xff0c;我只是简单的讲了讲python的基础用法。当然&#xff0c;可能有些地方总结的并不全面&#xff0c;很多知…

MyBatis 的在使用上的注意事项及其辨析

1. MyBatis 的在使用上的注意事项及其辨析 文章目录 1. MyBatis 的在使用上的注意事项及其辨析2. 准备工作3. #{ } 与 ${ } 的区别和使用3.1 什么情况下必须使用 ${ }3.1.1 拼接表名3.1.2 批量删除3.1.3 模糊查询3.1.3.1 使用 ${ }的方式3.1.3.2 使用 #{ } 的方式 4. typeAlias…

童心与美食的邂逅,蒙自源邀你共绘梦想画卷

激情夏日所带来的热情如同孩子们的梦想一样炽热而澎湃。为了庆祝六一儿童节&#xff0c;从5月25日起&#xff0c;蒙自源旗下各大门店准备了一系列的活动&#xff0c;以迎接这个属于孩子们的特别日子。 特别活动期间&#xff0c;蒙自源特意为孩子们推出了一系列独具特色的美食。…

Cobalt_Strike(CS)渗透工具安装使用到免杀上线

Cobalt_Strike&#xff08;CS&#xff09;安装到免杀上线 原文链接&#xff1a; cs免杀上线 点我 https://mp.weixin.qq.com/s?__bizMzkxNDY5NzMxNw&amp;mid2247483862&amp;idx1&amp;snc6b4da3ce5772a075431098227397baa&amp;chksmc16b3cdcf61cb5ca06f61513…

Flutter开发效率提升1000%,Flutter Quick教程之在特定位置插入Widget

当我们要将Widget插入一个Column,Row或者Listview等有多个子元素的Widget的时候&#xff0c;有两种情况&#xff0c;一种是顺序插入&#xff0c;一种是非顺序插入。顺序插入就是Widget的排列顺序和插入顺序相同&#xff0c;非顺序插入则不是。 一&#xff0c;顺序插入。如图所…

树莓派通过PCA9685控制FT2331M舵机(Python)

很久之前整过PWM舵机&#xff0c;刚好最近师弟需要&#xff0c;并且网上现有教程不是很完整&#xff0c;就整理一下。方便交流以及后面回顾。 首先要明确&#xff0c;在这个控制方式中需要用到哪些方面&#xff1a; 1、树莓派与PCA9685之间使用I2C通信 2、PCA9685通讯协议 3…

牛客网刷题 | BC113 数字三角形

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 KiKi学习了循环&am…

【Text2SQL 论文】DBCopilot:将 NL 查询扩展到大规模数据库

论文&#xff1a;DBCopilot: Scaling Natural Language Querying to Massive Databases ⭐⭐⭐⭐ Code: DBCopilot | GitHub 一、论文速读 论文认为目前的 Text2SQL 研究大多只关注具有少量 table 的单个数据库上的查询&#xff0c;但在面对大规模数据库和数据仓库的查询时时却…

RHEL7.9修改分区

系统RHEL7.9 他因为安装软件&#xff0c;需要修改分区 进入超级用户root&#xff0c;输入lsblk 查看分区&#xff0c;可见465.8G系统盘sda下有三个物理卷&#xff0c;其中sda3下/home有410.6G&#xff0c;需要这部分拆分出200G软件和100G的数据库分区 备份/home 目录下文件 c…