zoukankan      html  css  js  c++  java
  • 链表 206 Reverse Linked List, 92,86, 328, 2, 445

    表不支持随机查找,通常是使用next指针进行操作。

    206. 反转链表

     

     

     

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    //时间:O(n)  只遍历了一遍链表
    //空间:O(1) 开了三个指针的空间
    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            ListNode* pre = NULL, *cur = head, *next = NULL;  //head为头指针指向链表中的第一个元素
            while(cur != NULL){
                //直到cur指向为空,循环结束。即pre指向链表的最后一个结点,也是新链表的头结点
                next = cur->next;
    
                cur->next = pre;
                pre = cur;
                cur = next;
            }
            return pre;   
        }
    };

    需要考虑以上两个问题,在本题中已经假定1 <= m <= n <= length of list

    思路:

     

    /**
     * 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 *guard = new ListNode(-1);
            guard -> next = head;
            
            ListNode *pre = guard;
            for(int i=1;i<=m-1;i++)
                pre = pre->next;   //pre指向需要翻转链表的前一个结点
            
            ListNode *cur = pre->next;  //i指向翻转链表的第一个结点
            ListNode *post = cur->next;
            for(int i=1;i<=n-m;i++){
                cur->next = post->next;
                post->next = pre->next;
                pre->next = post;
                post = cur->next;
            }
            
            return guard -> next;
        }
    };

    完整的翻转链表程序:

    // list.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include "pch.h"
    #include <iostream>
    using namespace std;
    
    /**
    
     * Definition for singly-linked list.
    
     */
    
    struct ListNode {
    
        int val;
    
        ListNode *next;
    
        ListNode(int x) : val(x), next(NULL) {}
    
    };
    
    
    
    // 根据n个元素的数组arr创建一个链表, 并返回链表的头
    
    ListNode* createLinkedList(int arr[], int n) {
    
    
    
        if (n == 0)
    
            return NULL;
    
    
    
        ListNode* head = new ListNode(arr[0]);
    
        ListNode* curNode = head;
    
        for (int i = 1; i < n; i++) {
    
            curNode->next = new ListNode(arr[i]);
    
            curNode = curNode->next;
    
        }
    
    
    
        return head;
    
    }
    
    
    
    // 打印以head为头结点的链表信息内容
    
    void printLinkedList(ListNode* head) {
    
    
    
        ListNode* curNode = head;
    
        while (curNode != NULL) {
    
            cout << curNode->val << " -> ";
    
            curNode = curNode->next;
    
        }
    
    
    
        cout << "NULL" << endl;
    
    
    
        return;
    
    }
    
    
    
    // 释放以head为头结点的链表空间
    
    void deleteLinkedList(ListNode* head) {
    
    
    
        ListNode* curNode = head;
    
        while (curNode != NULL) {
    
            ListNode* delNode = curNode;
    
            curNode = curNode->next;
    
            delete delNode;
    
        }
    
    
    
        return;
    
    }
    
    
    
    
    
    // 206. Reverse Linked List
    
    // https://leetcode.com/problems/reverse-linked-list/description/
    
    // 时间复杂度: O(n)
    
    // 空间复杂度: O(1)
    
    class Solution {
    
    public:
    
        ListNode* reverseList(ListNode* head) {
    
    
    
            ListNode* pre = NULL;
    
            ListNode* cur = head;
    
            while (cur != NULL) {
    
                ListNode* next = cur->next;
    
                cur->next = pre;
    
                pre = cur;
    
                cur = next;
    
            }
    
    
    
            return pre;
    
        }
    
    };
    
    
    
    int main() {
    
    
    
        int arr[] = { 1, 2, 3, 4, 5 };
    
        int n = sizeof(arr) / sizeof(int);
    
    
    
        ListNode* head = createLinkedList(arr, n);
    
        printLinkedList(head);
    
    
    
        ListNode* head2 = Solution().reverseList(head);
    
        printLinkedList(head2);
    
    
    
        deleteLinkedList(head2);
    
    
    
        return 0;
    
    }

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* deleteDuplicates(ListNode* head) {
            ListNode* cur = head;
            while(cur && cur->next){
                ListNode* post = cur->next;
                if(post->val == cur->val){
                    cur->next = post->next;
                    delete post;
                }
                else
                    cur = cur->next;
            }
            
            return head;
        }
    };

     

    思路:在链表中,可以通过创建两个新的头结点指针,来分别指向小于x的结点和大于等于x的结点,遍历结束之后,再将两个新的链表重新连接起来。

    /**
     * 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 *l_head = NULL, *l_tail = NULL;
            ListNode *r_head = NULL, *r_tail = NULL;
            ListNode *p = head;
            
            while(p){
                if(p->val < x){
                   if(l_tail){
                       l_tail->next = p;
                       l_tail = l_tail->next;
                   } 
                    else
                        l_head = l_tail = p;
                }
                else{
                    if(r_tail){
                        r_tail->next = p;
                        r_tail = r_tail->next;
                    }
                    else
                       r_head = r_tail = p; 
                }
                p = p->next;
            }
            
            if(r_tail)
                r_tail->next = NULL;
            if(l_tail)
                l_tail->next = r_head;
            
            return l_head?l_head:r_head;
        }
    };

     

    思路:先将偶数索引的第一个节点记录下来,然后将奇数索引和偶数索引分开为两个链表,最后将奇数索引的最后一个节点指向偶数索引的第一个节点。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* oddEvenList(ListNode* head) {
            if(head==NULL || head->next == NULL)
                return head;
            ListNode* odd = head;
            ListNode* even = head->next;
            ListNode* t = even;
            while(even!=NULL && even->next!=NULL){
                odd->next = even->next;
                odd = odd->next;
                even->next = odd->next;
                even = even->next;
            }
            odd->next = t;
            return head;
        }
    };

     

    本题中是两个非负整数,且数字除0外前面不会有0。

    思路:

    1.首先用两个指针,分别同时遍历两个链表,按位相加,设置相应进位标志。
    2.当两个链表长度不一致时,结束按位相加的遍历之后,将剩余元素链接接上。(所以需要判断链表当前要计算的结点是否存在)
    3.需要注意连续进位。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode* res = new ListNode(0);
            ListNode* p = res;
            int add = 0;
            while(l1 || l2 || add){
                int n1 = l1 ? l1->val : 0;
                int n2 = l2 ? l2->val : 0;
                int sum = n1 + n2 + add;
                add = sum/10;
                p->next = new ListNode(sum%10);
                p = p->next;
                if(l1) l1 = l1->next;
                if(l2) l2 = l2->next;
            }
            return res->next;
        }
    };

     

    思路:使用栈的先进后出结构来实现从链表的后面往前面取数字。res记录当前两个结点的和,然后新建一个进位结点head赋值为sum/10,若没有进位就是0。把head的后继连到res,再把res指向head。直到循环退出后,返回res(返回时要判断res为0则返回res->next)。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            stack<int> s1, s2;
            while(l1){
                s1.push(l1->val);
                l1 = l1->next;
            }
            while(l2){
                s2.push(l2->val);
                l2 = l2->next;
            }
            int sum = 0;
            ListNode* res = new ListNode(0);
            while(!s1.empty() || !s2.empty()){
                if(!s1.empty()){
                    sum += s1.top();
                    s1.pop();
                }
                if(!s2.empty()){
                    sum += s2.top();
                    s2.pop();
                }
                res->val = sum % 10;
                ListNode* head = new ListNode(sum/10);
                head->next = res;
                res = head;
                sum /= 10;
            }
            return res->val == 0 ? res->next : res;
        }
    };
  • 相关阅读:
    第十章 系统级I/O
    第九章 虚拟内存
    第六章 存储器层次结构
    第八章 异常控制流(下)
    第八章 异常控制流(上)
    第三章 机器的程序级表示(下)
    第三章 机器的程序级表示(中)
    第三章 机器的程序级表示(上)
    python学习之列表的定义以及增删改查
    Python学习之字符串中的下标和切片以及逆序
  • 原文地址:https://www.cnblogs.com/Bella2017/p/10171107.html
Copyright © 2011-2022 走看看