面试常考算法题(一)--四种排序方法以及小和问题

本文介绍了面试中常见的几种排序算法,包括冒泡排序、选择排序、插入排序及归并排序,并详细分析了归并排序的时间和空间复杂度。此外,还探讨了小和问题,提供了一种高效的解决方案,通过递归方法解决,降低了时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常用算法题练习(一)

引言

算法的重要毋庸置疑,在面试过程中或多或少的会被问到算法,这一个系列的文章虽然冠以常用这一称呼,但是并不意味着所有算法都很简单,这一篇文章是系列文章的第一篇,包括以下几个算法题,部分相对而言有点难度的题目会有所讲解.

  • 冒泡排序,选择排序,插入排序源码
  • 归并排序的细节讲解与复杂度分析
  • 小和问题和逆序对问题

冒泡排序,选择排序,插入排序

冒泡排序

冒泡排序的思想就是将相邻的两个位置的数据进行比较,如果前面位置的数据大于后面位置的数据,则将两位置的数据进行交换,未排序元素中最大的数便会像一个气泡一样一路向后冒,最后会将其放在未排序数据的末尾.使其成为已排序数据的首位

时间复杂度O(n^2),空间复杂度O(1)

源码如下


    public static void bubbleSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = 1; j < arr.length - i; j++) {
                if (arr[j] < arr[j - 1]) {
                    swap(arr, j, j - 1);
                }
            }
        }
    }

    private static void swap(int[] arr, int i, int j) {
                //交换变量,等同于使用temp变量
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }


选择排序

选择排序的思想就是选择出未排序数据中最小的数放在未排序数据的首位.使其成为已排序数据的末尾.时间复杂度O(n^2),空间复杂度O(1)

源码如下

        
        public static void  selectionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {
                if (arr[j] < arr[minIndex]) {
                    swap(arr, j, minIndex);
                }
            }
        }
    }
                
         private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }


插入排序

插入排序是将前i个元素排好序,然后将第’i+1’个元素插入前面已排好顺序元素中的适当位置中,时间复杂度O(n^2),空间复杂度O(1).个人认为插入排序在某些情况下是优于冒泡排序和选择排序的,比如说一个数据其中的元素是1,2,3,4,5,6,时,冒泡排序和选择排序时间复杂度仍为O(n^2),而插入排序的复杂度在此时就变成了O(n).相对而言数据排布越整齐的数组,插入排序越占优势.


    public static void insertionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 1; i < arr.length; i++) {
            for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                swap(arr, j, j + 1);
            }
        }
    }

    private static void swap(int[] arr, int i, int j) {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

归并排序的细节讲解与复杂度分析

归并排序图解

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
归并排序图解
由上图可以看出,归并排序首先是将要排序的大数组分割成小数组,再对小数组进行排序,最后将排好序的小数组再进行排序并放入大数组中,分治策略实质上利用了二叉树的特性.归并排序是稳定排序.

归并排序一般情况下可采用递归的方式进行,在这里主要对归并排序中的阶段进行讨论,
阶段主要进行的操作就是将数组中的数据排列整齐,利用temp数组将数据保存,最后再复制回原数组中,如下图解:
imagepng
imagepng

归并排序Java代码

  public static void mergeSort(int[] arr) {
    
    
        if (arr == null || arr.length < 2) {
    
    
            return;
        }
        mergeSort(arr, 0 ,arr.length-1);
    }

    private static void mergeSort(int[] arr, int strat, int end) {
    
    
        if (strat == end) {
    
    
            return;
        }
        int mid = strat + (end - strat) / 2;
        mergeSort(arr, strat, mid
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值