链表面试题

203. 移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode *prev,*cur;
    cur=head;
    prev=NULL;
    while(cur)
    {
        if(cur->val==val)
        {
            struct ListNode *next=cur->next;
            free(cur);
            if(prev==NULL)//if(cur==head)
            head=next;//删除第一个
            else
                prev->next=next;

            cur=next;//这个要分开
            
        }
    else 
        {
            prev=cur;
            cur=cur->next;
        }
      
    }
    return head;

}

206. 反转链表
反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

第一种解法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* reverseList(struct ListNode* head)
{
    //头插完成单链表逆转
    //头插就是这个位置的next是现在的head;然后这个位置在变成head
    struct ListNode *newHead=NULL;
    struct ListNode *cur=head;
    while(cur)
    {
        struct ListNode *next=cur->next;
        cur->next=newHead;
        newHead=cur;
        cur=next;
    }
    return newHead;
}

第二种解法:

struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL||head->next==NULL)
    return head;
    struct ListNode *n1,*n2,*n3;
    n1=NULL;
    n2=head;
    n3=n2->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
        n3=n3->next;
    }
    return n1;
}

876. 链表的中间结点
给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* middleNode(struct ListNode* head){
    //快慢节点
    struct ListNode *fast,*slow;
    fast=head;
    slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    return slow;
}

链表中的倒K个节点
输入一个链表,输出该链表中倒数第k个结点。

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    //距离差,快的先走k
    //然后快的到空,慢的就到了倒数第k
    struct ListNode *fast,*slow;
    fast=slow=pListHead;
    while(k--)
    {
        if(fast)
            fast=fast->next;
        else
            return NULL;//k>链表长度
    }
    //存在
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(l1==NULL)
    return l2;
    if(l2==NULL)
    return l1;
    struct ListNode *cur1,*cur2,*newHead,*newTail;
    cur1=l1;
    cur2=l2;
    newHead=newTail=NULL;
   
    while(cur1&&cur2)
    {
        if(cur1->val<=cur2->val)
        {
           if(newTail==NULL)
                newHead=newTail=cur1;
           else
            {
                newTail->next=cur1;
                newTail=newTail->next;
            } 
            cur1=cur1->next;
        }
        else
        {
            if(newTail==NULL)
                newHead=newTail=cur2;
           else
            {
                newTail->next=cur2;
                //表尾记录,下一个位置是什么,在把下一个位置变成表尾
                newTail=newTail->next;//表尾拼接
            }
            cur2=cur2->next;
        }
       
    }
    //拷贝剩余元素
    if(cur1)
    {
      newTail->next=cur1;
    }
    if(cur2)
    {
        newTail->next=cur2;
    }
    return newHead;
}
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(l1==NULL||l2==NULL)
        return l1==NULL?l2:l1;
        struct ListNode *cur1,*cur2,*newHead,*newTail;
        newHead=newTail=(struct ListNode*)malloc(sizeof(struct ListNode));
        cur1=l1;
        cur2=l2;
        while(cur1&&cur2)
        {
            if(cur1->val<=cur2->val)
            {
                newTail->next=cur1;
                newTail=newTail->next;
                cur1=cur1->next;
            }
            else
            {
                newTail->next=cur2;
                newTail=newTail->next;
                cur2=cur2->next;
            }
        }
        if(cur1)
        newTail->next=cur1;
        if(cur2)
        newTail->next=cur2;
        struct ListNode *head=newHead->next;
        free(newHead);
        return head;
}
}

链表分割

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

//开空间的做法
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
         struct ListNode *cur,*lessHead,*lessTail,*greatHead,*greatTail;
        cur=pHead;
        lessHead=lessTail=(struct ListNode*)malloc(sizeof(struct ListNode));
        greatHead=greatTail=(struct ListNode*)malloc(sizeof(struct ListNode));
        while(cur)
        {
            if(cur->val<x)
            {
                lessTail->next=cur;
                lessTail=lessTail->next;
                cur=cur->next;
            }
            else{
                greatTail->next=cur;
                greatTail=greatTail->next;
                cur=cur->next;
            }
        }
        if(greatTail)
            greatTail->next=NULL;
        lessTail->next=greatHead->next;
        struct ListNode *head=lessHead->next;
        free(lessHead);
        free(greatHead);
        return head;
    }
};

链表的回文结构
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        if(A==NULL||A->next==NULL)
            return true;
        struct ListNode *fast,*slow,*start1,*start2;
        start1=fast=slow=A;
       
        //找到中间节点
        while(fast&&fast->next)
        {
            fast=fast->next->next;
            slow=slow->next;
        }
        //后半部分逆转
        
        struct ListNode *n1,*n2,*n3;
        n1=NULL;
        n2=slow;
        n3=n2->next;
        while(n2->next)
        {
            n2->next=n1;
            n1=n2;
            n2=n3;
            if(n3->next)
                n3=n3->next;
        }
        start2=n2;
        //遍历
        while(start1&&start2)
        {
            if(start1->val!=start2->val)
            {
                return false;
            }
            start1=start1->next;
                start2=start2->next;
            
        }
        return true;
    }

160. 相交链表
编写一个程序,找到两个单链表相交的起始节点

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    
    int lenA=0;
    int lenB=0;
    struct ListNode *curA=headA;
    struct ListNode *curB=headB;
    while(curA)
    {
        ++lenA;
        curA=curA->next;
    }
 
    while(curB)
    {
        ++lenB;
        curB=curB->next;
        
    }
    curA=headA;
    curB=headB;
    int gab=abs(lenA-lenB);
    if(lenA>lenB)
    {
        while(gab--)
        {
            curA=curA->next;
        }
    }
    else
    {
        while(gab--)
        {
            curB=curB->next;
        }
        
    }
    while(curA&&curB)
    {
        if(curA==curB)
        {
            return curA;
        }
        curA=curA->next;
        curB=curB->next;
    }
    return NULL;
    
}

141. 环形链表
给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

bool hasCycle(struct ListNode *head) {
    struct ListNode *fast,*slow;
    fast=slow=head;
    while(fast&&fast->next)
    {
         fast=fast->next->next;
            slow=slow->next;
        if(fast==slow)
        
          return true;
      
    }
    return false;
    
}

142. 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 //先判断是否有环
 struct ListNode* hasCycle(struct ListNode *head) {
    struct ListNode *fast,*slow;
    fast=slow=head;
    while(fast&&fast->next)
    {
    //距离差是一步,可以确保追上,步数大了就不太行
         fast=fast->next->next;
            slow=slow->next;
        if(fast==slow)
        return fast;//fast是相遇点,不一定是环的第一个节点
      
    }
    return NULL; 
}
struct ListNode *detectCycle(struct ListNode *head) {
     struct ListNode *cur=hasCycle(head);
     if(cur)
     {
         while(cur)
         {
             if(cur==head)
             return cur;
             cur=cur->next;
             head=head->next;
         }
     }
     return NULL;
}

138. 复制带随机指针的链表

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
	//拷贝数据
    if(head==NULL)
    return head;
    struct Node *cur=head;
    while(cur)
    {
        struct Node *newNode=(struct Node*)malloc(sizeof(struct Node));//一定要注意,这次又给忘记了
        newNode->val=cur->val;
        newNode->next=cur->next;//先赋值,再改指向
        cur->next=newNode;
        cur=newNode->next;
    }

    //拷贝随机指针
    cur=head;
    while(cur)
    {
        struct Node *copy=cur->next;
        if(cur->random)
        {
            copy->random=cur->random->next;
        }
        else
            copy->random=NULL;
            cur=copy->next;

    }
    //拆链
    struct Node *newHead=NULL;
    cur=head;
    while(cur)
    {
        struct Node *copy=cur->next;
        struct Node *next=copy->next;
        cur->next=next;
        if(newHead==NULL)
            newHead=copy;
        if(next)
        copy->next=next->next;

        cur=next;
    }
    return newHead;
}

147. 对链表进行插入排序
对链表进行插入排序

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* insertionSortList(struct ListNode* head){
    if(head==NULL||head->next==NULL)
        return head;
    struct ListNode *node=head->next;
    struct ListNode *tail=head;
    while(node)
    {
        if(node->val<tail->val)
        {
            struct ListNode *prev=NULL;
            struct ListNode *cur=head;
            while(cur&&cur->val<=node->val)//从第一个开始找
            //找到第一个大于node的值,cur大于node
            {
               prev=cur;
               cur=cur->next;//同时向后移动
            }
            tail->next=node->next;
            //可能在头部插入
            if(prev)
            prev->next=node;
            else
            head=node;
            node->next=cur;
            //下一个数据的排序,tail不变
            node=tail->next;
        }
        else
        {
            node=node->next;
            tail=tail->next;
        }
    }
        return head;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值