今天简单总结了几种算法,具体有:
【选择排序,冒泡排序,插入排序,蛮力字符串匹配,顺序查找,凸包问题的蛮力解法】
选择排序:(假定升序,问题规模为n)
【步骤】
I、(初始int k = 0),假定第k数为最小min;
2、然后将其与其他n-1个数作比较,若有比a[k] 小的,则两数交换位置;
3、k++且k<n-1;跳到步骤1
【具体算法】
public static int[] selectSort(int[] array){
for(int i = 0; i < array.length - 1; i++)
for(int j = i + 1; j < array.length; j++){
if(array[i] > array[j])
array[i] = array[j] + (array[j] = array[i]) * 0;
}
return array;
【分析】
I、输入规模为数组的大小n;
II、基本操作为“比较”;
III、“比较”的次数仅仅依赖于数组的规模,所以不区分最优、最差效率;
IV、基本操作执行次数:
V、T(n) = O(n^2)
冒泡排序:(假定非降序,问题规模为n)
【步骤】
1、(初始int k = 0),作第k次冒泡;
2、一次冒泡中,每两个相邻的数作比较,若序号大的数比序号小的数小,则交换位置,截止到下标为n-2-k的数;
3、k++且k<n-1;跳到步骤1
【具体算法】
<pre name="code" class="java">public static int[] bubbleSort(int[] array){
for(int i = 0;i <= array.length - 2; i++)
for(int j = 0;j <= array.length - 2 - i; j++)
if(array[j] > array[j + 1])
array[j] = array[j + 1] + (array[j + 1] = array[j]) * 0 ;
return array;
}
【分析】
I、输入规模为数组的大小n;
II、基本操作为“比较”;
III、“比较”的次数仅仅依赖于数组的规模,所以不区分最优、最差效率;
IV、基本操作执行次数:
V、T(n) = O(n^2)
插入排序
【步骤】
1、(初始int k = 1),作第k趟插入;
2、一次插入排序中,待插入的数依次向下标小的方向扫描,找到合适的位置后,将该位置起的数依次向下标增大方向挪动一个位置,然后将待插入的数插入到合适的位置;
3、k++且k<n;跳到步骤1
【具体算法】
public static int[] insertSort(int[] array){
int insertNum = 0;
for(int i = 1; i < array.length; i++){
insertNum = array[i];
int j = i - 1;
while(j >= 0 && array[j] > insertNum){
array[j + 1] = array[j];
j--;
}
array[j + 1] = insertNum;
}
return array;
}
【分析】
I、输入规模为数组的大小n;
II、基本操作为“比较” array[j] > insertNum;
III、“比较”的次数不仅依赖于数组的规模,还依赖于特定的输入;
IV、最坏效率(与选择排序相等):
最优效率:
平均效率:约等于 (可看出,插入算法还是优于 选择排序 和 冒泡排序 的)
蛮力字符串匹配
public static int bruteForceStringMatch(String sourceString, String pattern){
for(int i = 0,j = 0; i < sourceString.length() - pattern.length(); i++){
j = 0;
while(j < pattern.length() && sourceString.charAt(i + j) == (pattern.charAt(j)))
j++;
if(j == pattern.length())
return i;
}
return -1;
}
【分析】
基本操作:比较;
最差效率:O(mn);
平均效率:Θ(n)
顺序查找
public static <T> int sequenceSearch(List<T> list, T target){
for(T t : list)
if(t.equals(target))
return list.indexOf(t);
return -1;
}
凸包问题的蛮力解法
【思路】
I、求出点集的每一线段ax + by = c中的a、b、c值;
II、将其他n-2个点代入ax + by - c中,检查符号是否相同,此处一共有几种情况回发生:
1)代入后为0,且点在线段之外,则舍弃此线段
2)代入后为0,且点在线段上,若其他点符号相同,则保留线段,否则舍弃
3)代入后,有符号不相同的情况,舍弃线段
4)代入后,符号都相同,则保留线段
【具体算法】
/*array参数代表待求凸包的点集,用二维数组表示,第一维表示的是X轴的数值,第二维表示的是Y轴的数值 */
public static int[][] bruteForce(int[][] array){
int[][] arrayResult = {}; // 存放凸包极点和线段的数组,数组只有两列,每行代表一个线段,eg:a[0][0]=0,a[0][1]=1 表示的是端点为结点 0 和结点 1的线段
int[] value = new int[array.length]; //存放n-2个结点代入某一线段公式后的值
int valueKey = 0; //记录value数组的下标移动
// 初始化arrayResult数组,由于arrayResult数组存放的是凸包线段的端点的编号,所以arrayResult的行数就是线段数
if(array != null)
arrayResult = new int[array.length * (array.length - 1) / 2][2]; //凸包最多的线段数就是点集(n个结点)所能组成的最大线段数数 (n - 1) * n / 2
for(int i = 0; i < arrayResult.length;i++)
for(int j = 0; j < array[0].length; j++)
arrayResult[i][j] = -1;
//记录除线段外的n-2个点代入线段公式后的符号是否相同,true为相同
boolean hasSameSign = true;
double a = 0, b = 0, c = 0;
int resultArrayKey = 0, k = 0;
//最外的两层循环是蛮力算出点集中的所有可能线段,i和j代表点的编号
for(int i = 0; i < array.length - 1; i++)
for(int j = i + 1; j < array.length; j++){
a = array[j][1] - array[i][1];
b = array[i][0] - array[j][0];
c = array[i][0] * array[j][1] - array[i][1] * array[j][0];
hasSameSign = true;
//算出线段的X轴和Y轴区间
int maxX = CompareNumber.max(array[i][0], array[j][0]),
minX = CompareNumber.min(array[i][0], array[j][0]),
maxY = CompareNumber.max(array[i][1], array[j][1]),
minY = CompareNumber.min(array[i][1], array[j][1]);
valueKey = 0;
//历遍其他n-2个点,将其代入线段公式
for(k = 0;k < array.length;k++){
if(k == i || k == j)
continue;
value[valueKey] = (int)(array[k][0] * a + array[k][1] * b - c); //代入代入线段公式后的值
if(value[valueKey] == 0 && ((array[k][0] > maxX) || (array[k][0] < minX) ||
(array[k][1] > maxY) || (array[k][1] < minY))){ //特殊情况一:有点刚好在线段所表示的直线上,且该点在线段之外,则此线段不是凸包的边界
hasSameSign = false;
break;
}else if((value[valueKey] != 0)){
if((valueKey != 0) && CompareNumber.checkSign(value[valueKey], value[valueKey - 1]) < 0){ //当n-2个点里有其中两个点代入线段公式后,符号不相同,说明此线段不是凸包边界
hasSameSign = false;
break;
}
else
valueKey++;
}
}
if(hasSameSign){
arrayResult[resultArrayKey][0] = i;
arrayResult[resultArrayKey++][1] = j;
}
}
return arrayResult;
}
【分析】
输入规模:点集的点个数n
基本操作:点代入线段公式求值
时间效率:对于不同点的每一个n(n-1)/2来说,要对其他(n-2)个点求出ax+by-c的符号,所以 T(n) = O()