刷题记录6

题目1 力扣       力扣

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr){
            return list2;
        }else if(list2 == nullptr){
            return list1;
        }else if(list1->val > list2->val){
            list2->next =  mergeTwoLists(list1,list2->next);
            return list2;
        }else{
            list1->next = mergeTwoLists(list1->next,list2);
            return list1;
        } 
    }
};

 使用递归的方法,确定下一个返回的节点。

链表本来就具有递归的属性。

题目2 力扣

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr){
            return list2;
        }else if(list2 == nullptr){
            return list1;
        }else if(list1->val > list2->val){
            list2->next =  mergeTwoLists(list1,list2->next);
            return list2;
        }else{
            list1->next = mergeTwoLists(list1->next,list2);
            return list1;
        } 
    }
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* ans = nullptr;
        for(int i = 0;i<lists.size();++i){    
            ans = mergeTwoLists(ans,lists[i]);
        }
        return ans;
    }
};

新建一个结果链表,然后逐一与list中的链表顺序合并。

第二种做法是两两匹配合并,使用递归的方法实现了两两分类再合并。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr){
            return list2;
        }else if(list2 == nullptr){
            return list1;
        }else if(list1->val > list2->val){
            list2->next =  mergeTwoLists(list1,list2->next);
            return list2;
        }else{
            list1->next = mergeTwoLists(list1->next,list2);
            return list1;
        } 
    }
    ListNode* merge(vector<ListNode*>& lists,int L,int R){
        if(L==R){
            return lists[L];
        }
        if(L>R){
            return nullptr;
        }
        int mid =((R-L)>>1)+L;
        return mergeTwoLists(merge(lists,L,mid),merge(lists,mid+1,R));
    }
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int n = lists.size();
        return merge (lists,0,n-1);
    }
};

题目3 力扣

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr || head->next == nullptr ){
            return head;
        }
        ListNode* newHead = head->next;
        ListNode* rest = newHead->next;
        newHead->next = head;
        head->next = swapPairs(rest);
        return newHead;
    }
};

 标记head,newhead,rest三个位置,将head 和 newhead反转之后继续向下进行。

题目3 力扣

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummynode = new ListNode(0);
        dummynode->next = head;

        ListNode* p= dummynode;
        ListNode* q= dummynode;

        for(int i = 0;i<n+1;++i){
            p = p->next;
        } 
        while(p){
            p=p->next;
            q=q->next;
        }

        ListNode* delNode = q->next;
        q->next = delNode->next;

        ListNode* res = dummynode->next;
        delete dummynode;
        return res;
    }
};

 先设立一个虚拟的节点dummynode,再设定两个指针p与q,让p预先跑n次,再让q和p一起跑,当p指向nullptr时,q指向要删除节点的前一位,最后标记要删除结点后一个位置,用指针把前后位置链接。最后标记dummynode的下一位,把dummynode删除,返回标记好的dummynode的下一位即可(防止头节点是空节点)

题目4 力扣

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head == nullptr||head->next == nullptr || k == 0){
            return head;
        }
        ListNode* cur = head;
        int size = 0;
        while(cur != nullptr){
            size++;
            cur = cur->next;
        } 
        k%=size;
        if(k == 0){
            return head;
        }

        ListNode* p=head;
        ListNode* q=head;

        while(k>0){
            q=q->next;
            k--;
        }
        while(q->next != nullptr){
            p = p->next;
            q = q->next;
        }
        ListNode* newHead = p->next;
        p->next = nullptr; 
        q->next = head;
        
        return newHead;
    }
};

 首先获得数组长度,对k处理,如果刚好是长度的倍数,直接返回原数组。之后使用双指针,确定链表的新头部,然后处理成正常的链表返回新头部即可。

题目 5 力扣

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。

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

因为是有序链表所以简单判断即可。

题目6 力扣

 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

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

 先创建一个虚拟节点dummynode,然后遍历,如果遇到前后相同的情况,就记录这个值,删除之后所有相同的值 。

这里虚拟节点new之后没有删除

也可以采用下面的方法

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

直接用ListNode类型,使用时&dummy,最后返回dummy.next即可。

题目7 力扣

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

class Solution {
private:
    void reverse(ListNode *head) {
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while(cur!=nullptr){
            ListNode* next= cur->next;
            cur->next = pre;
            pre = cur;
            cur = next; 
        }
    }
public:
    ListNode *reverseBetween(ListNode *head, int left, int right) {
        ListNode* dummyNode = new ListNode(-1,head);

        ListNode* pre = dummyNode;
        for(int i=0;i<left-1;++i){
            pre =pre->next;
        }
        ListNode* rightNode = pre;
        for(int i=0;i<right-left+1;++i){
            rightNode = rightNode->next;
        }
        ListNode* leftNode = pre->next;
        ListNode* cur = rightNode->next;

        pre->next = nullptr;
        rightNode->next = nullptr;

        reverse(leftNode);
        pre->next = rightNode;
        leftNode->next = cur;

        return dummyNode->next;
    }
};

 

画图厘清节点关系即可。交换可使用上面的技巧。

题目8  力扣

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 

/**
 * 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) {
        unordered_set<ListNode*>seen;
        while(head!=nullptr){
            if(seen.count(head)){
                return true;
            }
            seen.insert(head);
            head=head->next;
        }
        return false;
    }
};

使用哈希表检测是否有重复值。

题目9 力扣

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        unordered_set<ListNode*>seen;
        while(head!=nullptr){
            if(seen.count(head)){
                return head;
            }
            seen.insert(head);
            head = head->next;
        }
        return nullptr;
    }
};

与上一题一致,这一题只需要返回那个位置即可。

题目10力扣

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode* cur = head;
        int n=0;
        while(cur!=nullptr){
            ++n;
            cur = cur->next;
        }
        cur = head;
        for(int i = 0;i<n/2;++i){
            cur = cur->next;
        }
        return cur;
    }
};

 进行两次遍历,第一次查到链表的大小,第二次查到中间节点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值