• 链表基本操作题


    1. 链表反转,

    // 3指针,原地反转

    /**
     * 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) {
            ListNode* pre = NULL, *cur = head, *nxt = NULL;
            while(cur)
            {
                nxt = cur->next;
                cur->next = pre;
                pre = cur;
                cur = nxt;
            }
            return pre;
        }
    };

    2. 翻转链表m到n的结点,要求一次遍历完成(leetcode92)

    Node* reverseBetween(Node* head, int m, int n)
    {
        Node h(0);
        h.next = head;  //设置一个头节点,处理m=1的情况
        Node* p = &h;
        Node* tail;
        for(int i = 1; i <= n; i++)
            if(i < m) // p指向第n-1个节点位置
                p = p->next;
            else if(i == m) // tail指向第第n个节点,这个节点反转后处在反转部分的最后一个
                tail = p->next;
            else { //每次将tail后面一个节点拿出来,放在p后面,即头插法
                Node* item = tail->next;
                tail->next = tail->next->next;
                item->next = p->next;
                p->next = item;
            }
        return h.next;
    }

    3. 两个链表相加(leetcode2)

    Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
    Output: 7 -> 0 -> 8
    Explanation: 342 + 465 = 807.

        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode vhead(0), *p = &vhead;
            int carry = 0;
            while(l1 || l2 || carry)
            {
                int tmp = carry;
                if(l1 != NULL)  tmp += l1->val;
                if(l2 != NULL)  tmp += l2->val;
                carry = tmp / 10;
                tmp %= 10;
                
                ListNode* next = l1 ? l1 : l2;  // 交错
                if(next == NULL)  next = new ListNode(tmp); // 进位
                next->val = tmp;
    
                p->next = next;
                p = p->next;
    
                l1 = l1 ? l1->next : NULL;
                l2 = l2 ? l2->next : NULL;
            }
            return vhead.next;
        }

    4. 求链表中的倒数第K个节点

    一种直观的思路是先遍历链表得到链表的长度,然后第二次遍历就能找到第k个节点,但是需要进行两次遍历,不是好的方法;
    这里使用两个指针实现一次遍历,第一个指针先走k-1步,第二个指针一直不动;然后两个指针同时移动,知道第一个指针遍历完成。因为两个指针间隔为k-1,所以第二个指针指向的节点即为倒数第k个节点。
    ————————————————
    版权声明:本文为CSDN博主「大树先生的博客」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/Koala_Tree/article/details/79011152

        ListNode* getKthFromEnd(ListNode* head, int k) {
            ListNode* p1 = head, *p2 = head;
            for(int i = 0;i < k-1;i++)  p2 = p2->next;
            while(p2->next)
            {
                p1 = p1->next;
                p2 = p2->next;
            }
            return p1;
        }

    5. 判断两个链表是否相交 leetcode160

    思路一:最简单的先遍历一遍得到lenA, lenB,让长的先走掉差,再 同步走

    思路二:先两者同时走,先到null的去另一条,两者再走掉差,此时长的也到null了改去另一条,此时剩下的长度相同。

    思路三:将其中一条首尾相连,转化成了找环的入口

    // 思路二    
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* pa = headA, *pb = headB;
        while(pa != pb)
        {
            pa = pa == NULL ? headB : pa->next;
            pb = pb == NULL ? headA : pb->next;
        }   
        return pa;
    }

    5. 头插法和输出

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef struct Node
    {
        int val;
        Node* next;
        Node(int _val=0):val(_val), next(NULL){}
    }Node;
    
    // 构建链表
    // 头插法
    Node* insert(Node* head, int val)
    {
         Node* p = (Node*)malloc(sizeof(Node));
         p->val = val;
         p->next = head;
         head = p;
         return head;
    }
    
    // 遍历链表
    void print(Node* head)
    {
        Node* p = head;
        while(p)
        {
            printf("%d ", p->val);
            p = p->next;
        }
    }
    
    // 逆序输出
    void print_r(Node* head)
    {
        if(head == NULL)  return;
        if(head->next == NULL)
        {
            printf("%d ", head->val);
            return;
        }
        print_r(head->next);
        printf("%d ", head->val);
    }
    
    // 求倒数第k个节点
    void Kth_r(Node * head, int k)
    {
        Node *p = head, *p2 = head;
        for(int i = 0;i < k;i++) p = p->next;
        printf("p: %d
    ", p->val);
        while(p != NULL)
        {
            p = p->next;
            p2 = p2->next;
        }
        printf("p2: %d
    ", p2->val);
    }
    
    int a[] = {1, 2, 3, 4, 5}, n = 5;
    
    int main()
    {
        Node* head = (Node*)malloc(sizeof(Node));
        head->next = NULL, head->val = a[0];
        int i = 1;
        while(i < n)
        {
            head = insert(head, a[i]);
            i++;
        }
        print_r(head);
        printf("
    ");
    
        Kth_r(head, 2);
    
        return 0;
    }
  • 相关阅读:
    [题解] [JSOI2015] 圈地
    [题解] [JSOI2015] 最小表示
    [题解] [JSOI2015] 套娃
    [题解] [JSOI2015] 非诚勿扰
    [题解] [JSOI2015] 送礼物
    [题解] [JSOI2015] 送礼物
    [题解] [JSOI2015] 子集选取
    [题解] [JSOI2015] salesman
    AC自动机学习笔记
    [题解] [JSOI2014] 矩形并
  • 原文地址:https://www.cnblogs.com/lfri/p/12434194.html
Copyright © 2020-2023  润新知