C++ 链表 leetcode习题总结

链表的实现

struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };

最基本的实现链表的左右孩子指针,以及构造函数

链表的使用

我在做题中的习惯,是首先申请一个head节点,记得要申请空间TreeNode* head = new TreeNode()当然通过《程序员面试宝典》中提到,指针是可以定义的时候不申请空间,让其没有指向,但是引用定义时要有确定的网址。这里的head是为了我们返回结果链表时的首地址,返回head->next

除了head,就是申请TreeNode* p;指针p用来遍历我们的结果链表,或者添加节点,类似于游标

如果是对于两个链表做运算,那么就是一个while(l1!=nullptr && l2!=nullptr),while运行结束,l1和l2至少有一个是遍历结束了,if(l1==nullptr){while (l2……)}
if(l2==nullptr){while (l1……)}

Leetcode 206 反转链表

反转一个单链表。

示例:

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

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        stack<int> stack_list;
        ListNode* p ;
        ListNode* reverse = new ListNode();
        ListNode* cur = reverse;
        for(p = head; p!=nullptr; p = p->next){
            stack_list.push(p->val);
        }
        while(!stack_list.empty()){
            int value = stack_list.top();
            ListNode* node = new ListNode(value);
            reverse->next = node;
            reverse = reverse->next;
            stack_list.pop();
        }
        return cur->next;
    }
};

最简单的想法就是用一个栈遍历,再依次取出,构造结果链表。

这道题虽然简单,但是面试可能会问到,需要快速的写出答案,并且结果应该尽量简洁吧。

Leetcode官网给出的一种方法,可以节省空间的消耗。

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;
    }
};

一共是三个指针在活动要分清。首先翻转是从我们获得的链表到链尾遍历,改变它的prev指针指向自己的上一个被遍历到的节点,也就是逆序,curr表示当前正在操作的节点。next指针保存当前节点的next指针。因为当前next指针要指向逆序prev,所以在改变next指针之前,先把当前的next保存下来,为了遍历原链表的下一个节点。

Leetcode 141 环形链表

给定一个链表,判断链表中是否有环。

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

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

快慢指针法:

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head==NULL){
            return false;
        }
        ListNode *fast = head;
        ListNode *slow = head;
    while(fast->next!=NULL && slow->next != NULL && fast->next->next!=NULL){
            cout << "falst" << fast->val << "slow" << slow->val;
            fast = fast->next->next;
            slow = slow->next;
            if(fast==slow){
                return true;
            }
        }
        return false;
    }
};

Leetcode 287 寻找重复数

将链表的遍历顺序想象成一个跑到,如果快指针fast每次走两步,慢指针slow每次走一步,如果存在环,fast一定“扣圈”慢指针,在某一个位置相遇,这里判定的条件是地址,所以不用担心相同大小数字的干扰。

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,找出 这个重复的数 。

解答:
这道题用哈希表非常容易可以找到答案。

官方同时也用到了环形链表的解法

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = 0, fast = 0;
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while (slow != fast);
        slow = 0;
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }
};

链表的建立是通过节点的值(数组的值,例如7),去连接索引为7的数组的值,nums[7]。因为存在重复数,一定会有环形链表,,通过使用快慢指针,找到环形的入口,也就是重复的值。但这里一直有个疑惑,如果出现nums[0] = 1, nums[1] = 0,两个指针只会在这两个数里面转,如何保证只存在由重复数组成的环,没怎么想明白。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值