链表LintCode题目总结(入门-简单)

单链表LintCode题目总结(入门-简单)版

链表的实现:

class ListNode {
  public:
     int val;
     ListNode *next;
     ListNode(int val) 
     {         
       this->val = val;
       this->next = NULL;
     }
  }

225·在链表中找节点(入门)

样例1

输入:  1->2->3 and value = 3
输出: 最后一个结点

样例2

输入:  1->2->3 and value = 4
输出: null

代码实现

ListNode * findNode(ListNode * head, int val) {
        // write your code here
        ListNode *find=head;
        while(find!=NULL)//循环遍历直至空指针
        {
            if(val==find->val)
            {
                return find;
            }
            else
            find=find->next;
        }
        return NULL;
    }

228 · 链表的中点(入门)

描述
找链表的中点,并返回这个节点。
样例1:

输入:  1->2->3
输出: 2	
样例解释: 返回中间节点

样例2:

输入:  1->2
输出: 1	
样例解释: 如果长度是偶数,则返回中间偏左的节点。	

代码实现

ListNode * middleNode(ListNode * head) 
{
        // write your code here
        if (head == NULL) 
        return head;
        ListNode *fast=head->next;//快指针,一次遍历两个节点
        ListNode *slow=head;//慢指针,一次遍历一个节点,是我们需要返回的值
   
        while(fast!=NULL&&fast->next!=NULL)//当快指针指向空或其下一个表指向空结束循环
        {
            fast=fast->next->next;
            slow=slow->next;
        }
        return slow;
 }

466 · 链表节点计数(入门)

描述
计算链表中有多少个节点.

样例

样例  1:
	输入:  1->3->5->null
	输出: 3
	
	样例解释: 
	返回链表中结点个数,也就是链表的长度.

样例 2:
	输入:  null
	输出: 0
	
	样例解释: 
	空链表长度为0

代码实现

int countNodes(ListNode * head) {
        // write your code here
        int ans=0;//计数
        while(head!=NULL)
        {
            head=head->next;
            ans++;
        }
        return ans;
    }

483 · 链表转数组(入门)

描述
将一个链表转换为一个数组。

样例

样例 1:
输入: 1->2->3->null
输出: [1,2,3]

样例 2:
输入: 3->5->8->null
输出: [3,5,8]

代码实现

vector<int> toArrayList(ListNode * head) {
        // write your code here
        vector<int> v1;
        ListNode *find=head;
        while(find!=NULL)
        {
            v1.push_back(find->val);
            find=find->next;
        }
        return v1;
    }

35 · 翻转链表(一)(简单)

翻转一个链表

链表长度小于 100100

样例

样例 1:
输入:
链表 = 1->2->3->null
输出:
3->2->1->null

样例 2:
输入:
链表 = 1->2->3->4->null
输出:
4->3->2->1->null

代码实现

ListNode * reverse(ListNode * head) 
{
     // write your code here
       ListNode *Newhead=NULL;//记录前一个节点
       ListNode *Next=NULL;//用于标记下一个节点
       ListNode *Cur=head;//遍历和转向用
       while(Cur!=NULL)
       {
           Next=Cur->next;//记录下一个节点
           Cur->next=Newhead;//转向
           Newhead=Cur;//后移
           Cur=Next;//后移
       }
       return Newhead;
}

35反转链表
反转链表流程图

96 · 链表划分(简单)

描述
给定一个单链表和数值x,划分链表使得所有小于x的节点排在大于等于x的节点之前。你应该保留两部分内链表节点原有的相对顺序。
样例:

样例 1:
输入:
list = null
x = 0
输出:
null
解释:
空链表本身满足要求

样例 2:
输入:
list = 1->4->3->2->5->2->null
x = 3
输出:
1->2->2->4->3->5->null
解释:
要保持原有的相对顺序。

代码实现

ListNode * partition(ListNode * head, int x) {
			ListNode* phead = new ListNode(-1);//建立一个值为-1的头节点
       phead->next = head;//指向给定链表
       ListNode* pre = phead;//指向-1的节点
       ListNode* cur = phead;//指向-1的节点
       
       while(cur->next)//当cur走到最后一个节点出循环
       {
           if(cur->next->val >= x)//跟给定值比大小
           {
               cur = cur->next;//大于等于时,后移
           }
           else if(cur == pre)//当pre和cur指向同一个节点时
           {
               cur = cur->next;//后移
               pre = pre->next;//后移
           }
           else//出现小于的值时
           {
               ListNode* temp = cur->next;//记录cur的后一个节点,即记录需要处理的节点
               cur->next = temp->next;//指向后一个节点,起到删除temp的作用
               temp->next = pre->next;//temp插入到pre后的位置
               pre->next = temp;//原pre指向temp;
               pre = pre->next;//pre后移一位,即到达temp位;
           }   
       }
       return phead->next;
    }

96链表划分
链表划分图

112 · 删除排序链表中的重复元素(简单)

描述
给定一个排序链表,删除所有重复的元素,每个元素只留下一个。
样例

样例 1:

输入:
linked list = null
输出:
null
解释:
空链表返回null

样例 2:

输入:
linked list = 1->1->2->null
输出:
1->2->null
解释:
删除重复的1

样例 3:

输入:
linked list = 1->1->2->3->3->null
输出:
1->2->3->null
解释:
删除重复的13

代码实现

ListNode * deleteDuplicates(ListNode * head) {
        // write your code here
        ListNode *find=head;//用来遍历链表
        while(find!=NULL&&find->next!=NULL)
        {
            if(find->next->val==find->val)
            {
                ListNode *temp=find->next->next;//重复节点之后的节点
                delete find->next;//删除重复节点
                find->next=temp;//连接链表
            }
            else
            find=find->next;//后移
        }
        return head;
    }

165 · 合并两个排序链表(简单)

描述
将两个排序(升序)链表合并为一个新的升序排序链表

样例

样例 1:
	输入: list1 = null, list2 = 0->3->3->null
	输出: 0->3->3->null


样例2:
	输入:  list1 =  1->3->8->11->15->null, list2 = 2->null
	输出: 1->2->3->8->11->15->null

代码实现
这里我们使用一个递归函数来实现

  ListNode * mergeTwoLists(ListNode * l1, ListNode * l2) {
        // write your code here
        ListNode *temp;//定义一个暂时的链表
        if(l1==NULL&&l2!=NULL)//若l1空了且l2不为空,则temp链表后面项就后应该是l2
                return l2;
       if(l2==NULL&&l1!=NULL)
                return l1;
        if(l1==NULL&&l2==NULL)
            return NULL;
        if(l1->val>l2->val)//比较节点大小
        {
           temp=l2;//将小节点放入temp中
            l2->next=mergeTwoLists(l1,l2->next);//递归,放入节点的链表后移
        }
        else
        {
            temp=l1;
            l1->next=mergeTwoLists(l1->next,l2);
        }
        return temp;每递归一次就返回一次
    }

来个常规写法,思路是比较大小,然后放入新链表中。代码更好理解

 ListNode * mergeTwoLists(ListNode * l1, ListNode * l2) {
        // write your code here
        ListNode *head=new ListNode(-1);//整一个新节点,来存数据
        ListNode *cur=head;
        while(l1&&l2)//有一个链表为空就跳出循环
        {
           if(l1->val>l2->val)
           {
                cur->next=l2;
                l2=l2->next;   
           }
           else
           {
                cur->next=l1;
                l1=l1->next;  
           }
           cur=cur->next;//后移
        }
        cur->next=l1?l1:l2;//若出现有一个链表为空,将另一个链表放入cur中
        //a?b:c 当a为真时,返回b,否则返回c
        return head->next;
     }

166 · 链表倒数第n个节点(简单)

描述
找到单链表的倒数第n个节点,保证链表中节点的最少数量为n。
样例

样例 1:
	输入: list = 3->2->1->5->null, n = 2
	输出: 1

样例 2:
	输入: list  = 1->2->3->null, n = 3
	输出: 1

代码实现:
还是使用快慢指针来实现

ListNode * nthToLast(ListNode * head, int n) {
        // write your code here
        ListNode * fast=head;
        ListNode *slow=head;
        for(int i=0;i<n;i++)//让快指针往前先走n下
            {
                fast=fast->next;
            }
        while(fast!=NULL)//快慢指针一起走
        {
            fast=fast->next;
            slow=slow->next;
        }
        return slow;
    }

167 · 链表求和(简单)

描述
你有两个用链表代表的整数,其中每个节点包含一个数字。数字存储按照在原来整数中相反的顺序,使得第一个数字位于链表的开头。写出一个函数将两个整数相加,用链表形式返回和。
样例

样例 1:
输入: 7->1->6->null, 5->9->2->null
输出: 2->1->9->null	
样例解释: 617 + 295 = 912, 912 转换成链表:  2->1->9->null

样例 2:
输入:  3->1->5->null, 5->9->2->null
输出: 8->0->8->null	
样例解释: 513 + 295 = 808, 808 转换成链表: 8->0->8->null

代码实现
简单点在于,个位在前,所以只有两个问题需要解决
1.进位的处理。
2.链表可能长度不一致

ListNode * addLists(ListNode * l1, ListNode * l2) {
        // write your code here
        ListNode *head =new ListNode(-1);//一个新的节点
        ListNode *cur=head;//移动的指针
        int flag=0;//用来处理进位
        while(l1!=0||l2!=0||flag!=0)//只有当两个链表和进位均为零时,才会结束循环
        {
         		//a?b:c 当a为真时,返回b,否则返回c
            int l1val=l1!=NULL?l1->val:0;//取到数字,若链表为空,取0
            int l2val=l2!=NULL?l2->val:0;
            int sum=(l1val+l2val+flag)%10;//记录和,然后对10取余,保证为一位数字
            flag=(l1val+l2val+flag)/10;//对和除以10,保存进位
            ListNode *nextNode=new ListNode(sum);//创建新节点
            cur->next=nextNode;//放入新的节点中
            cur=cur->next;//节点后移
            if(l1!=NULL)//待处理两个节点的后移操作,因为两个链表可能长度不同,所以需要分别后移,
            			//若根据循环一起后期会导致越界
            {
                l1=l1->next!=NULL?l1->next:NULL;
            }
             if(l2!=NULL)
            {
                l2=l2->next!=NULL?l2->next:NULL;
            }
        }
        return head->next;
    }

173 · 链表插入排序(简单)

描述
用插入排序对链表排序
样例

样例 1:
	输入: 0->null
	输出: 0->null

样例 2:
	输入:  1->3->2->0->null
	输出 :0->1->2->3->null

代码实现

ListNode * insertionSortList(ListNode * head) {
        // write your code here
       ListNode *dummy=new ListNode(-1);
       while(head!=NULL)
       {
           ListNode *temp=dummy;//指向比较的数
           ListNode *next=head->next;//标记下一个需要处理的值
           while(temp->next!=NULL &&temp->next->val<head->val)//遇到大的值插入然后后移temp
           {
               temp=temp->next;
           }
           head->next=temp->next;//head指向temp中的大值
           temp->next=head;//temp指向head后面
           head=next;//head归位
       }
       return dummy->next;
    }

174 · 删除链表中倒数第n个节点(简单)

代码实现
跟之前找到链表中的倒数第n个节点类似,都是通过快慢指针来找到节点,多了一步删除操作

ListNode * removeNthFromEnd(ListNode * head, int n) {
        // write your code here
        ListNode * dummy = new ListNode(-1);
        dummy->next = head;
        ListNode *fast=dummy;
        ListNode *slow=dummy;
        if(head->next==NULL) return nullptr;
        for(int i=0;i<n;i++)
        {
            fast=fast->next;
        }
        while(fast->next!=NULL)
        {
            fast=fast->next;
            slow=slow->next;
        }
        slow->next=slow->next->next;//直接跳过倒数第n个节点
        
        return dummy->next;
    }

217 · 无序链表的重复项删除(简单)

描述
设计一种方法,从无序链表中删除重复项。

样例

样例 1:
输入:1->2->1->3->3->5->6->3->null
输出:1->2->3->5->6->null

样例 2:
输入:2->2->2->2->2->null
输出:2->null

代码实现

ListNode * removeDuplicates(ListNode * head) {
        // write your code here
    map<int, bool>mp;//定义一个map容器来存放数据,对于map容器不了解的,后面有其他人的博客链接
    if (head == NULL)
    {
        return head;
    }
    mp[head->val] = true;//用链表的数值做key值,如果存在value为true
    ListNode* tail = head;//用来保存不重复的值
    ListNode* now = head->next;
    while (now != NULL)
    {
        //用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,
        //如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器
        if (mp.find(now->val)==mp.end())//当出现未出现的值,满足if条件
        {
            mp[now->val] = true;//赋值
            tail->next = now;
            tail = tail->next;
        }
        now = now->next;//后移
    }
    tail->next = NULL;//尾指针赋空值
    return head;
    }

map容器介绍:C++ map用法总结(整理)
视频教程链接:map容器构造和赋值

219 · 在排序链表中插入一个节点(简单)

描述
在链表中插入一个节点。

样例
样例 1:

输入:head = 1->4->6->8->null, val = 5
输出:1->4->5->6->8->null
样例 2:

输入:head = 1->null, val = 2
输出:1->2->null

代码实现

ListNode * insertNode(ListNode * head, int val) {
        // write your code here
        ListNode *dummy=new ListNode(-1);//创建一个新的头节点
        dummy->next=head;
        ListNode *fast=dummy;
        if(head==NULL)//当目标链表为空时,返回给定值的链表
        {
            ListNode *temp=new ListNode(val);
            return temp;
        }
        while(fast->next!=NULL)
        {
            if(fast->next->val<val)//当链表节点值小于给定值时,链表指针后移
            {
                fast=fast->next;
            }
            else
            {
                ListNode *temp=new ListNode(val);//创建新节点
                ListNode *cur=fast->next;//记录当前节点的指针
                fast->next=temp;//指向新节点
                temp->next=cur;//指向保存的节点
                return dummy->next;
            }
        }
        //当链表走到末尾任然未插入节点时,在末尾插入
        ListNode *temp=new ListNode(val);
        ListNode *cur=fast->next;
        fast->next=temp;
        temp->next=cur;
        return dummy->next;
    }

294 · 简化链表(简单)

描述
给出一个字符链表,对其进行简化。
简化的过程为,保留链表的头尾节点,用数字代替掉中间的部分。
数字也要用字符链表表示。
样例

输入的字符链表用一个整型链表表示,链表的每个节点的值都是其对应的ASCII码。
原链表是 'h'->'e'->'l'->'l'->'o'->null。
简化后变为 'h'->'3'->'o'->null。//将ell这个三个字符用数字三代替
第二组样例中:
原链表是 'a'->'b'->...->'z'->null。
简化后变为 'a'->'2'->'4'->'z'->null。//将b-y的字母用数字24代替

输入1104->101->108->108->111->null
输出1104->51->111->null
输入297->98->...->122->null
输出297->50->52->122->null

代码实现

ListNode * simplify(ListNode * head) {
        //write your code here
        ListNode *fast=head;
        ListNode *insert=head;
        ListNode *slow=head;
        int count=-1;//计数变量
        while(fast->next)//移动链表
        {
            fast=fast->next;
            count++;
        }
         string s=to_string(count);//数字转字符
       for(int i=0;i<s.size();i++)
        {
            insert=new ListNode(s[i]);//插入字符
            slow->next=insert;//头节点指向新的字符
            slow=insert;//节点后移一位
        }
        slow->next=fast;//指向尾部节点
        return head;

372 · 在O(1)时间复杂度删除链表节点(简单)

描述
给定一个单链表中的一个等待被删除的节点(非表头或表尾)。请在在 O(1) 时间复杂度删除该链表节点。
样例

样例 1:
输入:
1->2->3->4->null
3
输出:
1->2->4->null
样例 2:
输入:
1->3->5->null
3
输出:
1->5->null

代码实现
通常情况下的删除节点是要知道被删除节点的前一个节点的,如果按照这种理解,那么这道题是无解的。
只能通过改变节点的值的方式来做了。但是,这样的话,如果要删除的节点是链表中的最后一个,那么也是无法删除的。

void deleteNode(ListNode * node) {
        // write your code here
        if(node) //先比较后跳转,链表本身就是一个递归结构。
        {
            node->val = node->next->val;//将后一个节点的值,赋给目标节点
            node->next = node->next->next;  //当前节点指向下下一个节点
        }
    }

451 · 两两交换链表中的节点(简单)

描述
给一个链表,两两交换其中的节点,然后返回交换后的链表。

样例
样例 1:

输入:1->2->3->4->null
输出:2->1->4->3->null
样例 2:

输入:5->null
输出:5->null

代码实现

ListNode * swapPairs(ListNode * head) {
        // write your code here
        ListNode *dummy=new ListNode(-1);
        ListNode *slow=head;
        ListNode *fast=dummy;
        while(slow&&slow->next)
        {
            ListNode *temp=slow->next->next;
            fast->next=slow->next;
            fast=fast->next;
            fast->next=slow;
            fast=fast->next;
            fast->next=NULL;
            slow=temp;
        }
        if(slow) 
        {
        fast->next=slow;
        }
        return dummy->next;
    }

452 · 删除链表中的元素(简单)

描述
删除链表中等于给定值 val 的所有节点。

样例
样例 1:

输入:head = 1->2->3->3->4->5->3->null, val = 3
输出:1->2->4->5->null
样例 2:

输入:head = 1->1->null, val = 1
输出:null

代码实现

ListNode * removeElements(ListNode * head, int val) {
        // write your code here
	    if(head == NULL) 
	        {
	            return NULL;
	        }
		ListNode *prev = head;
		ListNode *cur = head->next;
		while (cur != NULL) 
	    {
			if (cur->val != val)
	        {
				prev = cur;
			}
			else
	        {
				prev->next = cur->next;
				delete(cur);
			}
			cur = prev->next;
		}
		ListNode *NewHead = head;
		if (head->val == val) {
			NewHead = head->next;
			delete(head);
		}
		return NewHead;
	    }

489 · 链表化数组(简单)

描述
将一个数组变成链表

样例
例1:

输入: [1,2,3,4], 
输出: 1->2->3->4->null.2:

输入: [1,2], 
输出: 1->2->null.

代码实现

ListNode * toLinkedList(vector<int> &nums) {
        // write your code here
        if(nums.size()==0)
        {
            return NULL;
        }
        ListNode *dummy=new ListNode(-1);
        ListNode *pre=dummy;
        for(int i=0;i<nums.size();i++)
        {
            
            pre->next=new ListNode(nums[i]);
            pre=pre->next;
           
        }
        return dummy->next;
    }

756 · 两数相乘(简单)

描述
给出两个链表形式表示的数字,写一个函数得到这两个链表相乘乘积。

样例
样例 1:

输入:9->4->6->null,8->4->null
输出:79464
解释:946*84=79464
样例 2:

输入:3->2->1->null,1->2->null
输出:3852
解释:321*12=3852

代码实现

long long multiplyLists(ListNode * l1, ListNode * l2) {
        // write your code here
        long long s1=0;
        long long s2=0;
        //链表转int值然后相乘
        while(l1!=NULL||l2!=NULL)
        {
            if(l1!=NULL)
            {
                s1=s1*10;
                s1+=l1->val;
                l1=l1->next;
            }
            if(l2!=NULL)
            {
                s2=s2*10;
                s2+=l2->val;
                l2=l2->next;
            }
        }
        cout<<"s1: "<<s1<<" s2:"<<s2<<endl;
        long long ans=s1*s2;
        return ans;
    }

822 · 相反的顺序存储(简单)

描述
给出一个链表,并将链表的值以倒序存储到数组中。

样例
样例1

输入: 1 -> 2 -> 3 -> null
输出: [3,2,1]
样例2

输入: 4 -> 2 -> 1 -> null
输出: [1,2,4]

代码实现

 vector<int> reverseStore(ListNode * head) {
        // write your code here
        vector<int>ans;
        while(head)
        {
            ans.push_back(head->val);
            head=head->next;
        }
        reverse(ans.begin(),ans.end());
        return ans;
    }

1609 · 链表的中间结点(简单)

描述
给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。

样例
样例 1:

输入:1->2->3->4->5->null
输出:3->4->5->null
样例 2:

输入:1->2->3->4->5->6->null
输出:4->5->6->null

代码实现

 ListNode * middleNode(ListNode * head) 
 {
        // write your code here.
        ListNode *fast=head;
        ListNode *slow=head;
        while(fast != NULL && fast->next != NULL)
        {
            fast=fast->next->next;
            slow=slow->next;
        }
            return slow;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值