数组经典题型

第4章 数组


4.1 数组的相关观念

数组:代表一组数据,当有一组“相同数据类型”的数据需要管理时,可以考虑使用数组,使用统一的名称来管理它们,这个统一的名称称为“数组名”。这组数据中的每一个数据,称为“元素”,每一个元素通过编号进行区分,这个编号称为”下标/索引“,下标的范围:[0, 数组的长度-1],元素的表示方式:数组名[下标],这组数据的总个数称为数组的长度,数组名.length。

int[] arr= {4,5,7,6,1};

int[] nums=newint[5];

arr数组的第一个元素:arr[0]

arr数组的第二个元素:arr[1]

nums数组的第一个元素:nums[0]

nums数组的第二个元素:nums[1]

arr数组的长度:arr.length

nums数组的长度:nums.length

4.2 数组的声明、初始化、使用

数组的声明格式:

元素的数据类型[] 数组名;

数组的初始化:

静态初始化:

和声明合起来一句,元素的数据类型[] 数组名= {元素值1,元素值2,....};

声明和初始化分开呢,

元素的数据类型[] 数组名;

数组名=new元素的数据类型[]{元素值1,元素值2,....};

动态初始化:

和声明合起来一句,元素的数据类型[] 数组名=new元素的数据类型[长度];

声明和初始化分开呢,

元素的数据类型[] 数组名;

数组名=new元素的数据类型[长度];

数组的遍历:

快捷键:数组名.fori 或直接itar

for(inti=0; i<数组名.length; i++){

}

4.3 数组的算法

4.3.1 对元素的统计分析

通常:统计元素中偶数的个数、3的倍数的个数、平均值、总和、素数的个数.....

原则:从头到尾遍历数组的元素,挨个判断即可 或 挨个累加

例如:

publicclassArrayReview1 {

publicstaticvoidmain(String[] args) {

int[] arr= {8, 6, 9, 4, 2, 5, 3, 1};

//统计里面偶数和奇数的个数

inteven=0;//存储偶数的个数

intodd=0;//存储奇数的个数

//遍历数组的元素,判断它们是偶数还是奇数

for (inti=0; i<arr.length; i++) {

if(arr[i] %2==0){

even++;

}else{

odd++;

}

}

System.out.println("odd = "+odd);

System.out.println("even = "+even);

}

}

4.3.2 找最大值/最小值

思路:

情况一:元素值已经确定

(1)先假设第1个元素最大或最小,即把第一个元素赋值给max/min变量

(2)用max或min变量 与 数组剩下的元素一一比较,如果有比max大,比min小的情况,就修改max或min的值

publicclassArrayReview2 {

publicstaticvoidmain(String[] args) {

int[] arr= {8, 6, 9, 4, 2, 5, 3, 1};

//找最大值

/*

情况一:元素值已经确定

(1)先假设第1个元素最大或最小,即把第一个元素赋值给max/min变量

(2)用max或min变量 与 数组剩下的元素一一比较,如果有比max大,比min小的情况,就修改max或min的值

*/

intmax=arr[0];

for (inti=1; i<arr.length; i++) {

if(arr[i] >max){//if(max < arr[i]){

max=arr[i];

}

}

System.out.println("max = "+max);

}

}

情况二:元素的值暂时不确定的,想着在确定值的同时找最大值/最小值

(1)通常把max初始化一个小于等于当前元素取值范围的最小值

例如:元素值的范围是[0,100],max = 0

如果元素值没有具体范围,int类型的话,max = Integer.MIN_VALUE;

通常把min初始化为一个大于等于当前元素取值范围的最大值

例如:元素值的范围是[0,100],min = 100

如果元素值没有具体范围,int类型的话,max = Integer.MAX_VALUE;

(2)用max或min变量 与 数组所有元素一一比较,如果有比max大,比min小的情况,就修改max或min的值

publicclassArrayReview3 {

publicstaticvoidmain(String[] args) {

int[] arr=newint[10];

//找最大值和最小值

/*

情况二:元素的值暂时不确定的,想着在确定值的同时找最大值/最小值

(1)通常把max初始化一个小于等于当前元素取值范围的最小值

例如:元素值的范围是[0,100),max = 0

通常把min初始化为一个大于等于当前元素取值范围的最大值

例如:元素值的范围是[0,100),min = 100

(2)用max或min变量 与 数组所有元素一一比较,如果有比max大,比min小的情况,就修改max或min的值

*/

intmax=0;

intmin=100;

for (inti=0; i<arr.length; i++) {

arr[i] = (int)(Math.random()*100);

System.out.print(arr[i] +" ");

if(arr[i] >max){

max=arr[i];

}elseif(arr[i] <min){

min=arr[i];

}

}

System.out.println();

System.out.println("max = "+max);

System.out.println("min = "+min);

}

}

4.3.3 找最大值及其下标

情况一:元素不重复,假设元素已经确定

(1)声明两个变量,一个变量是max(存最大值),一个变量是index(存它的下标)

先假设第1个元素最大或最小,即把第一个元素赋值给max变量,index初始化为0

(2)用剩下的元素与max比较,如果有比max大的,同时修改max和index

publicclassArrayReview4 {

publicstaticvoidmain(String[] args) {

int[] arr= {8, 6, 9, 4, 2, 5, 3, 1};

//找最大值及其下标

/*

情况一:元素不重复,假设元素已经确定

(1)声明两个变量,一个变量是max(存最大值),一个变量是index(存它的下标)

先假设第1个元素最大或最小,即把第一个元素赋值给max变量,index初始化为0

(2)用剩下的元素与max比较,如果有比max大的,同时修改max和index

*/

intmax=arr[0];

intindex=0;

for (inti=1; i<arr.length; i++) {

if(arr[i] >max){//if(max < arr[i]){

max=arr[i];

index=i;

}

}

System.out.println("max = "+max);

System.out.println("index = ["+index+"]");

}

}

情况二:元素可能重复,假设元素已经确定

(1)第一步先找最大值

(2)第二步再找和最大值相等的所有元素的下标

publicclassArrayReview5 {

publicstaticvoidmain(String[] args) {

int[] arr= {8, 6, 9, 4, 2, 5, 9, 1};

//找最大值及其下标

/*

情况二:元素可能重复,假设元素已经确定

(1)第一步先找最大值

(2)第二步再找和最大值相等的所有元素的下标

*/

intmax=arr[0];

for (inti=1; i<arr.length; i++) {

if(arr[i] >max){//if(max < arr[i]){

max=arr[i];

}

}

System.out.println("max = "+max);

for (inti=0; i<arr.length; i++) {

if(arr[i] ==max){

System.out.println("index = ["+i+"]");

}

}

}

}

4.3.4 元素查找

情况一:元素是无序

只能顺序查找,从第一个元素开始判断它是否是目标值,如果是,就说明目标值存在,当所有元素都判断过了,才能确定目标不存在。

(1)先声明一个boolean的变量flag,初始化为flag = false(不存在)

(2)遍历数组,挨个元素与目标值比较,如果相等,flag修改为true,同时可以break了,因为目标值已存在可以确定了

(3)遍历结束后,如果flag==false,就说明目标值不存在。

或者

(1)先声明一个int的变量index,初始化为-1(不存在),(因为正常元素的下标不会是-1)

(2)遍历数组,挨个元素与目标值比较,如果相等,index=该元素的下标,同时可以break了,因为目标值已存在可以确定了

(3)遍历结束后,如果index==-1,就说明目标值不存在。

publicclassArrayReview6 {

publicstaticvoidmain(String[] args) {

int[] arr= {8, 6, 9, 4, 2, 5, 9, 1};

//查找目标值7是否存在

inttarget=7;

/*

只能顺序查找,从第一个元素开始判断它是否是目标值,如果是,就说明目标值存在,当所有元素都判断过了,才能确定目标不存在。

(1)先声明一个boolean的变量flag,初始化为flag = false(不存在)

(2)遍历数组,挨个元素与目标值比较,如果相等,flag修改为true,同时可以break了,因为目标值已存在可以确定了

(3)遍历结束后,如果flag==false,就说明目标值不存在。

或者

(1)先声明一个int的变量index,初始化为-1(不存在),(因为正常元素的下标不会是-1)

(2)遍历数组,挨个元素与目标值比较,如果相等,index=该元素的下标,同时可以break了,因为目标值已存在可以确定了

(3)遍历结束后,如果index==-1,就说明目标值不存在。

*/

booleanflag=false;//不存在

for (inti=0; i<arr.length; i++) {

if(arr[i] ==target){

flag=true;//存在

break;

}

}

if(flag){

System.out.println("存在");

}else{

System.out.println("不存在");

}

}

}

情况二:元素是有序的,假设元素是从小到大

二分查找:

思路:

(1)声明left,right,mid变量,left表示左边界的下标,right表示右边界的下标,mid表示当前查找范围的中间元素的下标

left = 第一个元素的下标 = 0,right = 最后一个元素的下标= 数组名.length-1,

mid = (left + right) / 2 ; 更优一点写法 mid = left + (right - left)/2;

(2)循环条件 left <= right,循环条件成立还要查找,否则就结束

(3)用目标值target与 数组名[mid]比较是否相等,还可以用 目标值target 与 数组名[left] 比较是否相等, 还可以用 目标值target 与 数组名[right 比较是否相等,如果它们都不成立,看目标值target 比 数组名[mid]大还是小,

如果目标值target 比 数组名[mid]小,去左边,即要修改右边界 right = mid - 1,如果之前 比较过(目标值target 与 数组名[left] ),还可以修改left=left+1,如果之前 没有比较过(目标值target 与 数组名[left] ),不能写 left=left+1

如果目标值target 比 数组名[mid]大,去右边,即要修改左边界 left = mid +1,如果之前 比较过(目标值target 与 数组名[right] ),还可以修改right = right-1,如果之前没有比较过(目标值target 与 数组名[right] ),不能写right = right-1.

publicclassArrayReview7 {

publicstaticvoidmain(String[] args) {

int[] arr= {1,5,9,14,36,56};

//查找目标值7是否存在

inttarget=7;

intindex=-1;//假设target不存在,正常下标不会是-1

/*

思路:

(1)声明left,right,mid变量,left表示左边界的下标,right表示右边界的下标,mid表示当前查找范围的中间元素的下标

left = 第一个元素的下标 = 0,right = 最后一个元素的下标= 数组名.length-1,

mid = (left + right) / 2 ; 更优一点写法 mid = left + (right - left)/2;

(2)循环条件 left <= right,循环条件成立还要查找,否则就结束

(3)用目标值target与 数组名[mid]比较是否相等,还可以用 目标值target 与 数组名[left] 比较是否相等, 还可以用 目标值target 与 数组名[right 比较是否相等,如果它们都不成立,看目标值target 比 数组名[mid]大还是小,

如果目标值target 比 数组名[mid]小,去左边,即要修改右边界 right = mid - 1,如果之前 比较过(目标值target 与 数组名[left] ),还可以修改left=left+1,如果之前 没有比较过(目标值target 与 数组名[left] ),不能写 left=left+1

如果目标值target 比 数组名[mid]大,去右边,即要修改左边界 left = mid +1,如果之前 比较过(目标值target 与 数组名[right] ),还可以修改right = right-1,如果之前没有比较过(目标值target 与 数组名[right] ),不能写right = right-1.

*/

intleft=0;

intright=arr.length-1;

while(left<=right){

intmid=left+ (right-left)/2;//left与right的值可能会被修改,每次修改完都要重新计算mid的值

if(target==arr[mid]){//找到了

index=mid;

break;

}elseif(target==arr[left]){//找到了

index=left;

break;

}elseif(target==arr[right]){//找到了

index=right;

break;

}elseif(target<arr[mid]){//暂时还没找到,去左边

right=mid-1;

//因为前面比较了 if(target == arr[left]),所以可以修改left

left++;

}else{//暂时还没找到,去右边

left=mid+1;

//因为前面比较了 if(target == arr[right],所以可以修改right

right--;

}

}

if(index==-1){

System.out.println("不存在");

}else{

System.out.println("存在");

}

}

}

4.3.5 反转

思路:

左边与右边的元素交换,对应位置的元素交换。

步骤:

(1)声明两个变量,left,right,left代表左边的下标,right代表右边的下标

(2)数组名[left] 与 数组名[right]交换,

(3)每次交换完, left++,right--

(4)循环条件 ,left < right

publicclassArrayReview8 {

publicstaticvoidmain(String[] args) {

int[] arr= {1,5,9,14,36,56};

//反转

//左边与右边的元素交换,对应位置的元素交换。

/*

步骤:

(1)声明两个变量,left,right,left代表左边的下标,right代表右边的下标

(2)数组名[left] 与 数组名[right]交换,

(3)每次交换完, left++,right--

(4)循环条件 ,left < right

*/

for(intleft=0,right=arr.length-1; left<right; left++,right--){

inttemp=arr[left];

arr[left] =arr[right];

arr[right] =temp;

}

for (inti=0; i<arr.length; i++) {

System.out.print(arr[i] +" ");

}

}

}

4.3.6 冒泡排序

目标:从小到大

总思路:相邻元素比较,如果前面的元素 比 后面的元素 大,就交换它们,n个元素需要比较n-1轮,每一轮都可以从第一个元素开始,每一轮已经排好序的元素可以不用参与了。

步骤:

(1)外循环控制轮数

(2)内循环每一轮比较的过程

publicclassArrayReview9 {

publicstaticvoidmain(String[] args) {

int[] arr= {8,6,2,4,9,1};

/*

目标:从小到大

总思路:相邻元素比较,如果前面的元素 比 后面的元素 大,就交换它们,

n个元素需要比较n-1轮,每一轮都可以从第一个元素开始,每一轮已经排好序的元素可以不用参与了。

步骤:

(1)外循环控制轮数

(2)内循环每一轮比较的过程

*/

/*

arr.length = 6,元素下标范围[0,5]

int i = 1,2,3,4,5

*/

for (inti=1; i<arr.length; i++) {

/*

i=1, j=0,1,2,3,4

arr[0]~arr[1]

arr[1]~arr[2]

arr[2]~arr[3]

arr[3]~arr[4]

arr[4]~arr[5]

i=2,j=0,1,2,3

arr[0]~arr[1]

arr[1]~arr[2]

arr[2]~arr[3]

arr[3]~arr[4]

本轮 arr[5]没有参与

i=3,j=0,1,2

i=4,j=0,1

i=5,j=0

前后元素:arr[j] 与 arr[j+1]

*/

for (intj=0; j<arr.length -i; j++) {

if(arr[j] >arr[j+1]){

inttemp=arr[j];

arr[j] =arr[j+1];

arr[j+1] =temp;

}

}

}

for(inti=0; i<arr.length; i++){

System.out.println(arr[i]);

}

}

}

4.3.7 选择排序

目标:从小到大

总思路:找出每一轮未排序元素的最小值,让它去到它应该在的位置。

步骤:

(1)外循环:控制轮数,n个元素依然是n-1轮

(2)内循环

A:先找出本轮的未排序元素的最小值及其现在的下标

第一轮:查找最小值的范围[0, arr.length-1]

第二轮:查找最小值的范围[1, arr.length-1]

....

B:如果它没有在它应该在的位置,就交换

第一轮,它应该在 [0]位置

第二轮,它应该在 [1] 位置

....

publicclassArrayReview10 {

publicstaticvoidmain(String[] args) {

int[] arr= {8,6,2,4,9,1};

/*

目标:从小到大

总思路:找出每一轮未排序元素的最小值,让它去到它应该在的位置。

步骤:

(1)外循环:控制轮数,n个元素依然是n-1轮

(2)内循环

A:先找出本轮的未排序元素的最小值及其现在的下标

第一轮:查找最小值的范围[0, arr.length-1]

第二轮:查找最小值的范围[1, arr.length-1]

....

B:如果它没有在它应该在的位置,就交换

第一轮,它应该在 [0]位置

第二轮,它应该在 [1] 位置

....

*/

for (inti=0; i<arr.length-1; i++) {

intmin=arr[i];

intindex=i;

for (intj=i+1; j<arr.length; j++) {

if(arr[j] <min){

min=arr[j];

index=j;

}

}

if(index!=i){

//交换arr[i] 与 arr[index]

inttemp=arr[i];

arr[i] =arr[index];

arr[index] =temp;

}

}

for(inti=0; i<arr.length; i++){

System.out.println(arr[i]);

}

}

}

4.4 二维数组

二维数组的声明:

元素的类型[][] 数组名;

例如:

int[][] arr; //推荐写法

intarr[][]; //也是对的

int[] arr[];//也是对的

二维数组的静态初始化:

元素的类型[][] 数组名= {{第一行的元素}, {第二行的元素},。。。。};

//如果声明和静态初始化不能在一句完成

元素的类型[][] 数组名;

数组名=new元素的类型[][]{{第一行的元素}, {第二行的元素},。。。。};

二维数组的动态初始化:

//每一行的列数是完全相同的,矩阵

元素的类型[][] 数组名=new元素的类型[总行数][每一行的列数];

例如:

abcde

fghij

zzzzz

每一行都是5个元素

元素的类型[][] 数组名=new元素的类型[3][5];

元素的类型[][] 数组名=new元素的类型[总行数][];

数组名[行下标] =new元素的类型[该行的列数];

//每一行的列数是不同的

例如:

abc

fghij

zzzzzhtgd

mn

元素的类型[][] 数组名=new元素的类型[4][];

数组名[0] =new元素的类型[3];

数组名[1] =new元素的类型[5];

数组名[2] =new元素的类型[9];

数组名[3] =new元素的类型[2];

第一行的元素:数组名[0][0]、数组名[0][1]、数组名[0][2]

第二行的元素:数组名[1][0]、数组名[1][1]、数组名[1][2]、数组名[1][3] 、数组名[1][4]

....

二维数组的遍历:

for(inti=0; i<二维数组名.length; i++){

for(intj=0; j<二维数组名[i].length; j++){

二维数组名[i][j]代表元素

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值