leetcode Remove Nth Node From End of List
题目: 输入一个数组,要求删除倒数第n个元素,然后返回这个数组。例如,输入数组为1,2,3,4,5,删除倒数第2个,则返回数组1,2,3,4。
题目思路:看到题目的时候,就是按照很正常的思路去想,把整个数组扫一遍,然后再找出倒数第n个元素,再把它删除,但是,细节处理比较多。先看第一次写的代码。
代码:
ListNode* removeNthFromEnd(ListNode* head, int n)
{
ListNode* te=head;
int size=0;
while(te!=NULL)//统计整个数组的长度
{
size++;
te=te->next;
}
if(size==0||size==1||n>size)//一些特殊情况的处理
return NULL;
if(n==size)
{
head=head->next;
return head;
}
te=head;
for(int i=1;i<=size;i++)//寻找倒数第n个元素
{
if(n+i==size)
{
if(te->next->next!=NULL)
{
ListNode* temp=te->next;
te->next=temp->next;
}
else
{
te->next=NULL;
}
break;
}
te=te->next;
}
return head;//得到最后的结果
}
再思考:题目写完的时候,总感觉特例有点多,为什么一定要扫两遍数组呢?倒数第n个就不可以一次性找出来吗?代码是不是可以更短更优美一点。要删除倒数第n个元素,一个指针是不可能实现的,那我要是再用一个指针呢?用两个指针,倒数第n 个,先让两个指针先相距n个单位,那等到一个指针指到数组的尾部,那么前一个指针的下一个就是我们要删除的元素。这种方法,分析来看虽然也需要两个单独的循环,但是,第二次循环往往是不用把整个数组扫完,所以,从这里来说它比上面那种方法来说相对意义 的得到了一定的优化,看代码。
ListNode* removeNthFromEnd(ListNode* head, int n)
{
if(head==NULL)
return NULL;
ListNode* t1=head;//第一个指针
ListNode* t2=head;//第二个指针
for(int i=0;i<n;i++)//使两个指针相距n个距离
t1=t1->next;
if(t1==NULL)//表示要删除的是数组的第一个元素
return head->next;
while(t1->next!=NULL)//寻找倒数第n个元素
{
t1=t1->next;
t2=t2->next;
}
t2->next=t2->next->next;
return head;
}
反思: 记得这道题上数据结构课的时候老师说过,但是当时也没有仔细听,现在做到这道题目的时候,才深有感悟,其实很多题,仔细想的话,总会有相对自己第一次想到的方法更巧一些。