各个数据结构和算法的链接总结如下:
待补充。

链表

总结:本部分内容其实就是考察对指针的操作。通过指针会改变对象指向的方向,这些都是需要注意。有一些技巧,类似于快慢指针,加一个脑袋(哨兵/头节点),hash等策略。需要注意变量的生命周期,内存安全,过程推演和边界/特殊情况。

简单部分

83.删除链表中的重复元素

class Solution {public:ListNode* deleteDuplicates(ListNode* head) {unordered_map<int,int> mp(0);ListNode* scan = head;ListNode temp(0);ListNode* pre = &temp;pre->next = head;while(scan){//mp[head->val]++;if(mp[scan->val]==1){//注意,这里是1,不是2!!卡在这里了。pre->next = scan->next;ListNode* del = scan;scan = scan->next;delete del;}else{mp[scan->val]++;//注意细节,我命名为scan,没有用headscan = scan->next;pre = pre->next;}}return head;}
};

141.环形链表 简单

第一次:计数法。注意,count只能判断0或者1.

class Solution {public:bool hasCycle(ListNode *head) {unordered_set<ListNode *> heads;while(head){if(heads.count(head)){return true;}heads.insert(head);head = head->next;}return false;}
};

第二次,快慢指针。

class Solution {bool hasCycle(ListNode *head) {ListNode *slow = head;ListNode *fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(fast && fast->next){if(fast==slow || fast->next==slow){return true;}}}return false;}
};

148.排序链表

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
看到这个复杂度要求就是归并排序。
递归三大流程:
断开;
分别排序;
合并。

public:ListNode* sortList(ListNode* head) {if (!head || !head->next){return head;}ListNode* slow = head;ListNode* fast = head;ListNode* brea = head;while(fast && fast->next){fast = fast->next->next;brea = slow;//因为断点是slow的前一个;slow = slow->next;}ListNode* head1 = head;ListNode* head2 = slow;brea->next = nullptr;//断开ListNode* part1 = sortList(head1);ListNode* part2 = sortList(head2);return merge(part1,part2);}

合并:
这个代码和那道合并两个排序链表的题是一样的。先弄一个哨兵头节点作为新链表的开头,然后依次比较2个原先链表的val,依次插到新链表的尾部。

private:ListNode* merge(ListNode* head1,ListNode* head2){ListNode temp(0);ListNode* head = &temp;while(head1 && head2){if(head1->val<=head2->val){head->next = head1;head1 = head1->next;}else{head->next = head2;head2 = head2->next;}head = head->next;}用 p->next = l1 ? l1 : l2 替代if(head1){head->next = head1;}if(head2){head->next = head2;}return temp.next;}
};

160.相交链表找交点

方法一:

class Solution {public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {unordered_set<ListNode *> dic1,dic2;while(headA || headB){if(headA) dic1.insert(headA);if(headB) dic2.insert(headB);if(dic1.find(headB)!=dic1.end()) return headB;if(dic2.find(headA)!=dic2.end()) return headA;if(headA) headA = headA->next;if(headB) headB = headB->next;}return nullptr;}
};

有点暴力了,而且和别人的hash法不太一样;
这个解法不好,应该先遍历链表,求各自长度,然后长的先走几步。

方法二:

class Solution {public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {int lenA(0),lenB(0);ListNode *temp = headA;while(temp){lenA++;temp = temp->next;}temp = headB;while(temp){lenB++;temp = temp->next;}int dif = lenA > lenB ? (lenA-lenB):(lenB-lenA);if(lenA > lenB){while(dif) {headA = headA->next; dif--;}}else{while(dif) {headB = headB->next; dif--;}}while(headA && headB){if (headA == headB) return headA;headA = headA->next;headB = headB->next;}return nullptr;}
};

202.快乐数

快慢指针。

class Solution {public:bool isHappy(int n) {int fast(0),slow(0);slow = round(n);fast = round(slow);while (fast!=1 || slow!=1){slow = round(slow);fast = round(round(fast));if(slow == fast && slow != 1) return false;}return true;}
private:int round(const int input){int sum(0);int num = input;while(num!=0){int a = num % 10;num /= 10;sum += a * a;}return sum;}
};

203.移除链表元素 简单

class Solution {public:ListNode* removeElements(ListNode* head, int val) {//ListNode* next=head;//if(head && head->next==nullptr && head->val==val) return nullptr;//ListNode* temp=head;//可以不要这一句ListNode tempH(0);ListNode* pre = &tempH;pre->next = head;while(head){if(head->val == val){//next = head->next;if(head->next) pre->next = head->next;else pre->next = nullptr;//可以不加上这个判断ListNode *del = head;head = head->next;del->next = nullptr;//这一句绝对不可以跑到下一句后面!delete del;//del = nullptr;}else {head = head->next; pre = pre->next;}}return tempH.next;//不可以是temp!}
};

这道题需要考虑 一般情况;链表里没有结点的值等于待删除val;输入的链表至多只有1个结点;删除的是头节点或尾结点;
头两种情况是一样的;待删除结点在尾结点和一般情况也是一样的;
后两种情况是类似的,也就是待删除结点是头节点比较麻烦。
这个时候,在链表前面再加上一个结点,return的时候绝对不可以是原链表头节点temp,因为它已经被删除了,不能对已经被删除的结点进行操作!

234.判断回文链表

看到回文就用栈。

class Solution {public:bool isPalindrome(ListNode* head) {std::stack<int> front;int count;ListNode *fast = head;ListNode *slow = head;while(slow){//fast && fast->next){//不能用||front.push(slow->val);slow = slow->next;//fast = fast->next;//count++;//if(fast && fast->next){//报错1:这里需要加上对fast的判断,因为此时fast可能已经为null了,此时fast->next是非法的//fast = fast->next;//    count++;//}}while(!front.empty() && head){if(front.top() != head->val) return false;front.pop();head = head->next;}return true;}
};

237.删除给定的链表结点

class Solution {public:void deleteNode(ListNode* node) {ListNode *next = node->next;node->val = next->val;node->next = next->next;next->next = nullptr;delete next;}
};

题目的意思是直接把这个结点的指针给你,所以你无法得到上一个结点的指针。所以要把下一个结点的val给他,然后把下一个结点删掉。

876.链表的中间结点

快慢指针

class Solution {public:ListNode* middleNode(ListNode* head) {ListNode* fast = head;ListNode* slow = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;}
};

1290.二进制链表转整数

class Solution {public:int getDecimalValue(ListNode* head) {int sum(0);while(head){sum = sum << 1;//不能仅仅是sum << 1,需要赋值操作接一下。if(head->val==1) sum += 1;head = head->next;}return sum;}
};

中等部分

2.两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

class Solution {public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {if(!l1 && !l2) return l1;//ListNode temp(0);不可以这么写,注意生命周期!!出了这个函数就没了,无法return &temp!//ListNode* temp = new ListNode(0);//应该这么写 <-问题1//ListNode* l3 = temp;//变量定义在这里,不在private里也可以,速度好像更快了//int val = 0;while(l1 && l2){val = l1->val + l2->val + val;//绝对不可以写成ListNode node(val%10);生命周期!!<-问题1ListNode *node= new ListNode(val%10); <-问题1l3->next = node;l3 = node;val /= 10;l1 = l1->next;l2 = l2->next;}if(l1) {pair<int,ListNode*> kids = add(l1,l3,val); <-问题2val = kids.first; <-问题2l3 = kids.second; <-问题2}if(l2) {pair<int,ListNode*> kids = add(l2,l3,val);val = kids.first;l3 = kids.second;}if(val!=0) l3 = add(l3,val);l3->next = nullptr;return temp->next;}
private:ListNode *temp = new ListNode(0);ListNode* l3 = temp;int val = 0;pair<int,ListNode*> add(ListNode* head,ListNode* l3,int num){ <-问题2//ListNode* add(ListNode* head,ListNode* l3,int num){ <-问题1//void add(ListNode* head,ListNode* l3,int val){ <-问题1int val = num;while(head){val = head->val + val;ListNode *node= new ListNode(val%10);l3->next = node;l3 = node;val /= 10;head = head->next;}return make_pair(val,l3); <-问题2}ListNode* add(ListNode* l3,int num){//void add(ListNode* l3,int val){int val = num;ListNode *node= new ListNode(val);l3->next = node;l3 = node;return l3; <-问题1}
};

这道题花了我不少时间!!其实来说,思路很快出来了,但是问题集中在c++语法上,出现了太多错误!
思路就是采用val%10和val/10的方式不断添加结点;如果有一个链表更长,那么再继续这个链表;如果链表都走完了还是有进位,那么再加一个结点;

<-问题1:
在循环里面创建一个结点,不能用ListNode temp(0),因为一旦出了循环,这个结点就析构了,循环里面l3一连串的链表添加全部失效,发生指针越界,出现stack use after scope报错;所以在这里,必须采用ListNode* temp = new ListNode(0)这种方式,这样写是在堆中申请了内存,即使离开了这个函数,堆中申请的内存还有效。
add()也是一样的问题,不能使用void,因为一旦离开了函数,里面的操作全部失效,必须定义为ListNode*。
<-问题2:
问题2也是一样的,在add()函数里面,val的值是有变化的,出去就没了(val还是原来的值),所以需要接一下。

需要复习作用域相关知识!
https://www.zhihu.com/question/319422326/answer/987410607

https://blog.csdn.net/u013007900/article/details/79338653
留意一下C++的栈区,堆区,自由存储区,全局/静态变量区,常量区等概念。

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

class Solution {public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode tempH(0); <-ListNode* pre = &tempH;pre->next = head;ListNode* temp = pre;ListNode* del = head;int count = 0;while(temp){count++;temp = temp->next;}int step = count - n - 1;  <-temp = pre;while(step > 0){pre = head;head = head->next;step--;}pre->next = head->next;del = head;delete del;return temp->next;}
};

思路:第一遍遍历链表长度,第二遍走count - n – 1;
前面需要加上一个脑袋,目的是解决删除结点是头节点或者链表只有一个结点的情况;
走的步数之所以-1是因为加了个脑袋。

24.两两交换链表中的结点

class Solution {public:ListNode* swapPairs(ListNode* head) {if(head == nullptr || head->next == nullptr) return head; <-别少了判断ListNode* temp = head;ListNode tempH(0); <-加个脑袋ListNode* help = &tempH;help->next = head;head = head->next;while(temp && temp->next){ListNode* help1 = temp;ListNode* help2 = temp->next;help->next = help2;temp = temp->next->next;help1->next = help2->next; help2->next = help1;       help = help->next->next;   <-别少了一个next}return head;}
};

绕来绕去的,把过程想清楚,图画明白是最重要的事情,不要跳步骤画图。

61.旋转链表

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

class Solution {public:ListNode* rotateRight(ListNode* head, int k) {if(head==nullptr || head->next==nullptr) return head;ListNode* temp = head;ListNode* tail = temp;ListNode* pre = temp;int count = 0;while(temp){count++;tail = temp;temp = temp->next;}int step = count - k % count;if(k==0 || step==count) return head; <-加上这个判断temp = head;while(step){pre = temp;temp = temp->next;step--;}tail->next = head;pre->next = nullptr;return temp;}
};

总的来说和之前的题目没有什么本质的区别,例如和 删除链表的倒数第n个结点 这道题就很像。关键就是找到交换结点的起始位置。

【leetcode刷题日记】链表相关推荐

  1. 一个算法笨蛋的12月leetCode刷题日记

    类似文章 一个算法笨蛋的2021年11月leetCode刷题日记 一个算法笨蛋的2021年12月leetCode刷题日记 一个算法笨蛋的2022年1月leetCode刷题日记 一个算法笨蛋的2022年 ...

  2. Leetcode刷题日记:21-25题篇

    Leetcode刷题日记:21-25题篇 简介 题目: 21. 合并两个有序链表 22. 括号生成 23. 合并K个升序链表 24. 两两交换链表中的节点 25. K 个一组翻转链表 注 简介 这个系 ...

  3. Leetcode刷题日记(十二)

    又是老台词:欢迎大家来到一晚一度的leetcode刷题日记时间.今天我们来讲讲队列的问题,队列这方面的基础知识需要的同学到博主前面的文章找吧.队列这方面的问题平时博主也是接触得比较少的.下面是一道利用 ...

  4. 【LeetCode刷题日记】常用算法基础和理解及运用

    在我们LeetCode刷题过程中,如果我们只是了解数据结构(数组,链表,数)的使用方法,那我们在面对复杂的题目时,是很难很好的解决问题的,因此我们要了解一些常用算法来帮助我们更好的解题. 递归和迭代 ...

  5. leetcode刷题日记(一)—— 数组

    因为暑期实习找得很不顺利,感觉自身最大的问题体现在刷题量偏少,操作系统,数据库基础不好,所以现在决定写博客来记录整个过程,希望能找到大厂offer,如果不能找到的话也算是为秋招做准备. 剑指offer ...

  6. LeetCode刷题日记 203. 移除链表元素

    删除链表中等于给定值 val 的所有节点. /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode ...

  7. leetcode刷题笔记-链表的使用

    一.单链表的基础:增删改查 问题:设计一个单链表,要求实现其增删改查功能.707. 设计链表 问题分析 往链表中添加元素的步骤 往链表中删除元素的步骤 注意:对于单链表来说,添加一个无用的头节点,再对 ...

  8. LeetCode刷题日记盛最多水的容器

    节后第一天,鉴于五一五天都没做过题,有点遗忘了,今天来看一道简单点的题,练下手. 先看下题: 给你 n 个非负整数 a1,a2,-,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条 ...

  9. 石器时代 —— Leetcode刷题日记 (一 百大热题)

    Date: 2019.10.22 - (C++ Version) 文章目录 All Labels: `热题100` L1 两数之和 L2 两数相加 暴力相加 递归 迭代 L3 无重复字符的最长子串 L ...

最新文章

  1. Matlab与线性代数 -- 矩阵的左除
  2. layui遍历json数组_Python列表边遍历边删除,怎么用才不报越界错误呢?
  3. 读redux源码总结
  4. 男人最佳的生育年限,程序员们,看看吧!!!
  5. 图片格式之RGB转BMP格式(含代码)
  6. mysql数据库简单语句
  7. 【LeetCode题解】402.移掉K位数字问题
  8. samba服务器_win10 更新导致无法连接samba服务器
  9. fw313r手机登录_迅捷(FAST)fw313r路由器手机设置教程
  10. 戴尔电脑vostro恢复出厂(预装Win10)的设置方法
  11. 联想g510拆键盘的简单方法_联想g510笔记本电脑键盘拆卸视频
  12. 外包的水有多深?华为15k+的外包测试岗能去吗?
  13. 云队友丨两年还债4个亿!罗永浩,你可真行
  14. coap 返回版本信息_coap组包格式的简单解析
  15. mysql执行存储过程报错1366_花花蘑菇
  16. 计算机为啥系统保护设置不了,我的电脑为什么设置了屏幕保护程序而不起作用 – 手机爱问...
  17. 在线Base64编码加密解密还原工具
  18. 两相编码器的FPGA驱动
  19. 【蓝桥杯方法篇】贪心算法详解一
  20. Mycat2.0搭建教程

热门文章

  1. 超市扫码属于应用计算机中的,操作系统概论自考2015年4月真题
  2. Windows10安装配置Maven
  3. 在蓝旭工作室学习的总结
  4. (3)风色从零单排《C++ Primer》 重要的基本类型
  5. 自然语言处理(NLP):20 基于知识图谱的智能问答系统
  6. docker下载mysql镜像并启动容器
  7. MySQL 5.7 下载与安装(Windows msi 图形化安装)
  8. 在线查看office文档
  9. 程序员吐槽_程序员吐槽大全,欢迎补充,吐槽有礼!!
  10. 如何有效管理我们的供应商?