链表基本操作题
1. 链表反转
// 3指针,原地反转
/** * 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) { ListNode* pre = NULL, *cur = head, *nxt = NULL; while(cur) { nxt = cur->next; cur->next = pre; pre = cur; cur = nxt; } return pre; } };
2. 翻转链表m到n的结点
要求一次遍历完成(leetcode92)
Node* reverseBetween(Node* head, int m, int n) { Node h(0); h.next = head; //设置一个头节点,处理m=1的情况 Node* p = &h; Node* tail; for(int i = 1; i <= n; i++) if(i < m) // p指向第n-1个节点位置 p = p->next; else if(i == m) // tail指向第第n个节点,这个节点反转后处在反转部分的最后一个 tail = p->next; else { //每次将tail后面一个节点拿出来,放在p后面,即头插法 Node* item = tail->next; tail->next = tail->next->next; item->next = p->next; p->next = item; } return h.next; }
3. 两个链表相加(leetcode2)
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode vhead(0), *p = &vhead; int carry = 0; while(l1 || l2 || carry) { int tmp = carry; if(l1 != NULL) tmp += l1->val; if(l2 != NULL) tmp += l2->val; carry = tmp / 10; tmp %= 10; ListNode* next = l1 ? l1 : l2; // 交错 if(next == NULL) next = new ListNode(tmp); // 进位 next->val = tmp; p->next = next; p = p->next; l1 = l1 ? l1->next : NULL; l2 = l2 ? l2->next : NULL; } return vhead.next; }
4. 求链表中的倒数第K个节点
一种直观的思路是先遍历链表得到链表的长度,然后第二次遍历就能找到第k个节点,但是需要进行两次遍历,不是好的方法;
这里使用两个指针实现一次遍历,第一个指针先走k-1步,第二个指针一直不动;然后两个指针同时移动,知道第一个指针遍历完成。因为两个指针间隔为k-1,所以第二个指针指向的节点即为倒数第k个节点。
————————————————
版权声明:本文为CSDN博主「大树先生的博客」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Koala_Tree/article/details/79011152
ListNode* getKthFromEnd(ListNode* head, int k) { ListNode* p1 = head, *p2 = head; for(int i = 0;i < k-1;i++) p2 = p2->next; while(p2->next) { p1 = p1->next; p2 = p2->next; } return p1; }
5. 判断两个链表是否相交 leetcode160
思路一:最简单的先遍历一遍得到lenA, lenB,让长的先走掉差,再 同步走
思路二:先两者同时走,先到null的去另一条,两者再走掉差,此时长的也到null了改去另一条,此时剩下的长度相同。
思路三:将其中一条首尾相连,转化成了找环的入口
// 思路二 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode* pa = headA, *pb = headB; while(pa != pb) { pa = pa == NULL ? headB : pa->next; pb = pb == NULL ? headA : pb->next; } return pa; }
5. 头插法和输出
#include<bits/stdc++.h> using namespace std; typedef struct Node { int val; Node* next; Node(int _val=0):val(_val), next(NULL){} }Node; // 构建链表 // 头插法 Node* insert(Node* head, int val) { Node* p = (Node*)malloc(sizeof(Node)); p->val = val; p->next = head; head = p; return head; } // 遍历链表 void print(Node* head) { Node* p = head; while(p) { printf("%d ", p->val); p = p->next; } } // 逆序输出 void print_r(Node* head) { if(head == NULL) return; if(head->next == NULL) { printf("%d ", head->val); return; } print_r(head->next); printf("%d ", head->val); } // 求倒数第k个节点 void Kth_r(Node * head, int k) { Node *p = head, *p2 = head; for(int i = 0;i < k;i++) p = p->next; printf("p: %d\n", p->val); while(p != NULL) { p = p->next; p2 = p2->next; } printf("p2: %d\n", p2->val); } int a[] = {1, 2, 3, 4, 5}, n = 5; int main() { Node* head = (Node*)malloc(sizeof(Node)); head->next = NULL, head->val = a[0]; int i = 1; while(i < n) { head = insert(head, a[i]); i++; } print_r(head); printf("\n"); Kth_r(head, 2); return 0; }
个性签名:时间会解决一切