数组常见算法总结

目录

1,数组排序

方法一:调用Arrays工具类的sort()方法对数组进行排序

方法二:冒泡排序

2,数组查找

方法一:通过使用Arrays工具类的binarySearch()方法

方法二:二分查找(进行二分查找的数组必须是有序的)

方法三:双指针查找 

方法四:遍历查找

3,数组乱序

4,数组旋转

向左旋转:(顺序旋转)

 向右旋转:(逆序旋转)

1,数组排序

方法一:调用Arrays工具类的sort()方法对数组进行排序

public static void main(String[] args) {
		//定义一个无序的数组
		int[] arr01= {1,2,3,18,4,8,6,48,58,6413,14,15,16,17};
		System.out.println(Arrays.toString(arr01));
		//排序前
		//用sort()方法对数组进行排序
		Arrays.sort(arr01);
		//排序后的数组
		System.out.println(Arrays.toString(arr01));
	}

方法二:冒泡排序

冒泡排序私对一个数组进行从小到大的排序。

步骤:

1、比较相邻的元素,如果第一个比第二个大,就交换位置。

2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

3、针对所有的元素重复以上的步骤,除了最后一个元素。

特点:每一轮循环后,最大的一个数被交换到末尾,因此,下一轮循环就可以“排除”最后的数,每一轮循环都比上一轮循环的结束位置靠前一位。

注意:

N个数字来排序
俩俩比较小靠前
总共比较N-1轮
每轮比较N-1-i次

public static void main(String[] args) {
	//无序数组
		int[] arr01= {1,2,3,18,4,8,6,48,58,6413,14,15,16,17};
//		System.out.println("交换前:"+Arrays.toString(arr01));
//使用异或运算符交换交换数组中相邻元素之间的位置(异或运算符交换位置只能是整型,字符型可以使用但是需要强制类型转换为整型,浮点型和字符串不可以)
//		arr01[1]=arr01[1]^arr01[2];
//		arr01[2]=arr01[1]^arr01[2];
//		arr01[1]=arr01[1]^arr01[2];
//		System.out.println("交换后"+Arrays.toString(arr01));
		
	//对整个数组进行冒泡排序
		//比较的轮数为:n-1(n为数组的个数
		for (int i = 0; i <arr01.length-1; i++) {
			//每轮比较的次数为n-i(n为数组的个数)(i为比较的轮数)
			for (int j =0; j < arr01.length-1-i; j++) {
				//比较
				if(arr01[j]>arr01[j+1]) {
					arr01[j]=arr01[j]^arr01[j+1];
					arr01[j+1]=arr01[j]^arr01[j+1];
					arr01[j]=arr01[j]^arr01[j+1];	;
				}
				System.out.printf("第%d次交换后的%s\n",j+1,Arrays.toString(arr01));
		}
	}

 优化后代码:每进行一次排序,都判断一下数组是否已经有序,如果有序则不用在进行排序。

public static void main(String[] args) {
	//无序数组
		int[] arr01= {1,2,3,18,4,8,6,48,58,6413,14,15,16,17};
//		System.out.println("交换前:"+Arrays.toString(arr01));
//		//使用异或运算符交换交换数组中相邻元素之间的位置(异或运算符交换位置只能是整型,字符型可以使用但是需要强制类型转换为整型,浮点型和字符串不可以)
//		arr01[1]=arr01[1]^arr01[2];
//		arr01[2]=arr01[1]^arr01[2];
//		arr01[1]=arr01[1]^arr01[2];
//		System.out.println("交换后"+Arrays.toString(arr01));
		
	//对整个数组进行冒泡排序
		//比较的轮数为:n-1(n为数组的个数)
		int counter=0;	
		for (int i = 0; i <arr01.length-1; i++) {
			//每轮比较的次数为n-i(n为数组的个数)(i为比较的轮数)
			//设置一个变量来判断数组是否有序
			//true为有序
			//false为无序
			boolean isSort=true;
			for (int j =0; j < arr01.length-1-i; j++) {
				//比较
				counter++;
				if(arr01[j]>arr01[j+1]) {
					arr01[j]=arr01[j]^arr01[j+1];
					arr01[j+1]=arr01[j]^arr01[j+1];
					arr01[j]=arr01[j]^arr01[j+1];	
					isSort=false;
				}
				System.out.printf("第%d次交换后的%s\n",j+1,Arrays.toString(arr01));
			}
				if(isSort==true) {
					break;			
				}
			System.err.printf("第%d轮交换后的%s\n",i+1,Arrays.toString(arr01));
		}
		System.out.println("总共比较了"+counter+"次");
	}

2,数组查找

方法一:通过使用Arrays工具类的binarySearch()方法

(注意:进行查找的数组必须是有序数组)

如果数组无序,首先需要对数组进行排序操作

public static void main(String[] args) {
		int[] arr01= {1,2,3,18,6,4,8,2,6,48,58,6413,14,15,16,17};
		int target=14;
		//快速排序
		Arrays.sort(arr01);
		System.out.println(Arrays.toString(arr01));
		
		//基于二分查找的数组必须有序
		int index=Arrays.binarySearch(arr01,target);
		System.out.println(index);
	}

方法二:二分查找(进行二分查找的数组必须是有序的

二分查找算法思想:

1,判断搜索数组的“中位元素”与要查找的“目标元素”是否相等。
        如果相等,代表查找成功,退出算法;
        如果不相等,继续比较“中位元素”与要查找的“目标元素”的大小关系;
        如果“中位元素”大于“目标元素”,当前数组的前半部分作为新的搜索数组,因为后半部分的所有元素都大于“目标元素”,它们全都被排除了。
        如果“中位元素”小于“目标元素”,当前数组的后半部分作为新的搜索数组,因为前半部分的所有元素都小于“目标元素”,它们全都被排除了。
2、在新的搜索数组上,重新开始第1步的工作。

public static void main(String[] args) {
		try(Scanner scanner=new Scanner(System.in)){
			int [] arr01= {12,5,8,4,56,8,484,848,495,95,84,85,9};
			System.out.println("请输入目标元素:");
			int target=scanner.nextInt();
			//定义首尾下标
			int low=0,high=arr01.length-1,index=-1;
			while (low<=high) {
				int mid=(low+high)/2;//中间元素的下标
				if (arr01[mid]==target) {
					index=mid;
					break;		
				}else if (arr01[mid]<target) {//目标元素在中间元素的后边,将high向中间元素的前边移动
					low=mid+1;
					
				}else if (arr01[mid]>target) {//目标元素在中间元素的前边,将low向中间元素的后边移动
					high=mid-1;
				}
				
			}
			System.out.println("目标元素是"+arr01[index]+"目标元素的下标"+index);
			
		}
	}

方法三:双指针查找 

通过两个下标,分别从数组头部和尾部,同时对该无序数组进行遍历,将数组中的每个元素与指定元素进行比较,从而确定该数组中是否存在指定元素。

public static void main(String[] args) {
		int [] arr01= {12,5,8,4,56,8,484,848,495,95,84,85,9};
		System.out.println("请输入目标元素:");
		int target=484;
		//从两头同时开始向中间查找
		for (int i = 0,k=arr01.length-1; i <= k; i++,k--) {
			//从头开始查找
			if (arr01[i]==target) {
				System.out.println("目标元素出现的位置是:"+i);
				break;
			}
			//从尾开始查找
			if (arr01[k]==target) {
				System.out.println("目标元素出现的位置是:"+k);
				break;
			}
		}
	}

方法四:遍历查找

可以通过对该数组进行遍历,将数组中的每个元素与指定元素进行比较,从而确定该数组中是否存在指定元素。

public static void main(String[] args) {
		String[] arr1= {"张三","李四","王五","李明"};
		String targetString="张三";
		int index=-1;
		for (int i = 0; i < arr1.length; i++) {
			if (arr1[i].equals(targetString)) {
				index=i;
				break;				
			}
		}
			if(index>=0) {
				System.out.println(targetString+"已找到");

			}else {
				System.out.println(targetString+"未找到");			
			}
	}

3,数组乱序

数组乱序,也被称为数组洗牌,实现算法中有一个非常著名的洗牌算法Fisher-Yates算法,是由 Ronald A.Fisher和Frank Yates于1938年发明的,后来被Knuth在自己的著作《The Art of Computer Programming》中介绍,很多人直接称Knuth洗牌算法。

 实现步骤:

1,假设有一组需要乱序的数组arr。
2,从arr中随机选取一个未乱序的元素。
3,将该元素与数组arr中最后一个未乱序的元素交换。
4,重复2-3的步骤,直到数组arr中元素全部完成乱序。

public static void main(String[] args) {
		int[] arr= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
		System.out.println(Arrays.toString(arr));
		int count=0;
		for (int i = arr.length-1; i>0 ; i--) {
			int index=(int)(Math.random()*i);
			arr[index]=arr[index]^arr[i];
			arr[i]=arr[index]^arr[i];
			arr[index]=arr[index]^arr[i];
			count++;
			System.out.printf("第"+count+"次交换完成后的数组"+Arrays.toString(arr));
			System.out.println("交换的两个元素的下标是"+i+":"+index);
		}
		System.out.println("最终交换完成后的数组"+Arrays.toString(arr));
	}

4,数组旋转

向左旋转:(顺序旋转)

将头元素和他后边的元素交换位置

public static void main(String[] args) {
		int[] arr2= {1,2,3,4,5,6,7,8,9};
	    System.out.println("原数组为:"+Arrays.toString(arr));
	//向左旋转(顺序旋转)将头元素和他后边的元素交换位置
		for (int i = 0; i < 2; i++) {
			//从头一个元素和他的后一个元素交换
			//顺序旋转(向右交换)
			for (int k = 0; k < arr2.length-1; k++) {
				arr2[k]=arr2[k]^arr2[k+1];
				arr2[k+1]=arr2[k]^arr2[k+1];
				arr2[k]=arr2[k]^arr2[k+1];
			}
		}
		System.out.println("向左旋转2次后的数组为:"+Arrays.toString(arr2));
	}

 向右旋转:(逆序旋转)

尾元素后他的前一个元素交换位置

public static void main(String[] args) {
		int[] arr= {1,2,3,4,5,6,7,8,9};
		int[] arr2= {1,2,3,4,5,6,7,8,9};
		System.out.println("原数组为:"+Arrays.toString(arr));
	//向右旋转	(逆序旋转)尾元素后他的前一个元素交换位置
		//外层循环决定循环的位数和旋转的次数、旋转3次
		for (int i = 0; i < 3; i++) {
			//交换的次数,每次向右旋转(移动)1次
			//从最后一个元素和他的前一个元素交换
			//交换的顺序(逆序旋转)(向左交换)
			for (int k = arr.length-1; k >0; k--) {
				arr[k]=arr[k]^arr[k-1];
				arr[k-1]=arr[k]^arr[k-1];
				arr[k]=arr[k]^arr[k-1];
			}
		}
		System.out.println("向右旋转3次后的数组为:"+Arrays.toString(arr));
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值