算法的笔记,直接上代码,思路和问题这些,都在代码注释上面

1、工具类

为了生成测试代码和比较器,专门写了一个数组工具类,代码如下:

/*** 数组工具类*/
public class ArrUtil {/*** 生成随机数组* 长度是[0,maxSize]* 每个值是[-maxValue,maxValue]** @param maxSize  数组最大长度* @param maxValue 数组最大值* @return 随机数组*/public static int[] generateRandomArr(int maxSize, int maxValue) {// Math.random() -> [0,1) 所有的小数,等概率返回一个// Math.random() * N -> [0,N) 所有小数,等概率返回一个// (int)(Math.random() * N) -> [0,N-1] 所有的整数,等概率返回一个// (int)(Math.random() * (maxSize + 1)) -> [0,maxSize] 所有的整数,等概率返回一个int size = (int) (Math.random() * (maxSize + 1));int[] arr = new int[size];for (int i = 0; i < arr.length; i++) {arr[i] = (int) (Math.random() * (maxValue + 1)) - (int) (Math.random() * maxValue);}return arr;}/*** 复制数组** @param arr 原数组* @return 复制数组*/public static int[] copyArr(int[] arr) {if (arr == null) {return null;}int[] res = new int[arr.length];for (int i = 0; i < arr.length; i++) {res[i] = arr[i];}return res;}/*** 比较数组是否相等** @param arr1 数组1* @param arr2 数组2* @return 是否相等*/public static boolean isEqual(int[] arr1, int[] arr2) {if (arr1 == null && arr2 == null) {return true;}if (arr1 == null || arr2 == null) {return false;}if (arr1.length != arr2.length) {return false;}for (int i = 0; i < arr1.length; i++) {if (arr1[i] != arr2[i]) {return false;}}return true;}public static void printArray(int[] arr) {if (arr == null) {return;}for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}/*** 获取的系统排序的对数器,用来验证自己的排序是不是正确的参照** @param arr 数组*/public static void sortComparator(int[] arr) {Arrays.sort(arr);}/*** 交换数组中的两个元素** @param arr 数组* @param i   索引1* @param j   索引2*/public static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}
}

2、选择排序

/*** 选择排序*/
public class SelectionSort {/*** 选择排序的思路是很接近人类思想的一种排序方式,就是在一堆数中,每次循环都挑出那个最小的,然后在剩下的里面继续这个操作* <p>* 过程:* arr[0~N-1]范围上,找到最小值所在的位置,然后把最小值交换到0位置。* arr[1~N-1]范围上,找到最小值所在的位置,然后把最小值交换到1位置。* arr[2~N-1]范围上,找到最小值所在的位置,然后把最小值交换到2位置。* …* arr[N-1~N-1]范围上,找到最小值位置,然后把最小值交换到N-1位置。* <p>* 算法复杂度: O(n^2)*/public static void selectionSort(int[] arr) {if (arr == null || arr.length < 2) {return;}for (int i = 0; i < arr.length - 1; i++) {int minIndex = i;for (int j = i + 1; j < arr.length; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}if (minIndex != i) {// 交换ArrUtil.swap(arr, i, minIndex);}}}/*** 用对数器的方法测试*/public static void main(String[] args) {// 测试次数int testTime = 500000;// 数组最大长度int maxSize = 100;// 数组最大值int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {// 先生成一个随机的数组int[] arr = ArrUtil.generateRandomArr(maxSize, maxValue);// 复制一个数组,用来做对照int[] arr1 = ArrUtil.copyArr(arr);int[] arr2 = ArrUtil.copyArr(arr);// 调用测试方法,排序一个数组selectionSort(arr1);ArrUtil.sortComparator(arr2);if (!ArrUtil.isEqual(arr1, arr2)) {succeed = false;System.out.println("原数组:");ArrUtil.printArray(arr);System.out.println("自己排序后:");ArrUtil.printArray(arr1);System.out.println("系统排序后:");ArrUtil.printArray(arr2);break;}}System.out.println(succeed ? "successful!" : "error!");}}

3、冒泡排序

/*** 冒泡排序*/
public class BubbleSort {/*** 冒泡排序的本质思想是通过对比,每次将一个最大的放到数组的最后,在选择的过程中,是将相邻两个做对比,大的依次往后交换* <p>* 过程:* 在arr[0~N-1]范围上:* arr[0]和arr[1],谁大谁来到1位置;arr[1]和arr[2],谁大谁来到2位置 … arr[N-2]和arr[N-1],谁大谁来到N-1位置* 在arr[0~N-2]范围上,重复上面的过程,但最后一步是arr[N-3]和arr[N-2],谁大谁来到N-2位置* 在arr[0~N-3]范围上,重复上面的过程,但最后一步是arr[N-4]和arr[N-3],谁大谁来到N-3位置* …* 最后在arr[0~1]范围上,重复上面的过程,但最后一步是arr[0]和arr[1],谁大谁来到1位置* <p>* 算法复杂度: O(n^2)*/public static void bubbleSort(int[] arr) {if (arr == null || arr.length < 2) {return;}for (int i = arr.length - 1; i > 0; i--) {for (int j = 0; j < i; j++) {if (arr[j] > arr[j + 1]) {ArrUtil.swap(arr, j, j + 1);}}}}/*** 用对数器的方法测试*/public static void main(String[] args) {// 测试次数int testTime = 500000;// 数组最大长度int maxSize = 100;// 数组最大值int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {// 先生成一个随机的数组int[] arr = ArrUtil.generateRandomArr(maxSize, maxValue);// 复制一个数组,用来做对照int[] arr1 = ArrUtil.copyArr(arr);int[] arr2 = ArrUtil.copyArr(arr);// 调用测试方法,排序一个数组bubbleSort(arr1);ArrUtil.sortComparator(arr2);if (!ArrUtil.isEqual(arr1, arr2)) {succeed = false;System.out.println("原数组:");ArrUtil.printArray(arr);System.out.println("自己排序后:");ArrUtil.printArray(arr1);System.out.println("系统排序后:");ArrUtil.printArray(arr2);break;}}System.out.println(succeed ? "successful!" : "error!");}
}

4、插入排序

/*** 插入排序*/
public class InsertSort {/*** 插入排序的思想和我们打扑克牌时给拿到的扑克牌排序一样,先将第一个数看作是有序的,* 然后将第二个数插入到有序的数组中,再将第三个数插入到有序的数组中,以此类推,* 直到将所有的数都插入到有序的数组中。* <p>* 过程:* 想让arr[0~0]上有序,这个范围只有一个数,当然是有序的。* 想让arr[0~1]上有序,所以从arr[1]开始往前看,如果arr[1]<arr[0],就交换。否则什么也不做。* …* 想让arr[0~i]上有序,所以从arr[i]开始往前看,arr[i]这个数不停向左移动,一直移动到左边的数字不再比自己大,停止移动。* 最后一步,想让arr[0~N-1]上有序, arr[N-1]这个数不停向左移动,一直移动到左边的数字不再比自己大,停止移动。* <p>* 算法复杂度: O(n^2)*/public static void insertSort(int[] arr) {if (arr == null || arr.length < 2) {return;}for (int i = 1; i < arr.length; i++) {int index = i;while (index > 0 && arr[index] < arr[index - 1]) {// 数组不越界,并且当前位置数值比前一个的小,将当前位置的数往前交换移动ArrUtil.swap(arr, index, index - 1);index--;}}}/*** 用对数器的方法测试*/public static void main(String[] args) {// 测试次数int testTime = 500000;// 数组最大长度int maxSize = 100;// 数组最大值int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {// 先生成一个随机的数组int[] arr = ArrUtil.generateRandomArr(maxSize, maxValue);// 复制一个数组,用来做对照int[] arr1 = ArrUtil.copyArr(arr);int[] arr2 = ArrUtil.copyArr(arr);// 调用测试方法,排序一个数组insertSort(arr1);ArrUtil.sortComparator(arr2);if (!ArrUtil.isEqual(arr1, arr2)) {succeed = false;System.out.println("原数组:");ArrUtil.printArray(arr);System.out.println("自己排序后:");ArrUtil.printArray(arr1);System.out.println("系统排序后:");ArrUtil.printArray(arr2);break;}}System.out.println(succeed ? "successful!" : "error!");}
}

4、二分查找

  • 二分查找:在有序数组中查找是否存在某个数
  • 认识二分查找:每次将剩下的数组一分为二,看看需要的数据是否存在,不存在,只在一半中继续二分,另一半丢弃
  • 二分查找的复杂度为:O(logN)
  • 大部分二分查找的数组要求是有序的,但不是绝对,在特殊的场景和限制中,可以是无序的

4.1、在有序数组中查找是否存在某个数

public class BinarySearchExist {/*** 二分查找:在有序数组中查找是否存在某个数* 存在返回true,不存在返回false* <p>* 二分查找的过程:* 1. 先找到数组的中间位置,判断中间位置的数是否等于要查找的数* 2. 如果等于,直接返回中间位置的下标* 3. 如果中间位置的数大于要查找的数,说明要查找的数在中间位置的左边,所以在左边继续查找* 4. 如果中间位置的数小于要查找的数,说明要查找的数在中间位置的右边,所以在右边继续查找* 5. 重复以上过程,直到找到要查找的数,或者查找范围为空*/public static boolean binarySearchExist(int[] arr, int num) {if (arr == null || arr.length == 0) {return false;}// 左下标int L = 0;// 右下标int R = arr.length - 1;// 中间位置下标int mid = 0;while (L < R) {// 和mid = (L + R ) / 2 是一个意思,都是求中间位置,预防了L+R溢出的问题mid = L + ((R - L) >> 2);if (arr[mid] == num) {return true;}if (arr[mid] < num) {// 中间位置比查询的数字小,说明要查询的在右侧,改表L下标,去右侧查找L = mid + 1;}if (arr[mid] > num) {// 中间位置比查询的数字大,说明要查询的在左侧,修改R下标,去右侧查找R = mid - 1;}}// 到这个位置,说明L == R,看看L位置是不是和要查询的值一样,如果一样就返回L,不一样就是没有,返回-1return arr[L] == num;}/*** 暴力方法写的比较器,用来判断算法的结果是否正确*/public static boolean existComparator(int[] arr, int num) {if (arr == null || arr.length == 0) {return false;}for (int i = 0; i < arr.length; i++) {if (arr[i] == num) {return true;}}return false;}/*** 用对数器的方法测试*/public static void main(String[] args) {// 测试次数int testTime = 500000;// 数组最大长度int maxSize = 100;// 数组最大值int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {// 先生成一个随机的数组int[] arr = ArrUtil.generateRandomArr(maxSize, maxValue);// 先排好序Arrays.sort(arr);// 随机生成一个需要查询的数字int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());boolean result = binarySearchExist(arr, value);boolean comparatorResult = existComparator(arr, value);if (result != comparatorResult) {succeed = false;ArrUtil.printArray(arr);System.out.printf("查找的值:%d,比较器结果:%b,算法结果:%b\n", value, comparatorResult, result);break;}}System.out.println(succeed ? "successful!" : "error!");}
}

4.2、在一个有序数组中,找>=value的最左位置

import java.util.Arrays;// 在一个有序数组中,找>=value的最左位置
public class BinarySearchNearLeft {/*** 在一个有序数组中,找>=value的最左位置,如果存在,返回满足的最左侧下标,不存在返回-1* 思路:还是用二分法查找,查询到满足条件的,就把那个结果存起来,继续查找,如果还有则更新保存的结果。* 因为我们要查找的是大于等于value的最左侧的值,当满足条件的时候,还需要往左来看是不是有更满足条件的,所以在满足条件的时候,要往左查找* 步骤:* 1、先找到数组的中间位置,判断中间位置的数是不是大于等于要查找的值* 2、如果中间位置满足条件,保存当前的中间位置的下标,再往左边查找(修改R下标)* 3、如果不满足,则往右侧查找(修改L下标)* 4、重复上面的过程*/public static int binarySearchNearLeft(int[] arr, int value) {if (arr == null || arr.length == 0) {return -1;}int L = 0;int R = arr.length - 1;// 保存结果的变量int resultIndex = -1;while (L <= R) {// 和mid = (L + R ) / 2 是一个意思,都是求中间位置,预防了L+R溢出的问题int mid = L + ((R - L) >> 2);if (arr[mid] >= value) {// 满足条件,保存下标,继续往左尝试resultIndex = mid;R = mid - 1;} else {// 不满足条件,往右尝试L = mid + 1;}}return resultIndex;}/*** 暴力方法写的比较器,用来判断算法的结果是否正确*/public static int nearLeftComparator(int[] arr, int num) {if (arr == null || arr.length == 0) {return -1;}for (int i = 0; i < arr.length; i++) {if (arr[i] >= num) {return i;}}return -1;}/*** 用对数器的方法测试*/public static void main(String[] args) {// 测试次数int testTime = 500000;// 数组最大长度int maxSize = 100;// 数组最大值int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {// 先生成一个随机的数组int[] arr = ArrUtil.generateRandomArr(maxSize, maxValue);// 先排好序Arrays.sort(arr);// 随机生成一个需要查询的数字int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());int result = binarySearchNearLeft(arr, value);int comparatorResult = nearLeftComparator(arr, value);if (result != comparatorResult) {succeed = false;ArrUtil.printArray(arr);System.out.printf("查找的值:%d,比较器结果:%d,算法结果:%d\n", value, comparatorResult, result);break;}}System.out.println(succeed ? "successful!" : "error!");}
}

4.3、在一个有序数组中,找<=value的最右位置

import java.util.Arrays;// 在一个有序数组中,找<=value的最右位置
public class BinarySearchNearRight {/*** 在一个有序数组中,找<=value的最右位置,如果存在,返回满足的最左侧下标,不存在返回-1* 思路:还是用二分法查找,查询到满足条件的,就把那个结果存起来,继续查找,如果还有则更新保存的结果* 因为我们要查找小于等于value的最右侧的值,所以在满足条件的时候,要继续往右查找,看有没有更加满足条件的值* 步骤:* 1、先找到数组的中间位置,判断中间位置的数是不是小于等于要查找的值* 2、如果中间位置满足条件,保存当前的中间位置的下标,再往右查找(修改L的下标)* 3、如果不满足,则往右侧查找(修改R下标)* 4、重复上面的过程*/public static int binarySearchNearRight(int[] arr, int value) {if (arr == null || arr.length == 0) {return -1;}int L = 0;int R = arr.length - 1;int resultIndex = -1;while (L <= R) {int mid = L + ((R - L) >> 1);if (arr[mid] <= value) {// 满足条件,保存结果,继续往右(修改L的下标)resultIndex = mid;L = mid + 1;} else {// 不满足条件,说明当前位置比要查找的值大,要往左查找(修改R的值)R = mid - 1;}}return resultIndex;}/*** 暴力方法写的比较器,用来判断算法的结果是否正确*/public static int nearRightComparator(int[] arr, int value) {if (arr == null || arr.length == 0) {return -1;}for (int i = arr.length - 1; i >= 0; i--) {if (arr[i] <= value) {return i;}}return -1;}/*** 用对数器的方法测试*/public static void main(String[] args) {// 测试次数int testTime = 500000;// 数组最大长度int maxSize = 100;// 数组最大值int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {// 先生成一个随机的数组int[] arr = ArrUtil.generateRandomArr(maxSize, maxValue);// 先排好序Arrays.sort(arr);// 随机生成一个需要查询的数字int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());int result = binarySearchNearRight(arr, value);int comparatorResult = nearRightComparator(arr, value);if (result != comparatorResult) {succeed = false;ArrUtil.printArray(arr);System.out.printf("查找的值:%d,比较器结果:%d,算法结果:%d\n", value, comparatorResult, result);break;}}System.out.println(succeed ? "successful!" : "error!");}
}

4.4、局部最小值问题

  • 局部最小值问题:在一个无序数组中,任意两个相邻的数不相等,[0]<[1]表示0位置局部最小,[n-1]<[n-2]表示n-1局部最小,返回中间局部最小的位置下标
  • 在局部最小值问题中,因为强制规定了任意两个相邻的数不相等,[0]<[1]表示0位置局部最小,[n-1]<[n-2]表示n-1局部最小,表示一列数中,前面下降,后面上升,则中间一定存在一个位置,该位置的值比它前后都小,即为局部最小位置

  
代码和测试程序:

/*** 局部最小值问题:在一个无序数组中,任意两个相邻的数不相等,[0]<[1]表示0位置局部最小,[n-1]<[n-2]表示n-1局部最小,返回中间局部最小的位置下标* 在局部最小值问题中,因为强制规定了任意两个相邻的数不相等,[0]<[1]表示0位置局部最小,[n-1]<[n-2]表示n-1局部最小,* 表示一列数中,前面下降,后面上升,则中间一定存在一个位置,该位置的值比它前后都小,即为局部最小位置*/
public class BinarySearchLocalMinimum {/*** 二分查找局部最小值,如果存在,返回一个局部最小的左侧下标,不存在则返回-1* 思路:* 先判断整个数组的最小和最大的两个边界是不是满足局部最小的定义,如果不满足,则返回-1,满足则一定存在局部最小* 用二分查找的方法,每次先判断中间位置是不是大于右侧和左侧,如果大于左侧,则代表左侧上升趋势,在左侧存在局部最小,* 如果大于右侧,则代表右侧下降趋势,右侧存在局部最小* 如果两个都不满足,则代表这个位置小于左侧和右侧,该位置就是局部最小* 步骤:* 1、先判断整个数组的最小和最大的两个边界是不是满足局部最小的定义,如果不满足,则返回-1,满足则一定存在局部最小* 2、判断中间位置如果相对于前一个是上升趋势,则代表左侧必然存在局部最小,从左侧查找(修改R的值)* 3、如果不满足,判断当前位置相对于下一个的趋势,如果是下降趋势,则右侧必然存在局部最小,从右侧查找(修改L的值)* 4、如果不满足,则代表该位置小于左侧和右侧,就是局部最小位置* 5、重复上面的步骤,直到找到为止*/public static int binarySearchLocalMinimum(int[] arr) {if (arr == null || arr.length == 0) {return -1;}// 判断0位置是否是局部最小if (arr.length == 1 || arr[0] < arr[1]) {return 0;}// 判断n-1位置是不是局部最小if (arr[arr.length - 1] < arr[arr.length - 2]) {return arr.length - 1;}// 如果到这里,代表0位置是下降趋势,n-2位置为上升趋势,一定在1~n-2上存在局部最小的位置int L = 1;int R = arr.length - 2;while (L < R) {int mid = L + ((R - L) >> 1);if (arr[mid] > arr[mid - 1]) {// mid-1到mid是上升趋势,表示在左侧存在局部最小的位置R = mid - 1;} else if (arr[mid] > arr[mid + 1]) {// mid到mid+1是下降趋势,表示在右侧存在局部最小的位置L = mid + 1;} else {// mid位置比mid-1小,而且比mid+1也小,表示mid就是局部最小位置return mid;}}return L;}/*** 判断查找的index是否正确的方法,因为每次返回的结果不固定,所以只需要判断找到的位置是不是正确就行*/public static boolean isRight(int[] arr, int index) {if (index == -1) {return arr == null || arr.length == 0;}if (index == 0) {return arr.length == 1 || arr[0] < arr[1];}if (index == arr.length - 1) {return arr[arr.length - 1] < arr[arr.length - 2];}return arr[index] < arr[index - 1] && arr[index] < arr[index + 1];}/*** 生成相邻不相等的数组*/public static int[] generateRandomArray(int maxSize, int maxValue) {int[] arr = new int[(int) (Math.random() * maxSize) + 1];arr[0] = (int) (Math.random() * maxValue) - (int) (Math.random() * maxValue);for (int i = 1; i < arr.length; i++) {do {// 循环生成不想等的值arr[i] = (int) (Math.random() * maxValue) - (int) (Math.random() * maxValue);} while (arr[i] == arr[i - 1]);}return arr;}/*** 用对数器的方法测试*/public static void main(String[] args) {// 测试次数int testTime = 500000;// 数组最大长度int maxSize = 100;// 数组最大值int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {// 生成一个相邻位置不相等的数组int[] arr = generateRandomArray(maxSize, maxValue);// 得到局部最小位置int index = binarySearchLocalMinimum(arr);System.out.println(index);// 判断是否正确if (!isRight(arr, index)) {succeed = false;ArrUtil.printArray(arr);System.out.printf("返回的位置:%d\n", index);break;}}System.out.println(succeed ? "successful!" : "error!");}
}

后记
个人学习总结笔记,不能保证非常详细,轻喷

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

行业分享丨基于SimSolid的大型汽车连续冲压模具刚度分析

*本文投稿自机械零部件制造业用户 汽车连续模具的刚度直接决定了冲压件质量&#xff08;尺寸精度、表面缺陷&#xff09;与模具寿命。传统有限元分析&#xff08;FEA&#xff09;在面对大型复杂模具装配体时&#xff0c;存在网格划分困难、计算资源消耗大、周期长等瓶颈。本文以…

用AI生成的html页面设计放到到Axure上实现再改造的方法

要将 AI 生成的 HTML 原型导入 Axure&#xff0c;该方法的核心逻辑是以 Figma 为 “中间桥梁”&#xff08;因 Axure 无法直接读取 HTML&#xff0c;需通过 Figma 转换格式&#xff09;&#xff0c;分 3 步即可完成&#xff0c;以下是详细操作指南&#xff08;含每步目标、具体…

从入门到实战:Linux sed命令全攻略,文本处理效率翻倍

从入门到实战&#xff1a;Linux sed命令全攻略&#xff0c;文本处理效率翻倍 文章目录从入门到实战&#xff1a;Linux sed命令全攻略&#xff0c;文本处理效率翻倍一、认识sed&#xff1a;什么是流编辑器&#xff1f;二、吃透sed工作原理&#xff1a;为什么它能高效处理文本&am…

TIOBE 8月编程语言榜深度解析:Python占比突破26%,Perl成最大黑马

根据TIOBE最新发布的2025年8月编程语言排行榜&#xff0c;一场静默的技术变革正在上演&#xff1a;Python以26.14%的占比首次突破26%大关&#xff0c;连续12个月稳居榜首。这一数据不仅刷新了Python自身的历史纪录&#xff0c;更成为TIOBE指数自2001年创立以来的最高单语言占比…

从发现到恢复,看瑞数信息如何构建“抗毁重构”实战路径

在信息化社会&#xff0c;“韧性”“弹性”这些词汇常被用来形容系统抵御和应对风险的能力&#xff0c;但对于身处关键基础设施行业的运营者来说&#xff0c;这些概念往往过于抽象&#xff0c;难以直接指导实践。 相比之下&#xff0c;“抗毁重构”更具画面感。它不仅是一个管理…

深入理解 jemalloc:从内存分配机制到技术选型

在高性能服务&#xff08;如数据库、缓存、JVM&#xff09;的底层优化中&#xff0c;内存分配效率直接影响系统整体性能。本文将从操作系统底层的malloc机制切入&#xff0c;详解 jemalloc 的设计理念、开源应用场景、实战案例&#xff0c;技术选型分析 一、操作系统底层的内存…

websoket使用记录

1.项目使用记录1.医疗项目中渲染回收柜温湿度&#xff0c;需要实时更新2.回收柜安瓿回收和余液回收时&#xff0c;需要前端发送指令给回收柜&#xff0c;比如开门、关门等。还需要收到回收柜结果&#xff0c;比如回收的药品信息等。我项目中用的是浏览器自带的websoket&#xf…

DevOps篇之通过GitLab CI 流水线实现k8s集群中helm应用发布

一. 设计思路 构建一个 GitLab CI 流水线&#xff0c;并且要集成到 K8s 集群中的 Helm 应用发布流程。首先&#xff0c;需要了解 GitLab CI 的基本结构&#xff0c;比如.gitlab-ci.yml 文件的配置&#xff0c;包括 stages、jobs、变量设置等。然后&#xff0c;结合之前讨论的 H…

详尽 | Deeplabv3+结构理解

https://arxiv.org/pdf/1802.02611.pdf https://link.springer.com/chapter/10.1007/978-3-319-10578-9_23 目录 Deeplabv3 Encoder部分 Decoder部分 补充摘要 SPP 空间金字塔池化层模块 Dilated/Atrous Conv 空洞卷积 Deeplabv3 deeplab-v3是语义分割网络&#xff0c;组…

【51单片机】【protues仿真】基于51单片机音乐盒(8首歌曲)系统

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 一、主要功能 1、数码管显示当前歌曲序号 2、按键切换歌曲和播放暂停​ 3、内置8首音乐 二、使用步骤 基于51单片机的音乐盒是一种能够存储和播放多首歌曲的电子设备&#xff0c;通过定时器产…

@ZooKeeper 详细介绍部署与使用详细指南

文章目录 **ZooKeeper 详细介绍、部署与使用** 1. 概述 & 核心介绍 1.1 什么是 ZooKeeper? 1.2 核心特性 1.3 核心概念 1.4 典型应用场景 2. 部署 (以 3 节点集群为例) 2.1 环境准备 2.2 安装步骤 (在所有节点执行) 2.3 启动与停止集群 2.4 防火墙配置 (如果开启) 3. 基本…

腾讯Hunyuan-MT-7B翻译模型完全指南:2025年开源AI翻译的新标杆

&#x1f3af; 核心要点 (TL;DR) 突破性成就&#xff1a;腾讯混元MT-7B在WMT25全球翻译竞赛中获得30/31项第一名双模型架构&#xff1a;Hunyuan-MT-7B基础翻译模型 Hunyuan-MT-Chimera-7B集成优化模型广泛语言支持&#xff1a;支持33种语言互译&#xff0c;包括5种中国少数民…

Web 集群高可用全方案:Keepalived+LVS (DR) 负载均衡 + Apache 服务 + NFS 共享存储搭建指南

文章目录Keepalived LVS&#xff08;DR&#xff09; Apache NFS项目背景业务场景与核心需求传统架构的痛点与局限技术方案的选型逻辑项目价值与预期目标项目实践项目环境基础配置配置 router配置免密登录-可选配置 nfs配置 web配置 LVS-RS配置 HA 和 LVS-DS配置 ha1配置 ha2测…

Prometheus监控预警系统深度解析:架构、优劣、成本与竞品

目录 一、Prometheus是什么&#xff1f;核心定位与架构 二、竞品分析&#xff08;Prometheus vs. Zabbix vs. Nagios vs. Commercial SaaS&#xff09; 三、部署成本分析 四、服务器资源消耗分析 五、给您的最终建议 一、Prometheus是什么&#xff1f;核心定位与架构 Prom…

Nginx反向代理及配置

Nginx反向代理 二级域名系统 顾名思义&#xff0c;我们有很多的这个不同的二级域名的用户来访问我们&#xff0c;比如说微博。它有一个主域名weibo.com。如果我叫一鸣,申请了一个微博&#xff0c;然后我就可以在微博这个主系统上申请一个二级域名来访问我微博的主页&#xff0…

嵌入式系统通信总线全景探秘:从板内到云端

引言 在嵌入式系统设计中&#xff0c;选择合适的通信总线是决定系统性能、成本和可靠性的关键因素。从简单的芯片间通信到复杂的工业网络&#xff0c;不同的总线技术各司其职&#xff0c;形成了嵌入式世界的"交通网络"。本文将深入探讨五种经典且重要的通信技术&…

2022版Unity创建时没有2D灯光(2D Light),没有Global LIght2D怎么办?

简单来说就是你的渲染管线没有升级到URP管线&#xff0c;所以才没有这些2D灯光 如果你的创建灯光和我一样&#xff0c;没有红线划掉的部分&#xff0c;说明你和我的问题一样&#xff0c;看下面的教程可以解决。 1. 确保Unity版本 确保你的Unity版本至少为2019.4或更高版本&…

技术小白如何快速的了解opentenbase?--把握四大特色

1.基本介绍 作为一名计算机专业相关背景的学生&#xff0c;我们或多或者接触过一些数据库&#xff0c;对于数据库肯定是有所了解的&#xff1b; 你可能学习的是和微软的sql server这样的数据库&#xff1b; 你可能接触的更多的是企业级项目开发里面使用的这个mysql数据库&#…

企业微信AI落地:如何选择企业微信服务商?

现在企业用企业微信做客户运营&#xff0c;最怕的不是“没AI工具”&#xff0c;而是“AI用不起来”——要么功能不贴业务场景&#xff0c;员工嫌麻烦不用&#xff1b;要么回复不专业&#xff0c;客户体验差&#xff1b;要么数据不同步&#xff0c;管理者看不到效果。其实解决这…

【学Python自动化】 11 标准库简介 —— 第二部分

一、格式化输出 reprlib 模块 提供定制版 repr()&#xff0c;缩略显示大型或深层嵌套对象import reprlib reprlib.repr(set(supercalifragilisticexpialidocious)) # "{a, c, d, e, f, g, ...}"pprint 模块 美化输出&#xff0c;添加换行和缩进显示复杂数据结构impor…