都说不会算法的只能算是个CRUD工具人,而学会算法,不仅能提高解题思路,培养逻辑思维,也是提高自己的必经之路。
况且要去中大型公司,笔试总免不了手撕算法题。
本系列将把自己解题的过程和思路记录下来,也是提高自己算法能力的一种方式。
尼尧的算法日记:相交链表/环形链表(LeetCode 160/141)
相交链表/环形链表的情形
- 相交链表
以下为单链链表存在相交的实例,编写一个程序,找到两个单链表相交的起始节点。(LeetCode.160 相交链表)
- 环形链表
存在单链表中尾部节点接到链表中某个节点,形成环状,写一个程序判断是否存在环。(LeetCode.141 环形链表)
解题思路
这两道题难度系数都是简单。
他们存在共通性,都可以用Hash表法解出。
然后也可以用双指针法,但是他们的双指针法有一点区别。
Hash表法
Hash表法的思想是利用Hash运算的原理,将引用/地址存在Hash上,由于Hash运算的特性,对已经存在对象的引用进行比较,即可得出结果。
我们这里可以用HashMap/HashSet来做个辅助,HashSet底层其实就是HashMap(将实际值存在key上,value上存PRESENT对象,由于key相等就会覆盖,就保证了元素不重复)。
来看看HashMap的Hash函数;
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
//即key.hashCode() ^ (key.hashCode()>>>16)
}
其中 ^ 即异或运算,>>> 右移运算,它们两个都是二进制的位运算。
十进制转换为二级制:给定的数循环除以2,直到商为0或者1为止。将每一步除的结果的余数记录下来,然后反过来就得到相应的二进制了。
举个栗子: 11 的 二进制为 1011
11/2 = 5 余1
5/2 = 2 余1
2/2 = 1 余0
1/2 = 0 余1
即二进制等于余数倒过来:1011
- 位异或运算(^)
运算规则是:两个数转为二进制,然后从高位开始比较,如果相同则为0,不相同则为1。
举栗子:2^11 = 9
2的二进制:10 11的二进制:1011
0010
^ 1011
= 1001 =