版权声明:此文章为许诗宇所写,如需转载,请写下转载文章的地址 https://blog.csdn.net/xushiyu1996818/article/details/82143504
题目及用例及linklist
package pid019;
public class LinkList {
public class ListNode {
public int val;
public ListNode next;
ListNode(int x)
{ val = x;
next=null;
}
}
ListNode first;
public LinkList(int x){
first=new ListNode(x);
first.next=null;
}
public void addLast(int x){
ListNode a=first;
while(a.next!=null){
a=a.next;
}
ListNode b=new ListNode(x);
a.next=b;
}
public void printList(){
ListNode a=first;
System.out.println("print listnode");
while(a!=null){//直到最后一个不为空的节点
System.out.print(a.val+" ");
a=a.next;
}
System.out.println();
}
}
package pid019;
/* 删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
*/
import pid019.LinkList;
import pid019.LinkList.ListNode;
public class main {
public static void main(String[] args) {
LinkList a=new LinkList(1);
a.addLast(2);
a.addLast(5);
a.addLast(15);
LinkList b=new LinkList(-5);
b.addLast(0);
b.addLast(500);
b.addLast(-100);
a.printList();
test(a.first,2);
a.printList();
b.printList();
test(b.first,4);
b.printList();
}
private static void test(ListNode ito,int ito2) {
Solution solution = new Solution();
String rtn;
long begin = System.currentTimeMillis();
System.out.println();
//开始时打印数组
solution.removeNthFromEnd(ito,ito2);//执行程序
long end = System.currentTimeMillis();
//System.out.println(":rtn" );
//System.out.print(rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,11ms,很快)
先得到链表长度,再根据长度,从头开始减去节点,具体在解法中
package pid019;
import pid019.LinkList.*;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
int length=0;
ListNode a=head;
ListNode temp;
while(a!=null){
length++;
a=a.next;
}
//比如5个,倒数第二就为第4个,为第三个与第五个相连,如果不是去掉第一个,为(length-n) (length-n).nex.next 相连
//如果是第一个,如果只有一个,返回null,否则将head的值改为下一个,next改为head.next.next
if(length==n){
if(length==1){//去掉只有一个的第一个
return null;
}
else{//去掉第一个
head.val=head.next.val;
temp=head.next;
head.next=temp.next;
temp.next=null;
return head;
}
}
else{
int i=1;
a=head;
while(i<length-n){
a=a.next;
i++;
}
temp=a.next;
a.next=temp.next;
temp.next=null;
return head;
}
}
}
解法二(别人的)
速度其实一样快,都是走length+n步,但看上去简洁了很多
而且减去头部很简洁 head=head.next,不用改head的val
典型的双指针算法
先让一个指针走找到第N个节点,然后再让一个指针指向头结点,然后两具指针一起走,直到前一个指针直到了末尾,后一个指针就是倒数第N+1个结点,删除倒数第N个结点就可以了。
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode pa = head;
ListNode pb = head;
// 找到第n个结点
for (int i = 0; i < n && pa != null; i++) {
pa = pa.next;
}
if (pa == null) {
head = head.next;
return head;
}
// pb与pa相差n-1个结点
// 当pa.next为null,pb在倒数第n+1个位置
while (pa.next != null) {
pa = pa.next;
pb = pb.next;
}
pb.next = pb.next.next;
return head;
}
}