1、移除链表元素
删除链表中等于给定值 val 的所有节点。OJ链接
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val)
{
if(head == NULL)
{
return NULL;
}
struct ListNode* cur = head;
struct ListNode* prev = NULL;
while(cur)
{
if(cur->val == val)
{
struct ListNode* next = cur->next;
if(prev == NULL)
{
head = next;
}
else
{
prev->next = next;
}
free(cur);
cur = next;
}
else
{
prev = cur;
cur = cur->next;
}
}
return head;
}
2、反转链表
示例:OJ链接
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* newhead = NULL;
struct ListNode* cur = head;
while(cur)
{
struct ListNode* next = cur->next;
cur->next = newhead;
newhead = cur;
cur = next;
}
return newhead;
}
3、链表的中间结点
给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。OJ链接
示例:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* fast = head;
struct ListNode* slow = head;
while(fast != NULL && fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
4、链表中倒数第k个结点。
输入一个链表,输出该链表中倒数第k个结点。OJ链接
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
ListNode* fast = pListHead;
ListNode* slow = pListHead;
while(k--)
{
if(fast)
{
fast = fast->next;
}
else
{
return NULL;
}
}
while(fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
};
5、合并两个有序链表
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode Node;
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
if(l1 == NULL)
return l2;
if(l2 = NULL)
return l1;
Node* head = NULL;
Node* tail = NULL;
head = tail = (Node*)malloc(sizeof(Node));
tail->next = NULL;
while(l1 && l2)
{
if(l1->val < l2->val)
{
tail->next = l1;
tail = tail->next;
l1 = l1->next;
}
else
{
tail->next = l2;
tail = tail->next;
l2 = l2->next;
}
}
if(l1)
{
tail->next = l1;
}
else{
tail->next = l2;
}
Node* list = head->next;
free(head);
return list;
}
//递归版
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
if(NULL == l1)
return l2;
if(NULL == l2)
return l1;
if(l1->val > l2->val)
{
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
else
{
l1->next = mergeTwoLists(l1->next, l2);
return l1;
}
}
6、链表分割
编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前给定一个链表的头指针 ListNode* pHead,请返回重新排列后的链表的头指针。注意:分割以后保持原来的数据顺序不变。OJ链接
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
ListNode* partition(ListNode* pHead, int x)
{
if(pHead == NULL)
return NULL;
struct ListNode* lessHead, *lessTail, *greaterHead, *greaterTail;
lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));
greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* cur = pHead;
while(cur)
{
if(cur->val < x)
{
lessTail->next = cur;
lessTail = lessTail->next;
}
else
{
greaterTail->next = cur;
greaterTail = greaterTail->next;
}
cur = cur->next;
}
greaterTail->next = NULL;
lessTail->next = greaterHead->next;
pHead = lessHead->next;
free(lessHead);
free(greaterHead);
return pHead;
}
};
7、链表的回文结构
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。OJ链接
示例:
1->2->2->1
返回:true
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
bool chkPalindrome(ListNode* A)
{
if(A == NULL || A->next == NULL)
return true;
struct ListNode* slow, *fast, *prev, *cur, *next;
slow = fast = A;
if(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
prev = NULL;
cur = slow;
while(cur)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
while(prev && A)
{
if(A->val != prev->val)
return false;
A = A->next;
prev = prev->next;
}
return true;
}
};
8、相交链表
编写一个程序,找到两个单链表相交的起始节点。OJ链接
如下面的两个链表:
在节点 c1 开始相交。
示例:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8输入解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
if(headA == NULL || headB == NULL)
return NULL;
int lenA =0, lenB = 0;
struct ListNode *curA = headA;
struct ListNode *curB = headB;
while(curA)
{
lenA++;
curA = curA->next;
}
while(curB)
{
lenB++;
curB = curB->next;
}
int sum = abs(lenA - lenB);
struct ListNode *longList = headA;
struct ListNode *shortList = headB;
if(lenB > lenA)
{
longList = headB;
shortList = headA;
}
while(sum--)
{
longList = longList->next;
}
while(longList && shortList)
{
if(longList == shortList)
{
return longList;
}
longList = longList->next;
shortList = shortList->next;
}
return NULL;
}
9、判断环形链表
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。OJ链接
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head)
{
if(head == NULL || head->next == NULL)
{
return false;
}
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
return true;
}
}
return false;
}
10、判断环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。OJ链接
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head)
{
if(head == NULL || head->next == NULL)
{
return NULL;
}
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
struct ListNode* meet = slow;
struct ListNode* start = head;
while(meet != start)
{
meet = meet->next;
start = start->next;
}
return meet;
}
}
return NULL;
}
11、复制带随机指针的链表
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。
我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。OJ链接
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head)
{
if(head == NULL)
{
return NULL;
}
Node* cur = head;
//复制链表
while(cur)
{
Node *nowNode = (Node*)malloc(sizeof(Node));
Node* next = cur->next;
cur->next = nowNode;
nowNode->val = cur->val;
nowNode->next = next;
cur = next;
}
//复制random
cur = head;
while(cur)
{
Node* copy = cur->next;
if(cur->random != NULL)
{
copy->random = cur->random->next;
}
else
{
copy->random = NULL;
}
cur = copy->next;
}
//连接拷贝节点
cur = head;
Node* copyHead = NULL;
Node* copyTail = NULL;
while(cur)
{
Node* copy = cur->next;
Node* next = copy->next;
if(copyHead == NULL)
{
copyHead = copyTail = copy;
}
else
{
copyTail->next = copy;
copyTail = copy;
}
cur->next = next;
cur = next;
}
return copyHead;
}
};
12、对链表进行插入排序
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* insertionSortList(struct ListNode* head)
{
if(head == NULL || head->next == NULL)
{
return head;
}
struct ListNode* sortHead = (struct ListNode*)malloc(sizeof(struct ListNode));
sortHead->next = head;
head = head->next;
sortHead->next->next = NULL;
struct ListNode* cur = head;
while(cur)
{
struct ListNode* next = cur->next;
struct ListNode* sortprev = sortHead;
struct ListNode* sortcur = sortHead->next;
while(sortcur)
{
if(cur->val > sortcur->val)
{
sortprev = sortcur;
sortcur = sortcur->next;
}
else
{
break;
}
}
sortprev->next = cur;
cur->next = sortcur;
cur = next;
}
struct ListNode* sortList = sortHead->next;
free(sortHead);
return sortList;
}
13、删除链表中重复的节点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5OJ链接
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead == NULL || pHead->next == NULL)
return pHead;
struct ListNode* n0 = NULL;
struct ListNode* n1 = pHead;
struct ListNode* n2 = n1->next;
while(n2 != NULL)
{
if(n1->val != n2->val)
{
n0 = n1;
n1 = n2;
n2 = n2->next;
}
else
{
while(n2 && n2->val == n1->val)
{
n2 = n2->next;
}
//连接数据
if(n0 == NULL)
pHead = n2;
else
n0->next = n2;
while(n1 != n2)
{
struct ListNode* next = n1->next;
free(n1);
n1 = next;
}
if(n2 != NULL)
n2 = n2->next;
}
}
return pHead;
}
};