zoukankan      html  css  js  c++  java
  • 反转链表类型题

    leetcode 206

    思路

    • 迭代:遍历链表,将当前节点的next指向前一个节点,中间过程需要保存前一个节点和下一个节点(反转后最后一个节点指向空)

      时间复杂度O(n),空间复杂度O(1)

    • 递归:将反转整个链表分解为两个子问题(反转head和反转head以外的其它节点),往下分解为只剩下一个节点(不需要反转),然后反转两个节点一直往上归并直至反转完整个链表

      时间复杂度O(n),空间复杂度O(n)(递归调用的栈空间)

    代码

    迭代

    class Solution {
    	public:
    		ListNode *reverseList(ListNode *head) {
    			ListNode *pre = nullptr;
    			ListNode *cur = head;
                ListNode *next;
    			while (cur) {
                    next = cur->next;
    				cur->next = pre;
    				pre = cur;
    				cur = next;
    			}
    			return pre;
    		}
    };
    

    递归

    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            //递归终止条件:当前节点为空或者只有一个节点
            if(head == nullptr || head->next == nullptr){
                return head;
            }
            //递的过程
            ListNode *newHead = reverseList(head->next);
            //归的过程
            head->next->next = head;
            head->next = nullptr; //最后的节点指向空 
            return newHead;
        }
    };
    

    leetcode 92

    思路

    • 方法一:将需要反转的链表区间反转后与不需要反转的区间拼接起来

      时间复杂度O(n),空间复杂度O(1)

    • 方法二:头插法,遍历反转区间,将当前节点放到反转起始的位置,直至反转区间节点反转完

      时间复杂度O(n),空间复杂度O(1)

    代码

    方法一

    class Solution {
    private:
        ListNode *reverseList(ListNode *head){
            if(!head || !head->next){
                return head;
            }
            ListNode *newHead = reverseList(head->next);
            head->next->next = head;
            head->next = nullptr;
            return newHead;
        }
    public:
        ListNode *reverseBetween(ListNode *head, int left, int right) {
    			ListNode *dummyNode = new ListNode(-1);
    			dummyNode->next = head;
    
                ListNode *pre = dummyNode;  //走left-1步找到left前一个节点
    			for (int i = 0; i < left - 1; i++) {
    				pre = pre->next;
    			}
                
                ListNode *rightNode = pre; //再走right - left + 1找到right
                for(int i = 0;i < right - left + 1;i++){
                    rightNode = rightNode->next;
                }
    
    			ListNode *leftNode = pre->next; //记录left前一个
                ListNode *subNode = rightNode->next; //记录right下一个
                
                rightNode->next = nullptr;//截断中间区域
    
                ListNode *midNode = reverseList(leftNode); //反转中间区域
    
                //重新连接
                pre->next = midNode;
                leftNode->next = subNode;
    			return dummyNode->next;
    		}
    };
    

    方法二

    class Solution {
    public:
        ListNode *reverseBetween(ListNode *head, int left, int right) {
    			//头插法
    			ListNode *dummyNode = new ListNode(-1);
    			dummyNode->next = head;
    
                ListNode *pre = dummyNode;
    			for (int i = 0; i < left - 1; i++) {
    				pre = pre->next;
    			}
    
    			ListNode *cur = pre->next;
    			ListNode *next;
    
    			for (int i = 0; i < right - left; i++) {
    				next = cur->next;
    				cur->next = next->next;
    				next->next = pre->next;
    				pre->next = next;
    			}
    			return dummyNode->next;
    		}
    };
    

    改编题目

    题目描述

    给定单链表的头指针head,两个整数left和right其中left < right,请你反转从1到left,以及位置right到末尾节点,返回反转后的链表

    注:链表长度>=2且left和right范围不超过链表本身

    示例

    输入

    [3,4,5,6,7,8],3,5
    

    输出

    [5,4,3,6,8,7]
    

    思路

    直接在leetcode92的基础上反转两次[1,left] [right,tail]

    代码

    class Solution {
    	private:
    		ListNode *reverseBetween(LisNode *head, int left, int right) {
    			//头插法
    			ListNode *dummyNode = new ListNode(-1);
    			dummyNode->next = head;
    
    			for (int i = 0; i < left - 1; i++) {
    				pre = pre->next;
    			}
    
    			ListNode *cur = pre->next;
    			ListNode *next;
    
    			for (int i = 0; i < right - left; i++) {
    				next = cur->next;
    				cur->next = next->next;
    				next->next = pre->next;
    				pre->next = next;
    			}
    			return dummyNode->next;
    		}
    	public:
    		ListNode *reverseList(listNode *head, int left, int right) {
    			ListNode *temp = head;
    			int tail = 0;
    			while (temp) {
    				temp = temp->next;
    				tail++;
    			}
    			//先反转左半边
    			head = reverseBetween(head, 1, left);
    			//再翻转右半边
    			head = reverseBetween(head, right, tail);
    			return head;
    		}
    };
    
  • 相关阅读:
    HDU 5542 The Battle of Chibi (离散化+树状数组优化DP)
    UVaLive 7637 Balanced String (构造)
    ZOJ 3512 Financial Fraud (左偏树)
    HDU 1512 Monkey King (左偏树+并查集)
    POJ 2311 Cutting Game (博弈)
    POJ 2348 Euclid's Game (博弈)
    Gym 101142C CodeCoder vs TopForces (搜索)
    Gym
    Spring注解
    sql语句中的占位符?有什么作用
  • 原文地址:https://www.cnblogs.com/Vicky1361/p/15025268.html
Copyright © 2011-2022 走看看