• 链表


    链表的数据结构体:

    struct node{
        int data;
        node* next;
        node(int data = 0):data(data), next(0){}
    };

    链表反转:设置三个指针,从前往后扫。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode * reverseList(ListNode *head) {
            if(head == NULL || head->next == NULL) return head;
            ListNode *p1 = head, *p2 = p1->next;
            p1->next = NULL;
            while(p2) {
                ListNode *p3 = p2->next;
                p2->next = p1;
                p1 = p2;
                p2 = p3;
            }
            return p1;
        }
    };

    反转中间某段:

    Leetcode25. Reverse Nodes in k-Group

    另起一个函数反转中间某段,注意指针为引用型。翻转的时候,依然需要三个指针。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        void inv(ListNode *&start, ListNode *&end){//reverse the node from start to end
            ListNode *p = start, *m = p->next, *q = m->next;
            start->next = end->next;
            while(m != end){
                m->next = p;
                p = m;
                m = q;
                q = q->next;
            }
            m->next = p;
            swap(start, end);
        }
        ListNode* reverseKGroup(ListNode* head, int k) {
            if(k < 2) return head;
            ListNode *p1 = head, *p2 = NULL;
            for(int i = 1; i < k&&p1 != NULL; i++) p1 = p1->next;
            if(p1 == NULL) return head;
            p2 = p1->next;
            inv(head, p1);
            while(true){
                p2 = p1->next;
                for(int i = 1; i < k&&p2 != NULL; i++) p2 = p2->next;
                if(p2 == NULL) return head;
                inv(p1->next, p2);
                p1 = p2;
            }
        }
    };

    ——————————————————————————————————————

     其他

    问题1:删除不知头结点链表的某个节点

    如果单向链表不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?

    思想为:把这个节点的下一个节点的值复制给该节点,然后删除下一个节点即可。

    问题2:怎么判断链表中是否有环?

    思想为:设置两个指针,一个步长为1,另一个步长为2,依次后移,如果相遇且都不为空,则有环。

    问题3:如果一个单向链表,其中有环,怎么找出这个链表循环部分的第一个节点?

    思想为:假设该节点在x位置处,假设步长为1的指针和步长为2的指针相遇在x处,

    那么当一个指针再从头节点处以步长1递进时,另一指针从x点以步长1递进时,两个指针就会在循环开始处相遇。

    简单证明:显然步长为2的指针多跑了k*循环长,而步长2跑的路程是步长1的两倍,则步长1跑了k*循环长。那么头节点和x节点离循环开始处距离相同。

    问题4:如何查找链表中倒数第k个节点?

    思想为:两个指向头结点的指针,一个先向后移动k位,然后两个同时向后面移动直到一个节点到达链尾,前面一个指针的位置就是了。

    问题5:两个有序链表如何合并?

    思想为:设两链表为La,Lb,设三指针pa,pb,pc。其中pa、pb指向两链表当前比较插入的结点,pc指向合并的链表的最后一个结点(初始状态可直接将其中一个链表 La 的头结点作为合并链表的尾结点)。

    问题6:编程序判断两个链表是否相交。

      如何知道两个单链表(无环)是否相交

      如果两个单链表(无环)相交,如何知道它们相交的第一个节点是什么

      如何知道两个单链表(有环)是否相交

      如果两个单链表(有环)相交,如何知道它们相交的第一个节点是什么

        答案

    这个问题的精彩解说请参见《编程之美》一书之《编程判断两个链表是否相交》,这里就不写了,该书的pdf文档在网上很好下。

    文章后面给了两个扩展问题:

    (1)如果链表可能有环,如何做判断?

    思想为:首先应该明白,只有一个链表有环的情况下是不会相交的,只有都有环或者都没有环的情况下才可能相交,都没有环的情况下最简便的方法就是判断链尾是否相交即可;都有环的情况下,分别找到环上的任一点,一个不动,另一个步进,即可判断是否相交。

    (2)如何求相交链表的第一个节点?应该为单链表情况

    思想为:方法一是先把任一个链表连成环,即从表尾接到表头,按照问题4的解法;方法二是计算两个链表的长度,而两个链表是按照尾部对齐的,那么从短链表的第一个位置从长链表的第长度差+1的位置依次比较指针值,相等的位置即是。

    关于链表的排序


    O(n^2)算法从前往后扫,交换结点内的值。

    O(nlogn)算法,O(1)插入删除(排序的时候,比参考点小,直接插入头节点前,否则插入尾节点后)。

    诸神对凡人心生艳羡,厌倦天堂。
  • 相关阅读:
    D. Minimax Problem
    Codeforces Round #592 (Div. 2) D,E
    Codeforces Round #587 (Div. 2) C
    Codeforces Round #587 (Div. 3) E
    Educational Codeforces Round 73 (Rated for Div. 2)
    HDU1247(Hat’s Words)
    HDU1251(统计难题)(字典树模板题
    HDU1525(Euclid's Game)规律博弈
    Find the answer
    Fansblog
  • 原文地址:https://www.cnblogs.com/dirge/p/5452546.html
Copyright © 2020-2023  润新知