链表
链表的数据结构体:
struct node{ int data; node* next; node(int data = 0):data(data), next(0){} };
链表反转:设置三个指针,从前往后扫。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode * reverseList(ListNode *head) { if(head == NULL || head->next == NULL) return head; ListNode *p1 = head, *p2 = p1->next; p1->next = NULL; while(p2) { ListNode *p3 = p2->next; p2->next = p1; p1 = p2; p2 = p3; } return p1; } };
反转中间某段:
Leetcode25. Reverse Nodes in k-Group
另起一个函数反转中间某段,注意指针为引用型。翻转的时候,依然需要三个指针。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: void inv(ListNode *&start, ListNode *&end){//reverse the node from start to end ListNode *p = start, *m = p->next, *q = m->next; start->next = end->next; while(m != end){ m->next = p; p = m; m = q; q = q->next; } m->next = p; swap(start, end); } ListNode* reverseKGroup(ListNode* head, int k) { if(k < 2) return head; ListNode *p1 = head, *p2 = NULL; for(int i = 1; i < k&&p1 != NULL; i++) p1 = p1->next; if(p1 == NULL) return head; p2 = p1->next; inv(head, p1); while(true){ p2 = p1->next; for(int i = 1; i < k&&p2 != NULL; i++) p2 = p2->next; if(p2 == NULL) return head; inv(p1->next, p2); p1 = p2; } } };
——————————————————————————————————————
其他
问题1:删除不知头结点链表的某个节点
如果单向链表不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?
思想为:把这个节点的下一个节点的值复制给该节点,然后删除下一个节点即可。
问题2:怎么判断链表中是否有环?
思想为:设置两个指针,一个步长为1,另一个步长为2,依次后移,如果相遇且都不为空,则有环。
问题3:如果一个单向链表,其中有环,怎么找出这个链表循环部分的第一个节点?
思想为:假设该节点在x位置处,假设步长为1的指针和步长为2的指针相遇在x处,
那么当一个指针再从头节点处以步长1递进时,另一指针从x点以步长1递进时,两个指针就会在循环开始处相遇。
简单证明:显然步长为2的指针多跑了k*循环长,而步长2跑的路程是步长1的两倍,则步长1跑了k*循环长。那么头节点和x节点离循环开始处距离相同。
问题4:如何查找链表中倒数第k个节点?
思想为:两个指向头结点的指针,一个先向后移动k位,然后两个同时向后面移动直到一个节点到达链尾,前面一个指针的位置就是了。
问题5:两个有序链表如何合并?
思想为:设两链表为La,Lb,设三指针pa,pb,pc。其中pa、pb指向两链表当前比较插入的结点,pc指向合并的链表的最后一个结点(初始状态可直接将其中一个链表 La 的头结点作为合并链表的尾结点)。
问题6:编程序判断两个链表是否相交。
如何知道两个单链表(无环)是否相交
如果两个单链表(无环)相交,如何知道它们相交的第一个节点是什么
如何知道两个单链表(有环)是否相交
如果两个单链表(有环)相交,如何知道它们相交的第一个节点是什么
这个问题的精彩解说请参见《编程之美》一书之《编程判断两个链表是否相交》,这里就不写了,该书的pdf文档在网上很好下。
文章后面给了两个扩展问题:
(1)如果链表可能有环,如何做判断?
思想为:首先应该明白,只有一个链表有环的情况下是不会相交的,只有都有环或者都没有环的情况下才可能相交,都没有环的情况下最简便的方法就是判断链尾是否相交即可;都有环的情况下,分别找到环上的任一点,一个不动,另一个步进,即可判断是否相交。
(2)如何求相交链表的第一个节点?应该为单链表情况
思想为:方法一是先把任一个链表连成环,即从表尾接到表头,按照问题4的解法;方法二是计算两个链表的长度,而两个链表是按照尾部对齐的,那么从短链表的第一个位置从长链表的第长度差+1的位置依次比较指针值,相等的位置即是。
关于链表的排序
O(n^2)算法从前往后扫,交换结点内的值。
O(nlogn)算法,O(1)插入删除(排序的时候,比参考点小,直接插入头节点前,否则插入尾节点后)。