一. 关于“擂台比武”
假设现在有一堆人要进行擂台比武,他们的战斗力如下:
[5, 1, 6, 3, 4, 2, 8]
数字越小代表战斗力越强
现在采用抽签模式,两两对决,胜者进入下一轮(如果奇数,单独人员可直接晋级),情况如下:
那么,如何把所有人的战斗力排名算出来呢?
二. 归并算法
如同擂台比武,先拆分成分各组,直到细分为单个,开始比较后合并
注意点:
- 拆分的时候要注意奇偶数的问题
- 合并的时候要注意比较排序,当一个数组排序完成,另外一个要把剩余的全部补充
三. 代码示例
/**
* @author yanghao
* @version MergeTest.java, v 0.1 2020-03-02 15:10
*/
public class MergeTest {
public static void main(String[] args){
Integer[] data = {5, 1, 6, 3, 4, 2, 8};
data = sort(data);
for(int i = 0;i < data.length; i ++){
System.out.print(data[i] + " = ");
}
}
private static Integer[] sort(Integer[] data){
int length = data.length;
if(length == 0){
return new Integer[0];
}
//分割
int mid = length%2 == 1 ? (length - 1)/2 : length/2 - 1;
Integer[] dataLeft = split(data, 0, mid);
Integer[] dataRight = split(data, mid + 1, length - 1);
//判断是否要继续分割
if(dataLeft.length > 1){
dataLeft = sort(dataLeft);
}
if(dataRight.length > 1){
dataRight = sort(dataRight);
}
//排序后合并
return merge(dataLeft, dataRight);
}
/**
* 拆分数组
* @param data
* @param start
* @param end
* @return
*/
private static Integer[] split(Integer[] data, int start, int end) {
Integer[] temp = new Integer[end - start + 1];
for(int i = 0;i <= end - start; i ++){
temp[i] = data[start + i];
}
return temp;
}
/**
* 合并数组
* @param dataLeft
* @param dataRight
* @return
*/
private static Integer[] merge(Integer[] dataLeft, Integer[] dataRight) {
Integer[] data = new Integer[dataLeft.length + dataRight.length];
int i = 0,j = 0,k = 0;
while (i < dataLeft.length && j < dataRight.length){
if(dataLeft[i] <= dataRight[j]){
data[k] = dataLeft[i];
i ++;
}else{
data[k] = dataRight[j];
j ++;
}
k ++;
}
//如果左边数组没有取完
while (i < dataLeft.length){
data[k] = dataLeft[i];
i ++;
k ++;
}
//如果右边数组没有取完
while (j < dataRight.length){
data[k] = dataRight[j];
j ++;
k ++;
}
return data;
}
}
来源:CSDN
作者:汤圆一号
链接:https://blog.csdn.net/weixin_43968234/article/details/104616081