22.1.9 链表
1. 哈希表
1)哈希表在使用层面上可以理解为一种集合结构
2)如果只有key,没有伴随数据value,可以使用HashSet结构(C++中叫UnOrderedSet)
3)如果既有key,又有伴随数据value,可以使用HashMap结构(C++中叫UnOrderedMap)
4)有无伴随数据,是HashMap和HashSet唯一的区别,底层的实际结构是一回事 5)使用哈希表增(put)、删(remove)、改(put)和查(get)的操作,可以认为时间复杂度为 O(1),但是常数时间比较大
6)放入哈希表的东西,如果是基础类型,内部按值传递,内存占用就是这个东西的大小
7)放入哈希表的东西,如果不是基础类型,内部按引用传递,内存占用是这个东西内存地 址的大小(8bits)
-
code:
public static void main(String[] args)
{
HashSet<Integer> hs = new HashSet<>();
hs.add(3);
hs.add(4);
System.out.println(hs.contains(3)) ;
hs.remove(3);
System.out.println(hs.contains(3)) ;
HashMap<Integer,String> hm = new HashMap<>();
hm.put(1,"Tx");
hm.put(2,"Zmy");
System.out.println(hm.get(1)) ;
System.out.println(hm.containsKey(1)) ;
System.out.println(hm.containsValue("zmy")) ;
hm.put(1,"Xt");//put函数可以用来修改hashmap中的值
System.out.println(hm.get(1)) ;
System.out.println(hm.containsKey(1)) ;
}
-
运行结果:
true
false
Tx
true
false
Xt
true
2. 有序表
有序表的概念:
1)有序表在使用层面上可以理解为一种集合结构
2)如果只有key,没有伴随数据value,可以使用TreeSet结构(C++中叫OrderedSet)
3)如果既有key,又有伴随数据value,可以使用TreeMap结构(C++中叫OrderedMap)
4)有无伴随数据,是TreeSet和TreeMap唯一的区别,底层的实际结构是一回事 5)有序表和哈希表的区别是,有序表把key按照顺序组织起来,而哈希表完全不组织
6)红黑树、AVL树、size-balance-tree和跳表等都属于有序表结构,只是底层具体实现 不同
7)放入哈希表的东西,如果是基础类型,内部按值传递,内存占用就是这个东西的大小
8)放入哈希表的东西,如果不是基础类型,必须提供比较器,内部按引用传递,内存占 用是这个东西内存地址的大小
9)不管是什么底层具体实现,只要是有序表,都有以下固定的基本功能和固定的时间复 杂度
有序表的基本操作
1)void put(K key, V value):将一个(key,value)记录加入到表中,或者将key的记录 更新成value。
2)V get(K key):根据给定的key,查询value并返回。
3)void remove(K key):移除key的记录。
4)boolean containsKey(K key):询问是否有关于key的记录。
5)K firstKey():返回所有键值的排序结果中,最左(最小)的那个。
6)K lastKey():返回所有键值的排序结果中,最右(最大)的那个。
7)K floorKey(K key):如果表中存入过key,返回key;否则返回所有键值的排序结果中, key的前一个。
8)K ceilingKey(K key):如果表中存入过key,返回key;否则返回所有键值的排序结果中, key的后一个。 以上所有操作时间复杂度都是O(logN),N为有序表含有的记录数
-
code:
TreeMap<Integer, String> treeMap1 = new TreeMap<>();
TreeSet<类对象> treeSet = new TreeSet<>(new NodeComparator);//需要自己提供比较器。
3. 单链表
-
单链表的节点结构
Class Node
{
V value;
Node next;
}
由以上结构的节点依次连接起来所形成的链叫单链表结构。
-
双链表的节点结构
Class Node
{
V value;
Node next;
Node last;
}
由以上结构的节点依次连接起来所形成的链叫双链表结构。
面试时链表解题的方法论
1)对于笔试,不用太在乎空间复杂度,一切为了时间复杂度
2)对于面试,时间复杂度依然放在第一位,但是一定要找到空间最省的方法 重要
技巧:
1)额外数据结构记录(哈希表等)
2)快慢指针
//快慢指针核心代码;
Node n1 = head;
Node n2 = head;
while(n2.next !=null && n2.next.next!=null)
{
n1 = n1.next;
n2 = n2.next.next;
}
//慢指针走一步,快指针走两步
//调好快慢指针后再进行需求操作。
-
example:
-
利用快慢指针判断单链表是否有环,并返回环的第一个节点:
-
思想:快指针每次走两步,慢指针每次走一步,若快慢指针第相遇,则说明这个单链表有环,然后快指针回到头结点的位置,快指针每次走一步,慢指针每次也走一步,快慢指针再次相遇的位置就是环的第一个节点。
-
注意:单链表只有一个next指针,也就是说节点后面只会跟一个节点。
-
Node n1 = head;
Node n2 = head;
while(n1 != n2)
{
if(n2.next.next == null || n2.next == null)
return null;//没有环
n2 = n2.next.next;
n1 = n1.next;
}
n2 = head;
while(n2 != n1)
{
n2 = n2.next;
n1 = n1.next;
}//当n1和n2相遇循环结束
return n1;