算法练习-链表相关算法

一、反转链表

        给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头

       循环中每一次只移动一个步骤 curNode->next = preNode

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* ReverseList(ListNode* head) {
        if(head == NULL || head->next == NULL) {
            return head;
        }
        ListNode* preNode = NULL;
        ListNode* nextNode = NULL;
        ListNode* curNode = head;
        while(curNode != NULL) {
            nextNode = curNode->next; //先记录next节点
            curNode->next = preNode; //指向前一个节点 每次移动一个步骤
            preNode = curNode;
            curNode = nextNode;
        }
        return preNode;
    }
};

二、合并两个排序的链表

        输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * @param pHead1 ListNode类 
     * @param pHead2 ListNode类 
     * @return ListNode类
     */
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        
        if(pHead1 == NULL) return pHead2;
        if(pHead2 == NULL) return pHead1;
        ListNode* cur1 = pHead1;
        ListNode* cur2 = pHead2;
        ListNode* curNode = new ListNode(-1); //创建一个head节点 作为记录使用
        ListNode* pHead = curNode;  //返回时候的记录信息
        while(cur1 && cur2) {
            if(cur1->val < cur2->val) {

                curNode->next = cur1; //当前节点赋值给最小的节点
                curNode = cur1;       //当前节点重新前移一个位置
                cur1 = cur1->next; 
            }
            else {
                curNode->next = cur2;
                curNode = cur2;
                cur2 = cur2->next;
            }
        }
        //  剩下的部分没有匹配的重新移动,进行匹配
        while(cur1) {
            curNode->next = cur1;
            curNode = cur1;
            cur1 = cur1->next;
        }
        while(cur2) {
            curNode->next = cur2;
            curNode = cur2;
            cur2 = cur2->next;
        }
        return pHead->next;
    }
};

三、链表中倒数最后k个结点

        

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pHead, int k) {
       
       if(pHead == NULL) return NULL;
       ListNode* cur = pHead;
       int count = 0;
       while(cur) {
        count ++;
        cur = cur->next;
       }
       if(k > count) {
        return NULL;
       }
       int index = 0;
       while(pHead) {
        if(index == (count - k)) {
            break;
        }
        pHead = pHead->next;
        index ++;
       }
       return pHead;
    }
};

四、单链表的排序

        给定一个节点数为n的无序单链表,对其按升序排序,因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。
归并排序的一般步骤为:
1.将待排序数组(链表)取中点并一分为二;
2.递归地对左半部分进行归并排序;
3.递归地对右半部分进行归并排序;
4.将两个半部分进行合并(merge),得到结果。

所以对应此题目,可以划分为三个小问题:
1.找到链表中点 (快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点);
2.写出merge函数,即如何合并链表。
3.写出mergesort函数,实现上述步骤

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */

class Solution {
public:
    ListNode* sortInList(ListNode* head) {
        if(head == NULL || head->next == NULL) {
            return head;
        }
        ListNode* midNode = getMidListNode(head); //奇数取中间,偶数取右边数
        ListNode* rightNode = midNode->next;
        midNode->next = NULL;

        ListNode* left = sortInList(head);
        ListNode* right = sortInList(rightNode);

        return Merge(left,right);
    }
    //获取中间节点
    ListNode* getMidListNode(ListNode* node) {
        if(node == NULL || node->next == NULL) {
            return node;
        }
        ListNode* slowPtr = node;
        ListNode* fastPtr = node->next; // 为啥要向后偏移一个位置
        while(slowPtr && fastPtr && fastPtr->next) {
            slowPtr = slowPtr->next;
            fastPtr = fastPtr->next->next;
        }
        return slowPtr;
    }
    //合并
    ListNode* Merge(ListNode* left,ListNode* right) {
        if(left == NULL) return right;
        if(right == NULL) return left;
        ListNode* curNode = new ListNode(-1);
        ListNode* phead = curNode;
        while(left && right) {
            if(left->val <= right->val) {
                curNode->next = left;
                left = left->next;
            }
            else {
                curNode->next = right;
                right = right->next;
            }
            curNode = curNode->next;
        }
        if(left) {
            curNode->next = left;
        }
        if(right) {
            curNode->next = right;
        }
        return phead->next;
    }
};


 

        

你可能感兴趣的:(链表,算法,数据结构)