每天一道算法题系列:
来源:力扣(LeetCode)
本题链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
来源是力扣,大家喜欢可以去力扣中文网做相应的其他的题,某浏览器直接搜力扣即可。
本题难度是中等
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
package com.example.likou.likou6;
import static jdk.nashorn.internal.objects.Global.print;
public class NodeTest {
Node head = null;
static class Node {
Node next;
int val;
Node() {
}
Node(int val) {
this.val = val;
}
Node(int val, Node next) {
this.val = val;
this.next = next;
}
}
public static void main(String[] args) {
NodeTest node1 = new NodeTest();
node1.addNode(1);
/* node1.addNode(2);
node1.addNode(3);
node1.addNode(4);
node1.addNode(5);*/
// node1.removeNode(3);
// node1.delete(3);
// node1.reNode(3);
Node node = new Node();
node1.removeNthFromEnd(node,1);
}
/**
* 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
*
* 示例:
*
* 给定一个链表: 1->2->3->4->5, 和 n = 2.
*
* 当删除了倒数第二个节点后,链表变为 1->2->3->5.
* 说明:
*
* 给定的 n 保证是有效的。
*
* @param node
* @param i
*/
/*
由于我们需要找到倒数第 m 个节点,因此我们可以使用两个指针 first
和second 同时对链表进行遍历,并且 first 比
second 超前 m 个节点。当 first 遍历到链表的末尾时,
second 就恰好处于倒数第 m 个节点。
这个解释很恰当了
比如我是
1 2 3 4 5
我要去掉到处第二个 ,也就是4 使其变成1 2 3 5
首先我们先拿出 1 2 3 4 5 做一个next的操作,next倒数第二次的2
变成了3 4 5 留着备用,像炒菜一样(我们称为a)
然后在取一个新的 1 2 3 4 5(我们称为b)
然后3 4 5 依次往后面next 等到next为空的时候,相当于进行了三次循环
所以我们的新的1 2 3 4 5 也进行3次循环 变成了 4 5
然后我们直接把next.next的值赋给.next
相当于就把4给删除了
因为第一次循环的a,已经比第二次的循环的b多走了2个数
等a.next到最后的时候,b还差2个next,所以b的下一个next就是要取代的数
*/
private void removeNthFromEnd(Node node,int i) {
/*这里主要是为了防止node为1个数的情况,然后一个数去掉一个数之后后面的代码会
报空指针异常
*/
Node node2 = new Node(0,head);
//因为我这里的题和力扣上面的参数有点差异,所以我就定义的node
node = node2 ;
Node node1 = head;
//这里主要是比最开始出发多i的值
for (int j = 0; j < i; j++) {
node1 = node1.next;
}
while(node1 != null){
node1 = node1.next;
node = node.next;
}
node.next = node.next.next;
//这里主要是进行一个辅助的操作
Node node3 = node2.next;
// printList(node2);
//这里主要进行一个打印的操作
printList(node3);
}
private void printList(Node node2) {
if(node2 == null){
System.out.println("");
}
//System.out.println(node2.val +"");
while (node2 != null ){
System.out.println(node2.val +"");
node2 = node2.next;
}
}
private Node reNode(int n) {
Node dummy = new Node(0, head);
Node first = head;
Node second = dummy;
for (int i = 0; i < n; ++i) {
first = first.next;
}
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
Node ans = dummy.next;
return ans;
}
//删除节点
public void delete(int no) {
Node temp = head;
boolean flag = false;//标识是否找到待删除节点
while (true) {
if (temp.next == null) {//已经遍历到最后
break;
}
if (temp.next.val == no) {//找到要删除的节点的前一个节点
flag = true;//标识
break;
}
temp = temp.next;//temp后移
}
if (flag) {//找到节点
//可以删除
temp.next = temp.next.next;
} else {
System.out.println("要删除的节点" + no + "不存在");
}
}
private void removeNode(int i) {
if (head == null) {
return;
}
Node pre = head;
Node cur = pre.next;
int x = 1;
while (cur != null) {
if (i == x) {
pre.next = cur.next;
return;
}
x++;
pre = cur;
cur = cur.next;
}
}
private void addNode(int i) {
Node pre = new Node(i);
if (head == null) {
head = pre;
return;
}
Node node = head;
while (node.next != null) {
node = node.next;
}
node.next = pre;
}
;
}
上一篇文章:每天一道算法题系列十七之电话号码的字母组合
请继续关注我,如果后面不忙了,会写一系列关于的设计模式等等等的文章。
如果本篇内容有问题,请第一时间联系我,我会第一时间修改。
谢谢大家。