6月4日刷题笔记——链表、栈

6月4日刷题笔记——链表、栈

题目1:21. 合并两个有序链表(简单题)

不会解,直接看题解。

知识点:链表、合并链表

方法1:暴力迭代法


class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        // 定义哨兵节点(就是定义个节点存放最后连接的结果)
        ListNode* preHead = new ListNode(-1);
        // 定义临时指针,用于存放当前值较小的节点
        ListNode* prev = preHead;
        // 循环结束条件为任意一个链表为空,此时剩下一个非空链表内剩余的元素一定是比前面已经比较过的元素大的了
        //(因为前提是两个有序的升序链表)
        while (l1 != nullptr && l2 != nullptr) {
            // 比较当前l1指向节点和l2指向节点哪个小,就将临时指针指向它,即将小的节点连接到结果链表中
            if (l1->val < l2->val) {
                // 临时指针的下一位指向较小的节点
                prev->next = l1;
                // 比较完当前元素,将指针指向下一个元素继续比较
                l1 = l1->next;
            } else {
                prev->next = l2;
                l2 = l2->next;
            }
            // 临时指针指向当前的较小节点
            prev = prev->next;
        }

        // 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
        prev->next = l1 == nullptr ? l2 : l1;
        // 返回下一位是因为哨兵节点首元素为-1,所以从它的下一位开始返回即为合并后的链表
        return preHead->next;
    }
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode-solu/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

根据题解复现代码:

/**
 * 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) {
        // 定义链表存放合并后的有序链表
        ListNode* preHead = new ListNode(-1);
        // 定义临时指针,存放当前较小节点
        ListNode* pre = preHead;
        // 循环连接两链表,当一个链表为空时,另一个链表剩下的节点都是大于前面节点的了,所以直接连在后面
        while(list1 != nullptr && list2 != nullptr){
            // 临时指针指向l1和l2当前指向的节点中较小的一方
            if(list1->val < list2->val){
                pre->next = list1;
                list1 = list1->next;
            }else{
                pre->next = list2;
                list2 = list2->next;
            }
            pre = pre->next;
        }
        // 剩下还没有遍历完的链表元素直接连在临时指针后
        pre->next = list1 == nullptr ? list2 : list1;
        return preHead->next;
    }
};

方法二:递归

(待理解)

根据题解复现代码:

/**
 * 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){
            list1->next = mergeTwoLists(list1->next, list2);
            return list1;
        }else{
            list2->next = mergeTwoLists(list1, list2->next);
            return list2;
        }
    }
};

题目2:203. 移除链表元素(简单题)

不会解,直接看题解。

知识点:链表:删除链表元素

方法一:暴力迭代

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        struct ListNode* dummyHead = new ListNode(0, head);
        struct ListNode* temp = dummyHead;
        while (temp->next != NULL) {
            if (temp->next->val == val) {
                temp->next = temp->next->next;
            } else {
                // 这里一定要写在else里
                // 如果写在if外不写else
                // 则如果最后一个元素是需要删除的元素时,此时pre=pre->next=NULL,再回来循环条件会报错
                temp = temp->next;
            }
        }
        return dummyHead->next;
    }
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/remove-linked-list-elements/solution/yi-chu-lian-biao-yuan-su-by-leetcode-sol-654m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

方法二:递归解法

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head == nullptr) return head;
        head->next = removeElements(head->next, val);
        return head->val == val ? head->next : head;
    }
};

题目3:206. 反转链表(简单题)

不会,直接上题解。

知识点:链表

方法一:暴力迭代

思路:
6月4日刷题笔记——链表、栈_第1张图片

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        // 1.存储前一个节点
        // 2.存储后一个节点
        // 3.将当前节点的next指向前一节点

        // 定义指针存储当前节点的前一节点
        ListNode* prev = nullptr;
        // ListNode* curr = head;
        // while(curr){
        //     // next 指针存储后一节点
        //     ListNode* next = curr->next;
        //     // 当前节点的next指向前一节点
        //     curr->next = prev;
        //     // 下次循环时,当前节点即为前一节点,为下一次的遍历赋值前一节点
        //     prev = curr;
        //     // 当前节点后移,继续遍历
        //     curr = next;
        // }
        while(head){
            ListNode* next = head->next;
            head->next = prev;
            prev = head;
            head = next;
        }
        return prev;
    }
};

还一个递归方法先不学了。

题目4:83. 删除排序链表中的重复元素(简单题)

知识点:链表、哈希表、删除链表元素

我的题解:

(通过的第一道链表题!)

/**
 * 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) {
        unordered_map<int , int> map;
        ListNode* pre = head;
        while(pre != nullptr){
            map[pre->val]++;
            pre = pre->next;
        }
        ListNode* preHead = new ListNode(0,head);
        ListNode* prev = preHead;
        while(prev->next){
            if(map[prev->next->val] > 1){
                map[prev->next->val]--;
                prev->next = prev->next->next;
            }else{
                prev = prev->next;
            }
        }
        return preHead->next;
    }
};

参考官方题解一次遍历的方法:

思路:
6月4日刷题笔记——链表、栈_第2张图片

代码:

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head) {
            return head;
        }

        ListNode* cur = head;
        // 循环条件为cur->next != null 说明只需要遍历到链表的最后一个节点即可
        while (cur->next) {
            if (cur->val == cur->next->val) {
                cur->next = cur->next->next;
            }
            else {
                cur = cur->next;
            }
        }

        return head;
    }
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-list/solution/shan-chu-pai-xu-lian-biao-zhong-de-zhong-49v5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

根据题解复现代码:

/**
 * 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 == nullptr) return head;
        ListNode* cur = head;
        while(cur->next){
            if(cur->val == cur->next->val){
                cur->next = cur->next->next;
            }else{
                cur = cur->next;
            }
        }
        return head;
    }
};

题目5:20. 有效的括号(简单题)

第二次做了,知道是栈的思路还是搞错了,哎。

知识点:栈

题解:

class Solution {
public:
    bool isValid(string s) {
        if(s.size() % 2 != 0) return false;
        unordered_map<char, char> pair{
            {')', '('},
            {']', '['},
            {'}', '{'}
        };
        stack<char> stk;
        for(auto ch:s){
            if(pair.count(ch)){
                if(stk.empty() || stk.top() != pair[ch]) return false;
                stk.pop();
            }else{
                stk.push(ch);
            }
        }
        return stk.empty();
    }
};

你可能感兴趣的:(链表,数据结构,leetcode)