链表的相关笔试面试题

1.反转一个链表,不能申请新空间:

思路:反转一个链表,不申请新空间,即将一个链表通过头插+头删的方法进行替换;
反转前:1->2->3->4->5->NULL;
反转后:NULL->5->4->3->2->1;

struct ListNode* Reverselist(struct ListNode* head){
   struct ListNode* result=NULL;
   struct ListNode* code=head;
   while(code!=NULL){
      struct ListNode* next=code->next;
      code->next=result;
      result=code;
      code=next;
   }
   return result;
}
   
2.删除表中指定的所有节点:

思路:判断链表的的节点的值是否为指定节点的值有三种情况:
(1)当头节点为空时的情况;
(2)当头节点为指定节点的值时的情况;
(3)当头节点不是指定节点时的情况;

struct ListNode* RemoveElement{struct ListNode *head,int val){
   if(head==NULL){      //判断头节点是否为空;
      return 0;
   }
  
   struct ListNode* Node=head;
   while(Node->next!=NULL){     //链表中的指定节点删除;
      if(Node->next->val==val){
         struct ListNode* next=Node->next->next;
         free(Node->next);
         Node->next=next;
      }
      else{
         Node=Node->next;
      }
     
      if(head->val==val){       //当头节点是想要删除的节点;
         struct ListNode* second=head->next;
         free(head);
         return second;
      }
      else{
         return head;
      }
         


3.合并两个有序链表:

将两个链表合并成一个有序链表,并返回;新链表是通过拼接两个链表所给定的链表的值;
如:1->2->4,1->3->4;
拼接后:1->1->2->2->3->4->4;

struct ListNode* MergoTwoList(struct Listnode* L1,struct ListNode* L2){
//先判断两个链表是否为空;
   if(L1==NULL){
      return L2;
   }

   if(L2==NULL){
      return L1;
   }
 
//创建一个新链表,将两个拼接的链表放到新链表中;
   struct ListNode* L1=c1;
   struct ListNode* L2=c2;
   struct ListNode* begin=NULL;
   struct ListNode* end=NULL;

   while(c1!=NULL&&c2!=NULL){
      if (c1->val <=c2->val){
                 if (last != NULL){
                      last->next = c1;
                      last = c1;
                 }
                 else{
                      result = last = c1;
                 }
                 c1 = c1->next;
           }
           else{
                 if (last != c2){
                      last->next = c2;
                      last = c2;
                 }
                 else{
                      result = last = c2;
                 }
                 c2 = c2->next;
           }
      }
      if (c1!= NULL){
           last->next = c1;
      }
      if (c2 != NULL){
           last->next = c2;
      }
      return result;
}

4.分割链表问题:

编写代码,给定一个值x为基准,将链表分割为两部分,所有小于x的结点排在大于或等于x的链表之前;分割以后要保持原来的数据顺序不变;

思路:一个小于x的结果链表,一个大于等于x的结果链表,根据和x的关系,尾插到不同的链表中,把两个链表链接起来;

注意:需要注意比x小的或比x大的链表有为空的情况;一定要保证结果链表的最后一个节点为NULL;

   struct ListNode *partition(struct ListNode *PHead, int x){
      struct ListNode *small = NULL;
      struct ListNode *smallLast = NULL;
      struct ListNode *big = NULL;
      struct ListNode *bigLast = NULL;
      struct ListNode *node = PHead;
      while (node != NULL){
         if (node->val < x){
                 if (small == NULL){
                      small = smallLast = node;
                 }
                 else {
                      smallLast->next = node;
                      smallLast = node;
                 }
           }
           else{
                 if (big == NULL){
                      big = bigLast = node;
                 }
                 else{
                      bigLast->next = node;
                      bigLast = node;
                 }
           }
           node = node->next;
      }
      if (smallLast != NULL){
           smallLast->next = big;
      }
      if (bigLast != NULL){
           bigLast->next = NULL;
      }
      if (smallLast != NULL){
           return small;
      }
      else{
           return big;
      }
}
5.返回链表的中间节点:

给定一个带有头结点head的非空单链表,返回链表的中间结点,如果两个中间结点,则返回第二个中间结点;在这里考察的主要是指针的运用,通过快慢指针进行遍历,当一个指针指向NULL时,另一个指针刚好指向该链表的中间节点;


struct ListNode *middleNode(struct ListNode * head){
      struct ListNode *fast = head;
      struct ListNode *slow = head;
      while (fast!=NULL){
           fast = fast->next;
           if (fast == NULL){
                 break;
           }
           slow = slow->next;
           fast = fast->next;
      }
      return slow;
}

6.删除链表中的重复节点问题:

在一个排序的链表中存在着重复得结点,请删除该链表中的重复结点,重复的结点不保留,返回链表头指针;如:链表1->2->3->3->4->4->5,处理后为1->2->3->4->5;
这里可以通过双指针遍历去查找,当前面的指针指向的节点的值与后一个指针指向节点的值相同时,后面的指针指向的位置不变,前面的指针继续向前走,当两个指针指向的值不同时,后面的指针走到前面的指针的位置,前面的指针继续向前寻找,知道遇到NULL;


struct ListNode *deleteDuplication(struct ListNode * pHead){
      if (pHead == NULL){
           return NULL;
      }
       struct ListNode *fack = (ListNode *)malloc(sizeof(ListNode));
       fack->next = pHead;
       struct ListNode * prev = fack;
       struct ListNode * p1 = pHead;
       struct ListNode * p2 = pHead->next;
       while (p2 != NULL){
            if (p1->val != p2->val){
                  prev = p1;
                  p1 = p2;
                  p2 = p2->next;
            }
            else{
                  while (p2 != NULL  && p2->val == p1->val){
                       p2 = p2->next;
                  }
                  prev->next = p2;
                  p1 = p2;
                  if (p2 != NULL){
                       p2 = p2->next;
                  }
            }
       }
       pHead = fack->next;
       free(pHead);
       return fack->next;
}

7.找到两链表交叉的起始节点:

//先求出链表的长度;
int getLength(struct ListNode * head){
      int len = 0;
      for (struct ListNode *n = head; n; n->next->next){
           len++;
      }
      return len;
}

struct ListNode *getIntersectionNode(struct ListNode *PheadA, struct ListNode *PheadB){
      int lenA = getLength(PheadA);
      int lenB = getLength(PheadB);
      struct ListNode * longer = PheadA;
      struct ListNode * shorter = PheadB;
      int diff=lenA - lenB;
      if (lenB > lenA)
      {
           longer = PheadB;
           shorter = PheadA;
           diff == lenB - lenA;
      }
      for (int i = 0; i < diff; ++i){
           longer = longer->next;
      }
      while (longer != shorter){
           longer = longer->next;
           shorter = shorter->next;
      }
      return longer;
}

8.判断链表是否带环,找到环的入口点:
struct ListNode *detcctCycle(struct  ListNode *head){
      if (head == NULL){
           return NULL;
      }
      struct ListNode* fast = head;
      struct ListNode *slow = head;
      while (1){
           fast = fast->next;
           if (fast == NULL){
                 return NULL;
           }
           fast = fast->next;
           
           if (fast == NULL){
                 return NULL;
           }
           slow = slow->next;
           if (fast == slow){
                 break;
           }
      }
      struct ListNode * n1 = head;
      struct ListNode *n2 = slow;
      while (n1 != n2){
           n1 = n1->next;
           n2 = n2->next;
      }
      return n1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值