案例
1、约瑟夫问题
/**
* @author: yzh
* @date: 2022/3/24 21:13
* @version: 1.0
* @describle: 解决约瑟夫问题
*/
@Slf4j
class SurvivalGaming {
private People first;
static class People {
private String name;
private int age;
private People next;
private boolean alive = true;
People(String name, int age, People next) {
this.next = next;
this.name = name;
this.age = age;
}
void killed() {
this.alive = false;
}
String say() {
return String.format("'name:%s,age:%d,alive:%b'", this.name, this.age, this.alive);
}
}
public void survivalGame(int count, int startIndex, int nightmare) {
Assert.isTrue(!(count < nightmare || startIndex < 0), "规则不成立,无法开启");
this.join(count);
while (startIndex > 0) {
first = first.next;
--startIndex;
}
log.info("请选手{}开始报数", first.say());
while (count >= nightmare) {
for (int i = 1; i < nightmare - 1; i++) {
first = first.next;
}
final People temp = first;
final People next = first.next;
next.killed();
log.warn("{}选手被杀害", next.say());
first = first.next.next;
temp.next = first;
--count;
}
this.survivor(nightmare - 1);
}
private void survivor(int num) {
while (num > 0) {
log.info("幸存者 {}",first.say());
first = first.next;
--num;
}
}
private void join(int count) {
log.info("请{}为成员依次围成一个圈", count);
People temp = null;
for (int i = 0; i < count; i++) {
if (null == first) {
first = new People(String.format("参赛者%s号", i + 1), i + 10, null);
temp = first;
} else {
People next = new People(String.format("参赛者%s号", i + 1), i + 10, null);
temp.next = next;
temp = next;
if (i == count - 1) {
temp.next = first;
}
}
}
}
public static void main(String[] args) {
SurvivalGaming game = new SurvivalGaming();
game.survivalGame(10, 0, 5);
}
}
2、递归
package com.yzhp.algorithm;
import lombok.extern.slf4j.Slf4j;
/**
* @auth yzh
* @date 2022/4/22 14:31
* @describe 递归 斐波那契数列
*/
@Slf4j
public class Recursion {
/**
* f(n) = f(n-1) + f(n-2)
* 时间复杂度:O(2^n)
* 空间复杂度:O(2^n)
* 模型:
* 2^0 2^1 2^2 2^3 ···
* f(1)
* f(3)
* f(2)
* f(5)
* f(2)
* f(4) f(1)
* f(3)
* f(2)
*/
public static int fas(int n) {
if (2 >= n) {
return 1;
}
return fas(n - 1) + fas(n - 2);
}
// 优化1:增加数组缓存结果
/**
* f(n) = f(n-1) + f(n-2)
* 时间复杂度:O(n)
* 空间复杂度:O(n)
* 模型:
* 重复值可以在数组取,只需要计算 f(1),f(2),f(3),f(4),f(5)
* f(1)
* f(3)
* f(2)
* f(5)
* f(2)
* f(4) f(1)
* f(3)
* f(2)
*/
public static int fas(int n, int[] cache) {
if (2 >= n) {
return 1;
}
if (0 == cache[n]) {
cache[n] = fas(n - 1, cache) + fas(n - 2, cache);
}
return cache[n];
}
// 优化2:尾递归
/**
* f(n) = f(n-1) + f(n-2)
* 时间复杂度:O(n)
* 空间复杂度:O(n)
* 模型:
* 重复值可以在数组取,只需要计算 f(3),f(4),f(5)
* f(3)
* f(5)
* f(2)【已知::ppre】
* f(4) f(1)【已知 = 1::ppre】
* f(3)【计算后已知::pre】
* f(2)【已知 = 1::pre】
*/
public static int fas(int n, int pre, int ppre) {
if (2 >= n) {
return pre;
}
return fas(n - 1, pre + ppre, pre);
}
// 一般模式
/**
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
public static int fas1(int n) {
if (2 >= n) {
return 1;
}
int f1 = 1, f2 = 1 , f3 = 0;
for (int i = 3; i <= n; i++) {
f3 = f1 + f2 ;
f1 = f2;
f2 = f3;
}
return f3;
}
public static void main(String[] args) {
int n = 45;
// 普通递归
// for (int i = 1; i < n; i++) {
// long l = System.currentTimeMillis();
// int fas = Recursion.fas(i);
// log.info("层级: {},结果: {},耗时: {}",i,fas,(System.currentTimeMillis()-l));
// }
/**
*14:54:18.975 [main] INFO com.yzhp.algorithm.Recursion - 层级: 43,结果: 433494437,耗时: 818
*14:54:20.350 [main] INFO com.yzhp.algorithm.Recursion - 层级: 44,结果: 701408733,耗时: 1375
*/
// 一般循环
// for (int i = 1; i < n; i++) {
// long l = System.currentTimeMillis();
// int fas = Recursion.fas1(i);
// log.info("层级: {},结果: {},耗时: {}",i,fas,(System.currentTimeMillis()-l));
// }
/**
*14:53:28.997 [main] INFO com.yzhp.algorithm.Recursion - 层级: 43,结果: 433494437,耗时: 0
*14:53:28.997 [main] INFO com.yzhp.algorithm.Recursion - 层级: 44,结果: 701408733,耗时: 0
*/
// 优化1:数据缓存
// int[] cache = new int[45];
// for (int i = 1; i < n; i++) {
// long l = System.currentTimeMillis();
// int fas = Recursion.fas(i, cache);
// log.info("层级: {},结果: {},耗时: {}", i, fas, (System.currentTimeMillis() - l));
// }
/**
* 14:54:46.694 [main] INFO com.yzhp.algorithm.Recursion - 层级: 43,结果: 433494437,耗时: 0
* 14:54:46.694 [main] INFO com.yzhp.algorithm.Recursion - 层级: 44,结果: 701408733,耗时: 0
*/
// 优化2:尾递归
for (int i = 1; i < n; i++) {
long l = System.currentTimeMillis();
int fas = Recursion.fas(i, 1,1);
log.info("层级: {},结果: {},耗时: {}", i, fas, (System.currentTimeMillis() - l));
}
/**
* 14:54:46.694 [main] INFO com.yzhp.algorithm.Recursion - 层级: 43,结果: 433494437,耗时: 0
* 14:54:46.694 [main] INFO com.yzhp.algorithm.Recursion - 层级: 44,结果: 701408733,耗时: 0
*/
}
}
排序
Level 1
冒泡排序
/**
* @auth yzh
* @date 2022/4/22 15:58
* @describe 冒泡排序
*/
public class BubbleSort {
/**
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 模型:
* 5 1 10 3
* i=0 1 5 10 3
* 1 5 10 3
* 1 5 3 10
* i=1 1 5 3 10
* 1 3 5 10
* 1=2 1 3 5 10
*/
public static int[] sort(int[] arr) {
int l = arr.length, temp = 0;
for (int i = 0; i < l; i++) {
for (int j = 0; j < l - 1 - i ; j++) {
if (arr[j] > arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
public static void main(String[] args) {
int[] arr = {19,6,16,5,20,49,1};
BubbleSort.sort(arr);
System.out.println(JSON.toJSONString(arr));
}
}
选择排序
/**
* @auth yzh
* @date 2022/4/22 17:23
* @describe 选择排序
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 原理:
* 外层循环:数组每个元素都遍历一次 0 1 2 ... n-1
* 内层循环:当前下表与后面元素进行比较, n次,n-1次... 1
* 记录当前下表 i 与后面元素比较,将最小值放在当前数组下标
*/
@Slf4j
public class SelectSort {
public static int[] sort(int[] arr) {
long s = System.currentTimeMillis();
int minIndex = 0, l = arr.length, min = 0;
for (int i = 0; i < l; i++) {
minIndex = i;
for (int j = 1 + i; j < l; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (i != minIndex) {
min = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = min;
}
}
log.info("选择排序用时{}毫秒", (System.currentTimeMillis() - s));
return arr;
}
public static void main(String[] args) {
int n = 5000;
int[] arr = new int[n];
Random random = new Random();
for (int i = 0; i < n; i++) {
arr[i] = random.nextInt(100000);
}
log.info("原始数组: \r\n{}", JSON.toJSONString(arr));
// int[] arr = {19,6,16,5,20,49,1};
SelectSort.sort(arr);
log.info(JSON.toJSONString(arr));
}
}
插入排序
/**
* @auth yzh
* @date 2022/4/24 14:54
* @describe 插入排序
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 原理:
* 1)从数组第二位与第一位开始比较
* 2)使用临时变量缓存当前位元素值
* 3)若前位大于后位,则将前位值赋值到后一位(临时值与当前位前位都要比——当前位小于后位就跳出)
* 4)将临时值赋值到结束位下表后一位(for循环 index-- 多执行一次)
*/
@Slf4j
public class InsertSort {
public static int[] sort(int[] arr) {
long s = System.currentTimeMillis();
int length = arr.length, temp = 0, index = 0;
// 起始位=1(数组第二元素)
for (int i = 1; i < length; i++) {
index = i;
// 后位 小于 前位
if (arr[i] < arr[i - 1]) {
temp = arr[i];
for (index = i - 1; index >= 0 && temp < arr[index]; index-- ) {
arr[index+1] = arr[index];
}
arr[index+1] = temp;
}
}
log.info("插入排序用时{}毫秒", (System.currentTimeMillis() - s));
return arr;
}
public static void main(String[] args) {
int n = 5000;
int[] arr = new int[n];
Random random = new Random();
for (int i = 0; i < n; i++) {
arr[i] = random.nextInt(100000);
}
log.info("原始数组: \r\n{}", JSON.toJSONString(arr));
// int[] arr = {19,6,16,5,20,49,1};
InsertSort.sort(arr);
log.info(JSON.toJSONString(arr));
}
}
希尔排序
/**
* @auth yzh
* @date 2022/4/24 16:20
* @describe 希尔排序
* 简介:希尔排序就是对插入排序的直接优化
* 时间复杂度:[O(nlogn),O(n^2)]之间
*/
@Slf4j
public class ShellSort {
public static int[] sort(int arr[]) {
long s = System.currentTimeMillis();
int length = arr.length;
int increasement = arr.length; // 下表间隔值
do {
increasement = increasement / 3 + 1;
for (int i = 0 ; i<increasement;i++){
for (int j = i+increasement ; j<length;j+=increasement){
if (arr[j]<arr[j-increasement]){
int k,temp;
temp = arr[j];
for ( k = j-increasement; k >=0 && temp < arr[k] ; k-=increasement) {
arr[k+increasement] = arr[k];
}
arr[k+increasement] = temp;
}
}
}
} while (increasement > 1);
log.info("希尔排序用时{}毫秒", (System.currentTimeMillis() - s));
return arr;
}
public static void main(String[] args) {
int n = 10000;
int[] arr = new int[n];
Random random = new Random();
for (int i = 0; i < n; i++) {
arr[i] = random.nextInt(100000);
}
// int[] arr = {8,6,2,5};
log.info("原始数组: \r\n{}", JSON.toJSONString(arr));
ShellSort.sort(arr);
log.info(JSON.toJSONString(arr));
}
}
1509



被折叠的 条评论
为什么被折叠?



