常考排序算法、二分查找和数组操作

1、冒泡排序

时间复杂度:O(n2)

public class bubble {
	public static void main(String[] args) {
		int[] arr = {3, 4, 10, 5, 2};
		bubbleSort(arr);
	}
	
	public static void bubbleSort(int[] arr) {
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid");
			return;
		} 
		
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - i - 1; j++) {
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
		}
		
		System.out.println(Arrays.toString(arr));
	}
}

2、选择排序

时间复杂度:O(n2)

public class select {
	public static void main(String[] args) {
		
		int[] arr = {2, 1, 8, 6, 7, 10};
		
		selectSort(arr);
		
	}
	
	public static void selectSort(int[] arr) {
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid");
			return;
		} 
		
		for (int i = 0; i < arr.length - 1; i++) {
			int index = i;
			
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[j] < arr[index]) {
					index = j;
				}
			}
			
			if (index != i) {
				int temp = arr[i];
				arr[i] = arr[index];
				arr[index] = temp;
			}
		}
		
		System.out.println(Arrays.toString(arr));
	}
}

3、插入排序

时间复杂度:O(n2)

public class InsertSort {
	public static void main(String[] args) {
		int[] arr = {20, 10, 8, 11, 15, 4};
		
		insertSort(arr);
		
		System.out.println(Arrays.toString(arr));
		
	}
	
	public static boolean insertSort(int[] arr) {
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid!!!");
			return false;
		}
		
		for (int i = 1; i < arr.length; i++) {
			int index = i;
			int current = arr[i];
			
			for (int j = i - 1; j >= 0; j--) {
				if (arr[j] < current) {
					arr[j + 1] = arr[j];
					index--;
				} else {
					break;
				}
			}
			
			if (index != i) {
				arr[index] = current;
			}
		}
		
		return true;
	}
}

4、快速排序

时间复杂度:O(n * log n)

public class QuicklySort {
	/**
	*快速排序算法代码实现
	*@param arr int类型数组
	*@param left int类型,排序起始位置
	*@param right int类型,排序结束位置
	*/
	public static void quicklySort(int[] arr, int left, int right) {
		//参数合法化判断
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid");
			return;
		}
		
		//递归基线判断标准
		if (left > right) {
			return;
		}
		
		//定义变量,左索引位置,右索引位置,基础元素base和交换值
		int l, r, base, temp;
		l = left;
		r = right;
		base = arr[left];
		
		//降序:从右边开始查找,找到比base大的数,跳出循环;从左边开始查找,找到比base小的数,跳出循环;
		//交换两数值
		while (l != r) {
			while (arr[r] <= base && l < r) {
				r--;
			}
			
			while (arr[l] >= base && l < r) {
				l++;
			}
			
			//交换
			if (l < r) {
				temp = arr[r];
				arr[r] = arr[l];
				arr[l] = temp;
			}
		}
		
		//base值回归中间
		arr[left] = arr[l];
		arr[l] = base;
		
		//递归
		quicklySort(arr, left, r - 1);
		quicklySort(arr, l + 1, right);
	}
	
	public static void main(String[] args) {
		int[] arr = {20, 10, 9, 5, 100, 44};
		
		System.out.println("排序前" + Arrays.toString(arr));
		
		quicklySort(arr, 0, arr.length - 1);
		
		System.out.println("排序后" + Arrays.toString(arr));
	}
}

5、二分查找

时间复杂度:O(log n)

class HalfSearch {
	public static void main(String[] args) {
		int[] arr = {1, 3, 5, 7, 9, 11, 13, 16, 20, 21, 100};
		int find = 21;
		int index = 0;
		
		index = findIndexOf(arr, find);
		
		if (-1 == index) {
			System.out.println("未找到!!!");
		} else {
			System.out.println("Find at " + index);
		}
	}
	
	/**
	*二分法查找已经排序(从小到大)的数组元素
	*@param arr int类型的目标数组
	*@param find int类型要查找的目标元素
	*@return int类型 返回所查找的元素所在的角标位置
					 返回-1表示没有找到或者函数运行失败
					 失败原因:1. 传入的arr数组为null; 2. arr数组长度为0
	*/
	public static int findIndexOf(int[] arr, int find) {
		
		//参数合法化判断
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid!!!");
			return -1;
		}
		
		/*
		1.控制角标,定义max,min
		2.定义index = -1 ,用于传回find所在的角标
		3.与要查找的find进行循环比较:
			3.1 mid = (max + min) / 2 在循环中反复重新定义
			3.2 使用while循环判断,当min>max的时候终止循环
			3.3 mid < find, min = mid + 1, 重新定义mid然后继续比较
			3.4 mid > find, max = mid - 1, 重新定义mid然后继续比较
			3.5 mid == find, 则index为对应的find的角标; break; 并返回index
		*/
		int max = arr.length - 1;
		int min = 0;
		int index = -1;
		
		while (min <= max) {
			
			int mid = (max + min) / 2;
			
			if (arr[mid] < find) {
				min = mid + 1;
			} else if (arr[mid] > find) {
				max = mid - 1;
			} else {
				index = mid;
				break;
			}
		}
		
		return index;
	}
}

6、将某一个元素添加到某一个数组,不影响排序

基本思路就是:1.找到位置 2.插入,后面元素整体后移 3.这里将末尾位置用0(无效)元素替代

class Add {
	public static void main(String[] args) {
		int[] arr = {1, 2, 6, 10, 20, 56, 98, 0};
		
		addNumberInArray(arr, 100);
		
		printAddArray(arr);
		
	}
	
	/**
	*将某一个元素数据插入到已排序的数组中,不影响原有数组顺序
	*@param arr int类型的已经排序好的数组(从小到大),0为无效元素
	*@param add int类型的需要插入的元素数据
	*@return boolean 返回true表示函数运行成功,返回false表示运行失败
					 失败原因:1.传入的arr数组为null 2.arr数组长度为0
	*/
	public static boolean addNumberInArray(int[] arr, int add) {
		
		/*
		1.参数合法化判断
		2.定义一个 int index = -1; 用来记录所插入位置的角标
		3.找到要插入的位置,循环遍历数组,当 arr[i] > add 的时候,index记录位置
		  break;这样可以提升效率,避免不必要的循环
		4.将add插入到数组中,从数组最大角标元素开始,即无效元素0开始,依次向后"替换":
		  4.1 这里需要判定,如果输入的数字大于任何一个数字,直接插入到数组最后
		  4.2 从 j = arr.length - 1 开始, j--, a[j] = a[j-1]; 一条语句即可替换
		  4.3 会空出 arr[index], 将add赋值即可
		6.返回true
		*/
		
		//参数合法化判断
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid!!!");
			return false;
		}
		
		int index = -1;
		
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] > add) {
				index = i;
				break;
			}
		}
		
		if (-1 != index) {
			for (int j = arr.length - 1; j > index; j--) {
				arr [j] = arr[j - 1];
			}
			arr[index] = add;	
		} else {
			arr[arr.length - 1] = add;
		}
		
		return true;
	}
	
	/**
	*遍历打印元素
	*@param arr int类型的数组
	*@return boolean 返回true表示函数运行成功,返回false表示运行失败
					 失败原因:1.传入的arr数组为null 2.arr数组长度为0
	*/
	public static boolean printAddArray(int[] arr) {
		
		//参数合法化判断
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid!!!");
			return false;
		}
		
		for (int i = 0; i < arr.length; i++) {
			System.out.println("arr[" + i + "] = " + arr[i]);
		}
		
		return true;
	}
}

7、删除数组中某一个元素,不影响排序

这里注意排重,将多个要删除的元素都删除,同样先找到元素,然后统计重复个数,然后删除,后面元素前移,末尾补0(无效元素)。

class Deletes {
	
	public static void main(String[] args) {
		int[] arr = {1, 3, 5, 7, 13, 13, 13, 15, 17, 19};
		
		deleteNumberInArray(arr, 13);
		
		printDeleteArray(arr);
	}
	
	/**
	*删除已排好序的数组arr中的所有delete元素,有可能无法删除
	*@param arr int类型已经排序好的数组,升序
	*@param delete int类型要进行删除的元素数据
	*@return boolean 返回true表示运行成功,返回false表示运行失败
					 失败原因:1.传入的arr数组为null; 2.arr数组长度为0
	*/
	public static boolean deleteNumberInArray(int[] arr, int delete) {
		
		//参数合法性判断
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid!!!");
			return false;
		}
		
		/*
		函数功能实现过程:
		1.找到要删除元素数据的角标 : 找到该元素; 找不到该元素
			1.1 定义一个index = -1, 用于记录角标,默认是没有即-1; 定义一个count = 0, 用于记录要删除元素个数
			1.2 循环遍历查找,如果找到,则index的值替换为对应元素的角标,并count++,然后进行结束循环判定:
				1.2.1 因为是排序好的,所以要删除的元素的重复会集中在一起,因此要对下一个元素是否也为要删除元素
					  进行判定:如果是,继续循环;如果不是,结束循环
		2.删除操作
			2.1 判断index是否为-1,当为-1的时候,说明没找到,如果不是-1,则可以进行删除操作
			2.2 删除步骤:
				2.2.1 确定第一个delete元素的角标,为index + 1 - count = i
				2.2.2 第i个元素会被第(i + count)个元素替换, i的最大值小于(arr.length - count),整体前移
		3.最后的数据整体换为0,表示无效数据,返回true
		*/
		int index = -1;
		int count = 0;
		
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] == delete) {
				index = i;
				count++;	
				
				//这里还要保证 i + 1 不能越界
				if (i + 1 != arr.length && arr[i+1] == delete) {
					continue;
				} else {
					break;
				}
			} 
		}
		
		if (-1 != index) {
			for (int i = index + 1 - count; i < arr.length - count; i++) {
				arr[i] = arr[i + count];
			}
			
			for (int j = arr.length - 1; j >= arr.length - count; j--) {
				arr[j] = 0;
			}
			
		} else {
			System.out.println("查无此数据,无法删除!!!");
		}
		
		return true;
	}
	
	/**
	*遍历打印删除操作后的数组
	*@param arr int类型数组,从小到大排列,并进行了删除操作,末位0表示无效元素
	*@return boolean 返回false表示运行失败,返回true表示运行成功
					 运行失败原因:1.传入的arr数组为null; 2.传入的arr数组长度为0
	*/
	public static boolean printDeleteArray(int[] arr) {
		
		//参数合法性判断
		if (null == arr || 0 == arr.length) {
			System.out.println("Input param is invalid!!!");
			return false;
		}
		
		for (int i = 0; i < arr.length; i++) {
			System.out.println("arr[" + i + "] = " + arr[i]);
		}
		
		return true;
	}	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值