算法26:递归练习

news2024/11/16 17:28:55

目录

题目1:给你一个字符串,要求打印打印出这个字符串的全部子序列(子序列不能重复)

题目2:打印一个字符串的全部排列。

题目3:针对题目2,要求去除重复元素

题目4:给定一个字符串,要求打印这个字符串中字符能够能够组成的全部子集,子集无重复值。

题目5:给你一个栈,请你逆序这个栈,不能申请额外的数据结构, 只能使用递归函数。 


递归是一个过渡,为动态规划做准备。递归写好了,可以大量的优化代码结构,但是缺点是逻辑不好懂。一个号的递归,参数设计尤为重要。

题目1:给你一个字符串,要求打印打印出这个字符串的全部子序列(子序列不能重复)

这一题需要注意的是,给定了一个字符串,而字符串肯定是有顺序的,比如字符串为abc, 那么他的子序肯定不会出现cba。因为这样的顺序完全被颠倒了。所有,子序是不能改变原字符串的整体顺序的,在保持整体顺序的情况下自由组合。

package code03.递归_06;

import java.util.ArrayList;
import java.util.List;

/**
 * 给你一个字符串,要求打印打印出这个字符串的全部子序列(子序列不能重复)
 */
public class StringSequence_02
{

    public static List<String> getChildSuquence(String str)
    {
        char[]  chars = str.toCharArray();
        List<String> result = new ArrayList<>();
        //path这个参数很重要,它就是一个逐层拼接完整的字符串
        //根据递归遍历的层数,组成不同的字符串,非常灵巧
        String path = "";
        func(chars, result, 0, path);
        return result;
    }

    /**
     * 字符串是有序的,所以子序列必须要按照字符串的整体序列进行。 比如abc, 子序列肯定不能
     * 出现ba或者ca这种情况。
     *
     * 当前递归的逻辑是从后往前,就是找到最后一个元素。 下标依次是:
     *  N-2... N
     *  N-3...N
     *  N-4...N
     *  0...N
     *  N代表的是数组最后一个元素的下标。 而 N+1 就是代表的是数组的长度,
     *  此时,已经没有对应的下标了,所以认为是出口
     *
     *  假设字符串为abc, 那么它的子集为
     *  1.空字符串
     *  2.c
     *  3.b
     *  4.bc
     *  5.a
     *  6. 52组合得到ac,53z组合河道ab,54组合得到abc
     */
    static void func (char[] chars, List<String> list, int index, String path)
    {
        /**
         * 递归的出口。
         * index是最后一个字符的下标。而index+1就是数组的长度
         * 所以就需要跳出递归了
         */
        if (index == chars.length) {
            //排除重复元素
            if (!list.contains(path)) {
                list.add(path);
            }
            return;
        }
        //一直往下找,直到数组的尽头,默认给个空字符串
        func(chars, list, index + 1, path); //此处index+1用的很灵巧,因为index值本身是没有改变的

        //此处会改变path的值,用的很灵巧
        //每一个方法对弈一个方法栈,而变量path存在本地变量表,方法结束,本地变量表销毁
        //因此,此处改变的path只是在当前方法中生效。不会影响其他方法中相同名称的path值
        path = path + String.valueOf(chars[index]);

        //此处开始根据路径进行拼接。
        func(chars, list, index + 1, path);
    }

    public static void main(String[] args) {
        String test = "abc";
        //String test = "abcc";
        List<String>  result = getChildSuquence(test);

        for (String str : result) {
            System.out.println(str);
        }
    }
}

这一题解释一下:

设计思路是根据数组的下标索引进行的,而递归是一直找到下标最后一个元素为止。

此时,如果最后一个元素为c。如果c不被包括,那么path为空字符串,func搜集到空字符串。如果c被包括,那就 func 搜集到的就是 空字符串与c的拼接。 即c。递归结束,返回上一层

此时,返回到元素b处,此时不包括b的元素搜集完毕。即搜集到空字符串和c。path重新组合。 此时path为空字符串和b的组合。再次func操作。而func内部又分为不包含path和包含path两种逻辑,此时针对的是c。如果不包含c,那就搜集到b。如果包含c,那就收集到了b和c的组合,即bc

以此类推.......

整个流程图如下:

搜集结果为: 空字符串、c、b、bc、a、ac、ab、abc 

题目2:打印一个字符串的全部排列

这个字符串的排序指的是可以任意变换字符串的顺序,而不是子字符串。 比如: abc 其中一个就是cba 但是ab a ac等都不属于全部排序

package code03.递归_06;

import java.util.ArrayList;
import java.util.List;

/**
 * 给定一个字符串,要求打印这个字符串的全部排序。
 * 注意:这个字符串的排序指的是可以任意变换字符串的顺序,而不是子字符串
 * 比如: abc 其中一个就是cba   但是ab a ac等都不属于全部排序
 */
public class PrintAllFullStr_03
{
    public static List<String> getAllStr(String str)
    {
        List<String> result = new ArrayList<>();
        String path = "";
        char[] chars = str.toCharArray();
        List<Character> list = new ArrayList<>();
        for (char cha : chars) {
            list.add(cha);
        }
        func(list, result, path);
        return result;
    }

    static void func (List<Character> chars, List<String> result, String path)
    {
        if (chars.isEmpty()) {
            result.add(path);
        }
        else {
            for (int i = 0; i < chars.size(); i++) {
                char cur = chars.get(i);
                //清除现场
                chars.remove(i);
                func(chars, result,  path + cur);
                //恢复现场
                chars.add(i, cur);
            }
        }
    }

    public static void main(String[] args) {
        String test = "abc";
        //String test = "acc";
        List<String> result = getAllStr(test);
        for (String str : result) {
            System.out.println(str);
        }
    }
}

其实,这一道题,还有另一种比较通用的解法,思路与题目1基本一样。

package code03.递归_06;

import java.util.ArrayList;
import java.util.List;

/**
 * 给定一个字符串,要求打印这个字符串的全部排序。
 * 注意:这个字符串的排序指的是可以任意变换字符串的顺序,而不是子字符串
 * 比如: abc 其中一个就是cba   但是ab a ac等都不属于全部排序
 */
public class PrintAllFullStr_03_opt
{
    public static List<String> getAllStr(String str)
    {
        char[] chars = str.toCharArray();
        List<String> result = new ArrayList<>();
        String path = "";
        func(chars, result, 0, path);
        return result;
    }

    static void func (char[]  chars, List<String> result, int index, String path)
    {
        if (index == chars.length) {
            result.add(path);
        }
        else {
            for (int i = index; i < chars.length; i++) {
                swap(chars, index, i);
                func(chars, result, index + 1, path + chars[index]);
                swap(chars, index, i);
            }
        }
    }

    public static void swap(char[] chs, int i, int j) {
        char tmp = chs[i];
        chs[i] = chs[j];
        chs[j] = tmp;
    }

    public static void main(String[] args) {
        String test = "abc";
        //String test = "acc";
        List<String> result = getAllStr(test);
        for (String str : result) {
            System.out.println(str);
        }
    }
}

针对通用解法,我们发现,既然chs始终是动态排序的,但是内部元素并不会减少。因此,可以稍微优化一下参数:

package code03.递归_06;

import java.util.ArrayList;
import java.util.List;

/**
 * 给定一个字符串,要求打印这个字符串的全部排序。
 * 注意:这个字符串的排序指的是可以任意变换字符串的顺序,而不是子字符串
 * 比如: abc 其中一个就是cba   但是ab a ac等都不属于全部排序
 */
public class PrintAllFullStr_03_opt2
{
    public static List<String> getAllStr(String str)
    {
        char[] chars = str.toCharArray();
        List<String> result = new ArrayList<>();
        func(chars, result, 0);
        return result;
    }

    static void func (char[]  chars, List<String> result, int index)
    {
        if (index == chars.length) {
            result.add(String.valueOf(chars));
        }
        else {
            for (int i = index; i < chars.length; i++) {
                swap(chars, index, i);
                func(chars, result, index + 1);
                swap(chars, index, i);
            }
        }
    }

    public static void swap(char[] chs, int i, int j) {
        char tmp = chs[i];
        chs[i] = chs[j];
        chs[j] = tmp;
    }

    public static void main(String[] args) {
        String test = "abc";
        //String test = "acc";
        List<String> result = getAllStr(test);
        for (String str : result) {
            System.out.println(str);
        }
    }
}

其实,这一道题的解题思路就是逐步确定每个位置,而记录位置的参数是index。然后for循环,把剩余的数组元素,依次填补当前位置。以此类推,典型的深度优先遍历算法。流程图如下:

题目3:针对题目2,要求去除重复元素

 去除重复元素,其实分为结果过滤和条件过滤。结果过滤就是走完所有的流程,到最后搜集结果的时候通过结果集去重。而条件过滤则是从源头排除,性能更高。以题目2为例。如果字符串为acc. 下标为1的时候,c出现一次,下一个c再次出现的时候,直接排除掉。

结果过滤:

package code03.递归_06;

import java.util.ArrayList;
import java.util.List;

/**
 * 给定一个字符串,要求打印这个字符串的全部排序, 并且
 * 这些排完序的字符串无重复数据
 *
 * 结果过滤: 执行完流程,待放入集合中时判断是否重复进行过滤。
 * 缺点很明显, 不管是否重复,所有流程都会走一遍,性能低
 *
 */
public class PrintAllFullStrNoRepeat_04
{
    public static List<String> getAllStr(String str)
    {
        char[] chars = str.toCharArray();
        List<String> result = new ArrayList<>();
        String path = "";
        func(chars, result, 0);
        return result;
    }

    static void func (char[]  chars, List<String> result, int index)
    {
        if (index == chars.length) {
            /**
             * 结果过滤,可以直接使用set
             * 此处使用的是list,需要判断集合是否存在重复元素
             */
            if (!result.contains(String.valueOf(chars))) {
                result.add(String.valueOf(chars));
            }
        }
        else {
            /**
             * index代表当前位置开头。
             * 比如index为0, 就是锁定0位置的开头数组。 for循环
             * 是找到 a b c 分别占据0的位置作为开头。 比如 a**. b**, c**
             *
             * 当index为1时,代表分别找到所有数据作为1下标位置开头。 即*a*, *b*, *c*
             *
             */
            for (int i = index; i < chars.length; i++) {
                swap(chars, index, i);
                func(chars, result, index + 1);
                swap(chars, index, i);
            }
        }
    }

    public static void swap(char[] chs, int i, int j) {
        char tmp = chs[i];
        chs[i] = chs[j];
        chs[j] = tmp;
    }

    public static void main(String[] args) {
        //String test = "abc";
        String test = "acc";
        List<String> result = getAllStr(test);
        for (String str : result) {
            System.out.println(str);
        }
    }
}

条件过滤:

package code03.递归_06;

import java.util.ArrayList;
import java.util.List;

/**
 * 给定一个字符串,要求打印这个字符串的全部排序, 并且
 * 这些排完序的字符串无重复数据
 *
 * 结果过滤: 执行完流程,待放入集合中时判断是否重复进行过滤。
 * 缺点很明显, 不管是否重复,所有流程都会走一遍,性能低
 *
 */
public class PrintAllFullStrNoRepeat_04_opt
{
    public static List<String> getAllStr(String str)
    {
        char[] chars = str.toCharArray();
        List<String> result = new ArrayList<>();
        String path = "";
        func(chars, result, 0);
        return result;
    }

    static void func (char[]  chars, List<String> result, int index)
    {
        if (index == chars.length) {
            result.add(String.valueOf(chars));
        }
        else {
            //ASCII码的范围是0-255, 它可以表示所有的字符
            //每一次递归都new一个,用的很巧妙。需要仔细揣摩
            boolean[] visited = new boolean[256];
            for (int i = index; i < chars.length; i++) {
                /**
                 * index是当前位置。第一次进入肯定是通过的。占据当前位置
                 *
                 * 原始字符数组为 a b c        原始数组为acc
                 * 1. a b c                   a c c   原始的c c位置没变。 也就是说第二个位置被第一个c占据了一遍
                 * 2. a c b                   a c c 此时的 c c是交换后的位置。也就是第二c想要再次来占据第二个位置作为后续数组的开头,重复占领该位置,直接pass掉
                 * 3. b a c                   c a c
                 * 4. b c a                   c c a
                 * 5. c a b                   c a c  同理
                 * 6  c b a                   c c a  同理
                 */
                if (!visited[chars[i]]) {
                    visited[chars[i]] = true;
                    swap(chars, index, i);
                    func(chars, result, index + 1);
                    swap(chars, index, i);
                }
            }
        }
    }

    public static void swap(char[] chs, int i, int j) {
        char tmp = chs[i];
        chs[i] = chs[j];
        chs[j] = tmp;
    }

    public static void main(String[] args) {
        //String test = "abc";
        String test = "accb";
        List<String> result = getAllStr(test);
        for (String str : result) {
            System.out.println(str);
        }
    }
}

题目4:给定一个字符串,要求打印这个字符串中字符能够能够组成的全部子集,子集无重复值。

弄懂了题目2,这一题其实就很简单了。

package code03.递归_06;

import java.util.ArrayList;
import java.util.List;

/**
 * 给定一个字符串,要求打印这个字符串的全部排序。
 * 注意:这个字符串的排序指的是可以任意变换字符串的顺序,而不是子字符串
 * 比如: abc 其中一个就是cba   但是ab a ac等都不属于全部排序
 */
public class PrintAllStr_05_opt
{
    public static List<String> getAllStr(String str)
    {
        char[] chars = str.toCharArray();
        List<String> result = new ArrayList<>();
        String path = "";
        func(chars, result, 0, path);
        return result;
    }

    static void func (char[]  chars, List<String> result, int index, String path)
    {
        if (index == chars.length) {
            result.add(path);
        }
        else {
            boolean[] visited = new boolean[256];
            for (int i = index; i < chars.length; i++) {
                visited[chars[i]] = true;
                swap(chars, index, i);
                func(chars, result, index + 1, path + chars[index]);
                if (index < chars.length-1) {
                    result.add(path + chars[index]);
                }
                swap(chars, index, i);
            }
        }
    }

    public static void swap(char[] chs, int i, int j) {
        char tmp = chs[i];
        chs[i] = chs[j];
        chs[j] = tmp;
    }

    public static void main(String[] args) {
        String test = "abc";
        //String test = "acc";
        List<String> result = getAllStr(test);
        System.out.println("length is " + result.size());
        for (String str : result) {
            System.out.println(str);
        }
    }
}

题目5:给你一个栈,请你逆序这个栈,不能申请额外的数据结构, 只能使用递归函数。 

package code03.递归_06;

import java.util.Stack;

/**
 * 题目:
 * 给你一个栈,请你逆序这个栈,
 * 不能申请额外的数据结构,
 * 只能使用递归函数。 如何实现?
 */
public class StackReverse_06 {

    public static void reverse (Stack<Integer> stack)
    {
        if (stack == null || stack.isEmpty()) {
            return;
        }
        //获取栈底元素
        int result = func(stack);
        /**
         * 继续逆转栈中剩余的元素
         * 例如栈中从上到下为 3 2 1
         * 第一次 获取result 1
         * 第二次 获取result 2
         * 第三次 获取result 3
         */
        reverse(stack);
        /**
         * 那么最后一次递归结束后,放入元素
         * 顺序是 放入 1 2 3. 顺序变为  1  2 3
         */
        stack.push(result);
    }

    /**
     * 当前递归,每次结束的时候找到的都是栈底元素
     * @param stack
     * @return
     */
    public static int func(Stack<Integer> stack)
    {
        //如果cur是栈底元素,那么当前pop以后栈就空了
        //直接返回cur
        int cur = stack.pop();
        if (stack.isEmpty()) {
            return cur;
        }
        else {
            //栈底元素
            int last = func(stack);
            //倒数第二个放入栈底
            stack.push(cur);
            return last;
        }
    }


    public static void main(String[] args) {
        Stack<Integer> test = new Stack<Integer>();
        test.push(1);
        test.push(2);
        test.push(3);
        test.push(4);
        test.push(5);
        System.out.println("逆转前顺序为: 5 4 3 2 1");
        reverse(test);
        System.out.print("逆转后顺序为: ");
        while (!test.isEmpty()) {
            System.out.print(test.pop());
            System.out.print(" ");
        }

    }
}

这一题很难,难在不允许使用其他的结构来辅助。只能在栈中自己折腾。既然是逆序,那么放置的顺序就是要反过来,栈的特性是先进后出,这就复杂了起来,下面看下整个流程:

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

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

相关文章

ARM的读写内存指令与栈的应用

1.基础读写指令 写内存指令&#xff1a;STR MOV R1, #0xFF000000 MOV R2, #0x40000000 STR R1, [R2] 将R1寄存器中的数据写入到R2指向的内存空间 需注意&#xff0c;此命令是将R1中的数据写给R2所指向的内存空间&#xff0c;而不是直接把R1的数据赋给R2&#xff0c;R2寄存器…

chatgpt赋能Python-python3_9如何安装

Python 3.9 安装教程 Python 是一款非常流行的编程语言&#xff0c;而 Python 3.9 是其中的最新版本。不过&#xff0c;有些人可能会遇到一些问题&#xff0c;因为这是一个新版本。在本篇文章中&#xff0c;我们将介绍 Python 3.9 的安装过程&#xff0c;并提供一些关键的步骤…

无线通信网 - 动态主机配置协议 DHCP

文章目录 1 概述2 DHCP2.1 工作原理2.2 报文类型 3 扩展3.1 网工软考真题 1 概述 #mermaid-svg-VTnvU3Vd01Y4gppz {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-VTnvU3Vd01Y4gppz .error-icon{fill:#552222;}#merm…

[CTF/网络安全] 攻防世界 Training-WWW-Robots 解题详析

[网络安全] 攻防世界 Training-WWW-Robots 解题详析 在这个小训练挑战中&#xff0c;你将学习 Robots_exclusion_standard&#xff08;机器人排除标准&#xff09;。 robots.txt 文件是由网络爬虫用来检查是否允许他们爬行和索引你的网站或仅部分内容。有时这些文件揭示目录结构…

Vivado HLS 第1讲 软件工程师该怎么了解FPGA架构

Vivado HLS是将基于C/C++描述的算法转化成相应的RTL代码,最终在FPGA上实现。这就要求软件工程师对FPGA的内部架构有一些基本的认识,目的在于保证生成的RTL代码在性能和资源上能够达到很好的平衡。实际上,C语言与FPGA是有一些对应关系的。比如: C语言中的数组可对应于FPGA中…

直方图与直方图均衡化

直方图 图像直方图是用来表现图像中亮度分布的直方图&#xff0c;给出的是图像中某个亮度或者某个范围亮度下共有几个像素&#xff0c;即统计一幅图某个亮度像素数量。 直方图作为一种简单有效的基于统计特性的特征描述子&#xff0c;在计算机视觉领域广泛使用。 它的优点主要…

上下文无关文法、句柄、正规文法、规范推导、文法二义性

目录 上下文无关文法 句柄 正规文法 规范推导 文法二义性 上下文无关文法 上下文无关文法&#xff08;Context-Free Grammar&#xff0c;CFG&#xff09;是一种形式语言&#xff0c;用于描述一类语言的语法结构。它由一组产生式规则组成&#xff0c;每个规则定义了如何将一…

hackthebox htb interface:CVE-2022-28368

本题考察:CVE-2022-28368 CVE-2022-28368 - 通过远程 CSS 字体缓存安装的 RCE 参考: https://www.0le.cn/archives/58.htmlhackthebox-interface信息搜集nmap扫描端口发现开放的22和80PORT STATE SERVICE REASON22/tcp open ssh syn-ac...https://www.0le.cn/archives/58.htm…

Spring 经典面试题总结

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

learn_C_deep_12 (深度理解“取整“、“取余“、“取模“运算、掌握运算符优先级 )

目录 关于“取整” "取整"规则 1、向零取整 2、向-∞取整 3、向∞取整 4、四舍五入 关于"取模和取余" 运算符优先级 关于“取整” #include <stdio.h> int main() {//本质是向0取整int i -2.9;int j 2.9;printf("%d\n", i); /…

【C++】 排列与组合算法详解(进阶篇)

文章目录 写在前面算法1&#xff1a;朴素算法思路缺点 算法2&#xff1a;递推预处理思路时间复杂度&#xff1a; O ( n 2 ) O(n^2) O(n2) 算法3&#xff1a;阶乘逆元思路时间复杂度&#xff1a; O ( n log ⁡ n ) O(n \log n) O(nlogn)思考&#xff1a;读者也可以尝试写 O ( n…

PySide6/PyQT多线程之 多线程 与 线程池的模板(拿来即用)

前言 关于PySide6/PyQT多线程系列的最后一篇。写这篇文章的动机是方便后续代码的直接复用。 本篇文章实际是水文&#xff0c;给出了 PySide6/PyQT的多线程以及线程池的基础使用模板&#xff0c;方便后面有需要时候直接拿来就用。 多线程 这里分两种情况来谈论&#xff0c;有返…

[Hadoop]MapReduce与YARN

目录 大数据导论与Linux基础 Apache Hadoop、HDFS MapReduce MapReduce思想 MapReduce设计构思 MapReduce介绍 MapReduce官方实例 Map阶段执行流程 Reduce阶段执行流程 shuffle机制 YARN YARN介绍 YARN架构、组件 程序提交YARN交互流程 YARN资源调度器Scheduler…

IOS新建应用

一&#xff1a;Application App。普通app。Document App。打开是记事本类似App。Game。新建游戏相关app。RealityKit为新建一个打开摄像机&#xff0c;一个Ar立方体的应用。 SenceKit为有一架飞机旋转的游戏App。 SpirteKit为一个手指头按上会出一个手指特效的应用。 Metal为一…

【IDEA使用指南】使用Hibernate框架的Java项目,如何通过数据库表自动生成实体模型?

文章目录 【IDEA使用指南】使用Hibernate框架的Java项目,如何通过数据库表自动生成实体模型?步骤1:找到并打开“Persistence”工具栏。步骤2:找到并打开“Import Database Schema” 窗口。步骤3:配置数据源信息步骤4:查看自动生成的实体模型。【IDEA使用指南】使用Hibern…

如何在IDEA中显示时序图

如何在IDEA中显示时序图 有时候&#xff0c;我们想要了解代码的运行过程的时候&#xff0c;想要看到方法的调用流程。 这个时候就希望有一个时序图可以看&#xff0c;但是人工来画时序图太麻烦了&#xff0c;有没有办法在IDEA中直接生成呢&#xff1f; 当然是可以的。 这里…

Access denied for user ‘root‘@‘localhost‘ (using password:YES) 解决方案

文章目录 问题描述解决方案&#xff1a; 问题描述 Access denied for user ‘root’‘localhost’:拒绝用户’root’localhost’的访问。 出现这个报错语句的一般原因是输入了错误的密码&#xff0c;也有可能是是root帐户默认不开放远程访问权限。 相关的解决方法是重新设置…

【Linux】sysfs文件系统

【Linux】sysfs文件系统 前言 一、sysfs文件系统 1.1 sysfs系统是什么 1.2 sysfs的运行机制原理 二、sysfs中重要的结构体 2.1 kobject和kset之间的关系 2.2 kobject结构体 2.3 kset结构体 前言 重要的环节&#xff1a;带着问题不断前进 sysfs文件系统是什么sysf文件系…

YOLOv5 实例分割入门

介绍 YOLOv5 目标检测模型以其出色的性能和优化的推理速度而闻名。因此,YOLOv5 实例分割模型已成为实时实例分割中最快、最准确的模型之一。 在这篇文章中,我们将回答以下关于 YOLOv5 实例分割的问题: YOLOv5检测模型做了哪些改动,得到了YOLOv5实例分割架构?使用的 Prot…

RTC实时时钟源码分析

1.先来看一下RTC的配置过程 2.RTC源码讲解 我们的工程中加入了 rtc.c 源文件和 rtc.h头文件&#xff0c;同时&#xff0c;引入了 stm32f10x_rtc.c 和 stm32f10x_bkp.c 库文件。 说明&#xff0c;首先是 RTC_Init&#xff0c;其代码如下&#xff1a; //实时时钟配置 //初始化…