链表-牛客简单题

反转链表

NC78 反转链表

思路:给定三个节点,pre表示前一个节点,cur表示当前节点,next表示下一个节点。在反转时,将next节点暂存当前节点的下一个节点,将cur指向前一个节点,就会实现当前节点的反转,接下来将pre后移,最后将cur后移到next即可

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode *pre = NULL, *cur = pHead, *next = NULL;
        while (cur) {
            next = cur -> next;
            cur -> next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

合并两个排序的链表

NC33 合并两个排序的链表

思路:不断比较两个链表值的大小即可,每次更小的时候右移,当一方达到最后的位置时,将val值设置为INT_MAX

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
#include <climits>
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        if (pHead1 == nullptr) return pHead2;
        if (pHead2 == nullptr) return pHead1;
        ListNode *head = new ListNode(0);
        ListNode *pre = head;
        while (pHead1 || pHead2) {
            int val1 = pHead1 ? pHead1 -> val : INT_MAX;
            int val2 = pHead2 ? pHead2 -> val : INT_MAX;
            if (val1 <= val2) {
                pre -> next = pHead1;
                pHead1 = pHead1 -> next;
            } else {
                pre -> next = pHead2;
                pHead2 = pHead2 -> next;
            }
            pre = pre -> next;
        }
        return head -> next;
    }
};

判断链表是否有环

判断链表是否有环

思路:采用快慢指针的思维,设置一个慢指针一次走一步,一个快指针一次走两步,如果存在环的话,那么两个指针一定会相遇的,返回true,如果不存在环,那么快指针一定会先为空,为空则退出寻找,返回false

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if (head == nullptr || head -> next == nullptr) return false;
        ListNode *slow = head, *fast = head;
        while (fast && fast -> next) {
            slow = slow -> next;
            fast = fast -> next -> next;
            if (slow == fast) return true;
        }
        return false;
    }
};

两个链表的第一个公共节点

NC66 两个链表的第一个公共节点

思路:两个链表的长度不一定相等,但是a+b == b + a,所以我们可以在任意链表达到null后变为另一个链表的头来进行遍历,这样可以保证一定相遇

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        ListNode *p1 = pHead1, *p2 = pHead2;
        while (p1 != p2) {
            p1 = p1 ? p1 -> next : pHead2;
            p2 = p2 ? p2 -> next : pHead1;
        }
        return p1;
    }
};

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

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

思路:前半段和后半段对称的数据串我们称为回文串,但是链表是单向的,眼下第一时间我们能想到开辟一个数组进行暂存,但其实我们也存在原地做法:①利用快慢指针找到链表的中点,快指针每次前进两格,慢指针前进一格,最后慢指针所处位置即为中点。②将中点后面一段链表进行反转,再依次进行比对,存在不相等的值就返回false。

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

class Solution {
public:
    /**
     * 
     * @param head ListNode类 the head
     * @return bool布尔型
     */

    ListNode* reverse(ListNode *head) {
        ListNode *pre = nullptr, *cur = head, *next = nullptr;
        while (cur) {
            next = cur -> next;
            cur -> next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

    bool isPail(ListNode* head) {
        // write code here
        if (head == nullptr || head -> next == nullptr) return true;
        ListNode *slow = head, *fast = head;
        while (fast && fast -> next) {
            slow = slow -> next;
            fast = fast -> next -> next;
        }
        slow = reverse(slow);
        while (slow) {
            if (slow -> val != head -> val) return false;
            slow = slow -> next;
            head = head -> next;
        }
        return true;
    }
};

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

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

思路:设定一个指针,从头开始遍历,若有相同的则删除,删除代码为node->next = node -> next -> next

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

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

链表中倒数最后k个结点

NC69 链表中倒数最后k个结点

思路:最容易想到的方法是遍历整个链表得到长度,在遍历程度减去k的值,得到这个点。这里就不用这个方法了。我们可以采用双指针法,快指针可以先遍历k次,然后快慢指针再一起遍历,得到慢指针就是倒数k个节点

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

以上就是牛客面试榜单的简单链表题,思路比较简洁,用于让大家快速过一遍😋😋😋

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值