记录刷题的日子5(2023.3.5)

前言

今天在街上发现了一条标语,写着“如果你不敢克服恐惧与担忧,那么你将从来不会知道,没有它们是多么美妙”,也算是被这句话激励了吧,我决定今天开始我害怕的指针相关题目!

剑指 Offer 06. 从尾到头打印链表

题目描述

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

前言

这个题我记得前阵子在力扣上面刷过,但是现在又忘了……既然是用数组返回,那么我就先按顺序存到数组里,然后再反转数组吧!
居然通过了!
天呢,我终于勇敢地进行了链表、指针相关的题目,而且通过这道题,我认识了栈这个知识点,原来栈不需要我自己写出来,在STL容器里已经定义了“栈”这个数据结构。小小地欢呼一下吧

思路
  • 方法1 利用栈
    将链表中每个结点的值按顺序压入栈中,然后再弹出,储存到vector< int>数组中。
 vector<int> reversePrint(ListNode* head) 
 {
    vector<int> result;
    stack<int> st;
    ListNode* cur = head;

    while(cur != NULL) 
    {
        st.push(cur->val);
        cur = cur->next;
    }

    while(!st.empty()) 
    {
        result.push_back(st.top());
        st.pop();
    }
    return result;
}
  • 方法2 递归
class Solution 
{
private:
    vector<int> v;
public:
    vector<int> reversePrint(ListNode* head) 
    {
        if(head)
        {
            reversePrint(head->next);
            v.push_back(head->val);
        }
        return v;
    }
};
  • 方法3
    利用vector容器的insert函数
	v.insert(v.begin() , p->val)
知识点

stack
stack即C++中的“栈”,是C++STL中一种先进后出(FILO)的容器。
1.stack的定义

	stack<typename> name;

2.stack常用函数

  • s.push( i ) //将 i 压入栈
  • s.top( ) //获取栈顶元素
  • s.pop( ) //弹出栈顶元素
  • s.empty( ) //检测stack是否为空,返回true为空,返回false为非空
  • s.size( ) //返回stack内元素的个数

以上五个函数时间复杂度均为O(1)

剑指 Offer 18. 删除链表的节点

题目描述

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。

前言

这道题看起来普普通通,完全没想到我的答案超出时间限制……额仔细检查了一下,原来是忘记写 p = p -> next

思路

解答区有个方法,定义了两个指针,一个指向当前结点,一个指向当前结点的前一个结点。

剑指 Offer 22. 链表中倒数第k个节点

题目描述

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

前言

这个常规方法做就可以了,我们首先求出链表的长度 length,然后顺序遍历到链表的第 length−k 个结点返回即可
解答区有个双指针的方法,就是指针1先走k步,然后指针2和指针1再一起走。

class Solution {
public:
	//这个方法是方法2
    ListNode* getKthFromEnd(ListNode* head, int k) {
        ListNode* fast = head;
        ListNode* slow = head;

        while (fast && k > 0) {
            fast = fast->next;
            k--;
        }
        while (fast) {
            fast = fast->next;
            slow = slow->next;
        }

        return slow;
    }
};

插入语

做到这里我突然认识到,在力扣上面,这个专题里通过率最高的题目,好像就是相对比较容易的题目,那么我就从链表、指针相关题目里最高的开始做好啦!这样多做几道就很有成就感

剑指 Offer 24. 反转链表

题目描述

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

前言

一开始我准备把链表每个结点指向的下一个结点都改变,后来发现太困难了,于是我想到可以通过改变每个结点的值,从而让这条链表记录的值和之前顺序相反,果然通过了。

思路
  • 前言中我用的方法(此处略)

  • 把链表每个结点指向的下一个结点都改变

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

剑指 Offer 25. 合并两个排序的链表

题目描述

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

前言

这个熟悉的题目,俨然是曾经数据结构讲过的一个经典算法,但是我忘记了,那么就好好回想一下吧。
玩了很长时间手机,心里慌慌张张的,感觉今天学得也太少了,赶紧把这个题努力地回想,反复试错终于做出来了。

易错点

注意到三种容易被忽略的情况

  • 链表l1、l2都为空;
  • 链表l1为空,l2不为空;
  • 链表l2为空,l1不为空
    我一开始忽略了这三种情况,直接当做都不为空,导致这种极端用例无法通过。
思路

本题思路有两个

  • 迭代,即我用的方法
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* preHead = new ListNode(-1);

        ListNode* prev = preHead;
        while (l1 != nullptr && l2 != nullptr) 
        {
            if (l1->val < l2->val) 
            {
                prev->next = l1;
                l1 = l1->next;
            } 
            else 
            {
                prev->next = l2;
                l2 = l2->next;
            }
            prev = prev->next;
        }

       prev->next = l1 == null ? l2 : l1;

        return preHead->next;
    }
};
  • 递归
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr)
         {
            return l2;
        } 
        else if (l2 == nullptr)
         {
            return l1;
        } 
        else if (l1->val < l2->val) 
        {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        } 
        else 
        {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }
};

再见

今天竟然做了5道题,从前想着每天最少五道题,哪知道最多的一天才五道呢!但是这已经是一个巨大的进步,接下来今天就躺床上休息了!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值