算法基础之递归

2.4 蓝桥杯基础算法之递归算法 递归算法是一种自我调用的过程,它允许函数直接或间接地调用自身。每一次函数调用都会将问题分解为更小的子问题,直至达到一个简单足以直接求解的问题。 阅读详情

暴力递归

暴力递归就是尝试

  1. 把问题转化为规模缩小了的同类问题的子问题
  2. 有明确的不需要继续进行递归的条件(base case)
  3. 有当得到了子问题的结果之后的决策过程
  4. 不记录每个子问题的解

汉诺塔问题:

汉诺塔(Tower of Hanoi)源于印度传说中,大梵天创造世界时造了三根金钢石柱子,其中一根柱子自底向上叠着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

这是示意图,a是起始柱,c是目标柱,b起到中转作用

    在进行转移操作时,都必须确保大盘在小盘下面,且每次只能移动一个圆盘,最终c柱上有所有的盘子且也是从上到下按从小到大的顺序。

举例:

三个盘子,1-2移到中,将3直接移动到右。再将1-2移动到右

public class Code01_Hanoi {
    public static void main(String[] args) {
        Hanoi(4);
    }
    public static void Hanoi(int n) {
        leftToRight(n);
    }

    // 请把1-N层圆盘 从左-》右
    public static void leftToRight(int n) {
        if (n == 1) { // base case
            System.out.println("Move 1 from left to right");
            return;
        }
        leftToMid(n - 1);
        System.out.println("Move " + n + " from left to right");
        midToRight(n - 1);
    }

    // 请把1-N层圆盘 从左-》中
    private static void leftToMid(int n) {
        if (n == 1) {
            System.out.println("Move 1 from left to mid");
            return;
        }
        leftToRight(n - 1);
        System.out.println("Move " + n + " from left to mid");
        rightToMid(n - 1);
    }
    private static void rightToMid(int n) {
        if (n == 1) {
            System.out.println("Move 1 from right to mid");
            return;
        }

        rightToLeft(n - 1);
        System.out.println("Move " + n + " from left to mid");
        leftToMid(n - 1);
    }

    private static void rightToLeft(int n) {
        if (n == 1) {
            System.out.println("Move 1 from right to left");
            return;
        }

        rightToMid(n - 1);
        System.out.println("Move " + n + " from right to mid");
        midToLeft(n - 1);
    }

    private static void midToLeft(int n) {
        if (n == 1) {
            System.out.println("Move 1 from mid to left");
            return;
        }

        midToRight(n - 1);
        System.out.println("Move " + n + " from mid to left");
        rightToLeft(n - 1);
    }

    private static void midToRight(int n) {
        if (n == 1) {
            System.out.println("Move 1 from mid to right");
            return;
        }

        midToLeft(n - 1);
        System.out.println("Move " + n + " from mid to right");
        leftToRight(n - 1);
    }
}

优化:

public class Code02_Hanoi {
    public static void main(String[] args) {
        func(3, "left", "right", "other");
    }

    public static void func(int N, String from, String to, String other) {
        if (N == 1) {
            System.out.println("Move 1 form " + from + " to " + to);
        } else {
            func(N - 1, from, other, to);
            System.out.println("Move" + N + " form " + from + " to " + to);
            func(N - 1, other, to, from);
        }
    }
}

打印一个字符串的全部子序列:

可以不连续的

   // "abc"
    // 打印一个字符串的全部子序列
    public static List<String> subs(String s) {
        char[] chars = s.toCharArray();

        String path = "";
        List<String> res = new ArrayList<>();
        process(chars, 0, res, path);
        return res;
    }

    // str 固定参数
    // 来到了str[index]字符,index是位置
    // str[0..index-1]已经走过了!之前的决定,都在path上
    // 之前的决定已经不能改变了,就是path
    // str[index....]还能决定,之前已经确定,而后面还能自由选择的话,
    // 把所有生成的子序列,放入到ans里去
    private static void process(char[] chars, int index, List<String> res, String path) {
        if (index == chars.length) {
            res.add(path);
            return;
        }

        process(chars, index + 1, res, path);
        process(chars, index + 1, res, path + chars[index]);
    }

打印一个字符串的全部子序列,要求不要出现重复字面值的子序列

    /**
     * 打印一个字符串的全部子序列,要求不要出现重复字面值的子序列
     */
    public static List<String> subsNoRepeat(String s) {
        char[] chars = s.toCharArray();

        String path = "";
        Set<String> set = new HashSet<>();
        process1(chars, 0, set, path);
        List<String> ans = new ArrayList<>();
        for (String cur : set) {
            ans.add(cur);
        }
        return ans;
    }

    private static void process1(char[] chars, int index, Set<String> res, String path) {
        if (index == chars.length) {
            res.add(path);
            return;
        }

        process1(chars, index + 1, res, path);
        process1(chars, index + 1, res, path + chars[index]);
    }

打印一个字符串的全部排列

   public static List<String> permutation(String s) {
        List<String> res = new ArrayList<>();
        if (s == null || s.length() == 0) {
            return res;
        }
        char[] chars = s.toCharArray();
        List<Character> list = new ArrayList<>();
        for (char ch : chars) {
            list.add(ch);
        }
        String path = "";
        process(list, path, res);
        return res;
    }

    private static void process(List<Character> rest, String path, List<String> res) {
        if (rest.isEmpty()) {
            res.add(path);
            return;
        }

        for (int i = 0; i < rest.size(); i++) {
            char ch = rest.get(i);
            rest.remove(i);
            process(rest, path + ch, res);
            rest.add(i, ch);
        }
    }

    public static List<String> permutation1(String s) {
        List<String> res = new ArrayList<>();
        if (s == null || s.length() == 0) {
            return res;
        }
        char[] chars = s.toCharArray();
        process1(chars, 0, res);
        return res;
    }

    private static void process1(char[] chars, int index, List<String> res) {
        if (index == chars.length) {
            res.add(String.valueOf(chars));
            return;
        }

        for (int i = index; i < chars.length; i++) {
            swap(chars, index, i);
            process1(chars, index + 1, res);
            swap(chars, index, i);
        }
    }

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

打印一个字符串的全部排列,要求不要出现重复的排列

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

    public static List<String> permutationNoRepeat(String s) {
        List<String> ans = new ArrayList<>();
        if (s == null || s.length() == 0) {
            return ans;
        }
        char[] str = s.toCharArray();
        process3(str, 0, ans);
        return ans;
    }

    private static void process3(char[] chars, int index, List<String> res) {
        if (index == chars.length) {
            res.add(String.valueOf(chars));
            return;
        }
        boolean[] visited = new boolean[256];
        for (int i = index; i < chars.length; i++) {
            if (!visited[chars[i]]) {
                visited[chars[i]] = true;
                swap(chars, index, i);
                process3(chars, index + 1, res);
                swap(chars, index, i);
            }
        }
    }

给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数,如何实现?

package com.zh.class10_17;

import java.util.Stack;

public class ReverseStackUsingRecursive {
    public static void reverse(Stack<Integer> stack) {
        if (stack.isEmpty()) {
            return;
        }
        int i = f(stack);
        reverse(stack);
        stack.push(i);
    }

    // 栈底元素移除掉
    // 上面的元素盖下来
    // 返回移除掉的栈底元素
    public static int f(Stack<Integer> stack) {
        int result = stack.pop();
        if (stack.isEmpty()) {
            return result;
        } else {
            int last = f(stack);
            stack.push(result);
            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);
        reverse(test);
        while (!test.isEmpty()) {
            System.out.println(test.pop());
        }
    }
}

2、算法基础:从谜题求解到递归应用 本文介绍了算法基础,从单词谜题求解到递归的应用。探讨了算法设计中的性能问题,以及如何利用数学工具如指数、对数、级数和模运算来辅助算法分析。通过归纳法和反证法等证明方法验证算法正确性,并深入讲解了递归的基本规则及其在实际问题中的应用,如打印数字的递归实现。最后总结了递归的设计要点和优化注意事项。 阅读详情

相关推荐

VMFS数据存储(datastore)丢失后恢复步骤

vmfs datastore恢复步骤

jetliu05的博客 3267

JZ54---字符流中第一个不重复的字符

题目 请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。 输出描述 如果当前字符流没有存在出现一次的字符,返回#字符。 思路 使用LinkedHashMap 链接输入的所有值。它的优点在于,不会自动排序,你是好久进入的map集合,它就在最后面追加上。如果出现以前重复的值,修改的位置就在以前那个位置 遍历map集合,找到第一个值为1的那个字

Eva_xiaoxi的博客 945

FPGA时序分析中的工艺角:从PVT原理到建立保持时间验证

在数字电路设计中,静态时序分析(STA)是确保芯片功能正确和性能达标的核心验证手段。其基本原理是通过计算信号在逻辑路径上的传播延迟,检查建立时间和保持时间是否满足寄存器采样要求。这项技术的核心价值在于,它能在芯片制造前就预测并消除时序违规,极大提高设计成功率。然而,实际芯片性能会受到工艺波动、电压变化和温度漂移(合称PVT)的显著影响。为了覆盖这些不确定性,时序分析必须采用基于工艺角的边界模型——用最慢的工艺角模型验证建立时间,用最快的工艺角模型验证保持时间。这种分析方法广泛应用于FPGA和ASIC设计流程

weixin_30181209的博客 198

算法数据结构(十五)----暴力递归

暴力递归就是尝试 1,把问题转化为规模缩小了的同类问题的子问题 2,有明确的不需要继续进行递归的条件(base case) 3,有当得到了子问题的结果之后的决策过程 4,不记录每一个子问题的解 熟悉什么叫尝试? 打印n层汉诺塔从最左边移动到最右边的全部过程 简单版本,规定6个函数,相互调用 public static void hanoi1(int n) { leftToRight(n); } // 请把1~N层圆盘 从左 -> 右 public static.

u011624267的博客 299

物理与工程中的‘黑话’:Kronecker delta和Levi-Civita符号到底简化了什么?

本文深入解析了物理与工程中常用的Kronecker delta和Levi-Civita符号的简化作用。通过对比传统表示与张量表示,展示了这些符号在向量运算、矩阵迹计算及流体力学模拟中的高效应用,显著提升计算效率和代码可读性。特别适合理论物理和工程数学领域的学习者与从业者。

weixin_27215403的博客 399

实用电路精讲系列---双级运放放大电路(差分放大+跟随缓冲)

本文分析了双极运放放大电路的工作原理及其典型应用。该电路结合差分放大器和跟随缓冲器,实现高精度信号放大与阻抗匹配。差分放大器通过放大差模信号并抑制共模噪声提升信噪比;跟随缓冲器则提供阻抗变换,确保信号稳定传输。两者协同工作可优化输入阻抗、增强噪声抑制并提高设计灵活性。文章还列举了10个典型应用案例,包括医疗设备、工业传感器和新能源系统等,展示了该电路在精密电子系统中的关键作用。最后通过实用电路分析,详细说明了各模块功能及设计注意事项。

weixin_40590799的博客 2957

全部类型转换

类型转换 ##一、基本类型转换 基本类型有以下四种: (1)int长度数据类型有:byte(8bits)、short(16bits)、int(32bits)、long(64bits)、 (2)float长度数据类型有:单精度(32bits float)、双精度(64bits double) (3)boolean类型变量的取值有:ture、false (3)char数据类型有:unicode字符,16位 (4)对应的类类型:Integer、Float、Boolean、Character、Double、Sho

qq_43510788的博客 3616

手把手教你用高频注入法辨识永磁同步电机电感参数(附MATLAB仿真)

本文详细介绍了高频注入法在永磁同步电机电感参数辨识中的工程实践与MATLAB仿真指南。通过高频信号注入法,无需拆解电机即可在线精确测量Ld和Lq参数,适用于电动汽车驱动和工业伺服等高精度控制场景。文章包含信号设计、硬件实现、解调算法及完整MATLAB仿真模型构建,帮助工程师快速掌握这一关键技术。

orange的博客 292

算法思维基础之“递归”

不管是数据结构还是算法思维,它们的目标都是降低时间复杂度。数据结构是从数据组织形式的角度达成这个目标,而算法思维则是从数据处理的思路上去达成这个目标。 本文介绍算法思维基础之一 ----递归 1. 什么是递归 在数学与计算机科学中,递归 (Recursion))是指在函数的定义中使用函数自身的方法,直观上来看,就是某个函数自己调用自己,有循环的意味在里面。 递归有两层含义: 递归问题必须可以分解为若干个规模较小、与原问题形式相同的子问题。并且这些子问题可以用完全相同的解题思路来解决; 递归问题的演化过程是

Yangchenju的博客 1787

Halcon深度学习2 -- 标注工具Deep Learning Tool下载安装

Deep Learning Tool为Halcon开发公司MVTec官方提供的一款标注工具: 标记培训数据是任何深度学习应用程序的关键的第一步。 当涉及到应用程序的性能,准确性和健壮性时,此标记数据的质量起着重要作用。 借助MVTec深度学习工具,我们正在为HALCON用户创建全面流畅的深度学习体验。 通过开发我们自己的解决方案,我们确保可以将其输出无缝集成到HALCON中。 该应用程序还使我们能够吸收在开发HALCON深度学习算法时获得的丰富经验和专业知识,而该算法自然也涉及很多标签! Deep.

fengyingv的博客 1万+

WSL2部署Cadence Virtuoso IC25.1:Ubuntu 26.04排障实录

WSL2以轻量虚拟机结合完整Linux内核,为Windows桌面环境提供了原生级Linux运行能力,解决了传统虚拟机资源开销大、双系统切换低效的问题。对于依赖X11图形协议、FlexNet许可服务和特定动态库的EDA工具链而言,利用WSL2部署Linux发行版需要关注系统集成、显示通路与许可连通性。从技术原理看,图形层X Server的配置、动态库依赖的补齐以及license服务的主机名解析,共同构成EDA工具在WSL2中稳定运行的关键环节。在芯片设计场景中,设计工程师常需在Windows办公机与Linux

weixin_29597551的博客 211

递归—基础算法

#基线条件和递归条件 #每个递归函数都有两部分:基线条件和递归条件。递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。 #栈:栈是一种数据结构,它是一种线性数据结构,只能在一端进行插入和删除操作,另一端是栈顶。栈的特点是先进后出,也就是说,最新添加的元素在栈顶,最先删除的元素在栈底。 #调用栈:计算机在内部使用被称为调用栈的栈。调用栈是用来存储函数调用信息的栈。每当一个函数被调用时,系统就将函数的返回地址和参数压入调用栈,当函数返回时,系统从调用栈中弹出返回地址和参数,并

2301_79805249的博客 249

基于YOLOv10深度学习的花生种子霉变检测系统

YOLO(You Only Look Once)是当前最先进的目标检测算法之一,具有快速、精准的特性。YOLOv10是YOLO系列的最新版本,相较于之前的版本,YOLOv10在特征提取、模型精度和速度上都有了显著的提升。YOLOv10采用了更深的卷积神经网络、更多的跨层特征融合方法,使得其在不同尺寸物体的检测和复杂场景的处理上都表现出了优异的性能。YOLOv10特别适合应用在需要快速处理并检测大量图像的任务中,如花生种子霉变检测等,能够实现精准、高效的检测。

2201_76125393的博客 648

基础递归算法

一.递归的基础知识 1.定义: 递归和平常函数之间的相互调用相同,不过递归是一种函数自己之间或者间接调用自己来完成对数值计算的方法。 2.原理:(需要用到栈的相关知识) 简单的函数调用: #include <stdio.h> void func_A() { printf("AAA\n"); func_B(); printf("aaa\n"); return; } void func_B() { printf("BBB\n"); func_C(); pri

m0_55124878的博客 374

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

递归算法(基础算法)

这篇文章介绍了递归算法的概念和应用,通过多个例题讲解递归的实现方法。主要内容包括: 递归概念:函数自调用,需满足累加问题、递归条件和边界三个条件 例题解析: 计算1到n的和 二分查找 汉诺塔问题 斐波那契数列 集合划分 数的计数 习题练习:爬楼梯、幂次方表示、因子分解 强调递归算法的重要性,建议读者深入学习 文章采用幽默风趣的语言,通过代码示例展示递归实现,适合算法初学者理解递归的基本原理和应用场景。

breeze_phantom 1365

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Leetcode基础算法-递归算法

递龟?递归!

machenme的博客 683

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

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

【算法基础】递归算法 - JAVA

分而治之:将大问题分解为相似的小问题边界条件:解决最基本情况的方法递归关系:大问题与小问题之间的联系。

qq_38955667的博客 2025

Java基础之递归算法

链表(Linked list)一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到是下一个节点的指针(Pointer)。 在链表数据结构中,我们需要使用到递归算法。 递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。 /** 在链表数据结构中,我们需要使用到递归算...

C_time的博客 320

递归算法的魔力:从基础到进阶的深入解析

递归算法在计算机科学中是一个既简单又强大的工具。通过函数调用自身,递归能帮助我们轻松解决许多看似复杂的问题,从经典的斐波那契数列,到更高阶的树形结构遍历。然而,递归的巧妙之处在于理解如何正确地定义“基准情况”和“递归情况”,从而确保算法的正确性和效率。本篇博客将带你从递归的基础概念入手,逐步深入探讨递归算法的应用及优化策略,帮助你在面试和实际编程中掌握这项必备技能。递归不仅仅是一种解决问题的方式,更是培养编程思维的重要手段。通过本篇博客的学习,你已经了解了递归算法的核心概念和它在各种问题中的应用。

17的博客 4530

码农小白 算法篇[递归] 递归基础

递归基础 1、递归概念 递归是一种方法(函数)调用自己的编程技术 void f(int n){ if(n == 0) //设置出口 return; f(n - 1); //调用自己 } 2、用递归求阶乘 /* * 求n的阶乘 * 找重复:n的阶乘 = n * [(n - 1)的阶乘],(n - 1)的阶乘 = (n - 1) * [(n - 2)的阶乘]…… * 找变化...

OutsideSystem的博客 291

算法基础之递归算法及应用

算法基础之递归算法及应用1. 递归的基础定义2. 递归解题思路3. 递归的应用3.1递归求阶乘3.2青蛙跳台阶/爬梯子问题(剑指offer10-2/LC70)3.3斐波那契数列(509)3.4汉诺塔问题4. 链表与递归4.1删除链表中的元素(203) 1. 递归的基础定义 递归的本质是一种解决问题的思想:将规模大的问题转化为规模小的问题来解决。 举个例子,假设游戏一共有10关,当每关的BOSS被打败时,会随机掉落金币。金币的数量 = 当前关数 * 一个1到100以内的随机数。 如果使用循环遍历每关,依次加

Buluchacha的博客 407

算法基础——递归

n!F(n)=F(n−1)+F(n−2)对于n≥2。

oopxiajun博客专栏 907

五大基础算法(枚举、递归、分治、贪心、模拟)

一、枚举法 枚举法,本质上就是搜索算法。 基本思想: 枚举也称作穷举,指的是从问题所有可能的解的集合中一一枚举各元素。 用题目中给定的检验条件判定哪些是无用的,哪些是有用的。能使命题成立。即为其解。

LinJM-机器视觉 3万+

基础算法——递归

刷剑指offer,遇到一些经典算法,现总结下想法。 递归算法最经典的问题非汉诺塔问题了。如果我是教算法的老师,我会和大家讲一个故事。故事的主人公名叫愚公,对,就是愚公移山的那个愚公,话说愚公老年的时候突然有一天发神经,发誓要将门前的两座大山移走(年轻的时候咋不发誓做呢,浪去了吧)。他对智叟诉说道,我虽然年纪大了,一个人没办法移走这两座大山,但是我有子子孙孙,无穷尽也,他们可以把大山移走。然后他的...

dmcAvenger的博客 625

C语言算法:递归算法基础

本文系统地介绍了递归思想及其在C语言中的实现方法。主要内容包括:递归的基本概念、三大要素(基本情况、递归情况、前进方向)以及调用栈执行过程;递归函数的设计模式(线性、二分、多重递归)和参数设计技巧;递归边界条件的处理方法;递归与循环的转换关系,特别是尾递归与循环的等价性;经典递归算法实现;递归性能分析与优化策略;以及递归在实际开发中的应用场景。 文章通过大量C语言代码示例,帮助读者从零开始掌握递归程序设计方法,并理解递归与循环的内在联系。适合有一定C语言基础,希望深入学习递归算法的程序员阅读。

2503_92860243的博客 650

《算法基础:打开算法之门》一2.4 递归

本节书摘来自华章出版社《算法基础:打开算法之门》一书中的第2章,第2.4节,作者 [美]托马斯 H 科尔曼(Thomas H Cormen),更多章节内容可以访问云栖社区“华章计算机”公众号查看 2.4 递归 利用递归技术,能将一个问题转化为同一个样子问题的求解过程。这是我最喜欢的经典的递归例子:计算n!(“n的阶乘”),它被定义为如下,对于一个非负数...

weixin_33711647的博客 186
上一篇: Python变量与数据结构
下一篇: 暴力递归到动态规划
给自己加加油
博客等级 码龄8年 302粉丝 110原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值