03/29 使用 海康SDK 对接时使用的 MysqlUtils

前言

最近朋友的需求, 是需要使用 海康sdk 连接海康设备, 进行数据的获取, 比如 进出车辆, 进出人员 

这一部分是 资源比较贫瘠时的一个 Mysql 工具类 

 

 

测试用例

public class MysqlUtils {

    public static String MYSQL_HOST = "192.168.31.9";
    public static int MYSQL_PORT = 3306;
    public static String MYSQL_DB = "20240811_vehicle_stats";
    public static String MYSQL_USERNAME = "root";
    public static String MYSQL_PASSWORD = "postgres";

    public static String COLUMN_CATM = "catm";
    public static String COLUMN_UPTM = "uptm";
    public static String SQL_DUMMY_SQL = "select 1;";

    public static boolean DEFAULT_ADD_CATM_UPTM = false;

    public static SingleStringColumnExtractor SINGLE_STRING_COLUMN_EXTRACTOR = new SingleStringColumnExtractor();
    public static GenericMapExtractor GENERIC_MAP_EXTRACTOR = new GenericMapExtractor();
    public static MyStatsVehicleFlowLogExtractor MY_STATISTICS_VEHICLE_FLOW_LOG_EXTRACTOR = new MyStatsVehicleFlowLogExtractor();
    public static MyStatsPeopleFlowLogExtractor MY_STATISTICS_PEOPLE_FLOW_LOG_EXTRACTOR = new MyStatsPeopleFlowLogExtractor();

    // disable constructor
    private MysqlUtils() {
        System.err.println("can't instantiate !");
    }

    // mysql jdbcDriver
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.err.println("can't found jdbcDriver !");
        }
    }

    public static void init() {
        MYSQL_HOST = ConfigUtils.getString("MYSQL_HOST", MYSQL_HOST);
        MYSQL_PORT = ConfigUtils.getInt("MYSQL_PORT", MYSQL_PORT);
        MYSQL_DB = ConfigUtils.getString("MYSQL_DB", MYSQL_DB);
        MYSQL_USERNAME = ConfigUtils.getString("MYSQL_USERNAME", MYSQL_USERNAME);
        MYSQL_PASSWORD = ConfigUtils.getString("MYSQL_PASSWORD", MYSQL_PASSWORD);

        DEFAULT_ADD_CATM_UPTM = ConfigUtils.getString("DEFAULT_ADD_CATM_UPTM", String.valueOf(DEFAULT_ADD_CATM_UPTM)).equalsIgnoreCase("true");
    }

    // 获取 jdbc 链接
    public static Connection getConnection(String ip, int port, String dbName, String userName, String password) {
        Connection con = null;
        try {
            con = DriverManager.getConnection(String.format("jdbc:mysql://%s:%d/%s?useUnicode=true&characterEncoding=UTF8", ip, port, dbName), userName, password);
        } catch (SQLException se) {
            se.printStackTrace();
            System.err.println("error while try to get an connection !");
        }

        return con;
    }

    public static Connection getConnection() {
        return MysqlUtils.getConnection(MYSQL_HOST, MYSQL_PORT, MYSQL_DB, MYSQL_USERNAME, MYSQL_PASSWORD);
    }

    // 执行 jdbc 查询
    public static <T> List<T> executeQuery(String sql, Function<ResultSet, T> recordExtractor) {
        Connection con = MysqlUtils.getConnection(MYSQL_HOST, MYSQL_PORT, MYSQL_DB, MYSQL_USERNAME, MYSQL_PASSWORD);
        PreparedStatement stat = null;
        ResultSet rs = null;
        List<T> result = new ArrayList<>();
        try {
            stat = con.prepareStatement(sql);
            rs = stat.executeQuery();
            while (rs.next()) {
                result.add(recordExtractor.apply(rs));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if(stat != null) {
                    stat.close();
                }
                if(rs != null) {
                    rs.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static List<Map<String, Object>> executeQuery(String sql) {
        return executeQuery(sql, GENERIC_MAP_EXTRACTOR);
    }

    // 执行 jdbc 更新
    public static int executeUpdate(String sql) {
        Connection con = MysqlUtils.getConnection(MYSQL_HOST, MYSQL_PORT, MYSQL_DB, MYSQL_USERNAME, MYSQL_PASSWORD);
        PreparedStatement stat = null;
        int updated = -1;
        try {
            stat = con.prepareStatement(sql);
            updated = stat.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if(stat != null) {
                    stat.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return updated;
    }


    public static String assembleInsertSql(String tableName, Map<String, Object> entity, boolean addCommonFields) {
        String insertSqlTemplate = " insert into %s (%s) values (%s); ";
        List<String> fieldNames = new ArrayList<>(), fieldValues = new ArrayList<>();
        for (String fieldName : entity.keySet()) {
            Object originalFieldValue = entity.get(fieldName);
            String fieldValue = resolveFieldValue(entity, fieldName, originalFieldValue);
            fieldNames.add(String.format("`%s`", fieldName));
            fieldValues.add(transferFieldValueIfNecessary(fieldValue));
        }
        if (addCommonFields) {
            Long currentTs = System.currentTimeMillis();
            addFixedFieldNames(fieldNames, currentTs, true);
            addFixedFieldValues(fieldValues, currentTs, true);
        }

        String sql = String.format(insertSqlTemplate, tableName,
                join(fieldNames, ", "),
                join(fieldValues, ", ")
        );
        return sql;
    }

    public static String assembleInsertSql(String tableName, Map<String, Object> entity) {
        return assembleInsertSql(tableName, entity, DEFAULT_ADD_CATM_UPTM);
    }

    public static String assembleBatchInsertSql(String tableName, List<Map<String, Object>> entityList, boolean addCommonFields) {
        String insertSqlTemplate = " insert into %s (%s) values %s; ";
        List<String> insertFieldNames = new ArrayList<>(), outerFieldValues = new ArrayList<>();
        Set<String> fieldNames = new LinkedHashSet<>();
        Long currentTs = System.currentTimeMillis();

        for (Map<String, Object> entity : entityList) {
            fieldNames.addAll(entity.keySet());
        }
        for (String fieldName : fieldNames) {
            insertFieldNames.add(String.format("`%s`", fieldName));
        }
        if (addCommonFields) {
            addFixedFieldNames(insertFieldNames, currentTs, true);
        }

        for (Map<String, Object> entity : entityList) {
            List<String> fieldValues = new ArrayList<>();
            for (String fieldName : fieldNames) {
                Object originalFieldValue = entity.get(fieldName);
                String fieldValue = resolveFieldValue(entity, fieldName, originalFieldValue);
                fieldValues.add(transferFieldValueIfNecessary(fieldValue));
            }

            if (addCommonFields) {
                addFixedFieldValues(fieldValues, currentTs, true);
            }
            outerFieldValues.add(String.format("(%s)", join(fieldValues, ", ")));
        }

        String sql = String.format(insertSqlTemplate, tableName,
                join(insertFieldNames, ", "),
                join(outerFieldValues, ", ")
        );
        return sql;
    }

    public static String assembleBatchInsertSql(String tableName, List<Map<String, Object>> entityList) {
        return assembleBatchInsertSql(tableName, entityList, DEFAULT_ADD_CATM_UPTM);
    }

    public static String assembleUpdateSql(String tableName, String idFieldName, Map<String, Object> entity, boolean addCommonFields) {
        String updateSqlTemplate = " update %s set %s %s; ";
        List<String> fieldNames = new ArrayList<>(), fieldValues = new ArrayList<>();
        for (String fieldName : entity.keySet()) {
            Object originalFieldValue = entity.get(fieldName);
            String fieldValue = resolveFieldValue(entity, fieldName, originalFieldValue);
            fieldNames.add(String.format("`%s`", fieldName));
            fieldValues.add(transferFieldValueIfNecessary(fieldValue));
        }
        if (addCommonFields) {
            Long currentTs = System.currentTimeMillis();
            addFixedFieldNames(fieldNames, currentTs, false);
            addFixedFieldValues(fieldValues, currentTs, false);
        }

        List<String> setClauseList = new ArrayList<>();
        for (int i = 0; i < fieldNames.size(); i++) {
            setClauseList.add(String.format(" %s = %s ", fieldNames.get(i), fieldValues.get(i)));
        }
        String setClause = join(setClauseList, ", ");

        String idValue = String.valueOf(entity.get(idFieldName));
        String whereCond = String.format(" where %s = %s ", idFieldName, transferFieldValueIfNecessary(idValue));

        String sql = String.format(updateSqlTemplate, tableName, setClause, whereCond);
        return sql;
    }

    public static String assembleUpdateSql(String tableName, String idFieldName, Map<String, Object> entity) {
        return assembleUpdateSql(tableName, idFieldName, entity, DEFAULT_ADD_CATM_UPTM);
    }

    public static List<String> assembleBatchSaveSql(String tableName, String idFieldName,
                                                    List<Map<String, Object>> entityList, Function<ResultSet, String> idExtractor,
                                                    boolean addCommonFields) {
        List<String> idList = entityList.stream().map(ele -> String.valueOf(ele.get(idFieldName))).collect(Collectors.toList());
        List<String> existsIdList = selectExistsById(tableName, idFieldName, idList, idExtractor);
        Map<String, Map<String, Object>> toInsertById = new LinkedHashMap<>(), toUpdateById = new LinkedHashMap<>();
        for (Map<String, Object> entity : entityList) {
            String idValue = String.valueOf(entity.get(idFieldName));

            Map<String, Map<String, Object>> entityByIdTmp = toInsertById;
            if (existsIdList.contains(idValue)) {
                entityByIdTmp = toUpdateById;
            }
            entityByIdTmp.put(idValue, entity);
        }

        List<String> result = new ArrayList<>();
        String insertSql = SQL_DUMMY_SQL;
        List<Map<String, Object>> toInsertList = new ArrayList<>(toInsertById.values());
        if (!isEmpty(toInsertList)) {
            insertSql = assembleBatchInsertSql(tableName, toInsertList, addCommonFields);
        }
        result.add(insertSql);

        List<Map<String, Object>> toUpdateList = new ArrayList<>(toUpdateById.values());
        for (Map<String, Object> toUpdate : toUpdateList) {
            String updateSql = assembleUpdateSql(tableName, idFieldName, toUpdate, addCommonFields);
            result.add(updateSql);
        }
        return result;
    }

    public static <T> List<String> assembleBatchSaveSql(String tableName, String idFieldName,
                                                        List<Map<String, Object>> entityList, Function<ResultSet, String> recordExtractor) {
        return assembleBatchSaveSql(tableName, idFieldName, entityList, recordExtractor, true);
    }

    public static List<String> selectExistsById(String tableName, String idFieldName, List<String> idList, Function<ResultSet, String> recordExtractor) {
        if (isEmpty(idList)) {
            return Collections.emptyList();
        }

        String querySqlTemplate = " select %s as id from %s %s; ";
        String idInSnippet = join(idList.stream().map(MysqlUtils::transferFieldValueIfNecessary).collect(Collectors.toList()), ", ");
        String whereCond = String.format(" where %s in (%s) ", idFieldName, idInSnippet);
        String querySql = String.format(querySqlTemplate, idFieldName, tableName, whereCond);

        return executeQuery(querySql, recordExtractor);
    }

    public static String generateQuerySql(String tableName, String whereCond) {
        String querySql = String.format(" select * from %s ", tableName);
        if (isNotBlank(whereCond)) {
            querySql = String.format(" %s where %s ", querySql, whereCond);
        }
        return querySql;
    }

    public static String generateDeleteSql(String tableName, String whereCond) {
        String querySql = String.format(" delete from %s ", tableName);
        if (isNotBlank(whereCond)) {
            querySql = String.format(" %s where %s ", querySql, whereCond);
        }
        return querySql;
    }

    public static String resolveFieldValue(Map<String, Object> entity, String fieldName, Object fieldValue) {
        if (fieldValue == null) {
            return null;
        }

        if (fieldValue instanceof Date) {
            return DateFormatUtils.format((Date) fieldValue);
        }
        if (fieldValue instanceof LocalDateTime) {
            LocalDateTime dateTime = ((LocalDateTime) fieldValue);
            return String.format("%s-%s-%s %s:%s:%s",
                    String.format("%04d", dateTime.getYear()),
                    String.format("%02d", dateTime.getMonthValue()),
                    String.format("%02d", dateTime.getDayOfMonth()),
                    String.format("%02d", dateTime.getHour()),
                    String.format("%02d", dateTime.getMinute()),
                    String.format("%02d", dateTime.getSecond())
            );
        }

        return String.valueOf(fieldValue);
    }

    public static void addFixedFieldNames(List<String> fieldNames, Long currentTs, boolean addCatm) {
        if (addCatm) {
            fieldNames.add(COLUMN_CATM);
        }
        fieldNames.add(COLUMN_UPTM);
    }

    public static void addFixedFieldValues(List<String> fieldValues, Long currentTs, boolean addCatm) {
        if (addCatm) {
            fieldValues.add(transferFieldValueIfNecessary(String.valueOf(currentTs)));
        }
        fieldValues.add(transferFieldValueIfNecessary(String.valueOf(currentTs)));
    }

    public static String transferFieldValueIfNecessary(String fieldValue) {
        if (fieldValue == null) {
            return "NULL";
        }

        if (fieldValue.contains("\"")) {
            fieldValue = fieldValue.replace("\"", "\\\"");
        }
        return String.format("\"%s\"", fieldValue);
    }

    public static String transferSingleQuoteFieldValueIfNecessary(String fieldValue) {
        if (fieldValue == null) {
            return "NULL";
        }

        if (fieldValue.contains("'")) {
            fieldValue = fieldValue.replace("'", "\\'");
        }
        return String.format("'%s'", fieldValue);
    }

    public static void fillOrTrimToFieldNames(Map<String, Object> entity, List<String> fieldNames, String defaultValue) {
        List<String> field2Remove = new ArrayList<>();
        for (Map.Entry<String, Object> entry : entity.entrySet()) {
            String fieldName = entry.getKey();
            if (!fieldNames.contains(fieldName)) {
                field2Remove.add(fieldName);
            }
        }
        for (String fieldName : field2Remove) {
            entity.remove(fieldName);
        }

        for (String fieldName : fieldNames) {
            if (!entity.containsKey(fieldName)) {
                entity.put(fieldName, defaultValue);
            }
        }
    }

    public static void fillOrTrimToFieldNames(Map<String, Object> entity, List<String> fieldNames) {
        fillOrTrimToFieldNames(entity, fieldNames, "");
    }

    public static String wrapSqlIn(List<String> list) {
        if (isEmpty(list)) {
            return "";
        }

        return String.format("\"%s\"", join(list, "\", \""));
    }

    public static boolean isBlank(String str) {
        return str == null || str.trim().length() == 0;
    }

    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    public static <T> boolean isEmpty(Collection<T> list) {
        return list == null || (list.size() == 0);
    }

    public static <T> String join(Collection<T> list, String seprator) {
        StringBuffer result = new StringBuffer();
        for (Iterator ite = list.iterator(); ite.hasNext(); result.append((String) ite.next())) {
            if (result.length() != 0) {
                result.append(seprator);
            }
        }
        return result.toString();
    }

}

 

 

GenericMapExtractor
public class GenericMapExtractor implements Function<ResultSet, Map<String, Object>> {

    @Override
    public Map<String, Object> apply(ResultSet resultSet) {
        try {
            Map<String, Object> result = new LinkedHashMap<>();
            int columnCount = resultSet.getMetaData().getColumnCount();
            for (int i = 1; i <= columnCount; i++) {
                String columnName = resultSet.getMetaData().getColumnName(i);
                result.put(columnName, resultSet.getObject(columnName));
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

 

 

MyStatsPeopleFlowLogExtractor
public class MyStatsPeopleFlowLogExtractor implements Function<ResultSet, StatsPeopleFlowLog> {

    @Override
    public StatsPeopleFlowLog apply(ResultSet resultSet) {
        try {
            Map<String, Object> entityMap = MysqlUtils.GENERIC_MAP_EXTRACTOR.apply(resultSet);
            JSONObject entityJson = (JSONObject) JSON.toJSON(entityMap);
            return StatsPeopleFlowLog.fromJSON(entityJson);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

 

 

部分截图

 

 

完 

 

 

 

 

 

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

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

相关文章

【蓝桥杯—单片机】第十一届省赛真题代码题解题笔记 | 省赛 | 真题 | 代码题 | 刷题 | 笔记

第十一届省赛真题代码部分 前言赛题代码思路笔记竞赛板配置内部振荡器频率设定键盘工作模式跳线扩展方式跳线 建立模板明确设计要求和初始状态显示功能部分数据界面第一部分第二部分第三部分调试时发现的问题 参数设置界面第一部分第二部分和第四部分第三部分和第五部分 按键功…

【C语言】数 组与指针:深度剖析与等价表达

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;数组与指针的基本关系&#x1f4af;数组与指针的互换使用数组下标与指针的等价性 &#x1f4af;六个表达式的等价性&#x1f4af;指针运算的注意事项&#x1f4af;数组…

Explain 是 SQL 查询优化中非常重要的工具,它用于分析 SQL 查询的执行计划

Explain 是 SQL 查询优化中非常重要的工具&#xff0c;它用于分析 SQL 查询的执行计划https://mp.weixin.qq.com/s/QKra-Sp5JoaEPSCqfffOtA

Leetcode—487. 最大连续1的个数 II【中等】Plus

2025每日刷题&#xff08;210&#xff09; Leetcode—487. 最大连续1的个数 II 实现代码 class Solution { public:int findMaxConsecutiveOnes(vector<int>& nums) {int zeros 0;int ans 0;for(int l 0, r 0; r < nums.size(); r) {if(nums[r] 0) {zeros;…

C32.【C++ Cont】静态实现双向链表及STL库的list

目录 1.知识回顾 2.静态实现演示图 3.静态实现代码 1.初始双向链表 2.头插 3.遍历链表 4.查找某个值 4.任意位置之后插入元素 5.任意位置之前插入元素 6.删除任意位置的元素 4.STL库的list 1.知识回顾 96.【C语言】数据结构之双向链表的初始化,尾插,打印和尾删 97.【C…

Docker的镜像

Docker的镜像 一&#xff0e;Docker镜像的概念 镜像是Docker&#xff08;镜像&#xff0c;容器&#xff0c;仓库&#xff09;三大核心概念之一。镜像本质上是一个只读文件&#xff0c;它包含了文件系统、源码、库文件、依赖、工具等运行应用程序所必须的文件。 镜像是由文件…

如何在Windows上使用Docker

引言 WSL2&#xff08;Windows Subsystem for Linux2&#xff09;是微软开发的一种技术&#xff0c;允许在 Windows 操作系统上运行 Linux 环境。它提供了一个兼容层&#xff0c;使得用户可以在 Windows 系统中直接运行 Linux 命令行工具、应用程序和开发工具&#xff0c;而无需…

赛博算命之 ”梅花易数“ 的 “JAVA“ 实现 ——从玄学到科学的探索

hello~朋友们&#xff01;好久不见&#xff01; 今天给大家带来赛博算命第三期——梅花易数的java实现 赛博算命系列文章&#xff1a; 周易六十四卦 掐指一算——小六壬 更多优质文章&#xff1a;个人主页 JAVA系列&#xff1a;JAVA 大佬们互三哦~互三必回&#xff01;&#xf…

Spring Web MVC项目的创建及使用

一、什么是Spring Web MVC&#xff1f; Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从⼀开始就包含在 Spring 框架中&#xff0c;通常被称为Spring MVC。 1.1 MVC的定义 MVC 是 Model View Controller 的缩写&#xff0c;它是软件工程中的一种软件架构…

Websocket从原理到实战

引言 WebSocket 是一种在单个 TCP 连接上进行全双工通信的网络协议&#xff0c;它使得客户端和服务器之间能够进行实时、双向的通信&#xff0c;既然是通信协议一定要从发展历史到协议内容到应用场景最后到实战全方位了解 发展历史 WebSocket 最初是为了解决 HTTP 协议在实时…

IDEA+DeepSeek让Java开发起飞

1.获取DeepSeek秘钥 登录DeepSeek官网 : https://www.deepseek.com/ 进入API开放平台&#xff0c;第一次需要注册一个账号 进去之后需要创建一个API KEY&#xff0c;然后把APIkey记录保存下来 接着我们获取DeepSeek的API对话接口地址&#xff0c;点击左边的&#xff1a;接口…

深度解读 Docker Swarm

一、引言 随着业务规模的不断扩大和应用复杂度的增加,容器集群管理的需求应运而生。如何有效地管理和调度大量的容器,确保应用的高可用性、弹性伸缩和资源的合理分配,成为了亟待解决的问题。Docker Swarm 作为 Docker 官方推出的容器集群管理工具,正是在这样的背景下崭露头…

嵌入式面试题 C/C++常见面试题整理_7

一.什么函数不能声明为虚函数? 常见的不能声明为虚函数的有:普通函数(非成员函数):静态成员函数;内联成员函数;构造函数;友元函数。 1.为什么C不支持普通函数为虚函数?普通函数(非成员函数)只能被overload&#xff0c;不能被override&#xff0c;声明为虚函数也没有什么意思…

Ubuntu MKL(Intel Math Kernel Library)

Get Intel oneAPI Math Kernel Library wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/79153e0f-74d7-45af-b8c2-258941adf58a/intel-onemkl-2025.0.0.940_offline.sh sudo sh ./intel-onemkl-2025.0.0.940_offline.sh MKL库的配置和使用-CSDN博客 CMak…

如何在Vscode中接入Deepseek

一、获取Deepseek APIKEY 首先&#xff0c;登录Deepseek官网的开放平台&#xff1a;DeepSeek 选择API开放平台&#xff0c;然后登录Deepseek后台。 点击左侧菜单栏“API keys”&#xff0c;并创建API key。 需要注意的是&#xff0c;生成API key复制保存到本地&#xff0c;丢失…

go-zero学习笔记(三)

利用goctl生成rpc服务 编写proto文件 // 声明 proto 使用的语法版本 syntax "proto3";// proto 包名 package demoRpc;// golang 包名(可选) option go_package "./demo";// 如需为 .proto 文件添加注释&#xff0c;请使用 C/C 样式的 // 和 /* ... */…

将Deepseek接入pycharm 进行AI编程

目录 专栏导读1、进入Deepseek开放平台创建 API key 2、调用 API代码 3、成功4、补充说明多轮对话 总结 专栏导读 &#x1f338; 欢迎来到Python办公自动化专栏—Python处理办公问题&#xff0c;解放您的双手 &#x1f3f3;️‍&#x1f308; 博客主页&#xff1a;请点击——…

yolov8 opencv模型部署(C++版)

TensorRT系列之 Windows10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速…

Android 常用命令和工具解析之Battery Historian

Batterystats是包含在 Android 框架中的一种工具&#xff0c;用于收集设备上的电池数据。您可以使用adb bugreport命令抓取日志&#xff0c;将收集的电池数据转储到开发机器&#xff0c;并生成可使用 Battery Historian 分析的报告。Battery Historian 会将报告从 Batterystats…

leetcode刷题日记 1

https://leetcode.cn/problems/decode-ways/description/ 题目分析 分析了一下题目&#xff0c;我的第一想法&#xff1a;和之前的上楼梯问题很像 为什么这么说呢&#xff0c;感觉他们的值和他们之前元素都有千丝万缕的联系 就像上楼梯问题 就是我们的dp问题 怎么解释呢&a…