java基础知识(五)--数组

本文介绍了Java中的数组,包括定义、初始化、内存分配、数组操作异常、基本操作和经典编程题解题思路。讲解了数组的概念、定义格式、动态与静态初始化,以及栈与堆的区别。同时,文章通过实例探讨了数组越界、空指针异常的处理,数组遍历、查找、排序和扩容问题。并提供了几个编程题,如计算数字出现次数、模拟豆机实验、储物柜难题等,分析了解题策略和思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4.01 数组概述和定义格式说明

数组是用来存储固定大小的同类型元素。是同一种类型数据的集合,本身为一个容器

好处:方便操作数据元素,数组中的数据元素

定义数组:

定义格式

数据类型 [] 变量名=new 数据类型[长度];
例: int [] array=new int [5];

分析数组:

左边:
int:数据类型(基本数据类型/引用数据类型)
[]:定义的数组类型
array:变量名
int [] array也可以定义成:int array[]
右边:
new int [5];
new:创建数组对象的关键字
int[5]:数组最多可以存放多少数据元素

** 数组相关数据类型默认值:

int 0
double 0.0
blooean flase

处理数组

数组的元素类型和数组的大小都是确定的,所以当处理数组元素时候,我们通常使用基本循环。

4.02 数组的初始化动态初始化

Java中的数组必须先初始化,然后才能使用。
所谓初始化,就是为数组中的数组元素分配内存空间,并为每个数组元素赋值

动态初始化:(由系统分配初始值)

数据类型 [] 变量名=new 数据类型[长度];
变量名[0]=值;
 ...

静态初始化:

(1)直接赋值
(2)遍历数组赋值
   for(初始值;判断条件;i++){
              //赋值
    }
(3)把已有的的数组的引用赋值给新创建的数组。

4.03 Java中内存分配以及栈和堆的区别

Java程序在运行时,需要在内存中分配空间。为了提高运算效率,有对空间进行了不同区域划分,因为每一片区域都有特定的处理数据方式和内存管理方式。


方法区
本地方法区
寄存器

例子:

class ArrayDemo1{
 public static void main(String[] args){
	int[] arr=new int[10];  //创建一个数组
	System.out.println(arr[0]);
	int[] arr2=arr;   //给新数组赋值
	arr2[0]=888;   //数组元素赋值
	System.out.println(arr[0]);  //888
	arr=null;   //值置空
	arr2=null;
	System.out.println(arr[0]);
    //报错 NullPointerException   引用变量找到不对象:要么压根没创建对象 要么本身是null
	//当一个对象没有被任何变量所引用的时候 则成为垃圾
	//垃圾有Java中垃圾回收机制处理 C/C++-free()函数
 }
}

执行流程:
在这里插入图片描述
在这里插入图片描述

4.04 数组操作的两个常见小问题越界和空指针

ArrayIndexOutofBoundsException 数组角标越界异常

是指数组中没有合格角标

NullPointerException 空指针异常

引用变量找到不对象:要么压根没创建对象 要么本身是null

4.05 数组的基本操作

  1. 遍历数组

    for循环遍历数组

    for(int i=0;i<数组.length;i++){  }
    
  2. 获取数组中最大和最小值

int[] arr=new int[]{1,2,3,4,5};
int max=arr[0];
		int min=arr[0];
		for(int i=0;i<arr.length;i++){
			if(arr[i]>max){
				max=arr[i];
			}
			if(arr[i]<min){
				min=arr[i];
			}
		}
  1. 将数组元素逆序输出
for(int i=arr.length-1;i>=0;i--){
			System.out.println(arr[i]);
		}
		arr=new int[]{1,2,3,4,5,6,7,8,9,10};
		for(int i=0;i<arr.length/2;i++){
			/*
			arr[i]=arr[i]^arr[arr.length-i-1];   //两数交换 方法一
			arr[arr.length-i-1]=arr[i]^arr[arr.length-i-1];
			arr[i]=arr[i]^arr[arr.length-i-1];
			*/
			
			/*
			int a=3;    两数交换 方法二
			int b=7;
			a=a+b;  //10
			b=a-b;  //10-7 3
			a=a-b;   //10-3 7
   			*/
		
			/*
			int temp=arr[i];   //两数交换 方法三
			arr[i]=arr[arr.length-1-i];	
			arr[arr.length-1-i]=temp;
			*/
		}
		for(int i=0;i<arr.length;i++){
			System.out.println(arr[i]);
		}
  1. 数组元素查找

    ①顺序查找

for(int i=0;i<arr.length;i++){
			if(arr[i]==要找的数){
				break;
			}
		}

②二分查找(前提是数组有序)

        int min=0;
		int max=arr.length-1;
		int mid=(min+max)/2;
		int key=要找的数;
		while(arr[mid]!=key){
			if(arr[mid]>key){
				max=mid-1;
			}
			if(arr[mid]<key){
				min=mid+1;
			}
			mid=(min+max)/2;
			if(min>max){
				mid=-1;
				break;
			}
		}
		System.out.println(mid);

在这里插入图片描述
在这里插入图片描述
5. 数组元素排序

//插入排序
public static void insertSort(){
		int[] arr=new int[10000];
		for(int i=0;i<arr.length;i++){
			arr[i]=(int)(Math.random()*5);
		}
		long start=System.currentTimeMillis();
		for(int i=1;i<arr.length;i++){
			int e=arr[i];
			int j;
			for(j=i;j>0&&arr[j-1]>e;j--){
				arr[j]=arr[j-1];
			}
			arr[j]=e;
		}
		long end=System.currentTimeMillis();
		System.out.println("插入排序time="+(end-start));
	}

在这里插入图片描述

//冒泡排序
public static void bubbleSort(){
		int[] arr=new int[10000];
		for(int i=0;i<arr.length;i++){
			arr[i]=(int)(Math.random()*5);
		}
		long start=System.currentTimeMillis();
		for(int i=0;i<arr.length-1;i++){
			for(int j=0;j<arr.length-1-i;j++){
				if(arr[j]>arr[j+1]){
					int temp=arr[j];
					arr[j]=arr[j+1];
					arr[j+1]=temp;
				}
			}
		}
		long end=System.currentTimeMillis();
		System.out.println("冒泡排序time="+(end-start));
	}

在这里插入图片描述

//选择排序
public static void selectSort(){
		int[] arr=new int[10000];
		for(int i=0;i<arr.length;i++){
			arr[i]=(int)(Math.random()*5);
		}
		long start=System.currentTimeMillis();
		for(int i=0;i<arr.length-1;i++){   //-1 最后一个数字没必要参与比较
			for(int j=i+1;j<arr.length;j++){
				if(arr[i]>arr[j]){
					int temp=arr[i];
					arr[i]=arr[j];
					arr[j]=temp;
				}
			}
		}
		long end=System.currentTimeMillis();
		System.out.println("选择排序time="+(end-start));
	}

在这里插入图片描述
6. 数组扩容问题

数组一旦创建 其容量不可改变
直接不行就间接 重新创建一个数组 
把原先数组里的元素赋值到新数组中
将新数组的地址赋予原先的变量
import java.util.Arrays;
class ArrayCopyDemo{
 public static void main(String[] args){
  int[] arr=new int[]{1,2,3,4,5};
  arr=arrayCopy(arr,arr.length+1);
  arr[5]=6;
  System.out.println(arrayToString(arr));
 }
 public static int[] arrayCopy(int[] arr,int newLength){
		int[] newArr=new int[newLength];  //[1,2,3,4,5,0]
		for(int i=0;i<arr.length;i++){
			newArr[i]=arr[i];
		}
		return newArr;
	}

在这里插入图片描述
在这里插入图片描述
8.经典例题:

  1. (计算数字的出现次数)编写程序,读取在1到100之间的整数,然后计算每个数出现的次数。段定输人是以0结束的。
import java.util.*;
class Demo4_10{
	public static void main(String[] args){
		resolve1();
	}
	public static void resolve1(){    //解法一
		int[] nums=new int[100];
		Scanner scanner=new Scanner(System.in);
		System.out.print("Enter the integers :");
		while(true){
			int num=scanner.nextInt();
			if(num==0){   //以0结尾
				break;
			}else{
				nums[num-1]++;  //例:如果数字4进入数组,将下标为4-1位置的元素+1,实际上元素四没有进入数组。
			}
		}	
		for(int i=0;i<nums.length;i++){    //循环输出元素下标+1,和次数下标相对应的元素
			if(nums[i]!=0){
				if(nums[i]==1){
					System.out.println(i+1+" occurs "+1+" time ");
				}else{
					System.out.println(i+1+" occurs "+nums[i]+" times ");
				}
			}
		}
	}
}
import java.util.*;
class Demo4_10{
	public static void main(String[] args){
		resolve2();
	}
	public static void resolve2(){   //解法二
		int[] nums=new int[0];
		Scanner scanner=new Scanner(System.in);
		System.out.print("Enter the integers :");
		while(true){
			int num=scanner.nextInt();
			if(num==0){
				break;
			}
			nums=Arrays.copyOf(nums,nums.length+1); //扩容
			nums[nums.length-1]=num;
		}
		insertSort(nums);   
		for(int i=0;i<nums.length;){  //计数
			int count=1;
			for(int j=i+1;j<nums.length;j++){
				if(nums[i]==nums[j]){
					count++;
				}else{
					break;
				}
			}
			if(count==1){
				System.out.println(nums[i]+" occurs "+1+" time");
			}else{
				System.out.println(nums[i]+" occurs "+count+" times");
			}
			i=i+count;
		}

	}
	public static void insertSort(int[] arr){  //插入排序
		for(int i=1;i<arr.length;i++){
			int e=arr[i];
			int j;
			for(j=i;j>0&&arr[j-1]>e;j--){
				arr[j]=arr[j-1];
			}
			arr[j]=e;
		}
	}
}

解题思路:

第一种解:(元素没有进入数组,利用下标进行标记)

  • 直接创建长度为100的数组

  • 输入一个数字,将该数字作为角标对应到数组中 然后相应元素+1
    直到输入0结束

  • 然后在遍历数组
    相应元素为0 不管

  • 输出时
    1 time
    >1 times

第二种解:(先排序 进行遍历看有几个连续相等 )

例2 2 2 3 4 4 4 4 4 5 5 6 6 7

  • 实例化一个长度为0数组,进入一个元素进行一次扩容。
  • 代码给出的是插入排序。(也可以使用冒泡排序,选择排序,详细见前面的三种排序方式)
  • 遍历整个数组,计数出相同元素出现的次数
  • 打印输出
  1. (游戏:豆机)豆机,也称为梅花瓶或高尔顿瓶,它是一个用来做统计实验的设备,是用英国科学家瑟弗兰克斯高尔顿的名字来命名的。它是-一个三角形状的均匀放置钉子(或钩子)的直立板子。
    在这里插入图片描述
    球都是从板子口落下的。每当球碰到钉子,它就有50%的机会落向左边或落向右边。在板子底部的槽子中都会累积一堆球。

    编写程序模拟豆机。程序应该提示用户输人球的个数以及机器的槽数。打印每个球的路径模拟它的下落。例如:在图7-13b中球的路径是LLRRLLR,而在图7-13c中球的路径是RLRRLRR。使用条形图显示槽中球的最终储备量。

import java.util.*;
class Demo4_13{
	public static void main(String[] args){
		Scanner scanner=new Scanner(System.in);
		System.out.print("Enter the number of balls to drop:");
		int ballsCount=scanner.nextInt();  //球的个数
		System.out.print("Enter the number of slots in the bean machine:");
		int slotsCount=scanner.nextInt();  //槽子的个数
		String[] paths=new String[ballsCount];//球的路径数组
		int[] slots=new int[slotsCount];  //槽子数组
		
		for(int i=0;i<ballsCount;i++){  //分别模拟每一个球的路径
			String path="";
			for(int j=0;j<slotsCount-1;j++){  //每一个球所经历的钉子
				if((int)(Math.random()*2)==0){  //左
					path+="L";
				}else{  //右
					path+="R";
				}
			}
			paths[i]=path;  //路径
		}
		for(int i=0;i<paths.length;i++){ //打印输出路径
			System.out.println(paths[i]);
		}
		for(int i=0;i<paths.length;i++){  //计数R的个数
			String path=paths[i];
			int count=0;
			for(int j=0;j<path.length();j++){
				if(path.charAt(j)=='R'){
					count++;
				}
			}
			slots[count]++;
		}
		for(int i=0;i<slots.length;i++){  //打印输出
			System.out.println("第"+(i+1)+"个槽子:"+slots[i]);
		}
	}
}

解题思路:

  • 提示用户输入球的个数
  • 提示用户输入槽子的个数-1—>钉子的排数
  • 模拟每个球的路径 for循环
    在碰到每个钉子for循环
    随机的生成两个数代表走左边/走右边
  • 统计每个路径中R的个数
  • 创立一维数组来接收槽子的球数
    以R的个数作为数组的下标,小球落入相应下标的元素+1
  • 打印输出小球路径和槽子的小球个数

3.(游戏:储物柜难题)一个学校有100个储物柜和100个学生。所有的储物柜在上学第一天都是关着的。随着学生进来,第一个学生(用S1表示)打开每个柜子。然后,第二个学生(用S2表示)从第二个柜子(用L2表示)开始,关闭相隔为1的柜子。学生S3从第三个柜子开始,然后改变每个第三个柜子(如果它是开的就关上,如果它是关的就打开)。学生S4从柜子L4开始,然后改变每个第四个柜子的开闭状态。学生S5从L5开始,然后改变每个第五个柜子的状态,依此类推,直到学生S100改变L100为止。
在所有学生都经过教学楼并且改变了柜子之后,哪些柜子是开的?编写程序找出答案。

import java.util.Scanner;
class Demo4_14{
public static void main(String[] args){
	Scanner scanner=new Scanner(System.in);
	System.out.print("输入学生的个数:");
	int count=scanner.nextInt();    //学生的人数
	boolean[] status=new boolean[20];  //储物柜当前的状态
	
	for(int i=0;i<count;i++){  //从第1~第100个学生
		for(int j=i;j<20;){
			status[j]=!status[j];
			j+=i+1;  //j=i+i+1
		}
	}
	for(int i=0;i<status.length;i++){   //打印输出
		String s=status[i]==true?"开":"关";
		System.out.print(s+" ");
	}
  }
}

解题思路:
(1)定义一个布尔数组表示当前柜子的开关状态
(2)每个学生for循环 步长为1

改变柜子的状态for循环  步长为 当前柜子数+当前人数

(3)打印输出各个柜子的开关状态

  1. 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
    你可以假设数组是非空的,并且给定的数组总是存在众数。
class LeetCode169{
	public static void main(String[] args){
     System.out.print(majorityElement(nums));
	}
	public static int majorityElement(int[] nums) {   //方法一
		int maj=nums[0];
		int count=1;
		for(int i=1;i<nums.length;i++){
			if(nums[i]==maj){
				count++;
			}else{
				count--;
				if(count==0){
					maj=nums[i];
					count=1;
				}
			}
		}
		return maj;
	}
}
class LeetCode169{
	public static void main(String[] args){
	  System.out.print(majorityElement(nums));
	}
public static int majorityElement(int[] nums) {  //方法二
        Arrays.sort(nums);   //排序
		int maxCount=0;  //计数
		int majority=0;      //留下的数字
		for(int i=0;i<nums.length;){  
			int count=1;
			for(int j=i+1;j<nums.length;j++){
				if(nums[i]==nums[j]){  //比较两数
					count++;
				}else{
					break;
				}
			}
			if(count>maxCount){
				maxCount=count;
				majority=nums[i];
			}
			i+=count;
			if(i>nums.length/2){
				break;
			}
		}
		return majority;
    }

解题思路:

方法一:

对数组进行排序--->遍历数组,计数找出出现最多的那个。

方法二:
元素相消的方法,最后留下的就是众数

(1)随便取出第一个元素,计数计做1,再取出第二个元素。
   计数为1时:
    两个进行比较,如果 相同--->计数+1
    			     不相等---->去掉第一个元素,计数计第二个元素
    计数大于1时 如果 相同----->计数+1
    				不相同----->计数-1,第二个元素消去
(2)以此方法全部消除完,留下的是众数。

5.在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄,他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。现在,给出提莫对艾希的攻击时间序列和提莫攻击的中毒持续时间,你需要输出艾希的中毒状态总时长。
你可以认为提莫在给定的时间点进行攻击,并立即使艾希处于中毒状态。

class LeetCode495{
	public static void main(String[] args){
	 System.out.print(findPoisonedDuration(timeSeries, duration));
	}
public static int findPoisonedDuration(int[] timeSeries, int duration) {  //中毒数组 持续时间
		if(timeSeries==null||timeSeries.length==0){
			return 0;
		}
		int total=0;
		for(int i=0;i<timeSeries.length-1;i++){
			int delt=timeSeries[i+1]-timeSeries[i];
			if(delt>duration){   //判断两击中点之间的时间
				total+=duration;
			}else{
				total+=delt;
			}
		}
		total+=duration;
		return total;
    }
}

解题思路:

中毒点  持续时间  中毒总时间
[1,4,7]    2     2+2+2=6
[1,3,5]    3     2+2+3=7
如果时间差大于中毒时间		满毒时间
如果时间差小于等于中毒事件	时间差
最后一秒直接+满毒时间

6.给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素。你可以返回满足此条件的任何数组作为答案。

import java.util.Arrays;
class LeetCode905{
	public static void main(String[] args){
		int[] A={1,2,3,4,5,6,7,8,9};

		A=sortArrayByParity(A);
		System.out.println(Arrays.toString(A));
	}
	public static int[] sortArrayByParity(int[] A) {   //方法一
		if(A==null){
			return null;
		}
		for(int i=1;i<A.length;i++){
			if(A[i]%2==0){
				int e=A[i];
				int;
				for(j=i;j>0&&A[j-1]%2==1;j--){
					A[j]=A[j-1];
				}
				A[j]=e;
			}
		}
		return A;
	}
}

import java.util.Arrays;
class LeetCode905{
	public static void main(String[] args){
		int[] A={1,2,3,4,5,6,7,8,9};

		A=sortArrayByParity(A);
		System.out.println(Arrays.toString(A));
	}
	 static int[] sortArrayByParity(int[] A) {   //方法二
		if(A==null){
			return null;
		}
		int start=0;
		int end=A.length-1;
		while(start<end){
			if(A[start]%2==0&&A[end]%2==0){
				start++;
			}else if(A[start]%2==0&&A[end]%2==1){
				start++;
				end--;
			}else if(A[start]%2==1&&A[end]%2==0){
				int temp=A[start];
				A[start]=A[end];
				A[end]=temp;
			}else{
				end--;
			}
		}
		return A;
	}
}
import java.util.Arrays;
class LeetCode905{
	public static void main(String[] args){
		int[] A={1,2,3,4,5,6,7,8,9};

		A=sortArrayByParity(A);
		System.out.println(Arrays.toString(A));
	}
public static int[] sortArrayByParity(int[] A) {   //方法三
		if(A==null){
			return null;
		}
        for(int i=0;i<A.length-1;i++){
			if(A[i]%2==9){
				continue;
			}
			for(int j=i+1;j<A.length;j++){
				if(A[j]%2==0){
					int temp=A[j];
					A[j]=A[i];
					A[i]=temp;
					break;
				}
			}
		}
		return A;
    }
   }

解题思路:

三种方法:
(1)插入排序思想

详情见排序方法中的插入排序。唯一不同的是判断条件从小到大---->从偶到奇

(2)夹逼思想
在这里插入图片描述
(3)选择排序思想

详细步骤见前面排序的三种方法之选择排序,唯一不同的是条件改为偶数每次插在数组的第一个位置上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值