2021-1-20反转链表

题目1 反转链表

示例:

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

解1 迭代法
设置三个指针p1,p2,p3,初始分别指向前三个元素
p2指向p1,并向后移动三个指针,直到p3指向NULL
并将最后一个元素指p1.

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
    	//链表为NULL,或只有一个元素
        if(head == NULL || head->next == NULL)
            return head;
        //定义并初始化三个指针
        ListNode* p1 = head;
        ListNode* p2 = head->next;
        ListNode* p3 = head->next->next;
        //head指向NULL
        head->next = NULL;
        //往后遍历,并赋值反转
        while(p3)
        {
            p2->next = p1;
            p1 = p2;
            p2 = p3;
            p3 = p3->next;
        }
        //对于最后一个元素单独处理
        p2->next = p1;
        //返回链表头
        return p2;
    }
};

解1 递归法
每次给函数传入两个指针p1,p2,初始分别指向前两元素,开始往后递归遍历。
当遍历到结尾,开始返回并p2指向p1,进行反转。

class Solution {
public:
	//额外设置指针,标记递归到最后时,反转后的起始节点(即最后一个结点)
    ListNode* pHead = NULL;
    ListNode* reverseList(ListNode* head) 
    {
   		//链表为NULL,或只有一个元素
        if(head == NULL || head->next == NULL) 
            return head;
        //递归遍历,初始传入链表前两个元素
        Turn(head,head->next);
        //头节点指NULL
        head->next = NULL;
        return pHead;
    }
    void Turn(ListNode* p1,ListNode* p2)
    {
    //遍历到结尾,尾结点标记给pHead,并开始返回
        if(p2 == NULL)
        {
            pHead = p1;
            return;
        }
        Turn(p1->next,p2->next);
        //p2指向p1
        p2->next = p1;
    }
};

题目2 二进制链表转整数

遍历链表,每遍历一位,num的值左移一位加上结点值。

class Solution {
public:
    int getDecimalValue(ListNode* head) {
        int num = 0;
        while(head)
        {
            num = (num<<1)+head->val;
            head = head->next;
        }
        return num;
    }
};

题目3 删除链表重复元素

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 1:
输入: 1->1->2
输出: 1->2

解1 快慢指针

  1. 设置两个指针pQuick、pSlow,初始指向链表前两个元素
  2. 若pQuick,pSlow指向的数据相同,则只移动pSlow
  3. 反之,两个指针一起向后移动
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
    	//链表空
        if(head == NULL) return head;
        //初始两个指针的值,链表前两个元素
        ListNode* pQuick= head;
        ListNode* pSlow = head->next;
        //循环遍历
        while(pSlow)
        {
        	//值相同
            if(pQuick->val == pSlow->val
            	//移动后一个指针
                pSlow = pSlow->next;
            else
            {
            	//包含重复元素移动过后,再遇到不同元素的情况,因此要执行一步pQuick下一个指向pSlow
                pQuick->next = pSlow;
                //两个指针后移
                pQuick = pSlow;
                pSlow = pSlow->next;
            }
        }
        //链表最后有重复元素的情况
        pQuick->next = pSlow;
        return head;
    }
};

解2 递归

  1. 递归遍历链表
  2. 返回过程中,返回值拼接到上次递归结点后面
  3. 若下一节点和上一节点值不同,正常返回本次head即可
  4. 若相同,则该节点额外赋值给pNode,一直返回该节点,直到遇到不同的结点
class Solution {
public:
    ListNode* pNode = NULL;
    ListNode* deleteDuplicates(ListNode* head) {
    	//若为走到最后,继续递归
        if(head)
        {
            pNode = deleteDuplicates(head->next);
        }
        //如果返回结点的值和head值相同,返回原pNode
        if(head && pNode && pNode->val == head->val)
        {
            return pNode;
        }
        //head下一个指向pNode
        if(head)
            head->next = pNode;
        //正常返回head即可
        return head;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值