1.查找单链表的倒数第K个节点
- 设置两个指针(一个记为快指针,一个记为慢指针),都先指向头节点
- 让快指针先走k-1步
- 快、慢指针都一步一步往下走,知道快指针为空,慢指针所在位置就是K节点所在位置
struct ListNode* FindKthToTail(struct ListNode* PListHead, unsigned int k) {
if (PListHead == NULL) { return null; }
struct ListNode *front = PListHead;
struct ListNode *back = PListHead;
//让前面的先走k-1步
for (int i = 0; i < k-1; i++) {
front = front->next;
}
while (front != NULL) {
front = front->next;
back = back->next;
}
return back;
}
2.在一个排序的链表中,删除该链表中重复的结点,重复的结点不保留,返回链表头指针
- 先设置3个指针,prev指向头节点、p1也指向头节点,p2指向头节点的下一个节点
- 比较p1和p2的值是否相等,若不相等,则三个指针都往后走一步;若相等,则p2指针往后走一步,其他两个指针不动,直到p2指针走到下一个不相等的位置。
- 删重复节点(p1到p2指针指向的前一个节点都是重复的)
- 设置一个节点,它的一个地址的指向为头节点(因为若头节点也是重复节点,早被删除)
struct ListNode* deleteDuplication(struct ListNode* pHead) {
if (pHead == NULL) { return NULL; }
struct ListNode *fake = (struct ListNode *)malloc(sizeof(struct ListNode));
fake->next = pHead;//假结点
struct ListNode *prev = fake;
struct ListNode *p1 = pHead;
struct ListNode *p2 = pHead->next;
while (p2 != NULL) {
if (p1->val != p2->val) {
prev = p1; p1 = p2; p2 = p2->next;
}
else {
while (p2 != NULL && p2->val == p1->val) {
p2 = p2->next;
}
struct ListNode *cur = p1;
while (cur != p2) {
struct ListNode *next = cur->next;
free(cur);
cur = next;
}
prev->next = p2;
p1 = p2;
if (p2 != NULL) { p2 = p2->next; }
}
}
pHead = fake->next;
free(fake);
return pHead;
}
3.找两个单链表的交点
- 先求两个链表相差的长度。
- 设置两个指针(快、慢指针问题)
- 快指针先走相差的长度-1步,如果快、慢指针不相等,则快、慢指针各往后走一步
- 返回快指针
int getLength(struct ListNode *head) {
int len = 0;
for (struct ListNode *n = head; n; n = n->next) {
len++;
}
return len;
}
struct ListNode* getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int lenA = getLength(headA);
int lenB = getLength(headB);
struct ListNode *longer = headA;
struct ListNode *shorter = headB;
int diff=lenA - lenB;
if (lenB > lenA) {
longer = headB;
shorter = headA;
diff = lenB - lenA;
}
for (int i = 0; i < diff; i++) {
longer = longer->next;
}
while (longer != shorter) {
longer = longer->next;
shorter = shorter->next;
}
return longer;
}
4.复杂链表的复制
一个链表的每个结点,有一个指向next指针指向下一个结点,还有一个random指针指向这个链表的随机结点或者NULL,返回复制后的新链表。
定义复杂链表的结构
typedef struct RNode {
int val;
struct RNode *next;
struct RNode *random;
}RNode;
RNode* Copy(RNode* head) {
//1.只复制结点中的value和next,让新结点跟在老结点后边
//2.再处理random复制
//3.把链表拆成两个
if (head == NULL) { return NULL; }
RNode *oldNode = head;
while (oldNode != NULL) {
RNode *newNode = (RNode*)malloc(sizeof(RNode));
newNode->val = oldNode->val;
RNode *oldNext = oldNode->next;
newNode->next = oldNext;
oldNode->next = newNode;
oldNode = oldNext;
oldNode = head;
while (oldNode != NULL) {
RNode *newNode = oldNode->next;
if (oldNode->random == NULL) {
newNode->random = NULL;
}
else {
newNode->random = oldNode->random->next;
}
oldNode = newNode->next;
}
oldNode = head;
newNode = head->next;
while (oldNode != NULL) {
RNode *newNode = oldNode->next;
oldNode->next = newNode->next;
if (newNode->next != NULL) {
newNode->next = newNode->next->next;
}
oldNode = oldNode->next;
}
return newNode;
}
}