链表相关面试题:返回一个链表的深度拷贝,对链表进行插入排序,删除链表中重复的结点

Posted 蚍蜉撼树谈何易

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表相关面试题:返回一个链表的深度拷贝,对链表进行插入排序,删除链表中重复的结点相关的知识,希望对你有一定的参考价值。

一、返回一个链表的深度拷贝。
题目描述:
在这里插入图片描述
解题思路:
1.首先将原链表的每个结点在后面都生成它的一个复制版本,同时将这些新结点依次连接到链表结点后面,这样新链表就变为了 7 7 13 13 11 11 10 1 1 NULL。
2.依次对它的random指针域赋值,在cur->random不为空的情况下,将 newnode->random=cur->random->next;
3.解链,将新复制出来的结点从链表中解出来,同时将解下来的结点连接起来,构成的便是复制出来的链表。核心:更改next指针指向。
在这里插入图片描述

struct Node* copyRandomList(struct Node* head) {
    if(head==NULL)
    {
        return NULL;
    }
    struct Node*cur=head;
     struct Node*newnode=NULL;
    //构建同等链表,并将其插入
    while(cur)
    {
        newnode=(struct Node*)malloc(sizeof(struct Node));
        newnode->next=newnode->random=NULL;
        newnode->val=cur->val;
        newnode->next=cur->next;
        cur->next=newnode;
        cur=newnode->next;
    }
    //将random指针指向改变,
    cur=head;
   while(cur)
   {
       newnode=cur->next;
       if(cur->random)
       {
           newnode->random=cur->random->next;//指向cur->random->next.这是因为使其刚好指向的是复制的那个结点,而不是原结点
       }
       cur=newnode->next;
   }
   //拆链
   cur=head;
   struct Node*newhead=cur->next;
   newnode=cur->next;
   while(newnode)
   {
       cur->next=newnode->next;
       cur=newnode;
       newnode=cur->next;
   }
   return newhead;
	
}

二、对链表进行插入排序
题目描述:
在这里插入图片描述
首先我们对插入排序进行了解:
这里给出的是数组插入排序,思想是一样的。
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
//方法:将其实位置至于数组的第二个元素,让他与前面的元素进行比较,若小于,将其置于temp变量中,然后根据条件依次后移前面排序好
//的数组其他元素,依次执行
void sort(int* arr, int len)
{
	int temp;
	for (int i = 1; i < len; i++)
	{
		int j = i-1;
		if (arr[i] > arr[i - 1])
		{
			int j = i - 1;
			temp = arr[i];
			for( ; j>=0&&temp>arr[j] ; j--)
			{
				arr[j +1] = arr[j];
			}
			//在结束循环时会执行--操作,所以指针指向所需插入的前一个元素
			arr[j + 1] = temp;
		}
	}
}
void test01()
{
	int a[] = { 1,4,2,0,9,5 };
	int len = sizeof(a) / sizeof(int);
	sort(a, len);
	for (size_t i = 0; i < len; i++)
	{
		printf("%d\\n", a[i]);
	}
}
int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

这里呈现的是链表插入排序的代码

struct ListNode* insertionSortList(struct ListNode* head)
{
    if(head==NULL||head->next==NULL)
    {
        return head;
    }
    struct ListNode*phead=NULL;//记录的是插入排序后链表的第一个有效元素
    struct ListNode*cur=head;//记录的是当前指向元素
    struct ListNode*pos=NULL;//pos此时记录的是大于cur的第一个结点
    struct ListNode*pre=NULL;//pre此时记录的插入的有效结点
    while(cur!=NULL)
    {  
        head=cur->next;
        pos=phead;
        pre=NULL;
        while(pos)
        {
            if(cur->val<=pos->val)
            {
              break;
            }
            pre=pos;
            pos=pos->next; 
        }
        if(pos==phead)
        {
            cur->next=phead;
            phead=cur;
        }
        else
        {
            cur->next=pos;
            pre->next=cur;
        }
        cur=head; 
    }
    return phead;
}

三、删除链表中重复的结点
题目描述:
在这里插入图片描述
解题思路:
在这里插入图片描述

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) 
    {
        if(pHead==NULL||pHead->next==NULL)
        {
            return pHead;
        }//如果只有一个元素,则必不可能有重复元素
        struct ListNode* prev=NULL;//记录的是链表的尾元素,尾结点,同时prev还充当着判断链表头结点是否为空(类似于链表中都是一个元素)。
        struct ListNode* cur=pHead;
        struct ListNode* pnext=pHead->next;
        while(next)
        {
           if(cur->val==pnext->val)
           {   
              while(pnext && cur->val==pnext->val)//确定删除的区间cur--del
              {
                 pnext=pnext->next;
              }
              while(cur!=pnext)
              {
                  struct ListNode* del=cur;
                  cur=cur->next;
                  free(del);
              }
              if(prev==NULL)//此步是为了确定链表是否有首元素,
              //同时记录了链表的尾结点,其实最好放在else后面,
              //因为当链表中没有重复结点的话,此时pHead会为空。
              {
                  pHead=cur;
              }
              else
              {
                  prev->next=cur;//此时cur记录的是pnext的值,类似于1 2 3 3 4 4  5此时你在将3删除干净后将链表组合为 1 2 4 4 5
              }
              if(pnext)
              {
                  pnext=pnext->next;
              }
           }
           else
           {
            prev=cur;
            cur=pnext;
            pnext=pnext->next;
           }
        }
        return pHead;
    }
};

共同进步!!

以上是关于链表相关面试题:返回一个链表的深度拷贝,对链表进行插入排序,删除链表中重复的结点的主要内容,如果未能解决你的问题,请参考以下文章

数据结构c语言篇 《二》带头双向循环链表实现以及链表相关面试题(下)

链表相关面试题:返回两个链表的第一个交点,判断单链表是否有环,返回入环的第一个结点

剑指Offer之面试题6:从尾到头打印链表

链表相关面试题第三篇

链表题 面试题02.04. 分割链表290. 单词规律20. 有效的括号

链表相关面试题第二篇