Android实习面试准备——数据结构与算法(一)

        目前准备冲击一下大厂的实习,现在开始刷面经,附上面经题目以及自己的一些答案,答案不是详细的代码,只是一些简要思路,算法方面关于时间和空间复杂度简单的就并没有附上去。如果有什么错误或者更好的答案,麻烦帮帮孩子,谢谢大佬们!!!

1、常用的数据结构

        线性:数组、链表、栈、队列(后面两种在C++中容器适配器,因为其底层实现可能是数组,也可能是链表)

        (1)数组:内存中连续存储多个元素,数组元素通过下标索引,下标从0开始;优点:查找是O(1)的复杂度,速度快

        缺点:数组大小固定且不能扩容;只能存储一种类型的数据;删除添加是O(n)的复杂度

        适用:频繁查找的场景,很少进行删除添加操作;对存储空间要求不高

        (2)链表:物理存储上非连续、非顺序的存储结构,数据的逻辑顺序是通过链表的指针地址来实现的,每个结点包含两个部分,一个是存储元素的数据域,一个是存储下一个结点地址的指针域。有单链表、双向链表、循环链表

        优点:添加删除是O(1)的复杂度

        缺点:因为含有大量指针域,占用空间大;查找慢,是O(n)的复杂度

        适用:数据量小;需要频繁的添加删除

        (3)栈:特殊的线性表,先进后出,栈顶放入元素叫入栈,栈顶取出元素叫出栈。

        适用:实现递归功能

        (4)队列:特殊的线性表,先进先出,一端添加元素,另一端取出

        适用:多线程阻塞队列管理

        (5)散列表:根据键值对来存储访问

        二维:树、图、堆

        (1)树:n个有限结点组成的有层次关系的集合。有二叉树(结点度最大为2)、红黑树、B+树

        (2)堆:总是一颗完全二叉树;结点的值总是不大于或不小于父节点的值

        (3)图:由结点的有穷集合V和边的集合E组成

2、数组

        (1)如何在一个1到100的整数数组中找到丢失的数字

        这里我的思路是:先询问丢失的数字是一个还是多个,再问数组是否排序

        若丢失的数字是一个:

        a. 无论排序与否都通用的数学方法:采用(n+1)*n/2算出1~100的和,再遍历累加数组,得到的两个数相减,就是丢失的那一个

        b. 若是排序数组的话:

        采用二分查找法:直到找到下标为mid的数组元素的值不等于mid+1,而其前一个元素满足

        遍历查找:直到找到nums[i] != i + 1的数组元素,将nums[i] - 1,得到的就是

        c. 若是未排序数组的话

        可以先排序再采用以上的方法,这是O(n*logn)的时间复杂度,根据相应的排序算法,还可能有O(logn)的空间复杂度,排序相关的内容之后再总结

        使用hash表,需要O(n)的辅助空间,时间复杂度是O(n)

        使用位运算(具体可以去leecode搜一下丢失的数字这个题)

        

        若丢失的数字是多个:

        采用BitSet(可以去查一下java的源码),询问是否可以直接使用java中的API,不然自己实现set方法和get方法(我这里来个简要版本,实现思路差不多,细节上有一些不一样)

   /**
     *BitSet的思路其实就用一个bit位表示这个数存不存在
     * 0代表不存在,1代表存在
     * 比如数字2要是在,那么就为0010
     * 数字5要是存在,就是10000
     * 其实实现上就是 1 >> (number-1)
     */
    private long[] words = new long[2]; //因为最多到100,我就直接这么初始化了
    public void set(int bitIndex) {
        int wordIndex = bitIndex >> 6; //其实就是除以64,确认数组中哪一个64位的元素上
        words[wordIndex] |= 1L >> (bitIndex-1);
    }
    
    public boolean get(int bitIndex) {
        int wordIndex = bitIndex >> 6;
        return (words[wordIndex] & (1L << bitIndex-1)) != 0;
    }

        (2)如何在给定的整数数组中找到重复的数字  

        询问重复的数字有几个,是找出任意一个,还是所有

        给定的什么样的整数数组,是个什么数字范围(是都在某个范围中,还是随机)

        是否排序过(这个肯定是没排序过,要是排序了可太容易了)

        通用方法:先排序再遍历;用hash表存起来,再遍历hash表        

        若给定的数组都在某个范围中,例如n+1个数字,都在1~n内

        a. 原地置换法(这是剑指offer上的题),其实就是swap(nums[i], nums[nums[i]]),但这个方法会修改数组

        b. 不会修改数组的方法:

            采用O(n)的辅助空间,把数字一个一个复制过来并判断

            二分查找 + 计数,例如[2, 3, 5, 4, 3, 6, 7, 2],中间是4,那么就扫一遍数组,计算1~4中有几个数字,这里有5个,那么重复的数字就在这里,4再分为1~2和3~4,3~4有三个数字,统计3和4在数组中出现的次数。但这个方法是有缺陷的,没有办法找到所有重复数字,并且最差的情况下是一个都找不到,例如[2, 3, 5, 4, 3, 6, 7, 8]。这是O(n*logn)的时间复杂度

             

        若是随机的数字:我能想到的只有BitSet了,每次set前,get一下,看看是不是为1,是的话就重复了,不是就set为1

        (3)如何在未排序的整数数组中找到最大值和最小值

        这题我脑子里能想到的只有设置max和min变量,遍历数组不断比较,始终保存那个较大的和较小的

        (4)在Java中如何从给定数组中删除多重复项

        先询问数组是不是排序的

       是在原数组上删除,直接返回原数组;还是返回一个新的数组

        a. 先排序,若直接返回原数组,采用快慢指针法,参考leecode27,差不多的意思;

        b. 要是返回新数组,可以排序后,复制到新的数组;也可以不排序,遍历数组放到hash表里,将hash表的key导出来就可以了,这个方法的时间复杂度是O(n),排序后复制也需要辅助空间,并且时间复杂度平均是O(n*logn)

        (5)大数加法

大数加法_牛客题霸_牛客网刷一下这个题就可以,就是按位相加,带上之前的进位

你可能感兴趣的:(android,面试,数据结构)