常用算法题练习(一)
引言
算法的重要毋庸置疑,在面试过程中或多或少的会被问到算法,这一个系列的文章虽然冠以常用
这一称呼,但是并不意味着所有算法都很简单,这一篇文章是系列文章的第一篇,包括以下几个算法题,部分相对而言有点难度的题目会有所讲解.
- 冒泡排序,选择排序,插入排序源码
- 归并排序的细节讲解与复杂度分析
- 小和问题和逆序对问题
冒泡排序,选择排序,插入排序
冒泡排序
冒泡排序的思想就是将相邻的两个位置的数据进行比较,如果前面位置的数据大于后面位置的数据,则将两位置的数据进行交换,未排序元素中最大的数
便会像一个气泡一样一路向后冒,最后会将其放在未排序数据的末尾
.使其成为已排序数据的首位
时间复杂度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数组将数据保存,最后再复制回原数组中,如下图解:
归并排序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