赞
踩
目录
1、数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。
即:数 ( 数据 ) 组 ( 一组 ) 就是一组数据。相当于容器,容纳多个同类型的元素。2、可以通过 数组名 .length 得到数组的大小 / 长度3、数组中存储的Java对象,实际上存放的是对象引用(内存地址),数组一旦创建,在Java中规定,长度就不能变。所有数组都有length属性,是Java自带的,用来获取元素个数4、数组的元素的内存地址是连续的,用数组元素第一个元素的地址代表堆内存中数组对象的内存地址,数组中元素是同类型的,因此每个元素所占用内存空间是一样的,又知第一个元素的内存地址以及数组中元素内存地址是连续的一段空间,进而可以通过下标,快速得到目标元素。线性表5、数组这种数据结构优缺点:优点:查/索引某个下标的元素效率较高,可以说是查找效率最高的。1)、每个元素的内存地址在存储空间是连续的2)、每一个元素的类型相同,即占用的内存空间大小一致3)知道第一个元素内存地址,知道每个元素占用的空间大小,又知道下标。故而通过一个数学表达式就可以计算出某个下标上的元素的内存地址,直接通过内存地址定位元素,检索效率最高。缺点:由于为了保证数组中每个元素的内存地址连续,子啊数组上随机增删数组效率低,因为随机增删数组会涉及到后面元素统一向前或者向后位移。数组不能存储大量数据,因为很难在内存空间上找到特别大的连续内存空间供数组使用。注意:数组最后一个元素的增删效率没什么影响 arr[arr.length-1]
1、数组声明定义:
数据类型 数组名[] = new 数据类型[大小];
int a[] = new int[5];//创建一个数组,名字是a,存放5个int类型数据
Person[] peaple = new Person[5];
这只是定义数组的一种方法,也可以先声明后用new方式分配内存空间
2、-静态初始化数组
int[] a = {2,5,7,98};
3、数组使用注意事项和细节
- 1) 数组是多个相同类型数据的组合,实现对这些数据的统一管理
- 2) 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
- 3) 数组创建后,如果没有赋值,有默认值
- int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
- 4) 使用数组的步骤
- 1. 声明数组并开辟空间(new)
- 2 .给数组各个元素赋值
- 3. 使用数组
- 5) 数组的下标是从 0 开始的。
- 6) 数组下标必须在指定范围内使用,否则报:下标越界异常,比如int [] arr=new int[5]; 则有效下标为 0-4。arr[5]会报运行时异常ArrayIndexOutOfBoundsException
7) 数组属引用类型,数组型数据是对象(object)4、 数组赋值机制1、基本数据类型赋值,这个值就是具体的数据,而且相互不影响2、 数组在默认情况下是引用传递,赋的值是地址。int[] arr1 = {1,2,3};int[] arr2 = arr1;
char[] arr1 = {'a','b','c'}; char[] arr2 = arr1; arr1[1] = '李'; //[a, 李, c],arr1和arr2指向同一个地址空间,因此修改arr1的元素,arr2元素也变了 System.out.println(Arrays.toString(arr2));
1、数组拷贝
new 的方式开辟不同的数据空间,修改 arr2, 不会对 arr1 有影响.循环遍历进行拷贝。
System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length)
Object src-----原数组
srcPos---原数组从哪个位置开始复制
Object dest-----目标数组,要拷贝到哪个数组
destPos----目标数组拷贝的初始位置
int length -----拷贝多长
int[] arr1 = {1,2,3,4,5,6}; int[] arr2 = new int[10]; //将arr1从数组下标为1的元素 1开始拷贝5个长度到arr2的下标为0的5个元素长度 System.arraycopy(arr1,1,arr2,0,5); //arr2:[2, 3, 4, 5, 6, 0, 0, 0, 0, 0]2、数组反转
//每次交换时,对应的下标 是 arr[i] 和 arr[arr.length - 1 -i]。对称位置下标 int temp = 0; int len = arr.length; //计算数组的长度 for( int i = 0; i < len / 2; i++) { temp = arr[len - 1 - i];//保存 arr[len - 1 - i] = arr[i]; arr[i] = temp; } //逆序遍历,顺序拷贝 for(int i = arr.length - 1, j = 0; i >= 0; i--, j++) { arr2[j] = arr[i]; }逆序遍历,顺序拷贝也能完成数组反转
3、数组添加/扩容
思路分析:1. 定义初始数组 int[] arr = {1,2,3}// 下标 0-22. 定义一个新的数组 int[] arrNew = new int[arr.length+1];3. 遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组4. 将 4 赋给 arrNew[arrNew.length - 1] = 4; 把 4 赋给 arrNew 最后一个元素5. 让 arr 指向 arrNew ; arr = arrNew; 那么 原来 arr 数组就被销毁6. 创建一个 Scanner 可以接受用户输入
Scanner myScanner = new Scanner(System.in); //初始化数组 int[] arr = {1,2,3}; do { int[] arrNew = new int[arr.length + 1]; //遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组 for(int i = 0; i < arr.length; i++) { arrNew[i] = arr[i]; } System.out.println("请输入你要添加的元素"); int addNum = myScanner.nextInt(); //把 addNum 赋给 arrNew 最后一个元素 arrNew[arrNew.length - 1] = addNum; //让 arr 指向 arrNew, arr = arrNew; //输出 arr 看看效果 System.out.println("====arr 扩容后元素情况===="); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } //问用户是否继续 System.out.println("是否继续添加 y/n"); char key = myScanner.next().charAt(0); if( key == 'n') { //如果输入 n ,就结束 break; } }while(true); System.out.println("你退出了添加...");
1、内部排序:指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法和插入式排序法)。
2、外部排序法:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。
3、冒泡排序法
冒泡排序(Bubble Sorting)的基本思想是: 依次 比较 相邻的两个数,正序则不动,倒序则交换位置,如此循环,直到整个数组为有序为止。 使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。
for( int i = 0; i < arr.length - 1; i++) {//外层循环是 arr.length-1 次 for( int j = 0; j < arr.length - 1 - i; j++) {//4 次比较-3 次-2 次-1 次 //如果前面的数>后面的数,就交换 if(arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } }
在 java 中,我们常用的查找有两种:
1) 顺序查找
2) 二分查找---算法中
1、System.arraycopy使用的基本定义
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
- src:源数组;
- dest:目的数组;
- destPos:目的数组放置的起始位置;
- length:复制的长度.
2、动态数组
// 容量检查
private void checkAndGrow() { // 容量检查 if (size == 0) { array = new int[capacity]; } else if (size == capacity) { // 进行扩容, 1.5 1.618 2 capacity += capacity >> 1; int[] newArray = new int[capacity]; System.arraycopy(array, 0, newArray, 0, size); array = newArray; }//添加数据
/** * 向 [0 .. size] 位置添加元素 * * @param index 索引位置 * @param element 待添加元素 */ public void add(int index, int element) { checkAndGrow(); // 添加逻辑 if (index >= 0 && index < size) { // 向后挪动, 空出待插入位置 System.arraycopy(array, index, array, index + 1, size - index); } array[index] = element; size++; }3、
优点
1. 按照索引查询元素速度快
2. 按照索引遍历数组方便缺点
1. 数组的大小固定后就无法扩容了
2. 数组只能存储一种类型的数据
3. 添加,删除的操作慢,因为要移动其他的元素。向尾部添加不影响
数组适用频繁查询,对存储空间要求不大,很少增加和删除的情况。
题目描述:给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。分析:
class Solution { public int[] plusOne(int[] digits) { for (int i = digits.length - 1; i >= 0; i--) { digits[i]++; digits[i] = digits[i] % 10; if (digits[i] != 0) return digits; } digits = new int[digits.length + 1]; digits[0] = 1; return digits; } }
题目描述:给定一个二进制数组 nums , 计算其中最大连续 1 的个数。
class Solution { public int findMaxConsecutiveOnes(int[] nums) { int ans = Integer.MIN_VALUE; int cur = 0; for(int num : nums){ if(num == 0){ ans = Math.max(cur, ans); cur = 0; }else{ cur++; } } return Math.max(cur, ans); } }
题目描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
分析:使用HashMap集合存储,key为数组元素,value为数组元素对应的下标。遍历数组判断map的key是否包含。
class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> map = new HashMap<>(); int[] result = new int[2]; for(int i=0;i<nums.length;i++){ if (map.containsKey(target - nums[i])){ result[0] = map.get(target - nums[i]); result[1] = i; return result; } map.put(nums[i],i); } return result; } }
题目描述:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
分析:辅助指针p,i是遍历指针,不等value的时候赋值给p位置元素。
class Solution { public int removeElement(int[] nums, int val) { int p =0; for(int i = 0;i<nums.length;i++){ if (nums[i] !=val){ nums[p] = nums[i]; p++; } return p; } }
题目描述:给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:
更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
class Solution { public int removeDuplicates(int[] nums) { int p1 = 0; int p2 =1; while(p2 < nums.length){ if (nums[p1] != nums[p2]){ nums[++p1] = nums[p2++]; }else{ p2++; } } return p1+1; } }
题目描述:给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
分析:双指针,每次比较较小的存入辅助数组,注意索引位置和双指针的关系
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int[] nums = new int[m+n]; int cur = 0; int p1 = 0; int p2 = 0; while(p1<m || p2<n){ if(p1 == m){ cur = nums2[p2++]; }else if(p2 == n){ cur = nums1[p1++]; }else if(nums1[p1] <= nums2[p2]){ cur = nums1[p1++]; }else { cur = nums2[p2++]; } nums[p1+p2-1] = cur; } for(int i = 0;i<nums1.length;i++){ nums1[i] = nums[i]; } } }倒序:
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int right = n-1; int left = m-1; int cur = nums1.length-1; while(right >= 0 && left >= 0){ if(nums1[left] > nums2[right]){ nums1[cur--] = nums1[left--]; } else{ nums1[cur--] = nums2[right--]; } } while(right >= 0){ nums1[cur--] = nums2[right--]; } while(left >= 0){ nums1[cur--] = nums1[left--]; } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。