题号 | 题目 | 说明 |
2 | Add Two Numbers 两个数字相加 | 低位在表头 |
19 | Remove Nth Node From End of List 移除链表倒数第N个节点 | |
21 | Merge Two Sorted Lists 混合插入有序链表 | |
23 | Merge k Sorted Lists 合并k个有序链表 |
递归 / 非递归 |
24 | Swap Nodes in Pairs 成对交换节点 | 递归 / 非递归 |
25 | Reverse Nodes in k-Group 每k个一组翻转链表 |
|
61 | Rotate List 旋转链表 | |
83 | Remove Duplicates from Sorted List 移除有序链表中的重复项 | |
147 | Insertion Sort List 链表插入排序 | |
148 | Sort List 链表排序 | 递归分治 |
206 | Reverse Linked List 倒置链表 |
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
var head = &ListNode{}
var cur = head
var carry = 0
for l1 != nil || l2 != nil {
var l1Val, l2Val = 0, 0
if l1 != nil {
l1Val = l1.Val
l1 = l1.Next
}
if l2 != nil {
l2Val = l2.Val
l2 = l2.Next
}
var sum = l1Val + l2Val + carry
carry = sum / 10
cur.Next = &ListNode{Val: sum % 10}
cur = cur.Next
}
if carry > 0 {
cur.Next = &ListNode{Val: carry}
}
return head.Next
}
首先要考虑的时,如何找到倒数第N个节点,pre和cur指针。首先cur指针先向前走N步,如果此时cur指向空,说明N为链表的长度,则需要移除的为首元素,那么此时我们返回head->next即可,如果cur存在,我们再继续往下走,此时pre指针也跟着走,直到cur为最后一个元素时停止,此时pre指向要移除元素的前一个元素
func removeNthFromEnd(head *ListNode, n int) *ListNode {
if head == nil || n <= 0 {
return nil
}
var dummpy = &ListNode{-1, head}
var cur, pre = dummpy, dummpy
for i := 0; i < n; i++ {
cur = cur.Next
if i != n-1 && cur == nil {
return head
}
}
for cur.Next != nil {
cur = cur.Next
pre = pre.Next
}
pre.Next = pre.Next.Next
return dummpy.Next
}
定义一个新链表,头结点,用于返回;当前节点用于对链表元素赋值以及跳转到下一个节点
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
var dummpy = &ListNode{-1, nil}
var cur = dummpy
for l1 != nil && l2 != nil {
if l1.Val < l2.Val {
cur.Next = l1
l1 = l1.Next
} else {
cur.Next = l2
l2 = l2.Next
}
cur = cur.Next
}
if l1 != nil {
cur.Next = l1
}
if l2 != nil {
cur.Next = l2
}
return dummpy.Next
}
递归法:
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 == nil {
return l2
}
if l2 == nil {
return l1
}
if l1.Val < l2.Val {
l1.Next = mergeTwoLists(l1.Next, l2)
return l1
} else {
l2.Next = mergeTwoLists(l1, l2.Next)
return l2
}
}
合并k个有序链表
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
增加了难度,变成合并k个有序链表了,但是不管合并几个,基本还是要两两合并。分治法 Divide and Conquer Approach。简单来说就是不停的对半划分,比如k个链表先划分为合并两个k/2个链表的任务,再不停的往下划分,直到划分成只有一个或两个链表的任务,开始合并。
迭代法
func swapPairs(head *ListNode) *ListNode {
var dummpy = &ListNode{-1, head}
var cur = dummpy
for cur.Next != nil && cur.Next.Next != nil {
var t = cur.Next.Next
cur.Next.Next = t.Next
t.Next = cur.Next
cur.Next = t
cur = t.Next
}
return dummpy.Next
}
递归遍历到链表末尾,然后先交换末尾两个,然后依次往前交换:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if (!head || !head->next) return head;
ListNode *t = head->next;
head->next = swapPairs(head->next->next);
t->next = head;
return t;
}
};
func swapPairs(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
var t = head.Next
head.Next = swapPairs(head.Next.Next)
t.Next = head
return t
}
class Solution {
public:
ListNode *reverseKGroup(ListNode *head, int k) {
if (head==NULL || head->next==NULL || k<=1) return head;
ListNode preHead(-1);
preHead.next = head;
ListNode *pre = &preHead;
ListNode *pTemp;
while (head != NULL) {
ListNode *pEnd = head;
for (int i=1; inext;
}
if (head == NULL) return preHead.next;
pTemp = pEnd->next;
for (int i=1; inext;
pTemp->next = pre->next;
pre->next = pTemp;
pTemp = pNext;
}
pre = pEnd;
pEnd->next = pTemp;
head = pTemp;
}
return preHead.next;
}
};
class Solution {
public:
ListNode *rotateRight(ListNode *head, int k) {
if (head==NULL || head->next==NULL || k<=0) return head;
ListNode *pPre = head;
ListNode *pTemp;
int len = 0;
while (pPre != NULL) {
len++;
pTemp = pPre;
pPre = pPre->next;
}
k = len - k%len;
pTemp->next = head;
for (int i=0; inext;
head = head->next;
}
pTemp->next = NULL;
return head;
}
};
移除有序链表中的重复项之二
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
Example 1:
Input: 1->2->3->3->4->4->5 Output: 1->2->5
Example 2:
Input: 1->1->1->2->3 Output: 2->3
定义一个新的节点,然后链上原链表,然后定义一个前驱指针和一个现指针,每当前驱指针指向新建的节点,现指针从下一个位置开始往下遍历,遇到相同的则继续往下,直到遇到不同项时,把前驱指针的next指向下面那个不同的元素。如果现指针遍历的第一个元素就不相同,则把前驱指针向下移一位
class Solution {
public:
ListNode *deleteDuplicates(ListNode *head) {
if (!head || !head->next) return head;
ListNode *dummy = new ListNode(-1), *pre = dummy;
dummy->next = head;
while (pre->next) {
ListNode *cur = pre->next;
while (cur->next && cur->next->val == cur->val) {
cur = cur->next;
}
if (cur != pre->next) pre->next = cur->next;
else pre = pre->next;
}
return dummy->next;
}
};
Given a sorted linked list, delete all duplicates such that each element appear only once.
Example 1:
Input: 1->1->2 Output: 1->2
Example 2:
Input: 1->1->2->3->3 Output: 1->2->3
遍历这个链表,每个结点和其后面的结点比较,如果结点值相同了,我们只要将前面结点的next指针跳过紧挨着的相同值的结点,指向后面一个结点
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode *cur = head;
while (cur && cur->next) {
if (cur->val == cur->next->val) {
cur->next = cur->next->next;
} else {
cur = cur->next;
}
}
return head;
}
};
class Solution {
public:
ListNode *deleteDuplicates(ListNode *head) {
if (head==NULL || head->next==NULL) return head;
ListNode *pCur, *pNext;
for (pCur=head, pNext=pCur->next; pNext!=NULL; ) {
if (pCur->val == pNext->val) {
pCur->next = pNext->next;
}
else {
pCur = pNext;
}
pNext = pNext->next;
}
return head;
}
};
func insertionSortList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {return head}
var dummpy = &ListNode{Val: -1, Next: head}
var cur = head.Next
head.Next = nil
head = cur
for head != nil {
var temp = head.Next
cur = dummpy
for cur.Next!=nil && cur.Next.Val <= head.Val {
cur = cur.Next
}
head.Next = cur.Next
cur.Next = head
head = temp
}
return dummpy.Next
}
func sortList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {return head}
var fast, slow, pre = head, head, head
for fast != nil && fast.Next != nil {
pre = slow
slow = slow.Next
fast = fast.Next.Next
}
pre.Next = nil
return merge(sortList(head), sortList(slow))
}
func merge(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 == nil {return l2}
if l2 == nil {return l1}
if l1.Val < l2.Val {
l1.Next = merge(l1.Next, l2)
return l1
} else {
l2.Next = merge(l1, l2.Next)
return l2
}
}
非递归法
func reverseList(head *ListNode) *ListNode {
var dummpy = &ListNode{Val: -1, Next: nil}
for head != nil {
var t = head.Next
head.Next = dummpy.Next
dummpy.Next = head
head = t
}
return dummpy.Next
}