盤點(diǎn)那些必問(wèn)的數(shù)據(jù)結(jié)構(gòu)算法題之鏈表
來(lái)自:juejin.im/post/5b8a0e99f265da43320730ba
0 概述
1 定義
//?aslist.h
//?鏈表結(jié)點(diǎn)定義
typedef?struct?ListNode?{
????struct?ListNode?*next;
????int?value;
}?listNode;
2 基本操作
/**
?*?創(chuàng)建鏈表結(jié)點(diǎn)
?*/
ListNode?*listNewNode(int?value)
{
????ListNode?*node;
????if?(!(node?=?malloc(sizeof(ListNode))))
????????return?NULL;
????node->value?=?value;
????node->next?=?NULL;
????return?node;
}
/**
?*?頭插法插入結(jié)點(diǎn)。
?*/
ListNode?*listAddNodeHead(ListNode?*head,?int?value)
{
????ListNode?*node;
????if?(!(node?=?listNewNode(value)))
????????return?NULL;
????if?(head)?
????????node->next?=?head;
????head?=?node;
????return?head;
}
/**
?*?尾插法插入值為value的結(jié)點(diǎn)。
?*/
ListNode?*listAddNodeTail(ListNode?*head,?int?value)
{
????ListNode?*node;
????if?(!(node?=?listNewNode(value)))
????????return?NULL;
????return?listAddNodeTailWithNode(head,?node);
}
/**
?*?尾插法插入結(jié)點(diǎn)。
?*/
ListNode?*listAddNodeTailWithNode(ListNode?*head,?ListNode?*node)
{
????if?(!head)?{
????????head?=?node;
????}?else?{
????????ListNode?*current?=?head;
????????while?(current->next)?{
????????????current?=?current->next;
????????}?
????????current->next?=?node;
????}
????return?head;
}
/**
?*?從鏈表刪除值為value的結(jié)點(diǎn)。
?*/
ListNode?*listDelNode(ListNode?*head,?int?value)
{
????ListNode?*current=head,?*prev=NULL;
????while?(current)?{
????????if?(current->value?==?value)?{
????????????if?(current?==?head)
????????????????head?=?head->next;
????????????if?(prev)
????????????????prev->next?=?current->next;
????????????free(current);
????????????break;
????????}
????????prev?=?current;
????????current?=?current->next;
????}
????return?head;
}
/**
?*?鏈表遍歷。
?*/
void?listTraverse(ListNode?*head)
{
????ListNode?*current?=?head;
????while?(current)?{
????????printf("%d",?current->value);
????????printf("->");
????????current?=?current->next;
????????if?(current?==?head)?//?處理首尾循環(huán)鏈表情況
????????????break;
????}
????printf("NULL\n");
}
/**
?*?使用數(shù)組初始化一個(gè)鏈表,共len個(gè)元素。
?*/
ListNode?*listCreate(int?a[],?int?len)
{
????ListNode?*head?=?NULL;
????int?i;
????for?(i?=?0;?i?????????if?(!(head?=?listAddNodeTail(head,?a[i])))
????????????return?NULL;
????}
????return?head;
}
/**
*?鏈表長(zhǎng)度函數(shù)
*/
int?listLength(ListNode?*head)
{
????int?len?=?0;
????while?(head)?{
????????len++;
????????head?=?head->next;
????}
????return?len;
}
3 鏈表相關(guān)面試題
3.1 鏈表逆序
/**
?*?鏈表逆序,非遞歸實(shí)現(xiàn)。
*/
ListNode?*listReverse(ListNode?*head)
{
????ListNode?*newHead?=?NULL,?*current?=?head;
????while?(current)?{
????????ListNode?*next?=?current->next;
????????current->next?=?newHead;
????????newHead?=?current;
????????current?=?next;
????}
????return?newHead;
}
/**
?*?鏈表逆序,遞歸實(shí)現(xiàn)。
?*/
ListNode?*listReverseRecursive(ListNode?*head)
{
????if?(!head?||?!head->next)?{
????????return?head;
????}
????ListNode?*reversedHead?=?listReverseRecursive(head->next);
????head->next->next?=?head;
????head->next?=?NULL;
????return?reversedHead;
}
3.2 鏈表復(fù)制
/**
?*?鏈表復(fù)制-非遞歸
?*/
ListNode?*listCopy(ListNode?*head)?
{
????ListNode?*current?=?head,?*newHead?=?NULL,?*newTail?=?NULL;?
????while?(current)?{
????????ListNode?*node?=?listNewNode(current->value);
????????if?(!newHead)?{?//?第一個(gè)結(jié)點(diǎn)
????????????newHead?=?newTail?=?node;
????????}?else?{
????????????newTail->next?=?node;
????????????newTail?=?node;
????????}
????????current?=?current->next;
????}
????return?newHead;
}
/**
?*?鏈表復(fù)制-遞歸
?*/
ListNode?*listCopyRecursive(ListNode?*head)
{
????if?(!head)?
????????return?NULL;
????ListNode?*newHead?=?listNewNode(head->value);
????newHead->next?=?listCopyRecursive(head->next);
????return?newHead;
}
3.3 鏈表合并
/**
?*?鏈表合并-非遞歸
?*/
ListNode?*listMerge(ListNode?*list1,?ListNode?*list2)
{
????ListNode?dummy;?//?使用空結(jié)點(diǎn)保存合并鏈表
????ListNode?*tail?=?&dummy;
????if?(!list1)
????????return?list2;
????if?(!list2)
????????return?list1;
????while?(list1?&&?list2)?{
????????if?(list1->value?<=?list2->value)?{
????????????tail->next?=?list1;
????????????tail?=?list1;
????????????list1?=?list1->next;
????????}?else?{
????????????tail->next?=?list2;
????????????tail?=?list2;
????????????list2?=?list2->next;
????????}
????}
????if?(list1)?{
????????tail->next?=?list1;
????}?else?if?(list2)?{
????????tail->next?=?list2;
????}
????return?dummy.next;
}
ListNode?*listMergeRecursive(ListNode?*list1,?ListNode?*list2)
{
????ListNode?*result?=?NULL;
????if?(!list1)
????????return?list2;
????if?(!list2)
????????return?list1;
????if?(list1->value?<=?list2->value)?{
????????result?=?list1;
????????result->next?=?listMergeRecursive(list1->next,?list2);
????}?else?{
????????result?=?list2;
????????result->next?=?listMergeRecursive(list1,?list2->next);
????}
????return?result;
}
3.4 鏈表相交判斷
/**
?*?鏈表相交判斷,如果相交返回相交的結(jié)點(diǎn),否則返回NULL。
?*/
ListNode?*listIntersect(ListNode?*list1,?ListNode?*list2)
{
????int?len1?=?listLength(list1);
????int?len2?=?listLength(list2);
????int?delta?=?abs(len1?-?len2);
????ListNode?*longList?=?list1,?*shortList?=?list2;
????if?(len1?????????longList?=?list2;
????????shortList?=?list1;
????}
????int?i;
????for?(i?=?0;?i?????????longList?=?longList->next;
????}
????while?(longList?&&?shortList)?{
????????if?(longList?==?shortList)
????????????return?longList;
????????longList?=?longList->next;
????????shortList?=?shortList->next;
????}
????return?NULL;
}
3.5 判斷鏈表是否存在環(huán)

/**
?*?檢測(cè)鏈表是否有環(huán)-Flod判圈算法
?*?若存在環(huán),返回相遇結(jié)點(diǎn),否則返回NULL
?*/
ListNode?*listDetectLoop(ListNode?*head)
{
????ListNode?*slow,?*fast;
????slow?=?fast?=?head;
????while?(slow?&&?fast?&&?fast->next)?{
????????slow?=?slow->next;
????????fast?=?fast->next->next;
????????if?(slow?==?fast)?{
????????????printf("Found?Loop\n");
????????????return?slow;
????????}
????}
????printf("No?Loop\n");
????return?NULL;
}
void?testListDetectLoop()
{
????printf("\nTestListDetectLoop\n");
????int?a[]?=?{1,?2,?3,?4};
????ListNode?*head?=?listCreate(a,?ALEN(a));
????listDetectLoop(head);
????//?構(gòu)造一個(gè)環(huán)
????head->next->next->next?=?head;
????listDetectLoop(head);
}
2s?-?s?=?nr?=>?s?=?nr
s?=?r?=?a?+?x?=>?a?+?x?=?(L-a)?=>?a?=?L-x-a
/**
?*?查找鏈表中環(huán)入口
?*/
ListNode?*findLoopNode(ListNode?*head)
{
????ListNode?*meetNode?=?listDetectLoop(head);
????if?(!meetNode)
????????return?NULL;
????ListNode?*headNode?=?head;
????while?(meetNode?!=?headNode)?{
????????meetNode?=?meetNode->next;
????????headNode?=?headNode->next;
????}
????return?meetNode;
}
3.6 鏈表模擬加法
list1:??(3?->?1?->?5?->?NULL)
list2:??(5?->?9?->?2?->?NULL)
result:?(8?->?0?->?8?->?NULL)
current->data?=?list1->data?+?list2->data?+?carry
(其中carry為低位的進(jìn)位,如果有進(jìn)位為1,否則為0)
/**
?*?鏈表模擬加法-非遞歸解法
?*/
ListNode?*listEnumarateAdd(ListNode?*list1,?ListNode?*list2)
{
????int?carry?=?0;
????ListNode?*result?=?NULL;
????while?(list1?||?list2?||?carry)?{
????????int?value?=?carry;
????????if?(list1)?{
????????????value?+=?list1->value;
????????????list1?=?list1->next;
????????}
????????if?(list2)?{
????????????value?+=?list2->value;
????????????list2?=?list2->next;
????????}
????????result?=?listAddNodeTail(result,?value?%?10);
????????carry?=?(?value?>=?10???1:?0);
????}
????return?result;
}
/**
?*?鏈表模擬加法-遞歸解法
?*/
ListNode?*listEnumarateAddRecursive(ListNode?*list1,?ListNode?*list2,?int?carry)
{
????if?(!list1?&&?!list2?&&?carry==0)
????????return?NULL;
????int?value?=?carry;
????if?(list1)
????????value?+=?list1->value;
????if?(list2)
????????value?+=?list2->value;
????ListNode?*next1?=?list1???list1->next?:?NULL;
????ListNode?*next2?=?list2???list2->next?:?NULL;
????ListNode?*more?=?listEnumarateAddRecursive(next1,?next2,?(value?>=?10???1?:?0));
????ListNode?*result?=?listNewNode(carry);
????result->value?=?value?%?10;
????result->next?=?more;
????return?result;
}
3.7 有序單向循環(huán)鏈表插入結(jié)點(diǎn)

如果原來(lái)鏈表為空或者插入的結(jié)點(diǎn)值最小,則直接插入該結(jié)點(diǎn)并設(shè)置為頭結(jié)點(diǎn)。
如果原來(lái)鏈表非空,則找到第一個(gè)大于該結(jié)點(diǎn)值的結(jié)點(diǎn),并插入到該結(jié)點(diǎn)的前面。如果插入的結(jié)點(diǎn)值最大,則插入在尾部。
/**
?*?簡(jiǎn)化版-有序無(wú)循環(huán)鏈表插入結(jié)點(diǎn)
?*/
ListNode?*sortedListAddNode(ListNode?*head,?int?value)
{
????ListNode?*node?=?listNewNode(value);
????if?(!head?||?head->value?>=?value)?{?//情況1
????????node->next?=?head;
????????head?=?node;
????}?else?{??//情況2
????????ListNode?*current?=?head;
????????while?(current->next?!=?NULL?&&?current->next->value?????????????current?=?current->next;
????????node->next?=?current->next;
????????current->next?=?node;
????}
????return?head;
}
/**
?*?簡(jiǎn)化版-有序無(wú)循環(huán)鏈表插入結(jié)點(diǎn)(兩種情況一起處理)
?*/
void?sortedListAddNodeUnify(ListNode?**head,?int?value)
{
????ListNode?*node?=?listNewNode(value);
????ListNode?**current?=?head;
????while?((*current)?&&?(*current)->value?value)?{
????????current?=?&((*current)->next);
????}
????node->next?=?*current;
????*current?=?node;
}
插入到prev和current之間。
插入到首尾交接處,如果是最小值重新設(shè)置head值。
/**
?*?有序循環(huán)鏈表插入結(jié)點(diǎn)
?*/
ListNode?*sortedLoopListAddNode(ListNode?*head,?int?value)
{
????ListNode?*node?=?listNewNode(value);
????ListNode?*current?=?head,?*prev?=?NULL;
????do?{
????????prev?=?current;
????????current?=?current->next;
????????if?(value?>=?prev->value?&&?value?<=?current->value)
????????????break;
????}?while?(current?!=?head);
????prev->next?=?node;
????node->next?=?current;
????if?(current?==?head?&&?value?value)?//?判斷是否要設(shè)置鏈表頭
????????head?=?node;
????return?head;
}
3.8 輸出鏈表倒數(shù)第K個(gè)結(jié)點(diǎn)
/**
*?鏈表倒數(shù)第K個(gè)結(jié)點(diǎn)-遍歷兩次算法
*/
ListNode?*getLastKthNodeTwice(ListNode?*head,?int?k)
{
????int?len?=?listLength(head);?????
????if?(k?>?len)
????????return?NULL;
????ListNode?*current?=?head;?
????int?i;
????for?(i?=?0;?i?len-k;?i++)??//遍歷鏈表,找出第N-K+1個(gè)結(jié)點(diǎn)
????????current?=?current->next;
????return?current;
}
/**
*?鏈表倒數(shù)第K個(gè)結(jié)點(diǎn)-遍歷一次算法
*/
ListNode?*getLastKthNodeOnce(ListNode?*head,?int?k)
{
????ListNode?*p1,?*p2;
????p1?=?p2?=?head;
????for(;?k?>?0;?k--)?{
????????if?(!p2)?//?鏈表長(zhǎng)度不夠K
????????????return?NULL;
????????p2?=?p2->next;
????}
????while?(p2)?{
????????p1?=?p1->next;
????????p2?=?p2->next;
????}
????return?p1;
}
推薦閱讀:
完全整理 | 365篇高質(zhì)技術(shù)文章目錄整理
專注服務(wù)器后臺(tái)技術(shù)棧知識(shí)總結(jié)分享
歡迎關(guān)注交流共同進(jìn)步
評(píng)論
圖片
表情

