leetcode 链表所有题目

简单题目

141 判断一个链表是否有环   使用快慢指针

class Solution {  
public:  
    bool hasCycle(ListNode *head) {  
        ListNode* pFast=head;  
        ListNode* pSlow=head;  
        if(head==NULL) return false;  
        while(pFast!=NULL)  
        {  
            pSlow=pSlow->next;  
            pFast=pFast->next;  
            if(pFast==NULL) return false;  
            pFast=pFast->next;  
            if(pFast==NULL) return false;  
            if(pFast==pSlow) return true;  
        }  
    }  
};

237 删除链表中的指定节点

给定链表中的一个节点,将这个节点删除。单链表的特点是:不能找到前驱结点,本题的方法是,将下一个节点的值复制到当前节点,然后跳过下一个节点。

class Solution {  
public:  
    void deleteNode(ListNode* node) {  
        if (node==NULL) return;  
        else  
        {  
            node->val=node->next->val;  
            node->next=node->next->next;  
        }  
    }  
}; 

83.在排序链表中删除重复的节点

Given  1->1->2 , return  1->2 .
Given  1->1->2->3->3 , return  1->2->3 .

方法1:使用一个循环,循环判断cur->next,之前需要判断head是否为空

class Solution {  
public:  
    ListNode* deleteDuplicates(ListNode* head) {  
       ListNode* cur=head;  
       if(head==NULL) return head;  
       while(cur->next)  
       {  
           if(cur->next->val==cur->val)  
           cur->next=cur->next->next;  
           else  
           cur=cur->next;  
       }  
       return head;  
    }  
};  
方法2:循环判断当前节点

class Solution {  
public:  
    ListNode* deleteDuplicates(ListNode* head) {  
       ListNode* cur=head;  
       while(cur)  
       {  
           while(cur->next&&cur->next->val==cur->val)  
           cur->next=cur->next->next;  
           cur=cur->next;  
       }  
       return head;  
    }  
};  
方法3:递归版本

class Solution {  
public:  
    ListNode* deleteDuplicates(ListNode* head) {  
      if(head==NULL||head->next==NULL) return head;  
      head->next=deleteDuplicates(head->next);  
      return head->val==head->next->val?head->next:head;  
    }  
}; 

160. Intersection of Two Linked Lists 找到两个链表的公共节点

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

方法1:先求两个链表的长度,然后让唱的指针先走掉长出的部分,最后两个链表一起走指针。时间复杂度为O(m+n),空间复杂度是1。

class Solution {  
public:  
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {  
        if(headA==NULL||headB==NULL) return NULL;  
        unsigned int lengthA=getLength(headA);  
        unsigned int lengthB=getLength(headB);  
        ListNode *pA=headA,*pB=headB;  
        if(lengthA<lengthB)  
       {   
           int clap=lengthB-lengthA;  
        while(clap!=0){  
        headB=headB->next;  
        clap--;}  
       }  
       else {  
           int clap=lengthA-lengthB;  
           while(clap!=0){  
           headA=headA->next;  
           clap--;}  
       }  
       while(headA!=headB&&headA!=NULL&&headB!=NULL)  
       {  
           headA=headA->next;  
           headB=headB->next;  
       }  
       return headA;  
  
    }  
    unsigned int getLength(ListNode* pcurrent)//长度计算函数  
    {  
        ListNode* p=pcurrent;  
        unsigned int length=0;  
        while(p!=nullptr)  
        {  
            ++length;  
            p=p->next;  
        }  
        return length;  
    }  
};  

 206 翻转链表

方法一:自己想的,初级想法
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
//注意处理开头部分和特殊情况
        if(head==NULL||head->next==NULL) return head;
        ListNode* pNext=head->next;
        if(pNext->next==NULL) {
            pNext->next=head;
            head->next=NULL;
            return pNext;
        }
        ListNode* pNextNext=pNext->next;
        head->next=NULL;
        pNext->next=head;
        while(pNextNext!=NULL)
        {
            ListNode* pTemp=pNextNext->next;
            pNextNext->next=pNext;
            pNext=pNextNext;
            pNextNext=pTemp;
        }
       
        return pNext;
        
    }
};

方法2:预设0表头,并添加另外一个指针,用这两个头指针操作后续节点
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //使用pre零头结点和cur原来的头结点处理链表,这个程序全程pre和cur都没有变,变的是他们指向的子节点
        ListNode* pre=new ListNode(0);//新建零表头
        pre->next=head;
        ListNode* cur=head;
        while(cur&&cur->next)
        {
            ListNode* temp=pre->next;//用一个指针存储需要被指向的父节点
            pre->next=cur->next;//pre指向原来的子节点
            cur->next=cur->next->next;//cur指向子节点的下一个节点,可能是空的
            pre->next->next=temp;//将子节点的下一个节点指向存储好的父节点位置temp,这里不能指向cur,因为cur保存的永远是原来的第一个头结点
        }
        //当cur头指向的下一个子节点是空节点时
        return pre->next;
        
    }
};

方法3:使用三个指针,循环操作,pre是当前节点的前一个节点,如果当前节点时头结点,pre预设为NULL,head是当前节点,next是head的下一个节点
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
       ListNode* pre=NULL;
        while(head){
            ListNode* next=head->next;
            head->next=pre;
            pre=head;
            head=next;
        }
        return pre;
    }
};
方法4:使用递归,找到最后一个节点,每层递归都是把当前节点的子节点的next指向当前节点,当前节点指向空,不会存在丢失现象,因为递归的层次保留了节点的指向信息。注意书写递归函数的返回位置和返回值是很很重要的。
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
      if(head==NULL||head->next==NULL) return head;//考虑head是空的情况,这句目的是找到最后一个节点
        ListNode* cur=reverseList(head->next);
        //递归的根节点时,cur得到的是当前head的子节点
        head->next->next=head;
        head->next=NULL;
        return cur;//cur保存最后的尾节点
    }
};

234  Palindrome Linked List 回文链表

自己想的方法,结果不对
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        //自己想的方法,使用递归的形式,参照206中的递归方法
        ListNode* pCur=head;   
        return comP(head,pCur,0);
    }
    bool comP(ListNode* head,ListNode* pCur,int count){
        
        if(pCur==NULL||pCur->next==NULL) {
            length=count;
            return true;
        }
        count++;
        bool tempdecide=comP(head,pCur->next,count);
        if(tempdecide==false) return false;
        count--;
        if(count*2<length) return tempdecide;
        if(head->val==pCur->next->val){
            head=head->next;
            return true;
        }
        else return false;
        
    }
    private:
    int length;
    
};
方法1:
(1)使用快慢指针,让快指针指向最后一个节点,慢指针指向中间位置;
(2)对慢指针进行操作,慢指针之后的链表做翻转操作(第206道题);
(3)相当于将原来的指针分成两个指针,然后依次比较两个指针每个值的大小,开始的链表从原来的头部比较
(4)比较的时候,当后面的链表结束的时候,比较结束,当原链表长度是奇数时,前面的链表最后一个节点不参与比较;
class Solution {
public:
    bool isPalindrome(ListNode* head) {
     if(head==NULL||head->next==NULL) return true;
        ListNode* slow=head;
        ListNode* fast=head;
        //让快指针运动到最后,这时如果是偶数个,慢指针指向中间偏左的节点,如果是奇数个,慢指针指向中间的节点
        while(fast->next&&fast->next->next)
        {
            slow=slow->next;
            fast=fast->next->next;
        }
        slow->next=reverseList(slow->next);
        slow=slow->next;
        while(slow){
            if(slow->val!=head->val) return false;
            slow=slow->next;
            head=head->next;
        }
        return true;
    }
    //翻转链表,使用206第三种方法
    ListNode* reverseList(ListNode* head){
        ListNode* pre=NULL;
        ListNode* next=NULL;
        while(head){
           next=head->next;
            head->next=pre;
             pre=head;
            head=next;  
        }
        return pre;
    }
};

方法3:递归调用,递归函数的返回值是布尔型,每次判断的结果是回调的结果与当前比较的与。注意,在类中定义一个指针用于保存初始头结点,相当于全局变量。

class Solution {
public:
    ListNode* temp;
    bool isPalindrome(ListNode* head) {
        if(head==NULL) return true;
        temp=head;
        return check(head);
    }
    bool check(ListNode* head){
        if(head==NULL) return true;
        bool tempcheck=check(head->next)&(temp->val==head->val);
        temp=temp->next;
        return tempcheck;
    }
};

21 合并两个排序链表 merge two linked list

方法1:自己写的方法,
(1)设置一个头指针,开始时指向较小的那个节点
(2)然后进入循环,每次指向较小的节点,并且被并入的节点对应的链表后移一个。
(3)要注意两个链表不一样长的时候,在结尾需要做处理。

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(l1==NULL) return l2;
        if(l2==NULL) return l1;
        ListNode* prehead=new ListNode(0);
         if(l1->val<l2->val)
        {
            prehead->next=l1;
            l1=l1->next;
        }
        else
        {
            prehead->next=l2;
            l2=l2->next;
        } 
        ListNode* temp=prehead->next;
        while(l1&&l2){
             if(l1->val<l2->val)
        {
            temp->next=l1;
            l1=l1->next;
        }
        else
        {
            temp->next=l2;
            l2=l2->next;
        } 
            temp=temp->next;
        }
        if(l1==NULL)
            temp->next=l2;
        else
            temp->next=l1;
        return prehead->next;

        
    }
};

方法2:递归方法

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(l1==NULL) return l2;
        if(l2==NULL) return l1;
        if(l1->val<l2->val)
        {
            l1->next=mergeTwoLists(l1->next,l2);
            return l1;
        }
        else
        {
            l2->next=mergeTwoLists(l2->next,l1);
            return l2;
        }

        
    }
};
方法3:
方法1的改进版本。
一方面,可以把开始的部分合并,方法是做一个头指针的拷贝,开始关于是否有空指针的判断也可以省略不写。另一个方面,最后的判断可以使用条件语句快速写出。
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* prehead=new ListNode(0);
        ListNode* head=prehead;
        while(l1&&l2){
             if(l1->val<l2->val)
        {
            prehead->next=l1;
            l1=l1->next;
        }
        else
        {
            prehead->next=l2;
            l2=l2->next;
        } 
            prehead=prehead->next;
        }
       prehead->next=l1?l1:l2;
        return head->next; 
    }
};

中等难度


61 Rotate List 

描述:给定一个链表,在链表的倒数第k个位置旋转链表

Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.

方法:先让一个指针移动k-1步,然后和另外一个头指针一起移动,当最前面的指针移动到末尾时,后面的指针正好移动到旋转位置;
注意要保存后一个指针的前一个指针,还要保存头指针。

自己写的:出现很多的调试错误
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head==NULL||k<=0) return head;
        ListNode* frontNode=head;
        //如果k的值大于链表长度怎么办?
        --k;
        while(k&&frontNode!=NULL)
        {
            frontNode=frontNode->next; 
            k--;
        }
        if(frontNode==NULL) return head;
        ListNode* backNode=head;
        ListNode* tempNode=head;
        while(frontNode->next){
            frontNode=frontNode->next;
            tempNode=backNode;
            backNode=backNode->next;
        }
        if(backNode==head) return head;
        frontNode->next=head;
        tempNode->next=NULL;
        return backNode;
    }
};
方法1: 首先遍历一边求出总的长度,并把链表编程环,然后根据整除数对链表做操作
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
      if(!head) return NULL;
        int length=1;
        ListNode* tail=head;
        while(tail->next){
            tail=tail->next;
            length++;
        }
        tail->next=head;//变成环状链表
        if(k%=length)//对移动k数取余数
        {
            for(auto i=0;i<length-k;i++) tail=tail->next;//让tail从尾节点移动到旋转节点的前一个节点
        }
        ListNode* newHead=tail->next;
        tail->next=NULL;
        return newHead;
    }
};

143 recorder List

Given a singly linked list LL0?L1?…?Ln-1?Ln,
reorder it to: L0?Ln?L1?Ln-1?L2?Ln-2?…

You must do this in-place without altering the nodes' values.

For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.

交叉更改链表顺序,但是不能直接改变数值

我的思路:使用快慢指针,将后半段链表翻转,使用前面回文串的思路,然后与第一个链表交叉起来。

这个思路与标准思路一致

class Solution {
public:
    void reorderList(ListNode* head) {
        if(head==NULL) return ;
        ListNode* fast=head;
        ListNode* slow=head;
        while(fast->next&&fast->next->next){//注意判断条件,需要后面两个子节点都判断
            fast=fast->next->next;
            slow=slow->next;
        }
        //操作slow指针后面的链表,将其翻转
        slow->next=reverseNode(slow->next);
        //将链表截断,slow指向空,然后新的slow指向后面的翻转链表
        ListNode* tail=slow;
        slow=slow->next;
        tail->next=NULL;
        //下面将两个链表合并到一起,注意末尾操作的特殊性
        ListNode* newHead=head;
        while(slow)//注意判断条件决定最后末尾的操作,head的长度可能比slow多一位
        {
            ListNode* next1=head->next;
            ListNode* next2=slow->next;
            head->next=slow;
            slow->next=next1;
            slow=next2;
            head=next1;
        }
        return ;
    }
    //翻转链表的函数
    ListNode* reverseNode(ListNode* head){
        //使用pre、head、next三个指针
        ListNode* pre=NULL;
        ListNode* next=NULL;
        while(head)//注意这里的判断条件,决定末尾的情况。一定不能出现空指针next操作
        {
            next=head->next;
            head->next=pre;
            pre=head;
            head=next;
        }
        return pre;
    }
};

142Linked List Cycle II 环状链表2

给定一个链表,返回链表环开始的节点,如果没有环,返回null。
分析:http://blog.csdn.net/wuzhekai1985/article/details/6725263
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head==NULL) return head;
        ListNode* fast=head;
        ListNode* last=head;
        while(fast->next&&fast->next->next)//注意需要先判断fast->next,因为必须满足这一点才能继续往下判断
        {
            last=last->next;
            fast=fast->next->next;
            if(last==fast) break;
            
        }
        if(fast->next==NULL||fast->next->next==NULL) return NULL;
        while(true){
            if(head==last) break;
            head=head->next;
            last=last->next;
        }
        return head;
    }
};

138Copy List with Random Pointer26.3%Medium

给出的链表在正常链表的基础上,每个节点还有一个随机指针指向此链表的一个节点,题目要求返回这个链表的一个拷贝
拷贝需要新建节点,难点在于怎么处理各节点之间的随机关系
思路:
(1)在原链表每个节点后面插入一个链表,并拷贝相应的值
(2)随机指针的处理,只要将新节点的随即指针指向它前面节点随机指针的下一个即可
(3)最后将链表拆解开
class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
       
        if(head==NULL) return NULL;
        RandomListNode* headCopy=head;//复制原来的头结点
         //第一步,在每个节点后面复制一个相同数值的节点
        while(head){
            RandomListNode* newNode=new RandomListNode(head->label);
            RandomListNode* next=head->next;
            head->next=newNode;
            newNode->next=next;
            head=next;
        }
        //第二步,处理随机指针,将每个新节点的random指针指向,它前面节点random指针指向的下一个节点
        RandomListNode* newHead=headCopy->next;
        RandomListNode* headCopyCopy=headCopy;
        while(headCopy){
            newHead->random=headCopy->random?headCopy->random->next:NULL;//注意random不一定指向一个节点,有可能是空值
            headCopy=headCopy->next->next;
            if(headCopy==NULL) break;
            newHead=newHead->next->next;//当到达尾部时,newHead处于结尾,这个语句将产生错误,所以需要在前面退出程序
        }
        //第三步,分解现在的链表
        headCopy=headCopyCopy;
        newHead=headCopy->next;
        while(headCopy&&headCopy->next&&headCopy->next->next){
            RandomListNode* middle=headCopy->next;
            RandomListNode* last=middle->next;
            headCopy->next=last;
            headCopy=middle;
            }
        headCopy->next=NULL;
        return newHead;
    }
};

https://www.nowcoder.com/practice/f836b2c43afc4b35ad6adc41ec941dba?tpId=13&tqId=11178&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking   这是牛客网上自己写的另外一个版本

92Reverse Linked List II   倒置链表 2

206的增进版本,截取链表的m到n的部分,翻转链表,在原来位置上改动,不允许额外的空间,要求一次完成
例如:

Given 1->2->3->4->5->NULLm = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note:
Given mn satisfy the following condition:

1 ≤ m ≤ n ≤ length of list.

自己的思路:与前面的206没有太大的区别,需要注意的几点是:

(1)应该设置表头指针,这样能处理第一个节点就参与旋转的情况;

(2)注意要设置多个指针保存中间段的入口和出口一共四个节点;

(3)m和n相等的情况是特殊的,在程序开始时直接处理。

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
         if(head==NULL||m==n) return head;
       
        ListNode* preHead=new ListNode(-1);//表头指针
        ListNode* result=preHead;
        preHead->next=head;//表头指针指向原来的头结点,这能解决开始头结点就需要旋转的情况
        ListNode* frontEntry=NULL;//保存入口之前的节点
        //需要表头指针
         for(int i=0;i<m;i++)
         {
             frontEntry=preHead;
             preHead=preHead->next; 
         }
        //下面旋转节点,采用三节点法,三个指针依次是preNode、preHead、next
        ListNode* preNode=NULL;
        ListNode* frontNode=preHead;//保存入口节点
        for(int i=0;i<n-m+1;i++){
            ListNode* next=preHead->next;
            preHead->next=preNode;
            preNode=preHead;//注意
            preHead=next;//注意这两行的顺序
            
        }
        //此时preNode指向出口节点,preHead指向出口节点的下一个节点
        frontEntry->next=preNode;//原来的入口指向中间新的头部
        frontNode->next=preHead;//中间新段的尾部指向后来剩余的头部
        return result->next;
    }
};

19Remove Nth Node From End of List33.3%Medium

将一个链表的倒数第n个节点去除,返回链表的头结点

Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.

主要的难点是删除的点是第一个时怎么操作,采取的办法是认为的定义一个头结点指向原来的头结点。

方法1,代码如下:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //如果移除的是第一个节点,呵呵
        //考虑这种特殊的情况,需要定义一个头结点指向原来的头结点,这样就能解决删除第一个节点的情况了
        ListNode* newHead=new ListNode(0);
        newHead->next=head;
        ListNode * fast =newHead,* slow=newHead;
        for(int i=0;i<n;i++)
            fast=fast->next;
        while(fast->next)
        {
            slow=slow->next;
            fast=fast->next;
        }
        ListNode* toBeDelete=slow->next;
        slow->next=slow->next->next;
        delete toBeDelete;
        return newHead->next;
    }
};

Add Two Numbers  27.6%Medium

描述:两个链表存储每一位数,求加和的新链表
要求:争取一次遍历成功

自己的代码:有错崩溃

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        //注意两个链表的长度可能不一样长
       int addNumber=0;
        ListNode* cl1=l1,* cl2=l2,* tempNode=l1;
        while(cl1&&cl2)
        {
            int temp=cl1->val+cl2->val+addNumber;
            if(temp>9){
        addNumber=1;
            cl1->val=temp-10;
            }
            else{
                addNumber=0;
                cl1->val=temp;
            }
            tempNode=cl1;
            cl1=cl1->next;
            cl2=cl2->next;
            
        }
        if(cl1==NULL&&cl2!=NULL)
        {
            tempNode->next=cl2;
        }
      
            while(tempNode)
            {
                int temp=tempNode->val+addNumber;//有错
                if(temp>9){
        addNumber=1;
            tempNode->val=temp-10;
            }
            else{
                addNumber=0;
                tempNode->val=temp;
            }
                            cl1=tempNode;
            tempNode=tempNode->next;
            }
        if(addNumber==1)
        {
            ListNode* temp=new ListNode(1);
            cl1->next=temp;
        }
        return l1;
    }
};

方法:新建一个链表,在循环中单独判断两个链表是否为空,使用sum保存每次的加和,并在链表中保存余数,在下一次循环中,这个sum值的起始值是除10后的数。

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
      ListNode *c1=l1;
        ListNode *c2=l2;
        ListNode * result=new ListNode(0);
        ListNode* tempNode=result;
        int sum=0;
        while(c1||c2)
        {
            sum/=10;
            if(c1)
            {
                sum+=c1->val;
                c1=c1->next;
            }
            if(c2){
                sum+=c2->val;
                c2=c2->next;
            }
            tempNode->next=new ListNode(sum%10);
            tempNode=tempNode->next;
        }
        if(sum>9)
        {
            tempNode->next=new ListNode(1);
        }
        return  result->next;
    }
};

另外一种方法:使用条件运算符简化代码

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
      ListNode* p=new ListNode(0);
        ListNode * temp=p;
        int extra=0;
        while(l1||l2||extra){
            int sum=extra+(l1?l1->val:0)+(l2?l2->val:0);
            extra=sum/10;
            temp->next=new ListNode(sum%10);
            temp=temp->next;
            l1=l1?l1->next:l1;
            l2=l2?l2->next:l2;
        }
        return p->next;
    }
};






445Add Two Numbers II46.1%Medium

描述:这个题目是增进版本,高位数在前面,低位数在后面

Example:

Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 8 -> 0 -> 7

24Swap Nodes in Pairs38.2%Medium

给定一个链表,交换两个相邻的节点

只能使用常数空间,不能更改节点的值
Given  1->2->3->4 , you should return the list as  2->1->4->3 .
思路:
因为第一个节点会变,所以设置表头指针。
由于奇偶性不同,一次循环需要处理两个节点。
如果是奇数个,最后一个节点不动。
自己写的代码: 题目比较简单,主要是考虑每次循环如何处理(要做三次指针操作,并且保存下一次循环的指针p)
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head==NULL) return head;
        ListNode* preHead=new ListNode(0);
        preHead->next=head;
        ListNode* p=preHead;
        while(p->next&&p->next->next){
            ListNode* next=p->next;
            ListNode* nextNext=next->next;
            ListNode* third=nextNext->next;
            p->next=nextNext;
            nextNext->next=next;
            next->next=third;
            p=next;
        }
        return preHead->next;
    }
};


86Partition List 32.5%Medium 类似快速排序

给定一个数,将链表重新排序
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
自己的思路:设置两个指针,分别指向小于指定数和大于指定数。当遍历完成之后,合并两个链表。
小链表要保存头部作为所有的头,大链表也要保存头部与小链表的尾部相连,大链表的为节点需要指向NULL。
如果所有的值都小于这个数,和所有值都大于这个数,程序也可以正常执行
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        if(head==NULL) return head;
        ListNode* small=new ListNode(-1);
        ListNode* big=new ListNode(-1);
        ListNode* smallCopy=small;
        ListNode* bigCopy=big;
        while(head){
            if(head->val<x){
                smallCopy->next=head;
                smallCopy=head;
            }
            else
            {
                bigCopy->next=head;
                bigCopy=head;
            }
            head=head->next;
        }
        bigCopy->next=NULL;
        smallCopy->next=big->next;
        delete big;
        delete small;
        return small->next;
    }
};
别人的思路基本一致。

82Remove Duplicates from Sorted List II29.4%Medium

给定一个排序链表,去除链表中所有重复的数,注意重复的数字全部去除。与版本I不同,版本1是留下一个重复的数字。
自己的思路:设置起始头结点,它所指向的数必须和后面的数不同。编不下去喽
看别人的思路使用递归

放一放吧

328Odd Even Linked List 43.4%Medium

将一个链表原来处在奇数位置的节点放到前面,偶数位置的节点放到后面
Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.
自己的思路:与86题思路类似,设置两个表头指针odd和even,分别指向奇数和偶数节点,完成后将奇数节点的尾节点指向偶数的头结点。
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        ListNode* preOdd=new ListNode(-1);
        ListNode* preEven=new ListNode(-1);
        ListNode* odd=preOdd;
        ListNode* even=preEven;
        bool oddOrEven=true;//奇数为true,偶数为false
        while(head){
            if(oddOrEven){
                odd->next=head;
                odd=head;
                oddOrEven=false;
            }
            else{
                even->next=head;
                even=head;
                oddOrEven=true;
            }
            head=head->next;
        }
        even->next=NULL;
        odd->next=preEven->next;
        return preOdd->next;
    }
};

109Convert Sorted List to Binary Search Tree  33.8%Medium


148 sort list  

将一个链表排序,要求时间复杂度是 O ( n  log  n ),空间复杂度是1.
使用归并排序
147 insertion sort list  
使用直接插入排序将一个链表排序。

25. Reverse Nodes in k-Group

自己写的代码:
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* last=head;
        ListNode*newHead=new ListNode(0);
        newHead->next=head;
        ListNode* first=newHead;
        int n=1;
        while(last)
        {
            if(n==k) {//如果收集到了k个节点
                ListNode* pre=last->next;
                ListNode* temp=first->next;
                ListNode* nowHead=first->next;
                while(n)
                {
                    ListNode* next=nowHead->next;
                    nowHead->next=pre;
                    pre=nowHead;
                    nowHead=next;
                    n--;
                }
                n=1;
                first->next=pre;
                first=temp;
                last=first->next;
                continue;
            }
            last=last->next;
            n++;
        }
        n--;
        return newHead->next;
    }     
    
};






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Rust 是一种现代的编程语言,特别适合处理内存安全和线程安全的代码。在 LeetCode 中,链表是经常出现的题目练习类型,Rust 语言也是一种非常适合处理链表的语言。接下来,本文将从 Rust 语言的特点、链表的定义和操作,以及 Rust 在 LeetCode链表题目的练习等几个方面进行介绍和讲解。 Rust 语言的特点: Rust 是一种现代化的高性能、系统级、功能强大的编程语言,旨在提高软件的可靠性和安全性。Rust 语言具有如下几个特点: 1. 内存安全性:Rust 语言支持内存安全性和原语级的并发,可以有效地预防内存泄漏,空悬指针以及数据竞争等问题,保证程序的稳定性和可靠性。 2. 高性能:Rust 语言采用了“零成本抽象化”的设计思想,具有 C/C++ 等传统高性能语言的速度和效率。 3. 静态类型检查:Rust 语言支持静态类型检查,可以在编译时检查类型错误,避免一些运行时错误。 链表的定义和操作: 链表是一种数据结构,由一个个节点组成,每个节点保存着数据,并指向下一个节点。链表的定义和操作如下: 1. 定义:链表是由节点组成的数据结构,每个节点包含一个数据元素和一个指向下一个节点的指针。 2. 操作:链表的常用操作包括插入、删除、查找等,其中,插入操作主要包括在链表首尾插入节点和在指定位置插入节点等,删除操作主要包括删除链表首尾节点和删除指定位置节点等,查找操作主要包括根据数据元素查找节点和根据指针查找节点等。 Rust 在 LeetCode链表题目的练习: 在 LeetCode 中,链表是常见的题目类型,而 Rust 语言也是一个非常适合练习链表题目的语言。在 Rust 中,我们可以定义结构体表示链表的节点,使用指针表示节点的指向关系,然后实现各种操作函数来处理链表操作。 例如,针对 LeetCode 中的链表题目,我们可以用 Rust 语言来编写解法,例如,反转链表,合并两个有序链表,删除链表中的重复元素等等,这样可以更好地熟悉 Rust 语言的使用和链表的操作,提高算法和编程能力。 总之,在 Rust 中处理链表是非常方便和高效的,而 LeetCode 中的练习也是一个非常好的机会,让我们更好地掌握 Rust 语言和链表数据结构的知识。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值