LeetCode 热题 HOT 100 打卡计划 | 第四天 | 每日进步一点点

86 阅读2分钟

图片.png

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

19. 删除链表的倒数第 N 个结点

思路

(双指针) O(n)

具体过程如下:

1、创建虚拟头节点dummy,并让dummy->next = head

2、创建快指针first和慢指针second,并让其都指向dummy

3、先让快指针firstn + 1步,而后firstsecond指针同时向后走,直到first指针指向空节点,此时second 指向节点的下一个节点就是需要删除的节点,将其删除。

4、最后返回虚拟头节点的下一个节点。

解释:

始终保持两个指针之间间隔 n 个节点,在 first 到达终点时,second 的下一个结点就是倒数第 n个节点。

图片.png

时间复杂度分析: 只遍历一次链表,因此时间复杂度为O(n)。

c++代码

 /**
  * 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* dummy = new ListNode(-1);
         dummy->next = head;
         ListNode* first = dummy;
         ListNode* second = dummy;
         for(int i = 0; i <= n; i++) first = first->next;
         while(first){
             first = first->next;
             second = second->next;
         }
         second->next = second->next->next;
         return dummy->next;
     }
 };

20. 有效的括号

思路

(栈) O(n)

定义一个栈,从前往后枚举每个字符:

  • 1、当遇到'(','{','['左括号时,将元素压进栈中

  • 2、当遇到')',']','}'右括号时,

    • 如果栈不为空并且栈顶元素是对应的左括号,说明这是匹配的符号,将栈顶元素pop出即可。
    • 否则,表示不匹配,return false
  • 3、最后,若栈是空栈,表示所有字符都已经匹配好了,若不是空栈,表示还存在未能匹配好的子符

时间复杂度分析: 每个字符最多进栈出栈一次,因此时间复杂度为O(n)。

c++代码

 class Solution {
 public:
     bool isValid(string s) {
         stack<int> stk;
         for(int i = 0; i < s.size(); i++){
             if(s[i] == '(' || s[i] == '{' || s[i] == '[') stk.push(s[i]);
             else if(s[i] == ')'){
                 if(!stk.empty() && stk.top() == '(') stk.pop();
                 else return false;
             }
             else if(s[i] == '}'){
                 if(!stk.empty() && stk.top() == '{') stk.pop();
                 else return false;
             }
             else if(s[i] == ']'){
                 if(!stk.empty() && stk.top() == '[') stk.pop();
                 else return false;
             }
         }
         return stk.empty();
     }
 };

21. 合并两个有序链表

思路

(线性合并) O(n)

解题过程如下:

  1. 新建虚拟头节点 dummy,定义 cur指针并使其指向 dummy

  2. l1l2 都不为为空时:

    • l1->val < l2->val,则令 curnext 指针指向l1l1后移;
    • l1->val >=l2->val,则令 curnext 指针指向l2l2后移;
    • cur后移一步;
  3. 将剩余的 l1l2 接到 cur 指针后边。

  4. 最后返回dummy->next

时间复杂度分析: O(n)

c++代码

 /**
  * 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* l1, ListNode* l2) {
         ListNode* dummy = new ListNode(-1);
         ListNode* cur = dummy;
         while(l1 && l2){
             if(l1->val < l2->val){
                 cur->next = l1;
                 l1 = l1->next;
             }else{
                 cur->next = l2;
                 l2 = l2->next;
             }
             cur = cur->next;
         }
         if(l1) cur->next = l1;
         if(l2) cur->next = l2;
         return dummy->next;
     }
 };