目录
数据结构之链表OJ::
1.移除链表元素
//删除链表中等于给定值val的所有结点
struct ListNode
{
int val;
struct ListNode* next;
};
//方法一
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* cur = head, * prev = NULL;
while (cur != NULL)
{
//1.头删
//2.非头删
if (cur->val == val)
{
if (cur == head)
{
head = head->next;
free(cur);
cur = head;
}
else
{
prev->next = cur->next;
free(cur);
cur = prev->next;
}
}
else
{
prev = cur;
cur = cur->next;
}
}
return head;
}
//不用二级指针的方法:返回头指针
//main函数调用方式:plist = removeElements(plist,6);
//方法二
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* cur = head;
struct ListNode* newhead = NULL;
struct ListNode* tail = NULL;
while (cur != NULL)
{
if (cur->val != val)
{
if (newhead == NULL)
{
newhead = cur;
tail = newhead;
cur = cur->next;
}
else
{
tail->next = cur;
cur = cur->next;
tail = tail->next;
}
}
else
{
struct ListNode* del = cur;
cur = cur->next;
free(del);
}
}
if (tail != NULL)
{
tail->next = NULL;
}
return newhead;
}
//方法三:
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* cur = head;
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* tail = guard;
while (cur != NULL)
{
if (cur->val != val)
{
tail->next = cur;
tail = tail->next;
cur = cur->next;
}
else
{
struct ListNode* del = cur;
cur = cur->next;
free(del);
}
}
//最后结点是val 就会出现此问题
if (tail != NULL)
{
tail->next = NULL;
}
head = guard->next;
free(guard);
return head;
}
//替代我们之前实现的二级指针
//1.返回新的链表头 2.设计为带哨兵位
2.反转链表
//反转链表
//方法一:取结点头插到新链表
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur = head;
struct ListNode* newhead = NULL;
while (cur)
{
struct ListNode* next = cur->next;
cur->next = newhead;
newhead = cur;
cur = next;
}
return newhead;
}
//方法二:翻转链表方向
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* prev = NULL;
struct ListNode* cur = head;
struct ListNode* next = NULL;
while (cur)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
3.链表的中间结点
//方法一:
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
//方法二:
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* cur1 = head;
int num = 0;
int mid = 0;
while (cur1 != NULL)
{
num++;
cur1 = cur1->next;
}
mid = num / 2 + 1;
cur1 = head;
for (int i = 1; i < mid; i++)
{
cur1 = cur1->next;
}
return cur1;
}
4.链表中倒数第k个结点
//方法一:
struct ListNode* FindKthToTail(struct ListNode* pListHead, unsigned int k)
{
struct ListNode* cur = pListHead;
int n = 0;
while (cur)
{
n++;
cur = cur->next;
}
if (k > n)
{
return NULL;
}
cur = pListHead;
int pos = n - k + 1;
for (int i = 1; i < pos; i++)
{
cur = cur->next;
}
return cur;
}
//方法二:
struct ListNode* FindKthToTail(struct ListNode* pListHead, unsigned int k)
{
struct ListNode* fast, * slow;
fast = slow = pListHead;
while (k--) //走k步
{
//k大于链表长度
if (fast == NULL)
return NULL;
fast = fast->next;
}
while (fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
//方法三:
struct ListNode* FindKthToTail(struct ListNode* pListHead, unsigned int k)
{
struct ListNode* fast = pListHead;
struct ListNode* slow = pListHead;
while (--k)
{
if (fast == NULL)
{
return NULL;
}
fast = fast->next;
}
if (fast == NULL)
{
return NULL;
}
while (fast->next)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
5.合并两个有序链表
//合并两个有序链表
//不带哨兵位
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
if (list1 == NULL)
{
return list2;
}
if (list2 == NULL)
{
return list1;
}
struct ListNode* begin1 = list1;
struct ListNode* begin2 = list2;
struct ListNode* newlist = NULL;
struct ListNode* begin3 = newlist;
while (begin1 != NULL && begin2 != NULL)
{
if (newlist == NULL)
{
if (begin1->val < begin2->val)
{
newlist = begin1;
begin1 = begin1->next;
begin3 = newlist;
}
else
{
newlist = begin2;
begin2 = begin2->next;
begin3 = newlist;
}
}
else
{
if (begin1->val < begin2->val)
{
begin3->next = begin1;
begin1 = begin1->next;
begin3 = begin3->next;
}
else
{
begin3->next = begin2;
begin2 = begin2->next;
begin3 = begin3->next;
}
}
}
if (begin1 == NULL)
{
begin3->next = begin2;
}
if (begin2 == NULL)
{
begin3->next = begin1;
}
return newlist;
}
//带哨兵位
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
guard->next = NULL;
struct ListNode* tail = guard;
struct ListNode* begin1 = list1;
struct ListNode* begin2 = list2;
while (begin1 && begin2)
{
if (begin1->val < begin2->val)
{
tail->next = begin1;
begin1 = begin1->next;
tail = tail->next;
}
else
{
tail->next = begin2;
begin2 = begin2->next;
tail = tail->next;
}
}
if (begin1)
{
tail->next = begin1;
}
if (begin2)
{
tail->next = begin2;
}
struct ListNode* head = guard->next;
free(guard);
return head;
}
6.链表分割
//链表分割
struct ListNode* partition(struct ListNode* pHead, int x)
{
struct ListNode* lessGuard = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* lessTail = lessGuard;
struct ListNode* greaterGuard = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* greaterTail = greaterTail;
lessGuard->next = NULL;
greaterGuard->next = NULL;
struct ListNode* cur = pHead;
while (cur)
{
if (cur->val < x)
{
lessTail->next = cur;
cur = cur->next;
lessTail = lessTail->next;
}
else
{
greaterTail->next = cur;
cur = cur->next;
greaterTail = greaterTail->next;
}
}
lessTail->next = greaterGuard->next;
greaterTail->next = NULL;
pHead = lessGuard->next;
free(greaterGuard);
greaterGuard = NULL;
free(lessGuard);
lessGuard = NULL;
return pHead;
}
7.链表的回文结构
//链表的回文结构
//方法一:找中间结点翻转链表
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* prev = NULL;
struct ListNode* cur = head;
struct ListNode* next = NULL;
while (cur)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
bool chkPalindrome(struct ListNode* head)
{
struct ListNode* mid = middleNode(head);
struct ListNode* rmid = reverseList(mid);
while (head && rmid)
{
if (head->val != rmid->val)
return false;
head = head->next;
rmid = rmid->next;
}
return true;
}
//方法二:
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* prev = NULL;
struct ListNode* cur = head;
struct ListNode* next = NULL;
while (cur)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
bool isPalindrome(struct ListNode* head)
{
struct ListNode* cur = head;
struct ListNode* copyGuard = (struct ListNode*)malloc(sizeof(struct ListNode));
copyGuard->next = NULL;
struct ListNode* copyTail = copyGuard;
while (cur)
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = cur->val;
copyTail->next = newnode;
copyTail = copyTail->next;
}
copyTail->next = NULL;
struct ListNode* rhead = reverseList(copyGuard->next);
while (rhead || head)
{
if (rhead->val != head->val)
{
return false;
}
rhead = rhead->next;
head = head->next;
}
free(copyGuard);
copyGuard = NULL;
return true;
}
8.相交链表
//方法一:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
struct ListNode* curA = headA;
struct ListNode* curB = headB;
while(curA != NULL)
{
while(curB != NULL)
{
if(curA == curB)
{
return curA;
}
curB = curB->next;
}
curB = headB;
curA = curA->next;
}
return NULL;
}
//方法二:
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
if (headA == NULL || headB == NULL)
{
return NULL;
}
struct ListNode* curA = headA;
struct ListNode* curB = headB;
int lenA = 1;
while(curA->next)
{
curA = curA->next;
lenA++;
}
int lenB = 1;
while (curB->next)
{
curB = curB->next;
lenB++;
}
if (curA != curB)
{
return NULL;
}
struct ListNode* longList = headA;
struct ListNode* shortList = headB;
if (lenA < lenB)
{
longList = headB;
shortList = headA;
}
int gap = abs(lenA - lenB);
while (gap--)
{
longList = longList->next;
}
while (longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
return longList;
}
9.环形链表
//环形链表
//快慢指针法:slow进环以后 fast开始追赶slow
bool hasCycle(struct ListNode* head)
{
struct ListNode* fast = head;
struct ListNode* slow = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (slow == fast)
{
return true;
}
}
return false;
}
10.环形链表II
//环形链表II
//方法一:公式证明推导
struct ListNode* detectCycle(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
struct ListNode* meet = slow;
while (meet != head)
{
meet = meet->next;
head = head->next;
}
return meet;
}
}
return NULL;
}
//方法二:转换成相交问题
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
if (headA == NULL || headB == NULL)
{
return NULL;
}
struct ListNode* curA = headA, * curB = headB;
int lenA = 1;
//找尾结点
while (curA->next)
{
curA = curA->next;
lenA++;
}
int lenB = 1;
while (curB->next)
{
curB = curB->next;
lenB++;
}
if (curA != curB)
{
return NULL;
}
struct ListNode* longList = headA, * shortList = headB;
if (lenA < lenB)
{
longList = headB;
shortList = headA;
}
//长的链表先走差距步
int gap = abs(lenA - lenB);
while (gap--)
{
longList = longList->next;
}
//同时走找交点
while (longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
return longList;
}
struct ListNode* detectCycle(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
struct ListNode* meet = slow;
struct ListNode* next = meet->next;
meet->next = NULL;
struct ListNode* entryNode = getIntersectionNode(head, next);
meet->next = next;
return entryNode;
}
}
return NULL;
}
11.复制带随机指针的链表
//复制带随机指针的链表
struct Node
{
int val;
struct Node* next;
struct Node* random;
};
struct Node* copyRandomList(struct Node* head)
{
//1.插入copy结点
struct Node* cur = head;
struct Node* copy = NULL;
struct Node* next = NULL;
while (cur)
{
next = cur->next;
copy = (struct Node*)malloc(sizeof(struct Node));
copy->val = cur->val;
cur->next = copy;
copy->next = next;
cur = next;
}
//2.更新random
cur = head;
while (cur)
{
copy = cur->next;
if (cur->random == NULL)
{
copy->random = NULL;
}
else
{
copy->random = cur->random->next;
}
cur = cur->next->next;
}
//3.copy结点要解下来链接在一起 恢复原链表
struct Node* copyHead = NULL;
struct Node* copyTail = NULL;
cur = head;
while (cur)
{
copy = cur->next;
next = copy->next;
if (copyTail == NULL)
{
copyHead = copyTail = copy;
}
else
{
copyTail->next = copy;
copyTail = copyTail->next;
}
//恢复原链表链接
cur->next = next;
cur = next;
}
return copyHead;
}