算法图解 学习笔记Ch1 算法简介 Ch2 选择排序

目录

  • 算法图解总结
  • 链表练习 (C++实现)
    • 练习题 leetcode 206. 链表逆序(简单)
    • 练习题 leetcode 92. 链表逆序II (中等)
    • 练习题 leetcode 160. 求两个链表的交点
    • 练习题 leetcode 24. 链表的节点交换
    • 练习题 leetcode 141. 链表求环
    • 练习题 leetcode 142. 链表求环II
    • 练习题 leetcode 86. 链表重新构造
    • 练习题 leetcode 138. 复杂的链表复制
    • 练习题 leetcode 21. 排序链表合并(2个)
    • 练习题 leetcode 23. 合并K个排序链表
    • 练习题 leetcode 234. 回文链表
    • 练习题 leetcode 25. K 个一组翻转链表
    • 练习题 leetcode 148. 排序链表
    • 练习题 leetcode 876. 链表的中间结点
    • 练习题 leetcode 1019. 链表中的下一个更大节点
    • 练习题 leetcode 143. 重排链表
    • 练习题 leetcode
    • 练习题 leetcode
  • 排序练习(C++实现)
    • 练习题 leetcode 969. 煎饼排序
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode
    • 练习题 leetcode

算法图解总结

算法图解 学习笔记Ch1 算法简介 Ch2 选择排序_第1张图片
(基本都是一些比较熟悉的知识了)

链表练习 (C++实现)

练习题 leetcode 206. 链表逆序(简单)

思路1:双指针
算法图解 学习笔记Ch1 算法简介 Ch2 选择排序_第2张图片


class Solution {
     
public:
    ListNode* reverseList(ListNode* head) {
     
        ListNode* pre = head;
        ListNode* cur = NULL;
        while(pre != NULL){
     
            ListNode* temp = pre->next; //暂存pre->next位置
            pre->next = cur; //反转
            cur = pre; //更新cur
            pre = temp; //指向pre->next的位置
        }
        return cur;
    }
};

思路2:递归
算法图解 学习笔记Ch1 算法简介 Ch2 选择排序_第3张图片

class Solution {
     
public:
    ListNode* reverseList(ListNode* head) {
     
        //递归
        if(head == NULL || head->next == NULL){
     
            return head;
        }
        ListNode* res = reverseList(head->next); // 反转链表的头结点
        head->next->next = head;
        head->next = NULL;
        return res;
    }
};

练习题 leetcode 92. 链表逆序II (中等)

解法一:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
     
        //  head表示需要反转的头节点,pre表示需要反转头节点的前驱节点
        ListNode* dummy = new ListNode(-1);
        ListNode* pre = dummy;
        dummy->next = head;

        for(int i = 0;i < m-1; i++){
     
            pre = pre->next;
        }
        ListNode* cur = pre->next;
        for(int i = m; i < n; i++){
     
            ListNode* t = cur->next;
            cur->next = t->next;
            t->next = pre->next;
            pre->next = t;
        }
        return dummy->next;
    }
};

解法二
算法图解 学习笔记Ch1 算法简介 Ch2 选择排序_第4张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
     
        ListNode* res = new ListNode(0);
        res->next = head;
        ListNode* begin  = res;

        //m的前一个节点
        for (int i = 1; i < m; i++){
     
            begin = begin->next;
        }

        //begin->next是第m位节点,cur
        ListNode *cur = begin->next;
        ListNode *temp = NULL;
        ListNode *pre = NULL;
        //反转n-m次
        for(int i = m; i <= n;i++){
     
            temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }

        //第m个节点指到第n+1个节点处
        begin->next->next = temp;
        //第m-1个节点指到第n个节点处
        begin->next = pre;

        return res->next;
    }
       
};

练习题 leetcode 160. 求两个链表的交点

题解:

设链表A的长度为a+c,链表B的长度为b+c,a为链表A不公共部分,b为链表B不公共部分,c为链表A、B的公共部分将两个链表连起来,A->B和B->A,长度:a+c+b+c=b+c+a+c,

若链表AB相交,则a+c+b与b+c+a就会抵消,它们就会在c处相遇;
若不相交,则c为nullptr,则a+b=b+a,它们各自移动到尾部循环结束,即返回nullptr

当ha或hb为空时,它们开始指向另一链表的头部,每次判断ha或hb是否为空进行赋值的好处是当链表AB没有公共部分时ha和hb同时为空,这样避免了死循环

class Solution {
     
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
     
        if(headA==NULL || headB==NULL){
     
            return 0;
        }
        ListNode* ha = headA;
        ListNode* hb = headB;

        while(ha != hb){
     
            ha = ha ? ha->next : headB;
            hb = hb ? hb->next : headA;
        }
        return ha;
    }
};

练习题 leetcode 24. 链表的节点交换

算法图解 学习笔记Ch1 算法简介 Ch2 选择排序_第5张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode* swapPairs(ListNode* head) {
     
        if(head == NULL){
     
            return head;
        }
        //新建一个空结点,用来指向头节点
        ListNode* res = new ListNode(0);
        res->next = head;

        ListNode *left, *right, *cur = res; //cur当前做改变的节点
        while(head != NULL && head->next != NULL){
     
            left = head;
            right = head->next;

            //left ,right swap
            cur->next = right;
            left->next = right->next;
            right->next = left;

            //cur更新
            cur = left;
            // head更新
            head = left->next;
        }
        return res->next;
    }
};

练习题 leetcode 141. 链表求环

/**
 * 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) {
     
        ListNode* fast = head;
        ListNode* slow = head;

        if(head == NULL){
     
            return false;
        }

        while(fast != NULL && fast->next != NULL){
     
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow){
     //如果快慢指针相遇
                return true;
            }
        }
        return false;
    }
};

练习题 leetcode 142. 链表求环II

思路:
快慢指针

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode *detectCycle(ListNode *head) {
     
        ListNode* fast = head;
        ListNode* slow = head;

        while(fast != NULL && fast->next != NULL){
     
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow){
     
                break;
            }
        }

        if(fast == NULL || fast->next == NULL){
     
            return NULL;
        }
		// 
        fast = head;
        int i = 0;
        while(fast != slow){
     
            fast = fast->next;
            slow = slow->next;
            i++;
        }
        return fast;
    }
};

练习题 leetcode 86. 链表重新构造

思路:
构造两个链表,最后拼接

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode* partition(ListNode* head, int x) {
     
        ListNode* minList = new ListNode(0);
        ListNode* maxList = new ListNode(0);
        ListNode* minPointer = minList;
        ListNode* maxPointer = maxList;

        while(head != NULL){
     
            if(head->val >= x){
     
                maxPointer->next = head;
                maxPointer = head;
            }else{
     
                minPointer->next = head;
                minPointer = head;
            }
            head = head->next;
        }
        maxPointer->next = NULL;
        minPointer->next = maxList->next;
        return minList->next;

    }
};

练习题 leetcode 138. 复杂的链表复制

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution {
     
public:
    Node* copyRandomList(Node* head) {
     
        if(head ==NULL){
     
            return head;
        }

        //遍历链表,建立映射关系
        unordered_map<Node*, Node*> map;
        
        Node* cur = head;
        while(cur){
     
            map[cur] = new Node(cur->val);
            cur = cur->next;
        }    

        // 遍历链表,根据map找新链表的random
        cur = head;
        while(cur){
     
            map[cur]->next = map[cur->next]; //
            map[cur]->random = map[cur->random]; //
            cur = cur->next;
        }
        return map[head];
    }
};

练习题 leetcode 21. 排序链表合并(2个)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
     
        ListNode* newList = new ListNode(0);
        ListNode* head = newList;

        while(l2 && l1){
     
            if(l1->val < l2->val){
     
                head->next = l1;
                l1 = l1->next;
            }else{
     
                head->next = l2;
                l2 = l2->next;
            }
            head = head->next;
        }

        if(l2 == NULL){
     
            head->next = l1;
        }else{
     
            head->next = l2;
        }
        return newList->next;
    }
};

练习题 leetcode 23. 合并K个排序链表

思路1:优先队列介绍
https://blog.csdn.net/weixin_36888577/article/details/79937886

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
     
        priority_queue<pair<int, ListNode*>, vector<pair<int, ListNode*>>, greater<pair<int, ListNode*>>> m;
        //  定义:priority_queue

        for(auto x : lists){
     
            if(x){
     
                m.push(make_pair(x->val,x));
            }
        }
        
        ListNode* root = new ListNode(-1);
        auto q = root;

        while(!m.empty()){
     
            auto cur = m.top();
            m.pop();
            q->next = cur.second;
            q = q->next;

            if(cur.second->next){
     
                m.push(make_pair(cur.second->next->val, cur.second->next));
            }
        }
        return root->next;
    }
};

思路2:分而治之

class Solution {
     
public:
    // 合并两个有序链表(递归)
    ListNode* merge(ListNode* p1, ListNode* p2){
     
        if(!p1) 
            return p2;
        if(!p2) 
            return p1;
        if(p1->val <= p2->val){
     
            p1->next = merge(p1->next, p2);
            return p1;
        }else{
     
            p2->next = merge(p1, p2->next);
            return p2;
        }
    }

    ListNode* merge(vector<ListNode*>& lists, int start, int end){
     
        if(start == end) 
            return lists[start];
        int mid = (start + end) / 2;
        ListNode* l1 = merge(lists, start, mid);
        ListNode* l2 = merge(lists, mid+1, end);
        return merge(l1, l2);
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
     
        if(lists.size() == 0) 
            return NULL;
        return merge(lists, 0, lists.size()-1);
    }
};

练习题 leetcode 234. 回文链表

思路1: 快慢指针 反转链表 比较

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
// 题解:快慢指针法,快指针走两步,慢指针走一步,找到链表的中点。然后,翻转后半部分。最后从头、中点开始判断是否相同。
    bool isPalindrome(ListNode* head) {
     
        if(head==NULL || head->next==NULL){
     
            return true;
        }

        ListNode* fast = head;
        ListNode* slow = head;
        ListNode* pre = NULL;

        //找中点
        while(fast && fast->next){
     
            slow = slow->next;
            fast = fast->next->next;
        }

        // slow之后断开,反转,反转完后,pre指向反转链表的头结点
        while(slow){
     
            ListNode* temp = slow->next;
            slow->next = pre;
            pre = slow;
            slow = temp;
        }

        // 比较链表,若为奇数,后半部分比前半部分多1各节点
        while(head && pre){
     
            if(head->val != pre->val){
     
                return false;
            }
            head = head->next;
            pre = pre->next;
        }
        return true;
    }
};

思路2: 栈

class Solution {
     
public:
    bool isPalindrome(ListNode* head) {
     

        stack<int> s;
        ListNode* p = head;

        // 入栈
        while(p){
     
            s.push(p->val);
            p = p->next;
        }

        p = head;
        while(p){
     
            if(p->val != s.top()){
     
                return false;
            }
            p = p->next;
            s.pop();
        }
        return true;
    }
};

练习题 leetcode 25. K 个一组翻转链表

思路:
算法图解 学习笔记Ch1 算法简介 Ch2 选择排序_第6张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
     
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
     
        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* pre = dummy; //初始化
        ListNode* end = dummy;

        while(end->next != NULL){
     
            //找到end,走k步
            for(int i = 0; i < k && end != NULL; i++){
     
                end = end->next;
            }
            // 跳出循环,到结尾
            if(end == NULL){
     
                break;
            }
            // 初始化 指针顺序:pre,start,end,next
            ListNode* start = pre->next;
            ListNode* next = end->next;
            // 断开end
            end->next = NULL;
            // 反转start-end之间的节点
            pre->next = reverse(start);
            // start连接上原来的链表 
            start->next = next;
            // 更新pre
            pre = start;
            // 更新end
            end = pre;
        }
        return dummy->next;
    }

    ListNode* reverse(ListNode* head){
     
        ListNode* pre = NULL;
        ListNode* cur = head;

        while(cur != NULL){
     
            ListNode* next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

练习题 leetcode 148. 排序链表

思路:
由于对时间和空间复杂度有要求,所以只能用归并排序了

练习题 leetcode 876. 链表的中间结点

练习题 leetcode 1019. 链表中的下一个更大节点

练习题 leetcode 143. 重排链表

练习题 leetcode

练习题 leetcode

排序练习(C++实现)

练习题 leetcode 969. 煎饼排序

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

练习题 leetcode

你可能感兴趣的:(刷题,C++)