本文共 10158 字,大约阅读时间需要 33 分钟。
所谓数组,是有序的元素序列。
若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便,
把具有相同类型的若干元素按无序的形式组织起来的一种形式。这些无序排列的同类数据元素的集合称为数组。int 的数组你就不能存float
也不能存double。数组是用于储存多个相同类型数据的集合。通常用Array表示,也称之为线性表,画图演示
(1)数组是相同数据类型的元素的集合。 (2)数组中的各元素的存储是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起。内存地址
(3)数组元素用整个数组的名字和它自己在数组中的顺序位置来表示。例如,a[0]表示名字为a的数组中的第一个元素,a[1]代表数组a的第二个元素,以此类推,(4)随机访问(查找)
数组是连续的内存空间和相同类型的数据。正是因为这两个限制,它才有了一个非常重要的特性:随机访问。但有利就有弊,这两个限制也让数组的很多操作变得非常低效,比如要想在数组中删除、插入一个数据,为了保证连续性,就需要做大量的数据搬移工作。
(5)数组的缺点:插入和删除 实现代码:
设数组的长度为n,现在,如果我们需要将一个数据插入到数组中的第k个位置。删除第N个位置的数据.那么需要移动删除和插入后面的数组元素
(6)使用数组一定要注意访问越界问题;所以一定要多加判断,尤其是在开始和结束。测试的时候也一样注意头和尾。
(1)一维数组
int a[],String a[] (2)多维数组
int a[][],int a[][][]。 int a[m][n]:内存空间是多少? m*n a[0][10]:
链表解决,a[0]:->10>2 a[1]->15
本质是一样的,都是数组。ArrayList是JDK封装了。不需要管扩容等操作;数组的话就要你全部操作 两者选择:
不知道数据大小的肯定选ArrayList。
如果你知道数据的大小而且你又非常关注性能那就用数组。
一维:a[] = new int[10]; ==> loc =
init_loc(初始内存地址)+index(数组的下标)size(数据的长度) 二维=>转化一维 1 2 3 4 5 6 =>
1 2 3 4 5 6 => 4的下标在二维里面是 (1 ,0) =>在一维里面是第3个。=> in(一维的长度)+j(在列
)=>13+0=3 a[i][j]: (i<n,j<m) loc=init_loc+(in+j)*size
数组是一个最基础最简单的数据结构,必须要完全搞懂。它是存储相同类型的一组数据,最大的两个特点就是下标和随机访问。缺点就是插入和删除是很慢的,时间复杂度为O(n)。
/** * @author zhz * @date 2020/11/11 **/public interface MyList { void add(int index, Object element); int size(); void add(Object element); void remove(int index); Object get(int index); String toString(); void ensureCapacityInternal();}import com.hr.tuling.array.MyList;import java.util.Arrays;/** * @author zhz * @date 2020/11/11 **/public class MyArrayList implements MyList { /** * 定义一个数组,用于保存集合中的数据 */ private Object[] elementData; /** * 定义一个变量,用于保存数组中实际存放元素的个数 */ private int size; /** * 获取数组中实际存放元素的个数 * * @return */ public int size() { return this.size; } /** * 无参构造方法(默认设置elementData数组的空间长度为10) */ public MyArrayList() { this.elementData = new Object[10]; } /** * 有参构造方法(指定设置elementData数组的空间长度) * * @param cap 需要设置elementData的空间长度 */ public MyArrayList(int cap) { //1、判断cap是否合法 if (cap < 0) { throw new RuntimeException("参数不合法,cap:" + cap); } //2、实例化elementData数组 this.elementData = new Object[cap]; } /** * 添加元素 * * @param element 需要添加的元素 */ @Override public void add(Object element) { //1、判断数组是否需要扩容 ensureCapacityInternal(); //2、把element添加进入数组中 elementData[size] = element; //3、更新size的值 size++; } /** * 根据索引获取元素值 * * @param index 索引值 * @return 数组中index索引对应的元素值 */ @Override public Object get(int index) { //1、判断索引是否合法,合法的取值范围:【0,size-1】 rangeCheck(index); //2、根据索引获取对应的元素值 return elementData[index]; } /** * 根据索引删除元素 * * @param index 索引值 */ @Override public void remove(int index) { //1、判断索引是否合法,合法的取值范围:【0,size-1】 rangeCheck(index); //2、把删除索引之后的元素往前移动一位 //2.1先获得删除索引及其之后的所有索引值 for (int i = index; i < size; i++) { //2.2把后一个元素往前移动一位 elementData[i] = elementData[i + 1]; } //3、把最后一个实际添加的元素设置为默认值 elementData[size - 1] = null; } /** * 根据索引插入元素 * * @param index 插入元素的索引位置 * @param element 需要插入的元素 */ @Override public void add(int index, Object element) { //1、判断索引是否合法,合法的取值范围:【0,size】-->插入的元素可以在实际添加元素的最末尾 if (index < 0 || index > size) { throw new ArrayIndexOutOfBoundsException("索引越界异常,index:" + index); } // 2.判断数组是否需要扩容 ensureCapacityInternal(); // 3.插入索引及其之后的元素往后挪动一位(从后往前挪动) // 3.1获得插入索引及其之后的所有索引值 for (int i = size - 1; i >= index; i--) { // 3.2把前一个元素往后挪动一位 elementData[i + 1] = elementData[i]; } // 4.在插入索引位置实现赋值操作 elementData[index] = element; // 5.更新size的值 size++; } /** * 检查索引是否合法(get和remove) * * @param index */ private void rangeCheck(int index) { //1、判断索引是否合法,合法的取值范围:【0,size-1】 if (index < 0 || index >= size) { throw new ArrayIndexOutOfBoundsException("索引越界异常,index:" + index); } } /** * 判断数组是否需要执行扩容操作 */ public void ensureCapacityInternal() { //1.1、当数组的空间长度等于数组实际存放元素的个数时,这时就需扩容扩容操作 if (elementData.length == size) { //1.2、创建一个比原数组空间长度更大的新数组 Object[] newArr = new Object[elementData.length * 2 + 1]; //1.3、把原数组中的元素拷贝进入新数组中 for (int i = 0; i < size; i++) { newArr[i] = elementData[i]; } //1.4、让原数组保存新数组的地址值 elementData = newArr; } } @Override public String toString() { return "ArrayList{" + "elementData=" + Arrays.toString(elementData) + '}'; } public static void main(String[] args) { MyList myList = new MyArrayList(7); myList.add(2); myList.add(3); myList.add(2); myList.add(3); System.out.println(myList.get(2)); }}
7.2、数组的反转
import java.util.Arrays;/** * 数组的反转 * 例如:数组{11, 22, 33, 44, 55, 66}反转后为{66, 55, 44, 33, 22, 11} * @author zhz * @date 2020/10/03 **/public class 数组的反转 { /** * 方法一: * 1)新建数组,用于保存反转后的结果 * 2)把需要反转数组中的元素倒序存入新数组中 */ public static int[] reverseOrderArray(int[] arr){ // 1.定义一个新数组,用于保存反转之后的结果 int[] temp=new int[arr.length]; // 2.把arr数组中的所有元素倒序的存入temp数组中 // 2.1通过循环获得arr数组中的每一个元素 for (int i = arr.length-1; i >= 0; i--) { // 2.2把arr数组中的元素倒序存入temp数组中 temp[arr.length-1-i]=arr[i]; } // 3.把反转之后的数组返回 return temp; } /** * 方法二:把需要反转数组的元素首尾交换即可 */ public static void reverseOrderArray1(int[] arr){ // 1.通过循环,获得数组前半部分的元素 for (int i = 0; i <arr.length/2; i++) { // 2.把arr[i]和arr[arr.length - 1 - i]做交换 int temp=arr[i]; arr[i]=arr[arr.length-1-i]; arr[arr.length-1-i]=temp; } } public static void main(String[] args) { int[] arr={ 11,22,33,44,55,66}; //System.out.println(Arrays.toString(数组的反转.reverseOrderArray(arr))); 数组的反转.reverseOrderArray1(arr); System.out.println(Arrays.toString(arr)); }}
7.3、 找数组中重复的元素
import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Set;/** * @author zhz * @date 2020/10/03 **/public class 找数组中重复的元素 { /** * 问题:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的, * 但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 * 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2 * * 解决:第一种,用map做计数器,当大于1时,则返回true,否则false */ public static boolean duplicate(int numbers[],int length,int [] duplication) { Map<Integer, Integer> map = new HashMap<>(); int count=1; // 1.判断arr为null或arr.length等于0的情况 if(numbers == null || length == 0) { return false; } for (int i = 0; i < length; i++) { // 3.判断数组元素是否合法 if(numbers[i] < 0) { return false; } if (!map.containsKey(numbers[i])){ map.put(numbers[i],count); }else{ map.put(numbers[i],map.get(numbers[i])+1); } } for (Map.Entry<Integer,Integer> entry : map.entrySet()){ if (entry.getValue()>1){ duplication[0]=entry.getKey(); return true; } } return false; } /** * 题目:在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数 * 组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 * 请找出数组中任意一个重复的数字。 * * 解决:用set去判重 */ public int findRepeatNumber(int[] nums) { Set<Integer> set=new HashSet<>();; int res=0; for (int num : nums) { if (!set.contains(num)) { set.add(num); }else { res=num; } } return res; } public static void main(String[] args) { 找数组中重复的元素.duplicate(new int[]{ 0, 3, 4, 1, 4, 8 },6,new int[]{ 1}); }}
7.4、使奇数位于偶数前面
import java.util.Arrays;/** * 使奇数位于偶数前面 * 输入一个整型数组,实现一个方法来调整该数组中的元素的顺序, * 使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。 * @date 2020/10/03 **/public class 使奇数位于偶数前面 { /** * 使奇数位于偶数前面 * @param array 需要调整奇偶数位置的数组 */ public static void reOrderArray(int[] array) { // 1.处理arr为null的情况 if (array == null) { throw new NullPointerException("空指针异常,array:" + array); } // 2.定义两个下标,min的初始值为0,max的初始值为arr.length - 1 int min = 0; int max = array.length - 1; // 3.定义一个循环,用于调整数组中奇偶数的位置 while (min < max) { // 如果min小于max,则一直调整数组中元素的位置 // 4.让min从前往后找,如果arr[min]的值为偶数,则停止查找 while (min < max && array[min] % 2 != 0) { min++; } // 5.让max从后往前找,如果arr[max]的值为奇数,则停止查找 while (min < max && array[max] % 2 == 0) { max--; } // 6.如果min的值不等于max,则交换arr[min]和arr[max]的值 if (min != max) { int temp = array[min]; array[min] = array[max]; array[max] = temp; } } } /** *新开一个数组空间 * @param nums * @return */ public int[] exchange(int[] nums) { if (nums==null||nums.length==0){ return nums; } int left=0; int right=nums.length-1; int[] res=new int[nums.length]; for (int i = 0; i < nums.length; i++) { if ((nums[i]&1)==0){ //偶数 res[right--]=nums[i]; }else{ res[left++]=nums[i]; } } return res; } public static void main(String[] args) { int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9}; 使奇数位于偶数前面.reOrderArray(array); System.out.println(Arrays.toString(array)); }}
我是小白弟弟,一个在互联网行业的小白,立志成为一名架构师
转载地址:http://gfbwz.baihongyu.com/