Java算法之BFS,DFS,动态规划和贪心算法的实现

yizhihongxing

Java算法之BFS、DFS、动态规划和贪心算法的实现

本文将详细讲解Java中BFS、DFS、动态规划和贪心算法的实现及使用场景。

BFS

BFS全称Breadth-First Search,即广度优先搜索。BFS算法主要应用于无权重图的最短路径查找,或者非加权的图上的搜索问题。BFS算法使用了队列的数据结构来辅助实现,具体实现步骤如下:

  1. 将起始节点加入队列;
  2. 从队列头取出一个节点,遍历它的所有未被访问过的邻居并标记为已访问;
  3. 将邻居节点加入队列;
  4. 如果队列不为空,则重复步骤2~3。

下面是一个BFS示例代码,用于计算在一个无权重图(以邻接矩阵方式存储)中从给定的起始节点到目标节点的最短路径:

public class BFS {
    public static void main(String[] args) {
        int[][] graph = {
                {0, 1, 1, 0, 0},
                {1, 0, 0, 1, 0},
                {1, 0, 0, 1, 1},
                {0, 1, 1, 0, 1},
                {0, 0, 1, 1, 0}
        };
        int start = 0, end = 4;
        System.out.println("The shortest path from " + start + " to " + end + " is " + bfs(graph, start, end));
    }

    public static int bfs(int[][] graph, int start, int end) {
        Queue<Integer> queue = new LinkedList<>();
        boolean[] visited = new boolean[graph.length];
        queue.add(start);
        visited[start] = true;
        int level = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int curr = queue.poll();
                if (curr == end) {
                    return level;
                }
                for (int j = 0; j < graph.length; j++) {
                    if (graph[curr][j] == 1 && !visited[j]) {
                        queue.offer(j);
                        visited[j] = true;
                    }
                }
            }
            level++;
        }
        return -1;
    }
}

DFS

DFS全称Depth-First Search,即深度优先搜索。DFS算法主要应用于图的遍历问题,具体实现步骤如下:

  1. 从起始节点开始,每次选择一个未被访问的邻居节点进行访问,并将其标记为已访问;
  2. 当前节点的所有邻居节点都被访问过后,则回溯到上一个未被访问的节点继续遍历。

下面是一个DFS示例代码,用于在一个无向图(以邻接表方式存储)中查找从起始节点到目标节点的路径:

public class DFS {
    static boolean det = false;
    static LinkedList<Integer>[] adjList;

    public static void main(String[] args) {
        adjList = new LinkedList[4];
        for (int i = 0; i < 4; i++) {
            adjList[i] = new LinkedList<>();
        }
        adjList[0].add(1);
        adjList[0].add(2);
        adjList[1].add(2);
        adjList[2].add(0);
        adjList[2].add(3);
        int start = 2, end = 3;

        visited = new boolean[4];
        visited[start] = true;
        dfs(start, end);
        if(det){
            System.out.println("Path exists");
        }else {
            System.out.println("Path does not exist");
        }
    }

    static boolean[] visited;

    public static void dfs(int node, int end) {
        if (!det) {
            if (node == end) {
                det = true;
            }
            Iterator<Integer> i = adjList[node].listIterator();
            while (i.hasNext()) {
                int n = i.next();
                if (!visited[n]) {
                    visited[n] = true;
                    dfs(n, end);
                }
            }
        }
    }
}

贪心算法

贪心算法(Greedy Algorithm)是一种在每一步取当前状态下最优解的算法,即贪心算法每次寻找当前最优解,并加以选择和保存。简单理解是尽可能地选择当前情况下最优的方案,从而达到全局最优的效果。贪心算法主要应用在需要求最优解的组合问题,具体实现步骤如下:

  1. 初始解为空解,即其中不包含任何一个原问题提出的元素;
  2. 在满足约束条件的前提下,确定该问题的最大加法递推性质所要求的元素并加入到当前解中;
  3. 使用该元素生成一个新问题,再从该新问题出发重复步骤2~3。

这里给出奶酪问题(LeetCode 882)的贪心算法示例代码:

假设有一个二维平面上的无限大的奶酪,上面散布着许多点,每个点表示一个奶酪。你的任务是找到一条线,这条线会将奶酪切成两份,并且两份奶酪大小相等。回答这条线为多长。奶酪的密度是均匀的,并且两者密度相同。

public class CheeseProblem {
    public static void main(String[] args) {
        int[][] cheese = {{1, 0}, {0, 1}, {1, 1}};
        System.out.println(cheeseSlice(cheese));
    }

    public static double cheeseSlice(int[][] cheese) {
        int n = cheese.length;
        double totalX = 0.0, totalY = 0.0;
        for (int[] point : cheese) {
            totalX += point[0];
            totalY += point[1];
        }
        double midX = totalX / n, midY = totalY / n;
        double[] distances = new double[n];
        for (int i = 0; i < n; ++i) {
            distances[i] = Math.sqrt((cheese[i][0] - midX) * (cheese[i][0] - midX) + (cheese[i][1] - midY) * (cheese[i][1] - midY));
        }
        Arrays.sort(distances);
        double sum1 = 0.0, sum2 = 0.0;
        for (int i = 0; i < n / 2; ++i) {
            sum1 += distances[i];
        }
        for (int i = n / 2; i < n; ++i) {
            sum2 += distances[i];
        }
        return Math.abs(sum1 - sum2);
    }
}

动态规划

动态规划(Dynamic Programming)是算法设计中的一种方法,该方法通常用于优化递归算法,例如求斐波那契数列的值。动态规划算法的基本思想是将原问题拆分为多个子问题,完成一个子问题后保存其结果,便于需要时使用已经完成的子问题的结果计算其他子问题。具体实现步骤如下:

  1. 将原始问题拆分为多个分解的子问题;
  2. 分别解决每个子问题,可以使用记忆化技术从已经计算的子问题中重用计算结果;
  3. 组合每个子问题的解来得到原始问题的解,从而实现对原始问题的求解。

以下是一个斐波那契数列的动态规划示例代码:

public class Fibonacci {
    public static void main(String[] args) {
        int num = 10;
        System.out.print(fibonacci(num));
    }

    public static int fibonacci(int num) {
        int[] memo = new int[num + 1];
        return helper(num, memo);
    }

    public static int helper(int num, int[] memo) {
        if (num <= 1) {
            return num;
        }
        if (memo[num] != 0) {
            return memo[num];
        }
        memo[num] = helper(num - 1, memo) + helper(num - 2, memo);
        return memo[num];
    }
}

以上就是BFS、DFS、贪心算法和动态规划算法的完整攻略,希望可以帮助到读者。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java算法之BFS,DFS,动态规划和贪心算法的实现 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Spring Boot如何排除自动加载数据源

    如果在使用Spring Boot时没有启用JPA或其他ORM库,则会默认加载数据源。但是,在某些情况下,您可能不想加载数据源。幸运的是,Spring Boot提供了几种方法来排除自动加载数据源。 方法一:使用 exclude 属性 在 application.properties 中,可以使用 spring.autoconfigure.exclude 属性来…

    Java 2023年5月20日
    00
  • Spring Boot 2.X优雅的解决跨域问题

    Spring Boot 2.X优雅的解决跨域问题 在前后端分离的开发模式下,跨域问题是一个常见的问题。在Spring Boot 2.X中,我们可以通过配置来优雅地解决跨域问题。本文将手把手教你如何在Spring Boot 2.X中解决跨域问题,包括配置跨域、使用注解解决跨域等。 1. 配置跨域 在Spring Boot 2.X中,我们可以通过配置来解决跨域问…

    Java 2023年5月14日
    00
  • java使用websocket,并且获取HttpSession 源码分析(推荐)

    Java使用WebSocket并获取HttpSession的攻略 WebSocket是一种双向通信协议,能够建立客户端和服务端之间的实时通信通道。本攻略将详细讲解Java如何使用WebSocket并获取HttpSession,步骤如下: 步骤1:添加依赖 在项目的pom.xml文件中添加以下依赖: <dependency> <groupId…

    Java 2023年5月23日
    00
  • Maven 项目用Assembly打包可执行jar包的方法

    下面是针对 Maven 项目使用 Assembly 插件打包可执行 jar 包的完整攻略,包含了两个示例。 准备工作 首先,确保已经安装 Maven 和 JDK 并配置好环境变量。 接下来,需要在 Maven 项目中添加 Assembly 插件的依赖和配置。 在项目的 pom.xml 文件中添加以下依赖: <dependencies> … &…

    Java 2023年5月20日
    00
  • SpringMvc框架的简介与执行流程详解

    以下是关于“SpringMVC框架的简介与执行流程详解”的完整攻略,其中包含两个示例。 1. 前言 SpringMVC是一种常用的Java Web开发框架,它基于MVC(Model-View-Controller)模式,将Web应用程序分为三个部分:模型、视图和控制器。本攻略将详细讲解SpringMVC框架的简介和执行流程。 2. 简介 SpringMVC框…

    Java 2023年5月16日
    00
  • Windows Server 2019 Web服务IIS配置与管理理论篇(术语解释、工作原理与常见的WEB服务器)

    Windows Server 2019 Web服务IIS配置与管理理论篇 一、术语解释 WEB 服务器:其实就是部署在服务器上的软件,用于处理用户的HTTP请求并返回相应的HTML或其他数据。 IIS:Internet Information Services,是Windows服务器上自带的WEB服务器软件,目前最新版本为IIS10。 应用程序池:一个IIS…

    Java 2023年6月15日
    00
  • Java System类详解_动力节点Java学院整理

    Java System类详解_动力节点Java学院整理 什么是System类? System类是Java程序中提供的一个包含了一些系统级别的属性和控制操作的类。在Java程序中,我们可以使用System类来读取和设置系统的属性、读写标准的输入流、创建和操纵java虚拟机和Java程序等。 System类中常见的方法 1. System.getProperty…

    Java 2023年5月24日
    00
  • 基于maven使用IDEA创建多模块项目

    下面是基于maven使用IDEA创建多模块项目的完整攻略。 1. 创建父项目 打开IDEA,选择File -> New -> Project。 在左侧栏选择Maven,并且在右侧方框中勾选Create from archetype选项。 在弹出的对话框中选择maven-archetype-quickstart,并点击Next。 填写GroupId…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部