数组常用方法(二分查找法包含原生手写)

本文详细介绍了Java中数组的各种操作,包括二分查找算法的实现,数组的扩容,寻找数组最值的方法,查询第二大值的策略,如何合并两个有序数组,打印杨辉三角,以及数组的插入和删除操作。这些内容涵盖了数组的基本操作及其优化技巧。
摘要由CSDN通过智能技术生成

1、二分查找法

二分查找数组中带有方法Arrays.binarySearch(数组,key);查到了返回第一个下标,查不到返回负数
该负数为应在数组中的位置+1取反;

二分查找法基本思想是基于已经排好序的数组(假设为升序),找到中间的那个数与被查找数对比,若比中间的数大,则往右再取中间,若小吗,往左取中间值再对比…
以下为手写原码:

package week02.day08.test;

public class BinarySearch {

	public static void main(String[] args) {
		int[] nums = {1,2,9,11,13};
		int need = 3;
		int index = binarySearch(need,nums);
		System.out.println("该数在数组中"+index+"位置");

	}

	public static int binarySearch(int need,int[] nums) {
		int mid ;
		int startIndex = 0;
		int endIndex = nums.length-1;
		while(startIndex<=endIndex) {
			mid = (startIndex+endIndex)/2;
			if(need>nums[mid]) { //如果查找的该数大于截取数组的下标中间值
				startIndex = mid +1;//在后半段去找,重新定义开始序号,
				//(不管数组个数是奇数个还是偶数个,都会取到一半或一半前的一个,比如数组长度为10,此时mid取值为4
				//mid已经大于下标为4的数了,所以下一次开始start取值为9/2+1=5,
			}else if(need<nums[mid]) {//前半段找
				endIndex = mid -1;//已经小于下标为4的数了,所以从3开始查找
			}else {
				return mid;
			}
		}
		return -1;//没取到
	}

}

2、数组的扩容

数组扩容带方法:nums = Arrays.copyOf(数组,新长度),把放进去的数组扩容,结果以返回值的形式给你
同理,缩容即是数组长度-1;
由于数组长度是不可改变的,扩容、缩容都是开辟新的数组空间重新赋值完成;
扩容思想就是把原数组已有数据复制给新的数组,并选定自己需要扩大的长度;
下面为数组扩容手写原码(已经封装为方法);
package week02.day08.test;

import java.util.Arrays;

public class DilatationArrays {

	public static void main(String[] args) {
		int[] nums = {1,3,4};
		nums = dilatationArrays(nums);
		System.out.println(Arrays.toString(nums));
	}
	//下面扩容两倍
	public static int[] dilatationArrays(int[] nums) {
		int[] newNums = new int[nums.length*2];
		for(int i =0;i<nums.length;i++) {
			newNums[i] = nums[i];
		}
		return newNums;
	}
}

3、数组最值问题

这是一个方法,用于找到数组中第一个最大值下标位置。
先将数组第一个值定位最大值,然后遍历数组进行”打擂台“,赢了的赋值给max,代码部分如下:

//找到数组中第一个最大值出现位置的索引。
	public static int getMaxIndex(int[] arrs) {
		int max = arrs[0];//先取第一个值为最大值
		int indexMax = 0;
		for(int i=0;i<arrs.length;i++) {
			if(max<arrs[i])//条件判断大的赋值为max存储
			{
				max=arrs[i];
				indexMax = i;
			}
		}
		return indexMax;
	}

4、数组内第二大值查询

不考虑数组为空的情况下,给定一个整型数组,数组成员10个,求该数组中第二大的数的下标。
(若有多个第二大值,找到第一个下标即可)
1、要想得到某数组第二大数的下标,需先排除掉所有最大值(最大值可能不是一个);
2、遍历第二遍,排除最大值,起始比较需拿最小值进行比较,不能用数组的第一个数进行比较,因为数组第一个数可能是最大值;
3、当最大值和最小值相等时,代表该数组为里数值都相等的数组,无第二大值例如{1}{1,1,1,1};

package week02.day07.work;
public class Test {
	public static void main(String[] args) {
		int[] arr = { 8, 1, 911, 47, 75, 5 ,-10};
		int secondMaxIndex = secondMaxIndex(arr);
		System.out.println("最大值"+arr[getMaxIndex(arr)]);
		System.out.println("最小值"+arr[getMinIndex(arr)]);
		System.out.println("第二大值"+arr[secondMaxIndex]);
	}
	public static int secondMaxIndex(int[] arrs) {
		int max = arrs[getMaxIndex(arrs)];//找到最大值
		int min = arrs[getMinIndex(arrs)];//取最小值上擂台和除了最大值以外的数对比
		if(min==max) {
			return -1;
		}//如果数组只有1个元素的情况........
		int secondMaxIndex=getMinIndex(arrs);//先取最小值的索引为第二大值
		for (int i = 0; i < arrs.length; i++) {
			if (arrs[i] != max) {
				if (arrs[i] > min) {
					min = arrs[i];
					secondMaxIndex=i;
				}
			}
		}
		return secondMaxIndex;
	}

//找到数组中第一个最大值出现位置的索引。
	public static int getMaxIndex(int[] arrs) {
		int max = arrs[0];//先取第一个值为最大值
		int indexMax = 0;
		for(int i=0;i<arrs.length;i++) {
			if(max<arrs[i])//条件判断大的赋值为max存储
			{
				max=arrs[i];
				indexMax = i;
			}
		}
		return indexMax;
	}

	public static int getMinIndex(int[] arrs) {
		int min = arrs[0];
		int indexMin = 0;
		for(int i=0;i<arrs.length;i++) {
			if(min>arrs[i]) {
				min = arrs[i];
				indexMin = i ;
			}
		}
		return indexMin;
	}
}

5、两个有序的数组,如何使用单层循环完成合并,且保证合并后有序。

首先我们知道数组的长度是无法改变的,要想获得一个两个数组之和的长度,一定需要定义第三个数组,然后前两个对比的数组,如何确定当前遍历到哪个数组哪个下标?我们定义三个变量,分别用于存储数组1当前的下标,数组2当前的下标及合并后的第三组数组下标;
每次从数组a拿出一个值和数组b拿出一个值进行比较,将对比得出的小的一个放入数组3,哪个数组取出的哪个数组下标+1;最后赋值给数组3,数组3下标+1;对比两个数组长度总和次数一定能够对比完成,某个数组循环完毕则退出循环。

package week02.day07.work;

import java.util.Arrays;

public class CombineOrderArrays {//合并有序数组
public static void main(String[] args) {
	int[] nums1 = {1,2,5};
	int[] nums2 = {2,3,8,9};
	int a = 0,b=0,c=0;
	int[] nums = new int[nums1.length+nums2.length];
	
	for(int i=0;i<nums.length;i++) {
		if(nums1[a]>nums2[b]) {
			nums[c]=nums2[b];
			b++;
		}else {
			nums[c]= nums1[a];
			a++;
		}
		c++;
		if(a==nums1.length||b==nums2.length) {//某一组数组对比完最后一个数后退出
			break;
		}
	}
	if(a<nums1.length) {//即表示数组1没读取完,接着a下标开始读取依次往后复制到数组3中
		for(int i=a;i<nums1.length;i++) {
			nums[c] = nums1 [i];
			c++;//将从a开始的数组1赋值给从c开始的数组3,依次录入剩下的;
		}
	}else {
		for(int i=b;i<nums2.length;i++) {//即表示数组2没读取完,接着b下标开始读取依次往后复制到数组3中
			nums[c] = nums2 [i];
			c++;
		}
	}
	
	System.out.println(Arrays.toString(nums));
}
}

6、二维数组打印杨辉三角

二维数组,即数组里存放的是数组,把外层数组想成行,内层数组为每行的每个数;所以需要重新赋值每个内层数组里的长度,内层第一个数组,下标为0,长度为0+1=1;
杨辉三角一维为行,二维为列,从排列方式可以知道第i行存在i列;
由于数组
每一个下方数字是由肩上两个数字和,即为i行i列数值等于i-1行j-1列加上i-1行j列.

package week02.day08.work;

import java.util.Scanner;

public class yangHuiTriangle {

	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		System.out.println("输入你要打印的行数");
		int num = scan.nextInt();
		int[][] yangHui =new int[num][];
		for(int i =0;i<yangHui.length;i++) {
			yangHui[i] =new int[i+1];
			//第i行数组长度为i+1,从第0行开始;
		}
		for(int i=0;i<num;i++) {//外层行数控制
			for(int j=0;j<=i;j++) {//内层每行列数控制
				if(j==0||j==yangHui[i].length-1) {
					yangHui[i][j]=1;
				}else {
					yangHui[i][j] = yangHui[i-1][j-1]+yangHui[i-1][j];
				}
				System.out.print(yangHui[i][j]+"\t");
			}
			System.out.println();
		}
		
		for(int i = 0;i<yangHui.length;i++) {
			for(int a=yangHui.length-i;a>0;a--) {
				System.out.print("\t");
			}
			for(int j=0;j<yangHui[i].length;j++) {
				
				System.out.print(yangHui[i][j]+"\t");
			}
			System.out.println();
		}
	}

}

7、数组的插入

数组插入的前提是一个有序数组,无序的插入直接在末尾加不就行了;
这里直接使用我们已知的方法 二分查找;找到该插入的位置,然后扩容,在该数后循环后移一位;
注意点:必须从数组末端开始后移,不然会将数据覆盖;

package week02.day08.test;

import java.util.Arrays;
import java.util.Scanner;

public class TestAdd {
	public static void main(String[] args) {
		int[] nums= {1,3,5,6,7,10,18};
		Scanner scan = new Scanner(System.in);
		System.out.println("输入一位数,插入数组");
		int num = scan.nextInt();
		int index = Arrays.binarySearch(nums, num);//使用二分查找找到该数在数组中什么位置
		index = index>=0?index:-(index+1);//负数表示没有这个数,返回的也就是-(应该在的位置+1)
		nums = Arrays.copyOf(nums, nums.length+1);//扩容一位
		for(int i=nums.length-1;i>index;i--) {
			nums[i]=nums[i-1];
		}//循环在插入数之后数进行后移
		nums[index]=num;
		System.out.println(Arrays.toString(nums));
		
	}
}

8、数组的删除

数组删除也就是找到该数在数组中的位置,然后循环前移,再使用缩容办法去掉最后一位即可;
注意点:必须从插入端开始前移,不然会将数据覆盖;

package week02.day08.test;

import java.util.Arrays;
import java.util.Scanner;

public class TestDelete {

	public static void main(String[] args) {
		int[] nums= {1,3,5,6,6,7,10,18};
		Scanner scan = new Scanner(System.in);
		System.out.println("输入一位数,数组中删除");
		int num = scan.nextInt();
		int index = Arrays.binarySearch(nums, num);
		if(index<0) {
			System.out.println("无此数据");
			return;
		}
		for(int i=index;i<nums.length-1;i++) {
			nums[i]=nums[i+1];
		}//扩容一位,循环前移前移从内往外	
		nums = Arrays.copyOf(nums, nums.length-1);//缩容一位
		
		System.out.println(Arrays.toString(nums));

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落日晓余晖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值