链表-牛客中等题(上)

链表中的节点每k个一组翻转

NC50 链表中的节点每k个一组翻转

思路:采用递归的思想,每次处理k个节点,不足的就返回当前的节点头,层层递归得到每k个一翻转

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

class Solution {
public:
    /**
     * 
     * @param head ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    ListNode* reverseKGroup(ListNode* head, int k) {
        // write code here
        ListNode *tail = head;
        for (int i = 0; i < k; i ++ ) {
            if (tail) tail = tail -> next;
            else return head;
        }
        ListNode *pre = nullptr, *cur = head, *next = nullptr;
        while (cur != tail) {
            next = cur -> next;
            cur -> next = pre;
            pre = cur;
            cur = next;
        }
        head -> next = reverseKGroup(tail, k);
        return pre;
    }
};

链表中环的入口结点

NC3 链表中环的入口结点

思路:采用快慢指针的方法,快指针一次走两步,慢指针走一步,如果有环的话,两个指针一定会相遇,这时再将快指针置于头节点上,开始遍历,当两个指针相等时,就是入口节点(链接中有详细解释为什么要这样做,不懂的小伙伴可以看看)


/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        if (pHead == NULL || pHead -> next == NULL) return NULL;
        ListNode *slow = pHead, *fast = pHead;
        while (fast && fast -> next) {
            slow = slow -> next;
            fast = fast -> next -> next;
            if (slow == fast) break;
        }
        if (fast == NULL || fast -> next == NULL) return NULL;
        fast = pHead;
        while (fast != slow) {
            fast = fast -> next;
            slow = slow -> next;
        }
        return slow;
    }
};

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

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

这题和上文中简单题的思路相同,我们同样可以采用快慢指针的方法,与简单题中不同的是我们需要一个前序节点来进行删除操作。

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

class Solution {
public:
    /**
     * 
     * @param head ListNode类 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        // write code here
        if (head == nullptr) return nullptr;
        ListNode *all = new ListNode(-1);
        all -> next = head;
        ListNode *slow = head, *fast = head;
        for (int i = 0; i < n; i ++ ) {
            if (fast) fast = fast -> next;
            else return nullptr;
        }
        ListNode *pre = all;
        while (fast) {
            pre = slow;
            slow = slow -> next;
            fast = fast -> next; 
        }
        pre -> next = slow -> next;
        return all -> next;
    }
};

链表相加(二)

NC40 链表相加(二)

思路:我们所熟知的加法是从个位开始进行相加的,但是链表是单向的,且是从最高位开始的,由此我们可以先反转链表,最后进行相加

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head1 ListNode类 
     * @param head2 ListNode类 
     * @return ListNode类
     */

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

    ListNode* addInList(ListNode* head1, ListNode* head2) {
        // write code here
        if (head1 == nullptr) return head2;
        if (head2 == nullptr) return head1;
        head1 = reverse(head1);
        head2 = reverse(head2);
        ListNode *res = new ListNode(-1);
        ListNode *head = res;
        int carry = 0;
        while (head1 || head2 || carry) {
            int val1 = head1 ? head1 -> val : 0;
            int val2 = head2 ? head2 -> val : 0;
            int temp = val1 + val2 + carry;
            carry = temp / 10;
            temp = temp % 10;
            head -> next = new ListNode(temp);
            head = head -> next;
            if (head1) head1 = head1 -> next;
            if (head2) head2 = head2 -> next;
        }
        return reverse(res -> next);
    }
};

单链表的排序

NC70 单链表的排序

思路:取巧方法:遍历整个链表,存入一个vector,然后sort函数排序,再次存入。普通方法:采用分治的思想,先用快慢指针将链表分成一段一段地,再使用合并链表的方式合并(简单题里面有),下面开整

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

class Solution {
  public:
    /**
     *
     * @param head ListNode类 the head node
     * @return ListNode类
     */

    ListNode* merge(ListNode* list1, ListNode* list2) {
        if (list1 == nullptr) return list2;
        if (list2 == nullptr) return list1;
        ListNode* res = new ListNode(-1);
        ListNode* head = res;
        while (list1 || list2) {
            int val1 = list1 ? list1 -> val : INT_MAX;
            int val2 = list2 ? list2 -> val : INT_MAX;
            if (val1 <= val2) {
                head -> next = list1;
                list1 = list1 -> next;
            } else {
                head -> next = list2;
                list2 = list2 -> next;
            }
            head = head -> next;
        }
        return res -> next;
    }

    ListNode* sortInList(ListNode* head) {
        // write code here
        if (head == nullptr || head -> next == nullptr) return head;
        ListNode *left = head, *mid = head -> next, *right = head -> next -> next;
        while (right && right -> next) {
            left = left -> next;
            mid = mid -> next;
            right = right -> next -> next;
        }
        left -> next = nullptr;
        return merge(sortInList(head), sortInList(mid));
    }
};

今天的算法题先写到这里,明天见朋友们(如果有人看的话)😍

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值