ps: 十大算法合集,学习来源是尚硅谷Java数据结构与java算法,自留复习。
1.二分法查找算法非递归实现
int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (arr[mid] > target) {
right = mid - 1;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
}
2.分治算法和汉诺塔问题
void hanoTower(int num, char a, char b, char c) {
if (num == 1) {
System.out.println("第1个盘从" + a + "->" + c);
} else {
hanoTower(num - 1, a, c, b);
System.out.println("第" + num + "个盘从" + a + "->" + c);
hanoTower(num - 1, b, a, c);
}
}
3.动态规划算法和背包问题
算法实现
int[] w = {1, 4, 3};
int[] value = {1500, 3000, 2000};
int m = 4;
int n = value.length;
int[][] v = new int[n + 1][m + 1];
int[][] path = new int[n + 1][m + 1];
for (int i = 0; i < v.length; i++) {
v[i][0] = 0;
}
for (int i = 0; i < v[0].length; i++) {
v[0][i] = 0;
}
重点
for (int i = 1; i < v.length; i++) {
for (int j = 1; j < v[0].length; j++) {
if (w[i - 1] > j) {
v[i][j] = v[i - 1][j];
} else {
if (v[i - 1][j] < value[i - 1] + v[i - 1][j - w[i - 1]]) {
v[i][j] = value[i - 1] + v[i - 1][j - w[i - 1]];
path[i][j] = 1;
} else {
v[i][j] = v[i - 1][j];
}
}
}
}
for (int i = 0; i < v.length; i++) {
for (int j = 0; j < v[0].length; j++) {
System.out.print(v[i][j] + " ");
}
System.out.println();
}
for (int i = 0; i < path.length; i++) {
for (int j = 0; j < path[i].length; j++) {
if(path[i][j]==1) {
System.out.print("第" + i + "个商品放入到背包中" + " ");
}else{
System.out.print(" * ");
}
}
System.out.println();
}
int i = path.length - 1;
int j = path[0].length - 1;
while (i > 0 && j > 0) {
if (path[i][j] == 1) {
System.out.print("第" + i + "个商品放入到背包中" + " ");
j -= w[i - 1];
}
i--;
}
输出结果
4.KMP算法和字符匹配问题
暴力匹配
![在这里插入图片描述](https://img-blog.csdnimg.cn/6e6170e154074462bfe8edbe08db945c.png)
static int violenceMatch(String str1, String str2) {
char[] s1 = str1.toCharArray();
char[] s2 = str2.toCharArray();
int l1 = s1.length;
int l2 = s2.length;
int i = 0;
int j = 0;
while (i < l1 && j < l2) {
if (s1[i] == s2[j]) {
i++;
j++;
} else {
j = 0;
i = i - (j - 1);
}
}
if (j == l2) {
return i - j;
}
return -1;
}
kmp算法(这里参考的方法来源是KMP算法 首先需要建立所要匹配字符的前缀表
static void prefixTable(char[] string, int[] prefix, int n)
prefix[0] = 0;
int len = 0;
int i = 1;
while (i < n) {
if (string[i] == string[len]) {
len++;
prefix[i] = len;
i++;
} else {
if (len > 0) {
len = prefix[len - 1];
} else {
prefix[i] = len;
i++;
}
}
}
for (int k = n - 1; k > 0; k--) {
prefix[k] = prefix[k - 1];
}
prefix[0] = -1;
System.out.print("前缀表 ");
for (int p : prefix) {
System.out.print(p + " ");
}
System.out.println();
}
利用前缀表进行查找 加快速度
static void kms_search(String str1, String str2) {
char[] text = str1.toCharArray();
char[] pattern = str2.toCharArray();
int[] prefix = new int[str2.length()];
prefixTable(pattern, prefix, prefix.length);
int i = 0, j = 0;
int m = text.length;
int n = pattern.length;
while (i < m) {
if (j == n - 1 && text[i] == pattern[j]) {
System.out.println("找到位置在 " + (i - j));
j = prefix[j];
}
if (text[i] == pattern[j]) {
i++;
j++;
} else {
j = prefix[j];
if (j == -1) {
j++;
i++;
}
}
}
}
5.贪心算法和集合覆盖问题
贪心算法结果不一定是最优(有可能最优解) 主要算法实现
HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
HashSet<String> allAreas = new HashSet<>();
ArrayList<String> selects = new ArrayList<>();
HashSet<String> tempSet = new HashSet<>();
String maxKey = null;
while (allAreas.size() != 0) {
maxKey = null;
for (String key : broadcasts.keySet()) {
tempSet.clear();
HashSet<String> area = broadcasts.get(key);
tempSet.addAll(area);
tempSet.retainAll(allAreas);
if (tempSet.size() > 0 &&
(maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())) {
maxKey = key;
}
}
if (maxKey != null) {
allAreas.removeAll(broadcasts.get(maxKey));
selects.add(maxKey);
}
}
System.out.println("结果 "+selects.toString());
6.普利姆算法(Prim)和修路问题
定义一个图结构类
class MGraph {
int verx;
char[] data;
int[][] weight;
public MGraph(int verx) {
this.verx = verx;
data = new char[verx];
weight = new int[verx][verx];
}
}
邻接矩阵举例
int[][] weight = {
{10000, 5, 7, 10000, 10000, 10000, 2},
{5, 10000, 10000, 9, 10000, 10000, 3},
{7, 10000, 10000, 10000, 8, 10000, 10000},
{10000, 9, 10000, 10000, 10000, 4, 10000},
{10000, 10000, 8, 10000, 10000, 5, 4},
{10000, 10000, 10000, 4, 5, 10000, 6},
{2, 3, 10000, 10000, 4, 6, 10000}
};
prim算法实现
void prim(MGraph graph, int v) {
int[] visited = new int[graph.verx];
visited[v] = 1;
int minWeight = 10000;
int h1 = -1, h2 = -1;
for (int k = 1; k < graph.verx; k++) {
for (int i = 0; i < graph.verx; i++) {
for (int j = 0; j < graph.verx; j++) {
if (visited[i] == 1 && visited[j] == 0 && graph.weight[i][j] < minWeight) {
minWeight = graph.weight[i][j];
h1 = i;
h2 = j;
}
}
}
System.out.println("边<" + graph.data[h1] + "," + graph.data[h2] + "> 权值=" + minWeight);
visited[h2] = 1;
minWeight = 10000;
}
}
7.克鲁斯卡尔算法(Kruskal)和公交车站问题
算法实现 1.定义边结构类
class Edge {
char start;
char end;
int weight;
public Edge(char start, char end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
}
2.定义顶点数组和邻接矩阵
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
private static final int INF = Integer.MAX_VALUE;
int[][] matrix = {
{0, 12, INF, INF, INF, 16, 14},
{12, 0, 10, INF, INF, 7, INF},
{INF, 10, 0, 3, 5, 6, INF},
{INF, INF, 3, 0, 4, INF, INF},
{INF, INF, 5, 4, 0, 2, 8},
{16, 7, 6, INF, 2, 0, 9},
{14, INF, INF, INF, 8, 9, 0},
};
3.根据顶点数组和邻接矩阵创建kruskal类 获取以下信息
static int edgeNum;
char[] vertex;
private int[][] matrix;
4.构造所有边
Edge[] getEdges() {
int len = vertex.length;
Edge[] edges = new Edge[edgeNum];
int k = 0;
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
if (this.matrix[i][j] != INF) {
Edge edge = new Edge(vertex[i], vertex[j], matrix[i][j]);
edges[k++] = edge;
}
}
}
return edges;
}
5.对边进行排序
private void sortEdge(Edge[] data) {
for (int i = 0; i < data.length - 1; i++) {
for (int j = 0; j < data.length - 1 - i; j++) {
if (data[j].weight > data[j + 1].weight) {
Edge temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
}
6.定义两个所需方法
int getEnd(int[] ends, int i) {
while (ends[i] != 0) {
i = ends[i];
}
return i;
}
int getPos(char c) {
for (int i = 0; i < vertex.length; i++) {
if (vertex[i] == c) {
return i;
}
}
return -1;
}
7.算法主体实现
void kruskal() {
int[] ends = new int[edgeNum];
int index = 0;
Edge[] res = new Edge[edgeNum];
Edge[] edges = getEdges();
sortEdge(edges);
System.out.println("排序后:" + Arrays.toString(edges));
for (int i = 0; i < edgeNum; i++) {
int p1 = getPos(edges[i].start);
int p2 = getPos(edges[i].end);
int m = getEnd(ends, p1);
int n = getEnd(ends, p2);
if (m != n) {
ends[m] = n;
res[index++] = edges[i];
}
}
System.out.println("最小生成树:" + Arrays.toString(res));
}
8.迪杰斯特拉算法(Dijkstral)和最短路径问题
过程分析 自己画的图解
具体代码 新建两个类
class VisitedVertex {
private int[] already_arr;
private int[] pre_visited;
private int[] dis;
public VisitedVertex(int length, int index) {
this.already_arr = new int[length];
this.pre_visited = new int[length];
this.dis = new int[length];
this.already_arr[index] = 1;
Arrays.fill(dis, 65535);
this.dis[index] = 0;
}
boolean in(int index) {
return already_arr[index] == 1;
}
int getDis(int index) {
return dis[index];
}
void updateDis(int index, int len) {
dis[index] = len;
}
void updatePre(int pre, int index) {
pre_visited[pre] = index;
}
int updateArr() {
int min = 65535;
int index = 0;
for (int i = 0; i < already_arr.length; i++) {
if (already_arr[i] == 0 && dis[i] < min) {
min = dis[i];
index = i;
}
}
already_arr[index] = 1;
return index;
}
void show(){
for (int i : already_arr) {
System.out.print(i+" ");
}
System.out.println();
for (int i : pre_visited) {
System.out.print(i+" ");
}
System.out.println();
for (int i : dis) {
System.out.print(i+" ");
}
}
}
class Graph {
private char[] vertex;
private int[][] matrix;
private VisitedVertex vv;
public Graph(char[] vertex, int[][] matrix) {
this.vertex = vertex;
this.matrix = matrix;
}
void dsj(int index) {
vv = new VisitedVertex(vertex.length, index);
update(index);
for (int i = 0; i < vertex.length; i++) {
index = vv.updateArr();
update(index);
}
vv.show();
}
void update(int index) {
int len = 0;
for (int i = 0; i < matrix[index].length; i++) {
len = vv.getDis(index) + matrix[index][i];
if (!vv.in(i) && len < vv.getDis(i)) {
vv.updateDis(i, len);
vv.updatePre(i, index);
}
}
}
}
9.弗洛伊德算法(Floyd)和最短路径问题
过程分析
时间复杂度比较高n^3 三层循环 算法实现 定义一个图结构
class Graphic {
char[] vertex;
int[][] dis;
int[][] pre;
public Graphic(char[] vertex, int[][] matrix, int length) {
this.vertex = vertex;
this.dis = matrix;
this.pre = new int[length][length];
for (int i = 0; i < pre.length; i++) {
Arrays.fill(pre[i], i);
}
}
void floyd() {
int len = 0;
for (int k = 0; k < dis.length; k++) {
for (int i = 0; i < dis.length; i++) {
for (int j = 0; j < dis.length; j++) {
len = dis[i][k] + dis[k][j];
if (len < dis[i][j]) {
dis[i][j] = len;
pre[i][j] = pre[k][j];
}
}
}
}
}
void show() {
for (int i = 0; i < dis.length; i++) {
for (int j = 0; j < dis[i].length; j++) {
System.out.print(dis[i][j] + " ");
}
System.out.println();
}
System.out.println();
for (int i = 0; i < pre.length; i++) {
for (int j = 0; j < pre[i].length; j++) {
System.out.print(pre[i][j] + " ");
}
System.out.println();
}
}
}
10.骑士周游回溯算法和马踏棋盘问题
算法实现
1.一些参数定义
static int X, Y;
static boolean[] visited;
static int step = 1;
2.获取下一个能走的位置集合
static ArrayList<Point> next(Point current) {
ArrayList<Point> list = new ArrayList<>();
Point p = new Point();
if ((p.x = current.x - 2) >= 0 && (p.y = current.y - 1) >= 0) {
list.add(new Point(p));
}
if ((p.x = current.x - 1) >= 0 && (p.y = current.y - 2) >= 0) {
list.add(new Point(p));
}
if ((p.x = current.x + 1) < X && (p.y = current.y - 2) >= 0) {
list.add(new Point(p));
}
if ((p.x = current.x + 2) < X && (p.y = current.y - 1) >= 0) {
list.add(new Point(p));
}
if ((p.x = current.x - 2) >= 0 && (p.y = current.y + 1) < Y) {
list.add(new Point(p));
}
if ((p.x = current.x - 1) >= 0 && (p.y = current.y + 2) < Y) {
list.add(new Point(p));
}
if ((p.x = current.x + 1) < X && (p.y = current.y + 2) < Y) {
list.add(new Point(p));
}
if ((p.x = current.x + 2) < X && (p.y = current.y + 1) < Y) {
list.add(new Point(p));
}
return list;
}
3.算法主体部分
static void traversalChess(int[][] chess, int row, int column) {
chess[row][column] = step;
visited[row * X + column] = true;
ArrayList<Point> list = next(new Point(column, row));
while (!list.isEmpty()) {
Point p = list.remove(0);
if (!visited[p.y * X + p.x]) {
step++;
traversalChess(chess, p.y, p.x);
}
}
if (step < X * Y ) {
chess[row][column] = 0;
visited[row * X + column] = false;
}
最后测试下打印结果如下
X = 8;
Y = 8;
int row = 1;
int col = 1;
int[][] chess = new int[X][Y];
visited = new boolean[X * Y];
long start = System.currentTimeMillis();
traversalChess(chess, row - 1, col - 1);
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start) + "毫秒");
for (int i = 0; i < chess.length; i++) {
for (int j = 0; j < chess[i].length; j++) {
System.out.print(chess[i][j] + " ");
}
System.out.println();
}
用贪心算法优化 把获得的ArrayList按从小到大排序
|