博客
关于我
数据结构之数组与经典面试题(二)
阅读量:366 次
发布时间:2019-03-05

本文共 10158 字,大约阅读时间需要 33 分钟。

1、定义

所谓数组,是有序的元素序列。
若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便,
把具有相同类型的若干元素按无序的形式组织起来的一种形式。这些无序排列的同类数据元素的集合称为数组。int 的数组你就不能存float
也不能存double。数组是用于储存多个相同类型数据的集合。通常用Array表示,也称之为线性表,画图演示
在这里插入图片描述

2、特点

(1)数组是相同数据类型的元素的集合。 (2)数组中的各元素的存储是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起。内存地址
(3)数组元素用整个数组的名字和它自己在数组中的顺序位置来表示。例如,a[0]表示名字为a的数组中的第一个元素,a[1]代表数组a的第二个元素,以此类推,

(4)随机访问(查找)
数组是连续的内存空间和相同类型的数据。正是因为这两个限制,它才有了一个非常重要的特性:随机访问。但有利就有弊,这两个限制也让数组的很多操作变得非常低效,比如要想在数组中删除、插入一个数据,为了保证连续性,就需要做大量的数据搬移工作。
(5)数组的缺点:插入和删除 实现代码:
设数组的长度为n,现在,如果我们需要将一个数据插入到数组中的第k个位置。删除第N个位置的数据.那么需要移动删除和插入后面的数组元素
(6)使用数组一定要注意访问越界问题;所以一定要多加判断,尤其是在开始和结束。测试的时候也一样注意头和尾。

3.表现形式

(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

4、ArrayList和数组

本质是一样的,都是数组。ArrayList是JDK封装了。不需要管扩容等操作;数组的话就要你全部操作 两者选择:
不知道数据大小的肯定选ArrayList。
如果你知道数据的大小而且你又非常关注性能那就用数组。

5、二维数组的内存地址是怎么样的?写出寻址公式?

一维: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个。=> i
n(一维的长度)+j(在列
)=>13+0=3 a[i][j]: (i<n,j<m) loc=init_loc+(in+j)*size

6、总结:

数组是一个最基础最简单的数据结构,必须要完全搞懂。它是存储相同类型的一组数据,最大的两个特点就是下标和随机访问。缺点就是插入和删除是很慢的,时间复杂度为O(n)。

7、经典面试

7.1 、例子:手写ArrayList
/** * @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/

你可能感兴趣的文章
Deep residual learning for image recognition
查看>>
IO控制方式
查看>>
IO控制器
查看>>
Java 异常
查看>>
BP神经网络学习--MATLAB源码详细注释
查看>>
LeetCode122.买卖股票的最佳时机2Golang版
查看>>
还在花冤枉钱找人做电子签名?看这儿,教你制作纯手写电子签名
查看>>
Java 知识点总结篇(2)
查看>>
Python 知识点总结篇(2)
查看>>
Python 知识点总结篇(3)
查看>>
Numpy 如何操作数组
查看>>
Win10 环境下安装压缩包版本 MySQL-8.0.13
查看>>
爬取网易科技滚动新闻
查看>>
vuex modules
查看>>
vue父子组件传参的4种方式
查看>>
中缀表达式转后缀表达式
查看>>
Java笔记:单链表
查看>>
Java基础题:小根堆为8,15,10,21,34,16,12,删除关键字8之后需重建堆,需要的比较次数为?
查看>>
phthon基本语法——温习
查看>>
sleep、wait、yield、join——简介
查看>>