刷题PIA 之 链表

0. 刷题BGM A Day at the Beach - j'san./Pandrezz

1. 反转链表 

描述:题意简单不赘述       

输入:单链表的头结点 pHead 

输出:反转链表的表头

算法:前插法 + 迭代

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* pReverseList = NULL;
        ListNode* pNode = pHead;
        ListNode* pPre= NULL;
  
  
        while(pNode != NULL){
            ListNode* pNext = pNode->next;
            if(pNext == NULL){
                pReverseList = pNode;
            }
            pNode->next = pPre;
            pPre = pNode;
            pNode = pNext;
        }
        return pReverseList;
    }
};

分析:1)创建新的链表指针指向头结点(ListNode* pNode = pHead;),返回整个链表元素。

           2)本题由于每迭代后,Pnode与Ppre直接无连接,故直接返回Pnode无法获得正确结果。

           3)根据分析 2)可改写 while 循环内容,改写代码如下所示。

while(Pnode != NULL)
        {
            ListNode *Pnext = Pnode->next;
            Pnode->next = Ppre;
            Ppre = Pnode;
			if(Pnext != NULL)
			{
				Pnode = Pnext;
			}else {
				return Pnode;
			}
        }

TRICK:反转以平移思想为准,从 Pnow->next 到 Ppre 到 Pnow 顺序平移

2. 链表内指定区间反转

描述:固定区间实现局部链表反转      

输入:单链表的头结点 pHead 

输出:局部反转链表的表头

算法:前插法 + 迭代

/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 * };
 */

#include <climits>
#include <cstdio>
#include <list>
class Solution {
  public:
    /**
     *
     * @param head ListNode类
     * @param m int整型
     * @param n int整型
     * @return ListNode类
     */
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(!head & !head->next) return head;
        ListNode* B = head,* A = new ListNode(-1),* C;
        int k = m - 1;
        A->next = head;
        ListNode* RES = A;
        while (k--) {
            B = B->next;
            A = A->next;
        }
        ListNode* T = A;
        k = n - m;
        while(k--)
        {
            C = B->next;
            B->next = C->next;
            C->next = T->next;
            T->next = C; 
        }
        return RES->next;
    }
};

3.合并两个排序的链表

描述:合并两个子顺序链表成一个合并顺序链表     

输入:两个单链表的头结点 pHead 

输出:合并链表

算法:迭代

#include <list>
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        ListNode* RES = new ListNode(-1);
		ListNode* A = pHead1,*B = pHead2;
		ListNode* T = RES;
		while(A && B)
		{
			if(A->val < B->val)
			{
				T->next = A;
				A = A->next;
			}
			else
			{
				T->next = B;
				B = B->next;
			}
			T = T->next;
		}
		if(A)
		{
			T->next = A;
		}
		else 
		{
			T->next = B;
		}
		return RES->next;
    }
};

4.判断链表是否有环

描述:给出一链表,判断是否带环   

输入:单链表的头结点 pHead 

输出:带环BOOL

算法:双指针 + 快慢指针

class Solution {
public:
    bool hasCycle(ListNode *head) {
        bool res = false;
        ListNode* F = head,* S = head;
        while(F->next && F)
        {
            F = F->next->next;
            S = S->next;
            if(F == S)
            {
                res = true;
                break;
            }
            
        }
        return res;
    }
};

TRICK :判断条件以快指针 F 及 F -> next 为条件。

5. 链表中环的入口结点

描述:给出一链表,判断是否带环 ,并输出入口节点  

输入:两个单链表的头结点 pHead 

输出:入口节点,若无环输出NULL

算法:双指针 + 快慢指针

#include <cmath>
class Solution {
  public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        ListNode* F = pHead, * S = pHead;
        int tag = 0;
        while (F->next && F) {
            S = S->next;
            F = F->next->next;
            if (F == S) {
                tag = 1;
                break;
            }
        }
        if (tag == 0) return NULL;
        else {
            S = pHead;
            while (S != F && tag == 1) {
                S = S->next;
                F = F->next;
            }
            return S;
        }
    }

TRICK :判断为有环后,将慢指针重置,两指针根据一次平移一格获得交汇点即为入口点。

6.链表中倒数最后k个结点

描述:给出一链表,给出链表后k个结点 

输入:单链表的头结点 pHead 

输出:后k个结点的头结点

算法:。。。

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pHead ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    ListNode* FindKthToTail(ListNode* pHead, int k) {
        int num = 0;
        ListNode* A = pHead;
        while(A) 
        {
            A = A ->next;
            num++;
        }
        if(num < k) return NULL;
        else{
        for(int i(0);i<num-k;i++)
        {
            pHead = pHead->next;
        }
        return pHead;
        }
    }

7. 删除链表的倒数第n个节点

描述:题意简单不赘述 

输入:单链表的头结点 pHead 

输出:除倒数第k个的链表表头

算法:。。。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

#include <endian.h>
#include <list>
#include <memory>
class Solution {
public:
    /**
     * 
     * @param head ListNode类 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        // write code here
        int num = 0;
        ListNode* A = head;
        ListNode* res = new ListNode(-1);
        res->next = head;
        ListNode* temp = res;
        while(A)
        {
            A = A->next;
            num++;
        }
        for(int i(0);i<num-n;i++)
        {
            temp = temp->next;
        }
        temp->next = temp->next->next;
        return res->next;
    }
};

TRICK:返回值可能包含前置链表时,实用动态创建链表

8. 两个链表的第一个公共结点

描述:题意简单不赘述 

输入:两个单链表的头结点 pHead 

输出:第一个共同的结点

算法:。。。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
#include <climits>
class Solution {
  public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        ListNode* A = pHead1;
        while (A) {
            ListNode* B = pHead2;
            while (B) {
                if (A->val == B->val && A == B) {
                    return A;
                } else {
                    B = B->next;
                }
            }
            A = A->next;
        }
        return NULL;
    }

TRICK:将A、B两链表遍历成环,即A -> next = NULL 时 A -> next = pHead2,B同理。

9.判断一个链表是否为回文结构

描述:题意简单不赘述 

输入:单链表的头结点 pHead 

输出:BOOL是否为回文标志

算法:。。。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head ListNode类 the head
     * @return bool布尔型
     */
    bool isPail(ListNode* head) {
        // write code here
        int l = 0;
        bool res = true;
        ListNode* A = head;
        while (A) {
            A=A->next;
            l++;
        }
        l = l/2;
        ListNode* B = head;
        while (l--) {
            B = B ->next;
        }
        B = ReverseList(B);
        ListNode* C = head;
        while (B) {
            if (C->val != B->val) {
                res = false;
            }
            C = C->next;
            B = B->next;
        }
        return res;
    }
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* pReverseList = NULL;
        ListNode* pNode = pHead;
        ListNode* pPre= NULL;
  
  
        while(pNode != NULL){
            ListNode* pNext = pNode->next;
            if(pNext == NULL){
                pReverseList = pNode;
            }
            pNode->next = pPre;
            pPre = pNode;
            pNode = pNext;
        }
        return pReverseList;
    }
};

10. 删除有序链表中重复的元素-I

描述:题意简单不赘述 

输入:单链表带重复元素的头结点 pHead 

输出:无重复元素的链表头结点

算法:。。。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
        // write code here
        ListNode* A = new ListNode(-1);
        A->next = head;
        ListNode* T = head;
        while(T&&T->next)
        {
            if (T->val == T->next->val) {
                T->next = T->next->next;
            }else
            {
                
            T = T->next;
            }
        }
        return A->next;
    }

11.链表的奇偶重排

描述:给一个单链表,使奇数编号项在前输出偶数编号项在后输出 

输入:单链表带重复元素的头结点 pHead 

输出:奇偶重排元素的链表头结点

算法:。。。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
#include <cmath>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* oddEvenList(ListNode* head) {
        // write code here
        if(!head || !head->next) return head;
        ListNode* A = head,* B = head->next,* mid = head->next;
        while (B&&B->next) {
            A->next = A->next->next;
            B->next = B->next->next;
            A = A->next;
            B = B->next;
        }
        A->next = mid;
        return head;
    }
};

12 单链表的排序

描述:题意简单不赘述

输入:单链表无序的头结点 pHead 

输出:有序链表头结点

算法:。。。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

#include <cmath>
#include <cstddef>
#include <vector>
class Solution {
public:
    /**
     * 
     * @param head ListNode类 the head node
     * @return ListNode类
     */
    ListNode* sortInList(ListNode* head) {
        // write code here
        if (!head) {
            return head;
        }
        ListNode* iter = head;
        vector<int> array;
        while (iter) {
            array.push_back(iter->val);
            iter = iter->next;
        }
        sort(array.begin(),array.end());
        int i = 0;
        iter = head;
        while (iter) {
            iter->val = array[i++];
            iter = iter->next;
        }
        delete iter;
        return head;
    }
};

TRICK:将链表内容存入vexctor,再通过sort排序,最后导入链表中。

注意 :

new ListNode(NULL) 含 value = 0;

ListNode * d = null ,不含value

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值