七、常用算法

文章目录

一、二分查找(非递归)

java 复制代码
package com.gyh.algorithm;

import com.gyh.search.BinarySearch;

import java.util.ArrayList;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class BinarySearchNotRecursion {
    public static void main(String[] args) {
        int[] arr = {-1, 11, 11, 11, 34, 89};
        int index = BinarySearchNotRecursion.search(arr, 89);
        System.out.println(index);
    }

    public static int search(int[] nums, int value) {
        if (nums == null || nums.length <= 0) {
            return -1;
        }
        int left = 0;
        int right = nums.length - 1;
        int mid;
        while (left <= right) {
            mid = (left + right) / 2;
            if (value < nums[mid]) {
                right = mid - 1;
            } else if (value > nums[mid]) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

二、分治算法

2.1 分治算法介绍

2.2 分治算法应用案例

java 复制代码
package com.gyh.algorithm;

/**
 * @author Gao YongHao
 * @version 1.0
 * 汉诺塔
 */
public class Hanoi {
    public static void main(String[] args) {
        hanoiTower(5, 'A', 'B', 'C');
    }

    public static void hanoiTower(int num, char a, char b, char c) {
        // 如果只有一个盘
        if (num == 1) {
            System.out.println("第1个盘从" + a + "->" + c);
            return;
        }

        // 如果我们有 n>= 2 情况,我们总是可以看做是两个盘 1. 最下边的一个盘 2. 上面的所有盘
        // 1. 先把 最上面的所有盘 A -> B ,移动过程会使用到 C
        hanoiTower(num - 1, a, c, b);
        // 2. 在把 最下面的盘放入C
        System.out.println("第" + num + "个盘从" + a + "->" + c);
        // 3. 把 B 塔所有的盘放到 C 塔上,移动过程使用到 a 塔
        hanoiTower(num - 1, b, a, c);

    }
}

三、动态规划算法

3.1 引出

3.2 基本介绍

3.3 应用实例

java 复制代码
package com.gyh.algorithm;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class KnapsackProblem {
    public static void main(String[] args) {
        int[] w = {1, 4, 3};
        int[] val = {1500, 3000, 2000};
        String[] valStr = {"吉他", "音响", "电脑"};
        int m = 4; // 背包的容量
        int n = val.length; // 物品的数量

        // v[i][j] 表示在前 i 个物品中能有装入容量为 j 的背包中的最大价值
        int[][] v = new int[n + 1][m + 1];
        // 用于记录方案方法
        String[][] items = new String[n + 1][m + 1];
        // 初始化第一行和第一列,这里在本程序中,可以不去处理,因为默认为0
        for (int i = 0; i < v.length; i++) {
            v[i][0] = 0; // 第一列设置为 0
            items[i][0] = "";
        }

        for (int i = 0; i < v[0].length; i++) {
            v[0][i] = 0; // 第一列设置为 0
            items[0][i] = "";
        }

        // 动态规划
        for (int i = 1; i < v.length; i++) {
            for (int j = 1; j < v[i].length; j++) {
                // 若当前物品的重量大于目前背包的容量
                // 则默认使用上一物品添加时在该背包容量情况下的价值
                if (w[i - 1] > j) {
                    v[i][j] = v[i - 1][j];
                    items[i][j] = items[i - 1][j];
                } else {
                    // 若当前物品的重量小于等于目前背包的容量
                    // 判断添加当前物品后的最大价值与上一物品添加时的最大价值谁大
                    // 注意:若添加完当前物品后还有背包容量,则需再加上该容量下的最大价值
//                    v[i][j] = Math.max(v[i - 1][j], val[i - 1] + v[i - 1][j - w[i - 1]]);

                    // 只有在这里才可能有新的方案给出
                    if (v[i - 1][j] <= val[i - 1] + v[i - 1][j - w[i - 1]]) {
                        v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];

                        String con;
                        items[i][j] = valStr[i - 1] + ((con = items[i - 1][j - w[i - 1]]).equals("") ? con : "+" + con);
                    } else {
                        v[i][j] = v[i - 1][j];
                        items[i][j] = items[i - 1][j];
                    }

                }
            }
        }


        // 输出 v
//        for (int[] ints : v) {
//            for (int anInt : ints) {
//                System.out.print(anInt + "\t\t");
//            }
//            System.out.println();
//        }

        for (int i = 1; i < v.length; i++) {
            for (int j = 1; j < v[0].length; j++) {
                System.out.print(v[i][j] + "," + items[i][j] + "\t\t");
            }
            System.out.println();
        }
    }


}

四、KMP算法

4.1 引出

4.2 暴力匹配法

java 复制代码
package com.gyh.algorithm;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class ViolenceMatch {
    public static void main(String[] args) {
        String str1 = "硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好";
        String str2 = "谷 尚硅谷";
        System.out.println(match(str1, str2));
    }

    public static int match(String origin, String sub) {
        char[] org = origin.toCharArray();
        char[] su = sub.toCharArray();

        int pos = 0; // 用于指示原串的匹配时的首位置
        int j = 0;

        while (pos < org.length && j < su.length) {
            if (org[pos] == su[j]) {
                pos++;
                j++;
            } else {
                pos = pos - j + 1; // 回溯到需要匹配的下一个位置
                j = 0;
            }
        }
        if (j == su.length) {
            return pos - j;
        }
        return -1;

    }
}

4.3 KMP算法

java 复制代码
package com.gyh.algorithm;

import java.util.Arrays;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class KMP {
    public static void main(String[] args) {
        String str1 = "硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好";
        String str2 = "谷 1尚硅谷";
        System.out.println(Arrays.toString(next(str2)));
        System.out.println(match(str1, str2, next(str2)));
    }

    public static int match(String str1, String str2, int[] next) {
        for (int i = 0, j = 0; i < str1.length(); i++) {
            // 需要处理 str1.charAt(i) != str2.charAt(j),去调整 j 的大小
            // KMP 算法核心点
            while (j > 0 && str1.charAt(i) != str2.charAt(j)) {
                j = next[j - 1];
            }
            if (str1.charAt(i) == str2.charAt(j)) {
                j++;
            }

            if (j == str2.length()) { // 找到了
                return i - j + 1;
            }
        }
        return -1;
    }

    // 获取到一个字符串(子串)的部分匹配值
    public static int[] next(String dest) {
        int[] next = new int[dest.length()];
        next[0] = 0; // 如果字符串的长度是 1 部分匹配值就是 0
        for (int i = 1, j = 0; i < dest.length(); i++) {
            // 当 dest.charAt(i) != dest.charAt(j),我们需要从next[j-1]获取新的j
            // 直到我们发现有 dest.charAt(i) == dest.charAt(j) 成立才退出
            // 这是kmp算法那的核心点
            while (j > 0 && dest.charAt(i) != dest.charAt(j)) {
                j = next[j - 1];
            }

            // 当dest.charAt(i) == dest.charAt(j) 满足时,部分匹配值就是+1
            if (dest.charAt(i) == dest.charAt(j)) {
                j++;
            }
            next[i] = j;
        }

        return next;
    }
}

五、贪心算法

5.1 基本介绍

5.2 应用实例

java 复制代码
package com.gyh.algorithm;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class GreedyAlgorithm {
    public static void main(String[] args) {
        // 定义地名集合
        Set<String> places = new HashSet<>(Arrays.asList("北京", "上海", "天津", "广州", "深圳", "成都", "杭州", "大连"));
        // 设置广播台的覆盖范围
        HashMap<String, Set<String>> broadCast = new HashMap<>();
        broadCast.put("K1", new HashSet<>(Arrays.asList("北京", "上海", "天津")));
        broadCast.put("K2", new HashSet<>(Arrays.asList("广州", "北京", "深圳")));
        broadCast.put("K3", new HashSet<>(Arrays.asList("成都", "上海", "杭州")));
        broadCast.put("K4", new HashSet<>(Arrays.asList("上海", "天津")));
        broadCast.put("K5", new HashSet<>(Arrays.asList("杭州", "大连")));
        // 用于存储结果
        Set<String> result = new HashSet<>();

        // 用于存储各关闭的覆盖信息
        HashSet<String> tempSet = new HashSet<>();

        String maxBName;
        int max;
        while (!places.isEmpty()) {
            maxBName = null;
            max = -1;
            // 遍历剩余的电台,找出最优解
            for (Map.Entry<String, Set<String>> stringListEntry : broadCast.entrySet()) {
                // 清空临时的set集合
                tempSet.clear();
                // 将当前的广播范围加入至临时集合中
                tempSet.addAll(stringListEntry.getValue());
                // 计算当前的广播的最大未覆盖的范围大小(tempSet会保留交集的结果)
                tempSet.retainAll(places);

                // 记录本轮中最大范围电台的信息
                // 为空表示是第一次添加
                // 若大于已遍历的最大电台未覆盖值则改写信息
                int count;
                if ((count = tempSet.size()) > 0 && (maxBName == null || count > max)) {
                    maxBName = stringListEntry.getKey();
                    max = count;
                }
            }
            // 记录最大的电台信息,并将其在原始map中的信息删除
            if (maxBName != null) {
                result.add(maxBName);
                places.removeAll(broadCast.get(maxBName));
                broadCast.remove(maxBName);
            }

        }
        System.out.println(result);

    }

}
相关推荐
Book_熬夜!2 分钟前
Python基础(六)——PyEcharts数据可视化初级版
开发语言·python·信息可视化·echarts·数据可视化
无问81711 分钟前
数据结构-排序(冒泡,选择,插入,希尔,快排,归并,堆排)
java·数据结构·排序算法
m0_6312704029 分钟前
高级c语言(五)
c语言·开发语言
customer0832 分钟前
【开源免费】基于SpringBoot+Vue.JS在线文档管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
2401_8582861135 分钟前
53.【C语言】 字符函数和字符串函数(strcmp函数)
c语言·开发语言
Flying_Fish_roe1 小时前
Spring Boot-版本兼容性问题
java·spring boot·后端
程序猿进阶1 小时前
如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?
java·ide·vscode·算法·面试·职场和发展·架构
Eloudy1 小时前
一个编写最快,运行很慢的 cuda gemm kernel, 占位 kernel
算法
程序猿练习生1 小时前
C++速通LeetCode中等第5题-无重复字符的最长字串
开发语言·c++·leetcode
slandarer1 小时前
MATLAB | R2024b更新了哪些好玩的东西?
java·数据结构·matlab