散列表:
就像 字典的ABCD...Z的索引一样,它的索引是通过哈希函数计算的。到索引位置后,可以再通过链表、数组或者其他方式存数据。
链表特点:
涉及到索引角标的增删改查操作,都需要先查到元素,然后才可以做其他操作,这种操作的复杂度是O(N);
链表一般会定义头尾指针,头尾的增删很方便,很适合用于实现队列(只有首尾操作)。
链表由于可以头插入和尾插入等等,所以实现逆序很方便,只需要遍历并进行依次头插入即可实现反转链表,也可以通过反转指针实现。
1 public void reverse() { 2 // temp 和next的位置像斐波那契一样在依次向后移动 3 Node temp = first; 4 last = first; 5 Node next = temp.getNext(); 6 for(int i = 0; i < size - 1; i++) { 7 Node nextNext = next.getNext(); 8 next.setNext(temp); 9 temp = next; 10 next = nextNext; 11 } 12 first = temp; 13 last.setNext(null); 14 }
动态链表:动态创建,长度不需要提前定死
静态链表:用数组模拟链表,数组内放包含数据和角标的对象,角标就代表着指针一样,主要用于不包含指针,引用的语言实现链表,不常用。
递归的空间复杂度:
若一个算法为递归算法,其空间复杂度为递归所使用的堆栈空间的大小,它等于一次调用所分配的临时存储空间的大小乘以被调用的次数。这个理解对吗?
快排的空间复杂度为o(logn)(最差为o(n)),这个我还能说得通。但归并排序的的栈的深度是确定的logn,每层都要申请大小为n的空间存储归并后的序列,为什么空间复杂度是o(n),而不是o(nlogn)?
这个是实现上的优化。你可以从始至终都只用一个O(N)的存储空间。每层递归都在这一个空间上做操作。而不是每层递归都去创建一个新的数组/vector/list....