1. 二分查找算法(非递归)

1.1 介绍

  • 二分查找算法只适用于从有序的数列种进行查找,将数列排序后再进行查找
  • 二分查找法的运行时间为对数时间O(log2 n),即查找到需要的目标位置最多只需要log2 n步

1.2 代码实现

public class BinarySearch {public static void main(String[] args) {int[] arr = {1, 3, 8, 10, 11, 67, 100};int index = binarySearch(arr, -7);System.out.println(index);}//二分查找的非递归实现public static 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) {return mid;} else if (arr[mid] > target) {right = mid - 1;//向左边查找} else {left = mid + 1;//向右边查找}}return -1;}
}

2. 分治算法

2.1 介绍

  • 就是把一个复制的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并,分治算法可以求解的一些境点问题
  • 二分查找
  • 大整数乘法
  • 棋盘覆盖
  • 合并排序
  • 快速排序
  • 线性时间选择
  • 最接近点对问题
  • 循环赛日程表
  • 汉诺塔

2.2 基本步骤

  1. 分解:将原问题分解成若干个规模较小,相互独立,与原问题形式相同的子问题
  2. 解决:若子问题规模较小而容易被解决则直接解决,否则递归各个子问题
  3. 合并:将各个子问题的解合并为原问题的解

2.3 汉诺塔问题

2.3.1 思路

  • 如果仅有一个盘,A->C
  • 有>=2个盘,总是可以看做是两个盘1.最下面的盘;2.上面的盘
  • 先把最上面的盘A->B
  • 最下面的盘A->C
  • B塔的所有盘B->C

2.3.2 代码实现

public class Hanoitower {public static void main(String[] args) {hanoiTower(10, 'A', 'B', 'C');}//使用分治算法,汉诺塔的移动方法public static void hanoiTower(int num, char a, char b, char c) {//只有一个盘if (num == 1) {System.out.println("第1个盘从" + a + "->" + c);} else {hanoiTower(num - 1, a, c, b);System.out.println("第" + num + "个盘从" + a + "->" + c);hanoiTower(num - 1, b, a, c);}}
}

3. 动态规划算法

3.1 介绍

  • 动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法
  • 与分治相似,也是将待求解问题分解成若干个子问题,先求子问题,然后从这些子问题的解得到原问题的解
  • 与分治不同的是,适用于用动态规划求解的问题,经分解得到子问题不是互相独立的,下一个子阶段的求解是建立在上一个子阶段解的基础上进行进一步求解
  • 动态规划可以通过填表的方式来逐步推进,得到最优解

3.2 背包问题

3.2.1 思想

  • 总价值最大,重量不能超出
  • 装入物品不能重复
物品 重量w 价格v
吉他 1 1500
音响 4 3000
电脑 3 2000

每次遍历到第i个物品,根据w[i]和v[i]来确定是否需要将该物品放入背包中,即对于给定的n个物品,C为背包容量,令v[i]·[j]表示再前i个物品总能够装入容量为j的背包中的最大价值

  • v[i]·[0]=v[0]·[j]=0
  • 当w[i]>j时,v[i]·[j]=v[i-1]·[j]
  • 当j>=w[i]时,v[i]·[j]=max{v[i-1]·[j],v[i]+v[i-1]·[j-w[i]}

3.2.2 代码实现

public class KnapsackProblem {public static void main(String[] args) {int[] w = {1, 4, 3};//物品的重量int[] val = {1500, 3000, 2000};//物品的价值int m = 4;//背包的容量int n = val.length;//物品的个数int[][] v = new int[n + 1][m + 1];//v[i][j]表示在前i个物品中能装入容量为j的背包中的最大价值int[][] path = new int[n + 1][m + 1];for (int i = 1; i < v.length; i++) {for (int j = 0; j < v[0].length; j++) {if (w[i - 1] > j) {v[i][j] = v[i - 1][j];} else {//v[i][j] = Math.max(v[i - 1][j], val[i - 1] + v[i - 1][j - w[i - 1]]);if (v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {v[i][j] = val[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++) {v[i][0] = 0;}for (int i = 0; i < v[0].length; i++) {v[0][i] = 0;}for (int i = 0; i < v.length; i++) {for (int j = 0; j < v[i].length; j++) {System.out.print(v[i][j] + " ");}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.printf("第%d个商品放入到背包\n", i);j -= w[i - 1];}i--;}}
}

4. KMP算法

4.1 暴力匹配算法

  • 有一个字符串str1="中国你中你国你国中国你好"和一个子串str2=“中国你好”,判断str1是否含有str2,如果存在返回第一次出现的位置。如果没有,返回-1
  • 假设现在str1匹配到i位置,字串str2匹配到j位置,则
  • 如果当前字符匹配成功(str1[i]==str2[j]),则i++,j++,继续匹配下一个字符
  • 如果str1[i]!=str2[j],令i=i(j-1),j=0。相当于每次匹配失败时,i回溯,j置为0
  • 有大量回溯,效率很低

4.1.1 代码实现

public class ViolenceMatch {public static void main(String[] args) {String s1 = "中国你中你国你国中国你好";String s2 = "中国你好-";int i = violenceMatch(s1, s2);System.out.println(i);}public static int violenceMatch(String str1, String str2) {char[] s1 = str1.toCharArray();char[] s2 = str2.toCharArray();int s1Len = s1.length;int s2Len = s2.length;int i = 0;//指向s1int j = 0;//指向s2while (i < s1Len && j < s2Len) {if (s1[i] == s2[j]) {//匹配成功i++;j++;} else {i = i - (j - 1);j = 0;}}if (j == s2Len) {return i - j;} else {return -1;}}
}

4.2 KMP算法

  • KMP算法常用于在一个文本串S内查找一个模式串P出现的位置
  • KMP通过一个next数组,保存模式串中前后最长公共子序的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间
  • str1 = “BBC ABCDAB ABCDABCDABDE”,str2="ABCDABD "
public class KMPAlgorithm {public static void main(String[] args) {String str1 = "BBC ABCDAB ABCDABCDABDE";String str2 = "ABCDABD";int[] next = kmpNext(str2);System.out.println(Arrays.toString(next));int index = kmpSearch(str1, str2, next);System.out.println(index);}public static int kmpSearch(String str1, String str2, int[] next) {//遍历for (int i = 0, j = 0; i < str1.length(); i++) {while (j > 0 && str1.charAt(i) != str2.charAt(j)) {j = next[j - 1];}if (str1.charAt(i) == str2.charAt(j)) {j++;}if (j == str2.length()) {//找到了return i - j + 1;}}return -1;}//获取到一个子串的部分匹配表public static int[] kmpNext(String dest) {//保存部分匹配值int[] next = new int[dest.length()];next[0] = 0;for (int i = 1, j = 0; i < dest.length(); i++) {while (j > 0 && dest.charAt(i) != dest.charAt(j)) {j = next[j - 1];}if (dest.charAt(i) == dest.charAt(j)) {j++;}next[i] = j;}return next;}
}

5. 贪心算法

5.1 集合覆盖问题

  • 贪婪(贪心)算法值在对问题进行求解时,在每一步选择中都采取最好或最优的选择,从而希望能导致结果是最好或最优的算法
  • 得到的结果不一定是最优结果,但是都是相对近似最优解的结果
  • 假设存在下面需要付费的广播台以及可以覆盖的地区,如何选择最少的广播台,可以让所有地区都接受信号
广播台 覆盖地区
K1 北京,上海,天津
K2 广州,北京,深圳
K3 成都,上海,杭州
K4 上海,天津
K5 杭州,大连
  • 贪心算法最佳应用-集合覆盖
  • 使用穷举法实现列出每个可能的广播台的集合,称为幂集,有n个广播台,则广播台的组合总有2^n-1个
广播台数量n 子集总数2^n 需要时间
5 32 3.2秒
10 1024 102.4秒
100 1.26*100^30 4*10^23

5.2 代码思路

  1. 遍历所有的广播电台,找到一个覆盖了最多未覆盖的地区的电台
  2. 将这个电台加入到一个集合中,想办法把该电台覆盖的地区在下一次比较时去掉
  3. 重复第1步直到覆盖了全部地区

5.3 代码实现

public class GreedyAlgorithm {public static void main(String[] args) {HashMap<String, HashSet<String>> broadcasts = new HashMap<>();HashSet<String> hashSet1 = new HashSet<>();hashSet1.add("北京");hashSet1.add("上海");hashSet1.add("天津");HashSet<String> hashSet2 = new HashSet<>();hashSet2.add("广州");hashSet2.add("北京");hashSet2.add("深圳");HashSet<String> hashSet3 = new HashSet<>();hashSet3.add("成都");hashSet3.add("上海");hashSet3.add("杭州");HashSet<String> hashSet4 = new HashSet<>();hashSet4.add("上海");hashSet4.add("天津");HashSet<String> hashSet5 = new HashSet<>();hashSet5.add("杭州");hashSet5.add("大连");broadcasts.put("K1", hashSet1);broadcasts.put("K2", hashSet2);broadcasts.put("K3", hashSet3);broadcasts.put("K4", hashSet4);broadcasts.put("K5", hashSet5);//存放所有地区HashSet<String> allAreas = new HashSet<>();for (Map.Entry<String, HashSet<String>> broadcast : broadcasts.entrySet()) {allAreas.addAll(broadcast.getValue());}//创建ArrayList存放选择的电台集合ArrayList<String> selects = new ArrayList<>();//一个临时集合,在遍历过程中,存放遍历过程中的电台覆盖的地区和当前还没有覆盖的地区的交集HashSet<String> tempSet = new HashSet<>();//保存在一次遍历过程中,能够覆盖最大未覆盖的地区对应的电台的keyString maxKey = null;while (allAreas.size() != 0) {maxKey = null;for (String key : broadcasts.keySet()) {tempSet.clear();//当前key能覆盖的地区HashSet<String> areas = broadcasts.get(key);tempSet.addAll(areas);//求出tempSet和allAreas的交集tempSet.retainAll(allAreas);//如果当前这个结合包含的未覆盖地区的数量,比maxKey指向的集合地区还多if (tempSet.size() > 0 &&(maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())) {maxKey = key;}}//将maxKey加入selectsif (maxKey != null) {selects.add(maxKey);//将maxKey指向的广播电台覆盖的地区从allAreas去掉allAreas.removeAll(broadcasts.get(maxKey));}}System.out.println("结果" + selects);}
}

6. 普里姆(Prim)算法

6.1 应用场景

-有7个村庄(A,B,C,D…),如何修路将村庄连通,总路程最短?

6.2 最小生成树

  • 修路问题本质就是最小生成树(Minimum Cost Spanning Tree,MST)问题
  • 给定一个带权的无向连通图,如何选取一颗生成树,使树上的所有边上权的总和为最小,叫最小生成树
  • N个顶点,一定有N-1条边
  • 求最小生成树的算法主要是普里姆和克鲁斯卡尔算法

6.3 图解

6.4 代码实现

public class PrimAlgorithm {public static void main(String[] args) {char[] data = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G'};int verxs = data.length;int[][] weight = new int[][]{{100, 5, 7, 100, 100, 100, 2},{5, 100, 100, 9, 100, 100, 3},{7, 100, 100, 100, 8, 100, 100},{100, 9, 100, 100, 100, 4, 100},{100, 100, 8, 100, 100, 5, 4},{100, 100, 100, 4, 5, 100, 6},{2, 3, 100, 100, 4, 6, 100}};MGraph graph = new MGraph(verxs);MinTree minTree = new MinTree();minTree.createGraph(graph, verxs, data, weight);minTree.showGraph(graph);minTree.prim(graph, 0);}
}//创建最小生成树
class MinTree {//创建图的邻接矩阵public void createGraph(MGraph graph, int verxs, char data[], int[][] weight) {for (int i = 0; i < verxs; i++) {//顶点graph.data[i] = data[i];for (int j = 0; j < verxs; j++) {graph.weight[i][j] = weight[i][j];}}}//显示图的方法public void showGraph(MGraph graph) {for (int[] link : graph.weight) {System.out.println(Arrays.toString(link));}}public void prim(MGraph graph, int v) {//标记节点是否被访问过int[] visited = new int[graph.verxs];//默认为0,表示没访问过for (int i = 0; i < graph.verxs; i++) {visited[i] = 0;}//把当前节点标记为已访问visited[v] = 1;//h1和h2记录两个顶点的下标int h1 = -1;int h2 = -1;int minWeight = 100;for (int k = 1; k < graph.verxs; k++) {for (int i = 0; i < graph.verxs; i++) {//i节点表示被访问过的节点for (int j = 0; j < graph.verxs; j++) {//j表示还没有访问过的节点if (visited[i] == 1 && visited[j] == 0 && graph.weight[i][j] < minWeight) {//替换minWeightminWeight = graph.weight[i][j];h1 = i;h2 = j;}}}System.out.println("边<" + graph.data[h1] + "," + graph.data[h2] + "> 权值:" + minWeight);//将找到的节点标记为已访问visited[h2] = 1;minWeight = 100;}}
}class MGraph {int verxs;//表示图的节点个数char[] data;//存放节点数据int[][] weight;//存放边public MGraph(int verxs) {this.verxs = verxs;data = new char[verxs];weight = new int[verxs][verxs];}
}

7. 克鲁斯卡尔(Kruskal)算法

7.1 应用场景

  • 某城市新增7个站点,ABCDEFG,需要修路将7个站点连通
  • 各个站点的距离用边线表示权,
  • 如何修路保证各个站点都能连通,且修建总里程最短
  • 克鲁斯卡尔算法是用来求加权连通图的最小生成树的算法
  • 具体做法:首先构造一个含n个顶点的森林,然后依权值从小到大连通王忠选择边加入到森林中,并使森林中不产生回路,直到变成一棵树位置

7.2 图解

7.3 代码实现

public class KruskalCase {private int edgeNum;//边的个数private char[] vertexs;//顶点数据private int[][] matrix;//邻接矩阵private static final int INF = Integer.MAX_VALUE;//表示两个顶点不能连通public static void main(String[] args) {char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};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}};KruskalCase kruskalCase = new KruskalCase(vertexs, matrix);kruskalCase.print();EData[] edges = kruskalCase.getEdges();System.out.println(Arrays.toString(edges));//排序前kruskalCase.sortEdge(edges);System.out.println(Arrays.toString(edges));//排序后kruskalCase.kruskal();}//构造器public KruskalCase(char[] vertexs, int[][] matrix) {//顶点数int vlen = vertexs.length;//初始化顶点this.vertexs = new char[vlen];for (int i = 0; i < vlen; i++) {this.vertexs[i] = vertexs[i];}//初始化边this.matrix = new int[vlen][vlen];for (int i = 0; i < vlen; i++) {for (int j = 0; j < vlen; j++) {this.matrix[i][j] = matrix[i][j];}}//统计边的条数for (int i = 0; i < vlen; i++) {for (int j = i + 1; j < vlen; j++) {if (this.matrix[i][j] != INF) {edgeNum++;}}}}public void kruskal() {int index = 0;//表示最后结果数组的索引int[] ends = new int[edgeNum];//用于保存已有最小生成树中的每个顶点在树中的终点//创建结果数组,保存最后的最小生成树EData[] rets = new EData[edgeNum];//获取图中所有边的集合EData[] edges = getEdges();//按照边的权值大小进行排序sortEdge(edges);//遍历edges数组,将边添加到最小生成树中,判断准备加入的边是否形成回路for (int i = 0; i < edgeNum; i++) {//获取第i条边的第一个顶点int p1 = getPosition(edges[i].start);//获取第二个顶点int p2 = getPosition(edges[i].end);//获取p1这个顶点在已有最小生成树中的终点int m = getEnd(ends, p1);int n = getEnd(ends, p2);//是否构成回路if (m != n) {//没有构成回路ends[m] = n;//设置m在已有最小生成树的终点rets[index++] = edges[i];//有一条边加入到rets}}//统计并打印“最小生成树”System.out.println("最小生成树" + Arrays.toString(rets));}//打印邻接矩阵public void print() {System.out.println("邻接矩阵为:\n");for (int i = 0; i < vertexs.length; i++) {for (int j = 0; j < vertexs.length; j++) {System.out.printf("%12d\t", matrix[i][j]);}System.out.println();//换行}}//对边进行排序private void sortEdge(EData[] edges) {for (int i = 0; i < edges.length - 1; i++) {for (int j = 0; j < edges.length - 1 - i; j++) {if (edges[j].weight > edges[j + 1].weight) {EData tmp = edges[j];edges[j] = edges[j + 1];edges[j + 1] = tmp;}}}}//传入顶点的值返回下标private int getPosition(char ch) {for (int i = 0; i < vertexs.length; i++) {if (vertexs[i] == ch) {return i;}}return -1;}//获取图中边,放到EData[]数组中,后面需要遍历该数组private EData[] getEdges() {int index = 0;EData[] edges = new EData[edgeNum];for (int i = 0; i < vertexs.length; i++) {for (int j = i + 1; j < vertexs.length; j++) {if (matrix[i][j] != INF) {edges[index++] = new EData(vertexs[i], vertexs[j], matrix[i][j]);}}}return edges;}//获取下标为i的顶点的终点,用于判断两个顶点的终点是否相同private int getEnd(int[] ends, int i) {while (ends[i] != 0) {i = ends[i];}return i;}
}//一个类EData,他的对象实例就表示一条边
class EData {char start;//边的一个点char end;//边的另一个点int weight;//边的权值public EData(char start, char end, int weight) {this.start = start;this.end = end;this.weight = weight;}//输出边的信息@Overridepublic String toString() {return "EData{" +"start=" + start +", end=" + end +", weight=" + weight +'}';}
}

8. 迪杰斯特拉(Dijkstra)算法

8.1 应用场景

  • 从G出发,到其他各个点的最短距离
  • 迪杰斯特拉算法是经典最短路径算法,用于计算一个节点到其他节点的最短路径,主要特点是以起始点为中心向外层扩展(广度优先搜索思想),直到扩展到终点为止

8.2 图解

9. 弗洛依德(Floyd)算法

9.1 简介

  • 和Dijkstra算法一样,Floyd算法也是一种用于寻找给定的加权图中顶点间最短路径的算法
  • Floyd计算各个顶点之间的最短路径,Dijkstra是计算图中某一个顶点到其他顶点的最短路径
  • 设置顶点vi到顶点vk的最短路径已知为Lik,顶点vk到vj的最短路径已知为Lkj,顶点vi到vj的路径为Lij,则vi到vj的最短路径为min((Lik+Lkj),Lij),vk的取值为图中所有顶点,则可获取vi到vj的最短路径

9.2 图解


9.3 代码实现

public class FloyAlgorithm {public static void main(String[] args) {char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};int[][] matrix = new int[vertex.length][vertex.length];final int N = 65535;matrix[0] = new int[]{0, 5, 7, N, N, N, 2};matrix[1] = new int[]{5, 0, N, 9, N, N, 3};matrix[2] = new int[]{7, N, 0, N, 8, N, N};matrix[3] = new int[]{N, 9, N, 0, N, 4, N};matrix[4] = new int[]{N, N, 8, N, 0, 5, 4};matrix[5] = new int[]{N, N, N, 4, 5, 0, 6};matrix[6] = new int[]{2, 3, N, N, 4, 6, 0};Graph graph = new Graph(vertex.length, matrix, vertex);graph.floyd();graph.show();}
}//创建图
class Graph {private char[] vertex;//存放顶点的数组private int[][] dis;//保持从各个顶点出发到其他顶点的距离private int[][] pre;//保存到达目标顶点的前驱顶点public Graph(int length, int[][] matrix, char[] vertex) {this.vertex = vertex;this.dis = matrix;this.pre = new int[length][length];//对pre数组初始化for (int i = 0; i < length; i++) {Arrays.fill(pre[i], i);}}//显示pre和dis数组public void show() {char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};for (int k = 0; k < dis.length; k++) {//输出pre数组的一行for (int i = 0; i < dis.length; i++) {System.out.print(vertex[pre[k][i]] + " ");}System.out.println();for (int i = 0; i < dis.length; i++) {System.out.print("(" + vertex[k] + "到" + vertex[i] + "的最短路径是" + dis[k][i] + ")");}System.out.println();}}//floyd算法public void floyd() {int len = 0;//变量保存距离//对中间顶点遍历,k就是中间顶点的下标for (int k = 0; k < dis.length; k++) {//从i顶点开始出发for (int i = 0; i < dis.length; i++) {//到达j顶点for (int j = 0; j < dis.length; j++) {len = dis[i][k] + dis[k][j];//求出从i顶点出发,经过k中间顶点,到达j顶点的距离if (len < dis[i][j]) {dis[i][j] = len;pre[i][j] = pre[k][j];//更新前驱顶点}}}}}
}

10. 马踏棋盘算法

10.1 思路图解

  • 马踏棋盘实际上是图的深度优先搜索(DFS)的应用
  • 如果使用回溯来解决,加入走到了53步,坐标(1,0)发现到了尽头,只能回退,查看其它路径,在棋盘上不停回溯

10.2 代码实现

public class HorseChessboard {private static int X;//棋盘的列数private static int Y;//棋盘的行数//标记棋盘的各个位置是否被访问过private static boolean visited[];//标记是否棋盘的所有位置都被访问,true表示成功private static boolean finished;public static void main(String[] args) {X = 8;Y = 8;int row = 1;//初始位置的行int col = 1;//初始位置的列int[][] chessboard = new int[X][Y];visited = new boolean[X * Y];//初始值都是falselong start = System.currentTimeMillis();traversalChessboard(chessboard, row - 1, col - 1, 1);long end = System.currentTimeMillis();System.out.println("耗时" + (end - start));//输出棋盘的最后情况for (int[] rows : chessboard) {for (int step : rows) {System.out.print(step + "\t");}System.out.println();}}public static void traversalChessboard(int[][] chessboard, int row, int col, int step) {chessboard[row][col] = step;visited[row * X + col] = true;//标记该位置已访问//获取当前位置可以走的下一个位置的集合ArrayList<Point> ps = next(new Point(col, row));//对ps所有的Point对象的下一步的位置的数目,进行非递减排序sort(ps);//遍历pswhile (!ps.isEmpty()) {Point p = ps.remove(0);//取出下一个可以走的位置//判断该点是否已经访问过if (!visited[p.y * X + p.x]) {//没有访问过traversalChessboard(chessboard, p.y, p.x, step + 1);}}if (step < X * Y && !finished) {chessboard[row][col] = 0;visited[row * X + col] = false;} else {finished = true;}}//根据当前位置,计算能走哪些位置,并放入一个集合中public static ArrayList<Point> next(Point curPoint) {ArrayList<Point> ps = new ArrayList<>();Point p1 = new Point();//表示可以走5的位置if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {ps.add(new Point(p1));}//6位置if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y - 2) >= 0) {ps.add(new Point(p1));}//7位置if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {ps.add(new Point(p1));}//0位置if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {ps.add(new Point(p1));}//1位置if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {ps.add(new Point(p1));}//2位置if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {ps.add(new Point(p1));}//3位置if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {ps.add(new Point(p1));}//4位置if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {ps.add(new Point(p1));}return ps;}//根据当前这一步的所有的下一步的选择位置,进行非递减排序public static void sort(ArrayList<Point> ps) {ps.sort(new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {//获取到o1的下一步的所有位置的个数int count1 = next(o1).size();int count2 = next(o2).size();if (count1 < count2) {return -1;} else if (count1 == count2) {return 0;} else {return 1;}}});}
}

数据结构和算法-14.程序员常用10种算法相关推荐

  1. 第 14 章 程序员常用 10 种算法

    第 14 章 程序员常用 10 种算法 1.二分查找算法 1.1.二分查找算法介绍 前面我们讲过了二分查找算法,是使用递归的方式,下面我们讲解二分查找算法的非递归方式 二分查找法只适用于从有序的数列中 ...

  2. 算法与数据结构学习(58)-程序员常用10种算法(佛洛依德算法)

    弗洛伊德(Floyd)算法介绍 和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算 ...

  3. [置顶] 完美程序员的10种品质

    完美程序员的10种品质 转载自:http://zhousir.net/ 谁是完美程序员?著名博客作家Alex Iskold在<明星软件工程师的10种特质>一文中给出这个问题的答案: 1. ...

  4. 完美程序员的10种品质

    导读:谁是完美程序员?著名博客作家Alex Iskold在<明星软件工程师的10种特质>一文中给出这个问题的答案: 1. 热爱编程 2. 完成事情 3. 持续重构代码 4. 使用设计模式 ...

  5. 数据结构和算法之常用 10 种算法

    目录 1.二分查找算法(非递归) 2.分治算法 2.1分治算法最佳实践-汉诺塔 3.动态规划算法 4.KMP 算法 4.1KMP 算法最佳应用-字符串匹配问题 5.贪心算法 5.1贪心算法最佳应用-集 ...

  6. 程序员必读10本算法书推荐

    算法可以说是学习编程时关键要掌握的技能之一,但是算法的"难"却吓退了很多人.有人学算法更多是为了通过面试,但是很多人没有意识到算法在提高编程技能方面,也起着很大的作用.实际上,无论 ...

  7. 数据结构与算法(程序员常用的十种算法:上1~5)

    一:二分查找 二分查找算法(非递归)介绍 (1)前面我们讲过了二分查找算法,是使用递归的方式,下面我们讲解二分查找算法的非递归方法 (2)二分查找法只适用于从有序的数列中进行查找(比如数字和字母等), ...

  8. 程序员常用十大算法(上)

    1.二分查找算法(非递归实现) 1.1 二分查找算法(非递归)介绍 我们以前了解过二分查找算法,但是使用的是递归实现,下面我们了解二分查找算法的非递归实现 (注意) :二分查找算法只适用于有序的数列. ...

  9. 对长度为200的有序表进行二分查找_程序员常用的查找算法(顺序、二分、插值、分块、斐波那契)...

    顺序查找 基本思想 属于线性查找和无序查找,从一端开始顺序扫描,直到找到与目标值value相等的元素. 这是最基本的查找方法,也是时间复杂度最高的查找算法. 在数据过多时,这种方法并不适用. 代码实现 ...

最新文章

  1. python的matplotlib背景线_python中matplotlib的颜色及线条 控制
  2. css之object-fit
  3. C# 类型运算符重载在类继承中的调用测试
  4. Raw264.7培养经验分享
  5. redhat7 32位mysql_Redhat7.3安装MySQL8.0.22的详细教程(二进制安装)
  6. 分布式认证方案-基于session的认证方式
  7. 使用Windbg内核调试连接调试用户态程序的方法
  8. linux打印软件,KX-MB2033CN Linux
  9. sysbench的框架实现介绍
  10. 登录Ubuntu提示有软件包可以更新
  11. 计算机网络图论,网络图论
  12. 树莓派系统最小img镜像的制作-备份与还原
  13. 设计一个重量转换程序 python
  14. 获取本电脑外网IP和内网IP
  15. 内嵌资源html,go 1.16 embed 实现资源文件(html, css, js等)内嵌
  16. Android Studio 实现跑马灯微项目实例
  17. 关于mysql 联表使用count的一个问题
  18. Elastic实战:canal自定义客户端,实现mysql多表同步到es
  19. CSDN之博客积分规则
  20. 欢迎访问我的快站clone-5483e9466f404.kuaizhan.com

热门文章

  1. 网站如何记录访客的个人信息?
  2. 退休当月要干到月底吗_要退休了,需要当月办理手续还是提前一个月办理?
  3. 中国医药导刊杂志中国医药导刊杂志社中国医药导刊编辑部2023年第3期目录
  4. 手机同声翻译软件哪个好?试试这款不错的同声互译软件
  5. 点击小眼睛完成密码框的显示与隐藏睁眼和闭眼
  6. 2020年Delphi25周年庆FireMonkey25个免费样本源码
  7. day01 python从入门到放弃----爬取某H网视频
  8. opencv 图片高质量保存
  9. 使用 go 服务启动前端dist包
  10. win10 mysql 启动 bat_windows系统下(如win10)如何将bat在系统开机但未登录情况下自动启动...