数组&链表

LeetCode
206.Reverse Linked List
24.Swap Nodes in Pairs
141.Linked List Cycle
142.Linked List Cycle II
25.Reverse Nodes in k-Group


LeetCode206 反转链表

https://leetcode-cn.com/problems/reverse-linked-list/
题目描述:
反转一个单链表。
示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

解题思路:

1.迭代方法:在原链表之前新建一个newHead,因为首节点会变,然后从head开始,将之后的一个节点移到newHead之后,重复此步骤直到head成为末节点为止。

2.递归方法 (套路解决递归问题 )

解法一:使用迭代
/**
 * 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 *newHead = NULL; //前指针节点
        //每次循环,都将当前节点指向它前面的节点,然后当前节点和前节点后移
        while (head) {
            ListNode *temp = head->next; //临时节点,暂存当前节点的下一节点,用于后移
            head->next = newHead; //将当前节点指向它前面的节点
            newHead = head; //前指针后移
            head = temp; //当前指针后移
        }
        return newHead;     
    }
};
解法二:使用递归
/**
 * 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 || !head->next) 
        return head;
    struct ListNode *newhead = reverseList(head->next); //newhead指针记录链表末尾节点
    head->next->next = head;
    head->next = NULL;
    return newhead;
    }
};

LeetCode24 两两交换链表中的节点

https://leetcode-cn.com/problems/swap-nodes-in-pairs/
题目描述:
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:

给定 1->2->3->4, 你应该返回 2->1->4->3.

解题思路:

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* swapPairs(ListNode* head) {
        if(head == NULL || head->next == NULL)return head;
        ListNode* first, *second, *current;
        first = head;//指向表头
        second = head->next;//指向表的第二个位置
       
        //第一次交换
        first->next = second->next;
        second->next = first;//此时first在second后面
        
        ListNode* result = second;//结果
        do{
            first = first->next;//向后移一个
            if(first == NULL || first->next == NULL){//判断后面是否有两个
                break;
            }
            second = second->next;//后移一个位置
            current = second;//保存当前的位置,用于后面交换
            second = second->next->next;//后移两个位置,到first后面
            //交换
            first->next = second->next;
            current->next = second;
            second->next = first;
        }while(1);
        
        return result;
    }
};
解法二:使用递归:
/**
 * 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 || head->next == NULL){
            return head;
        }
        //一共三个节点:head, next, swapPairs(next.next)
      	//下面的任务便是交换这3个节点中的前两个节点
        ListNode *next = head->next;
        head->next = swapPairs(next->next);
        next->next = head;
        //根据第二步:返回给上一级的是当前已经完成交换后,即处理好了的链表部分
        return next;
    }
};

LeetCode141 环形链表

https://leetcode-cn.com/problems/linked-list-cycle/
题目描述:
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例:
示例

解题思路:

1.硬做,判断遍历0.5秒后末尾指针是否为NULL。
2.set判重,时间复杂度O(n)。
3.快、慢指针,时间复杂度O(n),但空间复杂度较小。

解法三:
//快、慢指针
/**
 * 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;
        while(slow != NULL && fast != NULL && fast->next != NULL) {
            slow = slow->next;  //慢指针每次后移一步
            fast = fast->next->next;  //快指针每次后移两步
            if(slow == fast)
                return true;
        }
        return false;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值