iterator的使用+求数组中的第n大值+十大经典排序算法

news2024/10/4 16:48:05

目录

一、iterator的用法

二、求一个数组中的第n大值(n为2或者3)

1、求一个数组中的第二大值(不能使用排序)

 2、求一个数组中的第三大值(不能使用排序)

三、冒泡排序

1、基本思想

2、代码实现

3、存在问题及改进方式

四、 选择排序

1、基本思想

2、代码实现

五、插入排序

六、希尔排序

七、归并排序

 八、快速排序

1、算法步骤

2、算法实现

3、复杂度分析

九、堆排序

1、算法步骤(升序排序)

2、算法实现

十、计数排序

1、计数排序的特征

2、算法步骤

3、算法实现

4、适用范围

5、稳定排序和不稳定排序

十一、桶排序

1、算法实现

2、算法分析

 十二、基数排序

1、使用LSD实现基数排序算法

2、基数排序vs桶排序vs计数排序


一、iterator的用法

1、删除0到101中可以被2、被3、被5整除的数字

(1)方法一:使用for循环遍历删除

List<Integer> list = new ArrayList<>();

  // 将0-101存入list
        for(int i = 0;i <= 100;i++){
        list.add(i);
        }
        System.out.println(list);

        // 从list中删除能被2、被3、被5整除的数字
        for(int i = 0;i < list.size();i++){
            int num = list.get(i);
            if(num % 2 == 0 || num % 3 == 0 || num % 5 == 0){
                list.remove(Integer.valueOf(num));// 删除对象类型 new Integer(num)
                i--;
            }
        }
        System.out.println(list);

 (2)方法二:使用iterator删除

 List<Integer> list = new ArrayList<>();

        // 将0-101存入list
        for(int i = 0;i <= 100;i++){
            list.add(i);
        }
        System.out.println(list);

        // 从list中删除能被2、被3、被5整除的数字
        Iterator<Integer> iterator = list.iterator();
        // iterator会遍历到每一个元素
        while(iterator.hasNext()){// 判断下一个元素是否存在
            int num = iterator.next();// 获取下一个元素
            if(num %2 == 0 || num % 3 == 0 || num % 5 == 0){
                iterator.remove();// 删除下一个元素
            }
        }
        System.out.println(list);

二、求一个数组中的第n大值(n为2或者3)

1、求一个数组中的第二大值(不能使用排序)

/**
 * 求一个数组中的第二大数(不能使用排序)
 */
public class SecondMax {

    public int secondMax(int[] nums){
        // 拿到一个值作为最大值,拿到一个值作为第二大值
        int max = nums[0];
        int second = nums[1];
        if(second > max){
            int t = max;
            max = second;
            second = t;
        }

        // 从第三个数开始,不断调整second和max
        for(int i = 2;i < nums.length;i++){
            if(nums[i] > max){
                second = max;
                max = nums[i];
            }else if(nums[i] > second){
                second = nums[i];
            }
        }

        return second;
    }

    public static void main(String[] args) {
        int[] nums = {7,9,5,6,8};
        System.out.println(new SecondMax().secondMax(nums));
    }
}

 2、求一个数组中的第三大值(不能使用排序)

/**
 * 求一个数组中的第三大值
 */
public class ThirdMax {

    public int thirdMax(int[] nums) {
        Set<Integer> set = Arrays.stream(nums)
                .boxed()
                .collect(Collectors.toSet());
        nums = set.stream()
                .mapToInt(Integer::intValue)
                .toArray();

        // 1个元素
        if(nums.length == 1){
            return nums[0];
        }
        // 2个元素
        if(nums.length == 2){
            return nums[0] > nums[1] ? nums[0] : nums[1];
        }

        // 3个及三个元素
        // 假设获取到第一大值,第二大值,第三大值
        int max = nums[0];
        int second = nums[1];
        int third = nums[2];
        if(second > max){
            int t = max;
            max = second;
            second = t;
        }
        if(third > max){
            int t = max;
            max = third;
            third = t;
        }
        if(third > second){
            int t = second;
            second = third;
            third = t;
        }

        for(int i = 3;i < nums.length;i++){
            if(nums[i] > max){
                third = second;
                second = max;
                max = nums[i];
            }else if(nums[i] > second){
                third = second;
                second = nums[i];
            }else if(nums[i] > third){
                third = nums[i];
            }
        }

        return  third;
    }

    public static void main(String[] args) {
        int[] nums = {7,9,5,6,8};
        System.out.println(new ThirdMax().thirdMax(nums));
    }
}

三、冒泡排序

1、基本思想

将一个数组中的最大元素不断放在数组中的最后一个位置

2、代码实现

/**
 * 冒泡排序
 */
public class BubbleSort {

    /**
     * 交换数组中两个指定位置的数组元素的值
     * @param i
     * @param j
     * @param nums
     */
    private void swap(int i,int j,int[] nums){
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }

    public void bubbleSort(int[] nums){
       for(int i = 0;i < nums.length - 1;i++){// 处理length - 1次数组
           for(int j = 0;j <= nums.length - 2 - i;j++){// 处理一次数组 将数组中最大值移动到数组最后一个位置上
               if(nums[j] > nums[j+1]){
                  swap(j,j + 1, nums);
               }
           }
       }
    }

    public static void main(String[] args) {
        int[] nums = {3,2,1,6,5,4};
        new BubbleSort().bubbleSort(nums);
        System.out.println(Arrays.toString(nums));
    }
}

3、存在问题及改进方式

(1)存在问题:数组【1,2,3,4,5,6】也要进行一次冒泡排序

(2)改进方式:

public void bubbleSort(int[] nums){
       for(int i = 0;i < nums.length - 1;i++){// 处理length - 1次数组
           boolean flag = false;
           for(int j = 0;j <= nums.length - 2 - i;j++){// 处理一次数组 将数组中最大值移动到数组最后一个位置上
               if(nums[j] > nums[j+1]){
                  swap(j,j + 1, nums);
                  flag = true;
               }
           }
           // 没有一次交换,则flag为false,则nums为升序,则跳出外层循环
           if(!flag){
               break;
           }
       }
    }

四、 选择排序

1、基本思想

不断将数组中的最大元素放在第一个位置

2、代码实现

/**
 * 选择排序
 */
public class SelectSort {


    /**
     * 交换数组中两个指定位置的数组元素的值
     * @param i
     * @param j
     * @param nums
     */
    private void swap(int i,int j,int[] nums){
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }

    /**
     * 选择排序
     * @param nums
     */
    public void selectSort(int[] nums){
        for(int i = 0;i < nums.length - 1;i++){// 处理length - 1次数组
            int max = i;
            // 遍历当前数组,更新max
            for(int j = i+1;j < nums.length;j++){
                if(nums[j] > nums[max]){
                    max = j;
                }
            }
            swap(max,i,nums);
        }
    }

    public static void main(String[] args) {
        int[] nums = {3,2,1,6,5,4};
        new SelectSort().selectSort(nums);
        System.out.println(Arrays.toString(nums));
    }
}

五、插入排序

/**
 * 插入排序 核心思想:将数组分为有序区和无序区,有序区默认为第一个元素,从无序区中不断取出第一个元素作为待
 * 插入元素,对有序区中的元素从后向前进行查找,找到第一个比待插入元素小的元素,将待插入元素插入到该元素后
 * 面的位置上,如果在有序区中没有找到比待插入元素小的元素,将待插入元素插入到有序区中第一个元素的位置上
 */
public class InsertSort {
    public void sort(int[] arr){
        if(arr == null || arr.length == 0){
            return;
        }
        int length = arr.length;
        for(int i = 1;i < length;i++){// 取出有序区中的元素
            int t = arr[i];// 保存有序区中的元素
            int j = i - 1;// 保存无序区中的最后一个元素
            while (j>=0){
                if(arr[j] > t){
                    arr[j+1] = arr[j];
                    j--;
                }else {
                    // 找到第一个较小元素
                    /*arr[j+1] = t;*/
                    break;
                }
            }
            // 没找到第一个较小元素
            arr[j+1] = t;
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,7,5,8,2,4,6};
        System.out.println("排序前的数组:" + Arrays.toString(arr));
        new InsertSort().sort(arr);
        System.out.println("排序后的数组:" + Arrays.toString(arr));
    }
}

六、希尔排序

/**
 * 希尔排序 核心思想:插入排序,先保证数据部分有序,再将部分有序的数组通过插入排序合并成一个有序数组
 */
public class ShellSort {
    public void sort(int[] arr){
        // 入参判断
        if(arr == null || arr.length == 0){
            return;
        }

        int length = arr.length;
        // 确定步数
        for(int step = length / 2;step >= 1;step= step / 2){
            // 按照步数进行分组,每组两个元素
            for(int i = step;i < arr.length;i++){
                // 对每一组元素进行插入排序
                int j = i - step;
                int insertVal = arr[i];
                while (j>=0){
                    if(arr[j] > insertVal){
                        arr[j+step] = arr[j];
                        j -= step;
                    }else{
                        break;
                    }
                }
                arr[j+step] = insertVal;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,7,5,8,2,4,6};
        System.out.println("排序前的数组:" + Arrays.toString(arr));
        new ShellSort().sort(arr);
        System.out.println("排序后的数组:" + Arrays.toString(arr));
    }
}

七、归并排序

/**
 * 归并排序 核心思想:归并排序是建立在归并操作上的排序算法,该算法是分治法的一个典型应用
 */
public class MergeSort {

    public static int[] sort(int[] arr){
        // 入参判断
        if(arr == null || arr.length < 2){
            return arr;
        }

        int mid = arr.length / 2;
        int[] leftArr = Arrays.copyOfRange(arr, 0, mid);// 对一个数组进行范围性复制,得到一个新的数组
        int[] rightArr = Arrays.copyOfRange(arr,mid, arr.length);

        return merge(sort(leftArr),sort(rightArr));
    }

    /**
     * 辅助方法:将两个有序数组合并为一个有序数组
     * @param nums1
     * @param nums2
     */
    public static int[] merge(int[] nums1,int[] nums2){
        // 入参判断
        if(nums1 == null || nums1.length == 0){
              return nums2;
        }
        if(nums2 == null || nums2.length == 0){
              return nums1;
        }

        int[] result = new int[nums1.length + nums2.length];
        int i = 0;
        int j = 0;
        int k = 0;
        while (i < nums1.length && j < nums2.length){
            if(nums1[i] < nums2[j]){
                result[k++] = nums1[i++];
            }else {
                result[k++] = nums2[j++];
            }
        }

        while (i < nums1.length){
            result[k++] = nums1[i++];
        }
        while (j < nums2.length){
            result[k++] = nums2[j++];
        }

        return result;
    }

    public static void main(String[] args) {
        int[] arr = {3,7,5,8,2,4,6};
        System.out.println("排序前的数组:" + Arrays.toString(arr));
        System.out.println("排序后的数组:" + Arrays.toString(sort(arr)));
    }
}

 

 八、快速排序

1、算法步骤

(1)从数列中挑出一个元素作为基准(pivot),一般选择第一个元素作为数列的基准

(2)对数列进行排序,将所有比基准小的元素放在基准前面,将所有比基准大的放在基准后面,和基准相等的可以放在任意一边。在这个分区退出之后,该基准就位于数列的中间位置。(2)操作被称为分区(partition)操作。

(3)递归地(recursive)对小于基准的元素的子序列和大于基准的元素的子序列进行排序

2、算法实现

/**
 * 快速排序
 */
public class FastSort {
    /**
     * 对数组指定区间进行快速排序
     * @param arr
     * @param left
     * @param right
     */
     public static void sort(int[] arr,int left,int right){
         // 入参判断
         if(arr == null || arr.length < 2){
             return ;
         }

         // 递归到底的情况
         if(left>=right){
             return;
         }

         // 递归操作
         // 1、确定基准
         int pivot = arr[left];// 确定基准

         // 2、将区间数组中比基准小的元素放在基准前面,比基准大的元素放在基准后面,重复此操作
         int i = left;
         int j = right;
         while (i<j){
             // 从区间数组右边最后一个元素开始找,找到比基准小的第一个元素放在基准前面
             while (i<j && arr[j]>pivot){
                 j--;
             }
             if(i<j){
                 arr[i] = arr[j];
                 i++;
             }
             // 从区间数组左边第一个元素开始找,找到比基准大的第一个元素放在基准后面
             while (i<j && arr[i]<pivot){
                 i++;
             }
             if(i<j){
                 arr[j] = arr[i];
                 j--;
             }
         }
         // 将基准元素放到分区位置
         arr[i] = pivot;

         // 3、对区间数组的左右子区间分别进行快速排序
         sort(arr, left, i-1);
         sort(arr, i+1, right);
     }

    public static void main(String[] args) {
        int[] nums = {7,4,8,2,1,0,9,6,5,3};
        System.out.println("排序前的数组:"+ Arrays.toString(nums));
        sort(nums, 0, nums.length - 1);
        System.out.println("排序前的数组:"+ Arrays.toString(nums));
    }
}

3、复杂度分析

(1)快速排序的最坏情况的时间复杂度O(n^{2}),比如顺序数列的快排

(2)快速排序的平摊期望时间O(nlog_{2}^{n}),且O(nlog_{2}^{n})隐藏的常数因子比复杂度稳定等于O(log_{2}^{n})的归并排序要小很多。因此,对于绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序

九、堆排序

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一种等效于完全二叉树的数据结构,满足以下性质,即子节点的键值或索引总是小于(或者大于)他的父节点。堆排序是利用了堆概念的选择排序。有两种实现方法:

大顶堆:每个节点的值都大于或者等于其子节点的值,可用于实现升序排列的堆排序

小顶堆:每个节点的值都小于或者等于其子节点的值,可用于实现降序排列的堆排序

1、算法步骤(升序排序)

(1)使用heapify方法堆化数组

(2)交换堆首和堆尾元素

(3)调用swim()方法,使得除过堆尾元素的树满足最大堆的性质

(4)重复步骤(2),直到堆中只有一个元素

2、算法实现

/**
 * 堆排序
 */
public class HeapSort {

    /**
     * 获取当前节点的父节点的索引
     * @param index
     * @return
     */
    private static int getParentIndex(int index){
        if(index == 0){
            return -1;// 特殊表示
        }
        return (index - 1) / 2;
    }

    /**
     * 获取当前节点的左孩子节点的索引
     * @param index
     * @return
     */
    private static int getLeftIndex(int index){
        return index * 2 + 1;
    }

    /**
     * 对索引为compaerIndex的节点执行下沉操作
     * @param compareIndex 索引
     * @param arr 数组
     * @param length 数组长度
     */
    private static void swim(int compareIndex,int[] arr,int length){
         int compareVal = arr[compareIndex];
         // 记录当比较节点的索引
         int curIndex = compareIndex;
         // 获取左孩子节点的索引
         int leftIndex = getLeftIndex(curIndex);

         // 左孩子存在
        while (leftIndex < length){
            // 获取左右孩子节点中优先级较高节点的索引
            int changeIndex = leftIndex;
            int rightIndex = leftIndex + 1;
            if(rightIndex < length && arr[rightIndex] > arr[leftIndex]){
                changeIndex = rightIndex;
            }
            // 与当前节点比较,如果当前节点的优先级低于交换节点,则交换当前节点和交换节点
            if(compareVal < arr[changeIndex]){
                arr[curIndex] = arr[changeIndex];
                curIndex = changeIndex;
                leftIndex = getLeftIndex(curIndex);
            }else{
                break;
            }
        }
        arr[curIndex] = compareVal;
    }

    /**
     * 堆化数组,使得数组具备堆的性质
     * @param arr
     */
    private static void heapify(int[] arr){
        // 入参判断
        if(arr == null || arr.length == 0){
            return;
        }
        int lastIndex = arr.length - 1;
        // 获取最后一个节点的父节点的索引
        int lastParentIndex = getParentIndex(lastIndex);
        // 从该节点开始向前到堆顶节点进行进行下沉
        for(int i = lastParentIndex;i >= 0;i--){
           swim(i,arr,arr.length);
        }
    }

    /**
     * 交换数组arr中第i个元素和第j个元素的位置
     * @param i
     * @param j
     * @param arr
     */
    private static void swap(int i,int j,int[] arr){
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void sort(int[] arr){
         heapify(arr);
         if(arr == null || arr.length == 0){
             return;
         }
         // 堆排序
         for(int i = arr.length - 1;i > 0;i--){
             // 1、将堆中第一个元素与最后一个元素交换位置
             swap(0,i,arr);
             // 2、对堆顶元素做下沉操作
             swim(0, arr, i);
         }
    }

    public static void main(String[] args) {
        int[] arr = {3,10,12,5,6,98,4,5,34,25,36,75,10};
        System.out.println("排序前的数组:" + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序后的数组:" + Arrays.toString(arr));
    }
}

十、计数排序

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的新数组空间中。计数排序是一种线性时间复杂度的排序,要求输入的数据必须是确定范围的整数

1、计数排序的特征

(1)当输入的元素是n个0到k之间的整数时,它的运行时间是O(n+k)。计数排序不是比较排序,排序的速度快于任何比较排序算法

(2)由于用来计数的Hash数组的长度取决于待排序数组中数据的范围(等于待排序数组中的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要很大的时间和内存

(3)通俗地理解,例如有10个年龄不同的人,统计出有5个人年龄比A小,那A的年龄就排在第6位,使用这个方法就可以得到其他每个人的位置,也就排好了序。当然,年龄有重复时也需要进行特殊处理(为了保证稳定性),这就是为什么最后要反向填充待排序数组,以及将每个数字的统计减去1的原因

2、算法步骤

(1)找出待排序的数组中的最大元素

(2)统计待排序数组中值为i的元素出现的次数,存入数组Hash的第i项

(3)反向填充待排序数组,依次将Hash数组中的每一个元素i放在待排序数组的第index位置上,放Hash[i]次

3、算法实现

/**
 * 计数排序
 */
public class CountSort {

    private static int getMax(int[] arr){
        return Arrays.stream(arr).max().getAsInt();
    }

    public static  void sort(int[] arr){
        // 入参判断
        if(arr == null || arr.length < 2){
            return;
        }

        // 计数排序
        // 1、找到待排序数组中的最大元素
        int max = getMax(arr);
        int[] hash = new int[max + 1];
        // 2、统计待排序数组中每个元素i出现的次数,并存入hash数组中的第i项
        Arrays.stream(arr).forEach(item->{
            hash[item]++;
        });
        // 3、反向填充待排序数组
        int index = 0;
        for(int i = 0;i < hash.length;i++){
            int count = hash[i];
            while (count-- > 0){
                arr[index++]=i;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,10,12,5,6,98,4,5,34,25,36,75,10};
        System.out.println("排序前的数组:" + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序后的数组:" + Arrays.toString(arr));
    }
}

4、适用范围

计数排序适用于数据范围比较小的数组,且数组中的元素必须是非负整数

5、稳定排序和不稳定排序

(1)区别:相同元素的相对位置是否发生了改变,没改变就是稳定排序,改变了就是非稳定排序

(2)插入排序可以是稳定排序,也可以不是稳定排序,但一般来讲不是稳定排序

(3)计数排序既可以是稳定排序又可以是非稳定排序,但一般来讲是稳定排序

(4)快速排序不是稳定排序

十一、桶排序

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否取决于映射函数的确定。为了使得桶排序更加高效,我们需要做到以下两点:

(一)在额外空间充足的情况下,尽可能增大桶的数量

(二)所使用的映射函数能够将输入的N个数据均匀分配到k个桶中

(三)对于同种元素的排序,选择何种比较排序算法对桶排序性能的影响至关重要

1、算法实现

/**
 * 桶排序 核心思想:将在指定范围内的一堆数据按照映射关系放入不同的桶中,对每个桶进行排序,最终通过会回填的方式得到一个有序
 * 的数列
 * 关键点:1、确定桶的数目 2、将元素尽量均匀地放在每个桶中
 */
public class BucketSort {
    /**
     * 对数组进行排序
     * 数组中的元素的范围是[0,150)
     * @param arr
     */
    public static void sort(int[] arr){
        // 入参判断
        if(arr == null || arr.length == 0){
            return;
        }
        // 1、确定桶的个数
        int bucketCount = 15;
        // 2、确定元素与桶的映射关系(0-9,10-19,...,140-149)
        List<Integer>[] buckets = new List[15];
        for(int i = 0;i < buckets.length;i++){
            buckets[i] = new ArrayList<>();
        }
        // 3、将元素放入桶中
        Arrays.stream(arr).forEach(item->{
            buckets[item/10].add(item);
        });
        // 4、对每个桶进行排序
        for(int i = 0;i < buckets.length;i++){
            buckets[i].sort(Comparator.comparingInt(o -> o));
        }
        // 5、回填数组
        int index = 0;
        for(int i = 0;i < buckets.length;i++){
            List<Integer> bucket = buckets[i];
            while (bucket.size() > 0){
                arr[index++] = bucket.remove(0);
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,10,12,5,6,98,123,114,125,101,100,12,146,4,5,34,25,36,75,10};
        System.out.println("排序前的数组:" + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序后的数组:" + Arrays.toString(arr));
    }
}

2、算法分析

(1)最快的情况

输入的数据都被均匀地分配到每一个桶中

(2)最慢的情况

输入的数据都被分配到了一个桶中

(3)桶中元素示意图

 十二、基数排序

基数排序的原理是将整数按位数分割成不同的数字,然后按每个位数分别进行比较。基数排序的方式可以采用LSD或MSD。

MSD:先从高位开始进行排序,在每个关键字上,可采用计数排序

LSD:先从低位开始进行排序,在每个关键字上,可采用桶排序

1、使用LSD实现基数排序算法

/**
 * 基数排序 核心思想:按位取余放桶中,对桶排序再回填
 */
public class RadixSort {

    /**
     * 获取arr中的最大元素
     * @param arr
     * @return
     */
    public static int getMax(int[] arr){
        return Arrays.stream(arr).max().getAsInt();
    }

    /**
     * 获取num的位数
     * @param num
     * @return
     */
    public static int getDigit(int num){
        int digit = 1;
        while(num/10 != 0){
            digit++;
            num = num / 10;
        }
        return digit;
    }

    public static void sort(int[] arr){
        // 入参判断
        if(arr == null || arr.length == 0){
            return;
        }
        // 获取arr中最大元素的位数
        int max = getMax(arr);
        int maxDigit = getDigit(max);
        int dev = 1;
        for(int k = 0;k < maxDigit;k++){
            // 桶排序
            int mod = 10;
            // 创建桶
            int bucketCount = 10;
            List<Integer>[] buckets = new List[bucketCount];
            for(int i = 0;i < buckets.length;i++){
                buckets[i] = new ArrayList<>();
            }
            // 按个位取余放入对应的桶中
            for(int i = 0;i < arr.length;i++){
                buckets[arr[i]/dev%mod].add(arr[i]);
            }
            // 对每个桶进行排序
            for(int i = 0;i < buckets.length;i++){
                buckets[i].sort((o1, o2) -> o1 - o2);
            }
            // 回填目标数组
            int index = 0;
            for(int i = 0;i < buckets.length;i++){
                List<Integer> bucket = buckets[i];
                while (bucket.size() > 0){
                    arr[index++] = bucket.remove(0);
                }
            }
            dev = dev * 10;
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,10,12,526,6,98,123,114,1125,101,100,12,146,4,5,34,25,36,75,10};
        System.out.println("排序前的数组:" + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序后的数组:" + Arrays.toString(arr));
    }
}

2、基数排序vs桶排序vs计数排序

这三种排序算法都采用了桶的概念,但对桶的使用方法上有明显差异

(1)基数排序:根据键值的每位数字来分配桶

(2)桶排序:每个桶中存储一定范围的数

(3)计数排序:每个桶中存储键值出现的次数

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

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

相关文章

AQS原理(AbstractQueuedSynchronizer)

本篇为 [并发与多线程系列] 的第四篇&#xff0c;对应Java知识体系脑图中的 并发与多线程 模块。 这一系列将对Java中并发与多线程的内容来展开。 AQS原理&#xff08;AbstractQueuedSynchronizer&#xff09; AQS原理&#xff08;AbstractQueuedSynchronizer&#xff09;AQS整…

java解决跨域问题时的403报错

什么是跨域问题&#xff1f; 当一个请求的url的协议&#xff0c;域名&#xff0c;端口三者之间任意一个与当前页面url不同 即为跨域 问题背景&#xff1a; 如图&#xff0c;前端端口为8090&#xff0c;而后端端口为8099&#xff0c;形成跨域&#xff0c;无法对接 试图利用Spr…

【MySQL面试高频误区】不可重复读和幻读到底有哪些区别?

欢迎关注公众号 【11来了】 &#xff0c;持续 MyBatis 源码系列内容&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址&#xff1a;点击查看文章导读&#xff01; 感谢你的关注&#xff…

zotero使用koofr+google drive/onedrive同步

最早了解到这个思路是来自 知乎-【从零开始使用Zotero】(3) Zotero文献同步方式 和 How to Sync Zotero Files Using WebDAV and Google Drive with Koofr: A Step-by-Step Guide 虽然周围很多人都在用Readpaper这种web端的了&#xff0c;但是经常逛Arxiv而且zotero的web插…

论文翻译 | Language Models are Few-Shot Learners 语言模型是少样本学习者(下)

6 更广泛的影响 语言模型对社会有着广泛的有益应用&#xff0c;包括代码和写作自动补全、语法辅助、游戏叙事生成、提高搜索引擎响应以及回答问题等。但它们也可能有潜在的危害性应用。GPT-3在文本生成质量和适应性方面优于较小的模型&#xff0c;并且增加了区分合成文本与人类…

使用GitLab CI构建持续集成案例

1. 部署GitLab &#xff08;1&#xff09;基础准备 解压软件包并导入镜像&#xff1a; [rootmaster ~]# curl -O http://mirrors.douxuedu.com/competition/Gitlab-CI.tar.gz [rootmaster ~]# tar -zxvf Gitlab-CI.tar.gz [rootmaster ~]# ctr -n k8s.io image import gitla…

408 笔记错题本

数据结构 树 线索二叉树 组成原理 第五章 计组 SISD 一两个指令和数据 不能采用数据并行技术&#xff0c;但是可以采用流水线技术&#xff0c;计组这门课 就是讨论的是SISD这个概念。 SIMD 应用&#xff1a;浮点机、向量处理机、优化for循环。 MISD 这个理论上是不存在…

考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)

考研论坛平台小程序 目录 基于java和微信小程序的考研论坛平台小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂…

华为资源分享

紫光云文档中心提供弹性计算服务文档https://www.unicloud.com/document/product/ElasticComputeService/index.html报文格式华为报文格式资料Info-Finder&#xff08;在线工具&#xff09; 报文格式华为IP网络电子书华为IP网络相关电子书IP网络系列丛书 - 华为企业业务华为产品…

[云] DockerCoins 练习笔记

DockerCoins DockerCoins 由 5 个服务组成 rng (随机数生成器): 这是一个Web服务&#xff0c;它的任务是生成随机字节。随机字节通常用于加密、安全令牌生成、测试等场景。 hasher (哈希计算器): 这个服务接收数据&#xff08;通常是通过POST请求发送的数据&#xff09;&#…

202408第十五届蓝桥杯青少组省赛C++中级组题解

202408第十五届蓝桥杯青少组省赛C++中级组题解 单选题 1、定义 char a[]="hello\nworld",执行 cout<<a,输出结果是(B) A、helloworld B、hello world C、 hellonworld D、 hello\nworld 解析:\n输出时会换行。 2、 的结果是(C)。 A、 B、

商城网站建设怎么建

商城网站已经成为企业迅速拓展市场、提升品牌形象的重要利器。随着互联网技术的飞速发展&#xff0c;传统的实体店面已经不能满足消费者多样化的购物需求。因此&#xff0c;搭建一个功能强大、用户友好的商城网站成为企业不可或缺的一环。 首先&#xff0c;商城网站的建设需要具…

OpenCAEPoro安装与测试(ASC 2024)

首先简单总结一下经验&#xff1a; 在之前的测试和学习中&#xff0c;由于自己是虚拟机或者云服务器&#xff0c;有root权限&#xff0c;经常无脑增删文件&#xff08;主要是为了图省事&#xff0c;看见报错就加回来&#xff0c;多出来就删除&#xff09;&#xff0c;但是在经…

D 咖饮品机闪耀荆州动漫嘉年华

在今年的国庆佳节&#xff0c;恰逢金秋时节&#xff0c;荆州动漫嘉年华盛大开幕&#xff0c;这场充满活力与创意的盛会吸引了无数动漫爱好者的目光。而在众多精彩的展示中&#xff0c;D 咖饮品机的出现无疑为这场嘉年华增添了一抹别样的色彩。 走进嘉年华现场&#xff0c;热闹的…

ubuntu18.04运行OpenPCDet出现的问题

一、概述 在编译成功OpenPCDet的源代码之后&#xff0c;发现在运行demo时候&#xff0c;依旧出现了很多问题&#xff0c;在此对出现的问题进行总结记录。 二、问题分析 &#xff08;一&#xff09;ModuleNotFoundError:No module named av2 如图所示 这个问题比较简单&#x…

(C语言贪吃蛇)14.用绝对值方式解决不合理的走位

目录 前言 解决方式 运行效果 总结 前言 我们上节实现了贪吃蛇四方向走位&#xff0c;但是出现了一些不合理的走位&#xff0c;比如说身体节点和头节点重合等等&#xff0c;本节我们便来解决这个问题。 我们希望贪吃蛇撞到自身时游戏会重新开始&#xff0c;并且贪吃蛇的运动方…

TryHackMe 第6天 | Web Fundamentals (一)

这一部分我们要简要介绍以下 Web Hacking 的基本内容&#xff0c;预计分三次博客。 在访问 Web 应用时&#xff0c;浏览器提供了若干个工具来帮助我们发现一些潜在问题和有用的信息。 比如可以查看网站源代码。查看源代码可以 右键 网页&#xff0c;然后选择 查看网站源代码&…

Discord 用户突破2亿:CEO 谈发展规划、产品策略及游戏通信的未来

Discord,这个最初为游戏玩家打造的社区平台,如今已经发展成为一个拥有超过2亿月活跃用户的全球性社交网络。创始人兼CEO Jason Citron在经历了多次创业尝试后,最终将Discord打造成了一个不可或缺的游戏通信工具。以下是Jason Citron在接受GamesBeat采访时,对Discord的现状、…

招联金融2025校招内推

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

MAE(平均绝对误差)和std(标准差)计算中需要注意的问题

一、MAE&#xff08;平均绝对误差&#xff09; 计算公式&#xff1a; yi​ 是第i个实际值y^​i​ 是第i个预测值 计算方法&#xff1a; MAE就是求实际值与预测值之间的误差&#xff0c;需要给出预测值和原始的实际值 二、std&#xff08;标准差&#xff09; 计算公式&#x…