目录
两数相加
题目
分析
相加并不难,难点在于处理进位和链表长度不一致的问题
- 可以在统一相加后继续单独处理长链表,但这样有点麻烦,所以可以将两条链表视作相同长度
- 当某条链表遍历到尾后,可以将后续处理时拿到的数值看作0,这样就不会影响相加的结果
- 因为可能在最高位有进位,所以可能需要多增加一个结点(也就是多经历一次循环)
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode *head = nullptr, *tail = nullptr; int flag = 0; while (l1 || l2 || flag) { int a = l1 ? l1->val : 0, b = l2 ? l2->val : 0; l1 = l1 ? l1->next : nullptr; l2 = l2 ? l2->next : nullptr; int sum = a + b + flag; flag = sum / 10; ListNode* node = new ListNode(sum % 10); if (head == nullptr) { head = tail = node; } else { tail->next = node; tail = tail->next; } } return head; } };
相交链表
题目
分析
其实就是一个数学题
- 是力扣的官解捏,写的很详细
总之这两个遍历的指针无论什么情况最终都会相等,为null / 指向相交结点
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if(headA==nullptr || headB==nullptr){ return nullptr; } ListNode* pa=headA,*pb=headB; while(pa!=pb){ pa=(pa==nullptr)?headB:pa->next; pb=(pb==nullptr)?headA:pb->next; } return pa; } };
回文链表
题目
分析
回文嘛,只要从头尾往中间遍历判断数值是否相等就好了
- 因为原结构是单链表,不方便逆序遍历,所以可以借助数组先把数值存放起来
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: bool isPalindrome(ListNode* head) { vector<int> base; ListNode* tmp = head; while (tmp) { base.push_back(tmp->val); tmp = tmp->next; } int i = 0, j = base.size() - 1; while (i < j) { if (base[i] != base[j]) { return false; } ++i;--j; } return true; } };
排序链表
题目
分析
因为它的进阶要求需要nlogn和常数空间,所以可以借助归并排序
- 先将链表不断切分成两段,直到切分为单个结点为止
- 再以合并两个有序链表的逻辑进行合并 -- 1合2,2合4....,最终返回的指针就是我们的新头结点
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { ListNode* cut(ListNode* head) { ListNode *slow = head, *fast = head, *pre = nullptr; while (fast && fast->next) { pre = slow; slow = slow->next; fast = fast->next->next; } pre->next = nullptr; return slow; } ListNode* merge(ListNode* h1, ListNode* h2) { ListNode *head = nullptr, *tail = nullptr; if (h1->val < h2->val) { head = h1; h1 = h1->next; } else { head = h2; h2 = h2->next; } tail = head; while (h1 && h2) { if (h1->val < h2->val) { tail->next = h1; h1 = h1->next; } else { tail->next = h2; h2 = h2->next; } tail = tail->next; } if (h1) { tail->next = h1; } if (h2) { tail->next = h2; } ListNode* tmp = head; return head; } public: ListNode* sortList(ListNode* head) { if (head == nullptr || head->next == nullptr) { return head; } ListNode* new_head = cut(head); head = sortList(head); new_head = sortList(new_head); return merge(head, new_head); } };