Leetcode初级算法(链表篇)
删除链表的倒数第N个节点
感觉自己对于链表的知识还是了解的不够深入,所以没有想到用双指针进行操作。我的想法是这样的,首先计算整个链表的长度,然后遍历到长度减去n的节点处,执行删除操作。
自己的代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* cur=head;
ListNode *cou=head;
int i=0;
int count=1;
while(cou->next!=NULL)
{
cou=cou->next;
count++;
}
if(count==1) return NULL;
if(count==n) {head=head->next;
return head;}
while(head->next!=NULL && i<count-1-n)
{
head=head->next;
i++;
}
if(head->next!=NULL)
{
ListNode *temp;
temp=head->next;
head->next=temp->next;
}
return cur;
}
};
相信看过代码后都会觉得这个代码的逻辑比较奇怪,尤其是
if(count==1) return NULL; if(count==n) {
head=head->next;
return head;
}
这段代码,感觉是根据测试案例试出来的。的确是这样的,我的代码在[1,2]去掉倒数第二个元素或者[1,2,3]去掉倒数第三各元素的时候总是会去除中间的额元素,经排查原因应该是head节点的理解有些问题。我认为的head是头指针,head->next才是第一个结点,但这代码里的意思好像是head就已经是第一个节点了,所以在后面判断的时候有些bug。当然我们还是习惯用比较常规的方法就是用双指针的方法进行问题的解决:
这里放出大神的代码:
class Solution{
public:
ListNode* removeNthFromEnd(ListNode* head,int n){
if(!head->next) return NULL;
LisNode *pre=head,*cur=head;
for(int i=0;i<n;i++) cur=cur->next;
if(!cur) return head->next;
while(cur->next){
cur=cur->next;
pre=pre->next;
}
pre->next=pre->next->next;
return head;
}
};
下面我来解释一下这段代码的意思,定义了两个指针,两个指针相差n个距离,这样的话当其中一个指针指向结尾处的时候,另一个指针就自然指向了我们需要删除的前一个元素位置了,然后执行删除操作,这样非常的快捷。
反转链表
感觉这道题有些帅,试着走了一遍逻辑,并不是像我之前以为的一个新链表然后反向遍历读出数据,但是这个逻辑是一次反转一个,用到dummy始终指向头结点、cur始终指向当前的节点、tmp指向下一个结点,逻辑就是将cur下一个指向tmp的下一个结点,将tmp指向头结点,然后dummy再指向tmp,然后再次进行迭代。仔细思考一下这个反转转的真的很有智慧。代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head) return head;
ListNode *dummy=new ListNode(-1);
dummy->next=head;
ListNode *cur=head;
while(cur->next)
{
ListNode *tmp=cur->next;
cur->next=temp->next;
tmp->next=dummy->next;
dummy->next=tmp;
}
return dummy->next;
}
};
合并两个有序链表
这题比较简单,就是不断地判断;如果有一个链表已经比较晚了,则直接把后面所有的元素再加到新链表中就OK了。代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1!=NULL&&l2==NULL) return l1;
if(l1==NULL&&l2!=NULL) return l2;
ListNode head(0);
ListNode* l3=&head;
while(l1!=NULL&&l2!=NULL)
{
if(l1->val<l2->val)
{
l3->next=l1;
l1=l1->next;
}
else
{
l3->next=l2;
l2=l2->next;
}
l3=l3->next;
}
if(l1!=NULL)
l3->next=l1;
if(l2!=NULL)
l3->next=l2;
return head.next;
}
};
回文链表
解释在代码注释里了,感觉学到了一招快速到达链表的中央了(slow与fast的应用,fast->next->next是slow->next速度的两倍,当fast->next指向结尾,slow指向中间!!)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
//O(n)时间表示不能有嵌套循环, O(1)空间表示不能再次添加新链表
if(!head||!head->next) return true;
ListNode *slow=head,*fast=head;
stack<int> s;
s.push(head->val);
while(fast->next!=NULL && fast->next->next!=NULL)
{
slow=slow->next;
fast=fast=fast->next->next; //fast的速度是slow的两倍,这样就能保证slow最后能找到链表的中间
s.push(slow->val);
}
if(fast->next==NULL)
s.pop(); //说明是奇数个,中间的就不用进行比较了,所以直接pop掉比较后面的
while(slow->next!=NULL)
{
slow=slow->next;
int tmp=s.top();
s.pop();
if(tmp!=slow->val) return false;
}
return true;
}
};
环形链表
环形链表是循环链表的最简单形式,即首尾是相连的。所以若我们指定两个指针,fast和slow。两个指针同时从头结点开始出发,fast指针走两步,slow指针走一步;若链表有环,这两个指针肯定会在某点相遇;若链表无环,fast会直接先到达NULL。因为不断的循环,只要有环就一定会相遇,如果没环则一定会存在NULL。
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *slow=head,*fast=head;
while(fast!=NULL && fast->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast) return true;
}
return false;
}
};
Leetcode初级算法(链表篇)的更多相关文章
- LeetCode初级算法--链表01:反转链表
LeetCode初级算法--链表01:反转链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...
- LeetCode初级算法--链表02:合并两个有序链表
LeetCode初级算法--链表02:合并两个有序链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...
- LeetCode初级算法(树篇)
目录 二叉树的最大深度 验证二叉搜索树 对称二叉树 二叉树的层次遍历 将有序数组转换为二叉搜索树 二叉树的最大深度 二叉树,所以可以考虑用递归来做.由于根节点已经算过了,所以需要加上1:每次返回都是以 ...
- LeetCode初级算法(其他篇)
目录 缺失数字 位1的个数 颠倒二进制位 有效的括号 汉明距离 帕斯卡三角形 缺失数字 最初的想法是将0到n全部加起来,再减去输入的数字之和,那么差如果非零的话就是我们所需要的数字.但是一想,可能会发 ...
- Leetcode初级算法(字符串篇)
目录 反转字符串 颠倒整数 字符串中的第一个唯一字符 有效的字母异位词 验证回文字符串 实现strStr() 数数并说 最长公共前缀 字符串转整数(atoi) 反转字符串 和vector同样的进行sw ...
- LeetCode初级算法的Python实现--链表
LeetCode初级算法的Python实现--链表 之前没有接触过Python编写的链表,所以这里记录一下思路.这里前面的代码是和leetcode中的一样,因为做题需要调用,所以下面会给出. 首先定义 ...
- LeetCode初级算法(数组)解答
这里记录了LeetCode初级算法中数组的一些题目: 加一 本来想先转成整数,加1后再转回去:耽美想到测试的例子考虑到了这个方法的笨重,所以int类型超了最大范围65536,导致程序出错. class ...
- 【LeetCode算法】LeetCode初级算法——字符串
在LeetCode初级算法的字符串专题中,共给出了九道题目,分别为:反转字符串,整数反转,字符串中的第一个唯一字符,有效的字母异位词,验证回文字符串,字符串转换整数,实现strStr(),报数,最 ...
- LeetCode初级算法之数组:48 旋转图像
旋转图像 题目地址:https://leetcode-cn.com/problems/rotate-image/ 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: ...
随机推荐
- ffmpeg处理RTMP流媒体的命令和发送流媒体的命令(UDP,RTP,RTMP)
将文件当做直播送至live ffmpeg -re -i localFile.mp4 -c copy -f flv rtmp://server/live/streamName re限制输出速率, ...
- ffmpeg解码RTSP/TCP视频流H.264(QT界面显示视频画面)
源码下载地址: http://download.csdn.net/detail/liukang325/9489952 我用的ffmpeg版本为 ffmpeg-2.1.8.tar.bz2 版本低了恐怕有 ...
- luogu2622开灯问题2
#include<iostream> #include<cstdlib> #include<algorithm> #include<cstdio> #i ...
- 配置 VS Code 调试 PHP
配置 VS Code 调试 PHP 1.下载 xampp 集成服务器wampserver3.1.0-Apache2.4.7_PHP5.6.3-7.0.23-7.1.19_MySQL5.7.19_Mar ...
- Trilead,SSH2的Java调用
最近项目要部署10台设备,如果每台设备都手动进行部署想想也是醉了. 因为之前一直使用SecurityFX以及SecurityCRT,所以考虑是否可以使用基于SSH2的类库来实现文件拷贝以及远程命令调用 ...
- LVS实战1
(一).NAT模式:NAT模型:地址转换类型,主要是做地址转换,类似于iptables的DNAT类型,它通过多目标地址转换,来实现负载均衡:特点和要求: 1.LVS(Director)上面需要双网卡: ...
- tomcat如何修改发布目录
tomcat免重启 tomcat访问的时候如何去掉项目名访问: 其中fts是您的项目名. 1.tomcat6.0:<Host></Host>间加了一句<Context p ...
- 一 Akka学习 - actor
(引用 http://shiyanjun.cn/archives/1168.html) 一: 什么是Akka? Akka是JAVA虚拟机JVM平台上构建高并发.分布式和容错应用的工具包和运行时,是一个 ...
- python2.7系统性能监控psutil模块
系统环境:Centos7.4,系统自带python2.7.5 登录psutil官网,下载psutil的tar包:psutil-5.4.6.tar.gz,并使用命名sha256sum和官网的包进行核对, ...
- java基础知识(2)---语法基础
二:java语法基础: 1,关键字:其实就是某种语言赋予了特殊含义的单词. 保留字:其实就是还没有赋予特殊含义,但是准备日后要使用过的单词. 2,标示符:其实就是在程序中自定义的名词.比如类名,变量名 ...