链表面试试题
1:编写一个程序,找到两个单链表相交的起始节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode Node;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if (headA == NULL || headB == NULL) {
return NULL;
}
Node* lastA = headA;
Node* lastB = headB;
int sizeA=1;
int sizeB=1;
while(lastA->next){
sizeA++;
lastA=lastA->next;
}
while(lastB->next){
sizeB++;
lastB=lastB->next;
}
if (lastA != lastB) {
return NULL;
}
Node* curA = headA;
Node* curB = headB;
int pos = sizeA - sizeB;
if (pos > 0) {
while (pos--) {
curA = curA->next;
}
}
else {
while (pos++) {
curB = curB->next;
}
}
while (curA != curB) {
curA = curA->next;
curB = curB->next;
}
return curA;
}
2:给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
typedef struct ListNode Node;
struct ListNode* partition(struct ListNode* head, int x) {
Node* cur = head;
Node* rhead = NULL, * rcur = NULL, * lhead = NULL, * lcur = NULL;
while (cur) {
if (cur->val < x) {
if (rhead == NULL) {
Node* node = (Node*)malloc(sizeof(Node));
node->val = cur->val;
rhead=rcur = node;
}
else {
Node* node = (Node*)malloc(sizeof(Node));
node->val = cur->val;
rcur->next = node;
rcur = node;
}
}
else{
if (lhead == NULL) {
Node* node = (Node*)malloc(sizeof(Node));
node->val = cur->val;
lhead=lcur = node;
}
else {
Node* node = (Node*)malloc(sizeof(Node));
node->val = cur->val;
lcur->next = node;
lcur = node;
}
}
cur = cur->next;
}
if (rhead == NULL) {
return lhead;
}
if (lhead) {
lhead->next = NULL;
}
rcur->next = lhead;
return rhead;
}
3.给定一个链表,判断链表中是否有环。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode Node;
bool hasCycle(struct ListNode *head) {
Node*pFast=head;
Node*pSlow=head;
while(pFast&&pFast->next){
pFast=pFast->next->next;
pSlow=pSlow->next;
if(pFast==pSlow){
return true;
}
}
return false;
}
4:给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode Node;
struct ListNode *detectCycle(struct ListNode *head) {
if(head==NULL){
return NULL;
}
Node*pFast=head;
Node*pSlow=head;
Node*pInput=head;
while(pFast&&pFast->next){
pFast=pFast->next->next;
pSlow=pSlow->next;
if(pFast==pSlow){
while(pInput!=pSlow){
pInput=pInput->next;
pSlow=pSlow->next;
}
return pInput;
}
}
return NULL;
}
5:翻转链表
typedef struct ListNode Node;
struct ListNode* reverseList(struct ListNode* head){
Node*pre=NULL;
Node*next=NULL;
while(head!=NULL){
next=head->next;
head->next=pre;
pre=head;
head=next;
}
return pre;
}
6:删除链表中等于给定值 val 的所有节点。
示例:
输入: 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;
* };
*/
typedef struct ListNode Node;
struct ListNode* removeElements(struct ListNode* head, int val){
if (head == NULL) {
return NULL;
}
Node* rhead = NULL;
Node* cur = head;
while (cur) {
if (cur->val == val) {
if (rhead == NULL) {
head = cur->next;
free(cur);
cur = head;
}
else {
rhead->next = cur->next;
free(cur);
cur = rhead->next;
}
}
else{
rhead = cur;
cur = cur->next;
}
}
return head;
}
7:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
示例:输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
struct ListNode* reverseBetween(struct ListNode* head, int m, int n){
if(head==NULL||n<m){
return head;
}
Node*cur=head;
Node*start=cur;
Node*end=cur;
Node*next=NULL;
Node*pre=NULL;
for(int i=1;i<m;i++){
start=cur;
cur=cur->next;
end=cur;
}
for(int i=0;i<=n-m;i++){
next=cur->next;
cur->next=pre;
pre=cur;
cur=next;
}
start->next=pre;
end->next=cur;
if(m==1){
return pre;
}
return head;
}
8:请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
示例:
输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode Node;
void deleteNode(struct ListNode* node) {
node->val=node->next->val;
node->next=node->next->next;
}
9:合并两个有序链表
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
typedef struct ListNode Node;
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
Node*head=(Node*)malloc(sizeof(Node));
Node*p=head;
while(l1!=NULL&&l2!=NULL){
if(l1->val<=l2->val){
p->next=l1;
l1=l1->next;
}
else{
p->next=l2;
l2=l2->next;
}
p=p->next;
}
if(l1!=NULL){
p->next= l1;
}
else{
p->next=l2;
}
return head->next;
}
10:返回中间结点
要求:给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
typedef struct ListNode Node;
struct ListNode* middleNode(struct ListNode* head){
Node*pFast=head;
Node*pSlow=head;
while(pFast&&pFast->next){
pFast=pFast->next->next;
pSlow=pSlow->next;
}
return pSlow;
}
11:删除链表中的重复元素
要求:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例:
输入:1->1->2
输出:1->2
typedef struct ListNode Node;
struct ListNode* deleteDuplicates(struct ListNode* head){
if (head == NULL) {
return NULL;
}
Node* cur = head;
while (cur->next) {
if (cur->val == cur->next->val) {
cur->next = cur->next->next;
continue;
}
else {
cur = cur->next;
}
}
return head;
}
12:删除链表中的重复元素II
要求:给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
typedef struct ListNode Node;
struct ListNode* deleteDuplicates(struct ListNode* head){
if (head == NULL) {
return NULL;
}
Node* pre = NULL;
Node* cur = head;
while (cur) {
if (cur->next!=NULL&&cur->val == cur->next->val) {
int value = cur->val;
while (cur->next != NULL && cur->next->val == value) {
cur = cur->next;
}
if (pre == NULL) {
head = cur->next;
}
else {
pre->next = cur->next;
}
}
else {
pre = cur;
}
cur = cur->next;
}
return head;
}
13:删除链表倒数第n个结点
要求:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
typedef struct ListNode Node;
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
if (head == NULL) {
return NULL;
}
Node* pFast = head;
Node* pSlow = head;
int i = 0;
while (pFast) {
pFast = pFast->next;
i++;
}
int j = i - n - 1;
if (j < 0) {
return head->next;
}
while (j--) {
pSlow = pSlow->next;
}
pSlow->next = pSlow->next->next;
return head;
}
14:两两交换链表中的结点
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
typedef struct ListNode Node;
struct ListNode* swapPairs(struct ListNode* head){
if (head == NULL || head->next == NULL) {
return head;
}
Node* p1 = head;
Node* p2 = head->next;
Node* p3 = NULL;
Node*pre=(Node*)malloc(sizeof(Node));
Node* temp = head->next;
pre->next = head;
while (1) {
p3 = p2->next;
p2->next = p1;
pre->next = p2;
pre = p1;
pre->next = p3;
if (p3 && p3->next) {
p1 = p3;
p2 = p1->next;
}
else {
break;
}
}
return temp;
}