02打卡 排序算法总结 还需完善

目录

排序算法总结

相关概念

冒泡排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

L0977 有序数组的平方

思路

L0209 长度最小的子数组

滑动窗口找连续子集自我总结

L0059 螺旋矩阵

模拟思路


排序算法总结

相关概念

稳定:如果a原本在b前面,而a=b时,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b时,排序之后a可能出现在b的后面。

内排序:所有排序操作都在内存中完成。
外排序:通常是由于数据太大,不能同时存放在内存中,根据排序过程的需要而在外存与内存之间 数据传输才能进行。

时间复杂度:时间频度,一个算法执行所耗费的时间。算法中通常用数据比较次数与数据移动次数 进行衡量。
空间复杂度:算法执行所需要的内存大小。

冒泡排序

实现逻辑

  1. 使用两层for循环排序,外层的for每循环一次就完成了对一个数的排序
  2. 每完成一次,下一次需要比较的次数就少一次
  3. 内循环时两两循环比较,若当前数字较大,就放到右边
  4. 动图如下

性能分析

  • 外层循环 n 次,内层最多时循环 n – 1次、最少循环 0 次,平均循环(n-1)/2,所以循环体内总的比较交换次数为:n*(n-1) / 2 = (n^2-n)/2 ,按照计算时间复杂度的规则,去掉常数、去掉最高项系数,时间复杂度为O(N^2) 
  • 最优的空间复杂度为开始元素已排序,则空间复杂度为 0,最差的空间复杂度为开始元素为逆排序,则空间复杂度为 O(N),平均的空间复杂度为O(1) 

  • 冒泡排序是稳定排序

关键代码

    public void bubbleSort(int[] nums) {
        // i 代表已排序的数字个数 当 i = nums.length 说明排序结束
        for (int i = 0; i < nums.length; i++) {
            //当还有 nums.length - i 个数需要排序时,
            //nums[0] 需要和另外 nums.length - i - 1个数比较
            for (int j = 0; j < nums.length - i - 1; j++) {
                if (nums[j] > nums[j + 1]) {
                    int temp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = temp;
                }
            }
        }

    }

插入排序

实现逻辑

(想想斗地主排牌的顺序-插空)

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤2345

性能分析

如果插入排序的目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况:

(1) 最好情况:序列已经是升序排列,在这种情况下,需要进行的比较操作需(n-1)次即可。
(2) 最坏情况:序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。

插入排序的赋值操作是比较操作的次数减去(n-1)次。平均来说插入排序算法复杂度为O(N^2)。

最优的空间复杂度为开始元素已排序,则空间复杂度为 0;

最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);

平均的空间复杂度为O(1)

关键代码

   public void insertSort(int[] nums){
//        从第一个元素开始,该元素可以认为已经被排序
        for (int i = 1; i < nums.length; i++) {
            int temp = nums[i];
            int j;
            //在排第i个数的时候 是在前面 i-i个已排序的数字里找位置
            for (j = i - 1; j >= 0; j--) {
                if (nums[j] > temp) nums[j + 1] =nums[j];
                else break;
            }
            //这时 nums[j] < temp 就把 temp 给 nums[j + 1]
            nums[j + 1] = temp;
        }
    }

插入排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

插入排序

实现逻辑

性能分析

关键代码

L0977 有序数组的平方

思路

双指针倒序放置

终止条件为区间内无元素

    public int[] sortedSquares(int[] nums) {
        int[] resArr = new int[nums.length];
        int left = 0, right = nums.length - 1, index = nums.length - 1;
        while (left <= right) {
            int leftSquare = nums[left] * nums[left];
            int rightSquare = nums[right] * nums[right];

            if (leftSquare >= rightSquare) {
                resArr[index--] = leftSquare;
                left++;
            } else {
                resArr[index--] = rightSquare;
                right--;
            }
        }
        return resArr;

    }

L0209 长度最小的子数组

滑动窗口找连续子集自我总结

  • 对于每一个right 也就是右窗边 可能存在多个合适的左窗边(left)
  • 所以对于每一个right 用for循环去遍历 
  • 每一个right有多个left 这一步用while循环去遍历
 public int minSubArrayLen(int target, int[] nums) {
        int left = 0, sum = 0, res = nums.length + 1;
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= target) {
                res = Math.min(res, right - left + 1);
                sum -= nums[left++];
            }
        }
        return res == nums.length + 1 ? 0 : res;
    }

L0059 螺旋矩阵

模拟思路

这样写的话对于单双数不同的情况需要分别套路,因为当left == rigth时,已经不会进入下面的四个循环,会导致中间的值为0(默认值)。

或者是把下面四个循环的都变成大于等于、小于等于,这样的话相当于是每次循环都到达边界,那么就应该在每一个for循环之后都立刻更新left、rigth、top、bottom的值,而不能全都放在四个循环后面。

 public int[][] generateMatrix(int n) {
        int num = 1;
        int length = n - 1;
        int[][] res = new int[n][n];


        int left = 0, right = n - 1, top = 0, bottom = n - 1;
        while (left <= right && top <= bottom) {

                 
            if (left == right&&top == bottom){
                res[left][left] = num;
            }

            for (int j = left; j < right; j++) {
                res[top][j] = num++;
            }
            for (int i = top; i < bottom; i++) {
                res[i][right] = num++;
            }
            for (int j = right; j > left; j--) {
                res[bottom][j] = num++;
            }
            for (int i = bottom; i > top; i--) {
                res[i][left] = num++;
            }
            left++;
            right--;
            top++;
            bottom--;
        }

        return res;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值