算法笔记

1、java集合教程

     算法的时间复杂度和空间复杂度详解

2、java运算符 与(&)、非(~)、或(|)、异或(^)

3、对于逆序处理应该首先想到栈  

【Java】Java双端队列Deque使用详解       【Java】Java队列Queue使用详解

4、异或运算符^

异或运算有以下三个性质。

  1. 任何数和 00 做异或运算,结果仍然是原来的数,即  a^0=a。
  2. 任何数和其自身做异或运算,结果是 00,即 a^a=0。
  3. 异或运算满足交换律和结合律,即 a^b^a=b^a^a=b^(a^a)=b^0=b。

5、数据重复问题,考虑使用set(set中元素是唯一的)

Java集合中List,Set以及Map等集合体系详解(史上最全) 

     java集合超详解

Java集合容器面试题(2020最新版) 笔记

6、ArrayList和LinkedList区别

时间复杂度

查询

对于存储相同列表的ArrayList和LinkedList来说,ArrayList内部的实现是基于对象数组,而LinkedList是基于指针的双向链表,ArrayList的查询是基于二分查找算法,LinkedList是不支持快速随机访问。所以,查询,ArrayList的速度是快鱼LinkedList的

插入和删除

当有元素插入和删除ArrayList时,该元素其后的元素都会进行移动,这就会造成移动会复制元素上的大量开销。相反的是,将元素插入或删除LinkedList只是简单的将该元素前后元素的next和previous节点进行修改即可

空间复杂度

LinkedList内部类是一个元素对象和上下节点,而ArrayList扩容是根据公式:新容量 = (旧容量*3 )/2 + 1,也就是每次容量大约会增加50%,如果用不完这50%,就会浪费很多空间。
所以,ArrayList在空间浪费上是大于LinkedList的。

7、判断单链表中是否有环,找到环的入口节点

8、.Android Studio 4.0 Run窗口中文乱码,terminal窗口git命令中文乱码解决办法

      android studio中文乱码各种情况的解决办法

9、岛屿类问题的通用解法、DFS 遍历框架

10、如何用栈实现队列功能以及如何用队列实现栈功能

11、深入学习二叉树(一) 二叉树基础

 二叉树,平衡二叉树,红黑树,B-树、B+树、B*树的区别

12、HashMap实现原理及源码分析

HashMap 是由数组和连表组成的,其中数组是HashMap的主体,连表是是为了解决hash冲突而存在的。

核心逻辑 数组下标N = F(key),其中F是hash算法,将key值计算为数组下标,如果多个key下标相同,则在相同位置后添加连表指向。

其中使用数据下标查找快的特点,解决查找问题,使用连表增删快的特点,处理增删问题。所以hash算法很重要,影响HashMap的效率。

HasHMap是线程不安全的,在迭代过程中,不能做数据的修改操作。

HashMap的扩容逻辑:

①HashMap对象中有四个重要参数参数

/**实际存储的key-value键值对的个数*/
transient int size;

/**阈值,当table == {}时,该值为初始容量(初始容量默认为16);当table被填充了,也就是为table分配内存空间后,
threshold一般为 capacity*loadFactory。HashMap在进行扩容时需要参考threshold,后面会详细谈到*/
int threshold;

/**负载因子,代表了table的填充度有多少,默认是0.75
加载因子存在的原因,还是因为减缓哈希冲突,如果初始桶为16,等到满16个元素才扩容,某些桶里可能就有不止一个元素了。
所以加载因子默认为0.75,也就是说大小为16的HashMap,到了第13个元素,就会扩容成32。
*/
final float loadFactor;

/**HashMap被改变的次数,由于HashMap非线程安全,在对HashMap进行迭代时,
如果期间其他线程的参与导致HashMap的结构发生变化了(比如put,remove等操作),
需要抛出异常ConcurrentModificationException*/
transient int modCount;

②HashMap有4个构造器,其他构造器如果用户没有传入initialCapacity 和loadFactor这两个参数,会使用默认值initialCapacity默认为16,loadFactory默认为0.75,initialCapacity最大为2的30次方

③在HashMap初始化时,是没有指定数组大小的,也就table数组为空,当执行put方法时,才使用initialCapacity和loadFactory扩展table数组。

put的代码:

public V put(K key, V value) {
        //如果table数组为空数组{},进行数组填充(为table分配实际内存空间),入参为threshold,
        //此时threshold为initialCapacity 默认是1<<4(24=16)
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
       //如果key为null,存储位置为table[0]或table[0]的冲突链上
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);//对key的hashcode进一步计算,确保散列均匀
        int i = indexFor(hash, table.length);//获取在table中的实际位置
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        //如果该对应数据已存在,执行覆盖操作。用新value替换旧value,并返回旧value
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;//保证并发访问时,若HashMap内部结构发生变化,快速响应失败
        addEntry(hash, key, value, i);//新增一个entry
        return null;
    }
  1. 判读是否需要扩展(table数组为空或者达到阀值)
  2. 判断key是否为空,如果为空方法哦table数组第一位或者第一位的冲突链上
  3. 对key的hashCode进一步计算,得到hash值,确保散列均匀
  4. 获取hash值在table中的位置table[i]。
  5. 遍历table[i],的连表,如果key值相同,覆盖原有value,如果没有相同的可以,添加到连表末尾,
  6. 如果添加后table的长度超过阀值,table数组增加一倍

为什么重写equal方法要重新hashCode方法

当使用对象作为key时,如果重写了equal方法,但是没有重新hashCode方法,在在存取比对key的hash值时,会认为key不一致,返回null

在重写equals的方法的时候,必须注意重写hashCode方法,同时还要保证通过equals判断相等的两个对象,调用hashCode方法要返回同样的整数值。而如果equals判断不相等的两个对象,其hashCode可以相同(只不过会发生哈希冲突,应尽量避免)

JDK1.8中HashMap的性能优化

假如一个数组槽位上链上数据过多(即拉链过长的情况)导致性能下降该怎么办?
JDK1.8在JDK1.7的基础上针对增加了红黑树来进行优化。即当链表超过8时,链表就转换为红黑树,利用红黑树快速增删改查的特点提高HashMap的性能,其中会用到红黑树的插入、删除、查找等算法。

什么时候扩容,扩容方法

当发生哈希冲突并且size大于阈值的时候,需要进行数组扩容,

扩容时需要新建一个长度为之前数组2倍的新的数组,

然后遍历当前table数组,通过hash值和新数组的长度,获取当前entry在新数组的位置,并添加到新数组中。

所以扩容相对来说是个耗资源的操作。

为什么会为原来的两倍,因为扩容时需要重新计算已有元素在新table数组的位置,并移动位置,按照位置计算的方法,如果是2的倍数扩容,得到的新的数组索引和老数组索引一致(大大减少了之前已经散列良好的老数组的数据位置重新调换),个人理解

 

Hash碰撞,解决方法

在计算Hash值时,多个key计算得到的Hash值相同,即为hash碰撞。

在hashMap中有一个hash值进一步处理的过程,让通过hash值计算出的数组位置尽量均匀,如果最后还是碰撞,即计算的数组位置相同,就在当了数组元素node连表后新增

13、Android Studio说:使用HashMap不如使用SparseArray?

SparseArray有两个优点:

1.避免了自动装箱(auto-boxing),

2.数据结构不会依赖于外部对象映射。HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置,存放的都是数组元素的引用,通过每个对象的hash值来映射对象。

其实一般来说,SparseArray执行效率比HashMap要慢一点,因为查找需要折半查找,而添加删除则需要在数组中执行。

虽说SparseArray性能比较好,但是由于其添加、查找、删除数据都需要先进行一次二分查找,所以在数据量大的情况下性能并不明显,将降低至少50%。 (它仅仅提高内存效率,而不是提高执行效率)
满足下面两个条件我们可以使用SparseArray代替HashMap:

  • 数据量不大,最好在千级以内
  • key必须为int类型,这中情况下的HashMap可以用SparseArray代替:

 

 17、超详细十大经典排序算法总结

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值