1.给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
示例:给定一个链表:1->2->3->4->5,和n = 2。当删除了倒数第二个节点后,链表为1->2->3->5
说明:题目保证给的n是一个有效的数据
方法一:暴力求解
(1)求得链表的长度
(2)删除丛链表头数起的第(L-n+1)个节点
方法二:快慢指针法
识别的方法:1.涉及链表的特殊位置,考虑快慢指针;2.要删除链表节点,找他的前驱
思路:
1.创建一个新的头节点newNode,newNode.next指向headNode。创建两个指针fast、slow。fast = headNode;slow = newNode;
2.先让fast走n步
3.然后fast和slow一起走,当fast==null时,此时的slow节点的下一个节点就是要删除的节点,则slow.next = slow.next.next;返回头结点的下一个节点,即newNode.next;
示意图:



class Solution {
public ListNode removeNthFromEnd(ListNode headNode, int n) {
ListNode fristNode = new ListNode(0,headNode);//在头节点之前设置一个节点
ListNode fast = headNode;
ListNode slow = fristNode;
while(n>0){//这里的n是有效的数据,不会使发生空指针异常
fast = fast.next;
n--;
}
while(fast!=null){//如果fast==null就说明要删除的就是头结点
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
ListNode ans = fristNode.next;
return ans;
}
}
结果:

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
例如:
输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807
输入:l1 = [0], l2 = [0] 输出:[0]
思路:
(1)两个数相加,满十进一(carry =sum/10)。将两个加数的和sum%10以后放在一个新的节点里
(2)满足条件(链表l1!=null和l2!=null),继续执行相加操作。当不满足条件(链表l1!=null和l2!=null) 以后,在判断carry是否大于1,如果大于1说明还要创建一个节点来接收这个数
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null, tail = null;
int carry = 0;
while (l1 != null || l2 != null) {
int n1 = l1 != null ? l1.val : 0;
int n2 = l2 != null ? l2.val : 0;
int sum = n1 + n2 + carry;
if (head == null) {
head = tail = new ListNode(sum % 10);
} else {
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
carry = sum / 10;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (carry > 0) {
tail.next = new ListNode(carry);
}
return head;
}
}
结果

3.两两交换链表中的节点:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成。示例:[1,2,3,4]->[2,1,4,3];[1]->[1];[]->[];24. 两两交换链表中的节点 - 力扣(LeetCode)
方法一:利用快慢指针
* 思路: * 1.检查头结点是否为空,是则返回null * 2.在头节点之前创建一个新节点D,D.next = head;创建两个指针fast、slow,fast == D;slow == head; * 3.先让fast = fast.next.next;检查fast是否等于null,是则返回D.next; * 4.若第3步fast!=null,以slow!=null&&fast!=null为循环条件,依次找到奇偶结点进行交换(在交换过程中,若slow = slow.next.next;slow==null;则直接return D.next) * 5.最终返回D.next;
public Node swapPairs(Node head) {
if(head==null){
return head;
}
Node D = new Node(0, head);
Node fast = D;
Node slow = head;
fast = fast.next.next;
Node temp = new Node(-1);
if(fast==null){//成立,则说明链表中只有一个节点
return D.next;
}
while(slow!=null&&fast!=null){
temp.no = fast.no;
fast.no = slow.no;
slow.no = temp.no;
slow = slow.next.next;
if(slow==null){
return D.next;
}
fast = fast.next.next;
}
return D.next;
}
主函数里面实现一下
public static void main(String[] args) {//验证交换两个节点
Linkedlist linkedlist1 = new Linkedlist();
linkedlist1.finallAdd(1);
linkedlist1.finallAdd(2);
linkedlist1.finallAdd(3);
linkedlist1.finallAdd(4);
linkedlist1.printList();
System.out.println("================");
Linkedlist.Node node = linkedlist1.swapPairs(linkedlist1.headNode);
linkedlist1.printList(node);
}
结果

方法二:递归
递归的出口,就是当链表为空或者链表中只有一个节点的情况,此时返回头结点。
令head为头结点,headNext为头结点的下一个节点,如果这两个节点交换以后,headNext就是新的头结点, 返回headNext即可。
剩下的节点的头结点是headNext的下一个节点就是headNext.next。此时的headNext.next就是head,它的下一个节点是headNext。然后一直递归下去,直到遇到出口就一层层的返回。
public Node recursiveswap(Node head){
if(head==null||head.next==null){
return head;
}
Node headNext = head.next;
head.next = recursiveswap(headNext.next);
headNext.next = head;
return headNext;
}
主函数里面实现一下
public static void main(String[] args) {//验证交换两个节点
Linkedlist linkedlist1 = new Linkedlist();
linkedlist1.finallAdd(1);
linkedlist1.finallAdd(2);
linkedlist1.finallAdd(3);
linkedlist1.finallAdd(4);
linkedlist1.printList();
System.out.println();
System.out.println("================");
Linkedlist.Node node = linkedlist1.recursiveswap(linkedlist1.headNode);
linkedlist1.printList(node);
}
结果

4.旋转链表61. 旋转链表 - 力扣(LeetCode)
思路:
1.遍历到最后一个节点,将最后一个节点last的next只想头结点
2.head和last一起移动n = len-k%len个位置
3.将last的next置为空
4.返回旋转以后新链表

class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head==null||head.next==null){//没有节点或者只有一个节点的情况,直接返回头结点
return head;
}
int len = 1;//用来计算链表的长度
ListNode temp = head;
while(temp.next!=null){//这里要保留最后一个节点
len++;
temp = temp.next;
}
ListNode last = temp;//记录最后一个节点
last.next = head;//让最后一个节点指向头结点
int n = len-k%len;//头结点和尾节点移动次数
while(n-->0){
head = head.next;
last = last.next;
}
last.next = null;
return head;
}
}
结果

5.删除已经排过序链表中重复的数字 83. 删除排序链表中的重复元素 - 力扣(LeetCode)
思路:
判断当前节点cur.val是否与下一个节点cur.next.val相等。相等则让当前节点的next指向下一个节点的下一个节点,即cur.next = cur.next.next。
不相等,则让当前节点跳向下一个节点cur = cur.next
继续上面的判断cur.next是否等于null,也就是cur.next所指向的那个节点是否为空,不为空则重复上面的操作,为空则返回head
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null) {
return head;
}
ListNode cur = head;
while (cur.next != null) {
if (cur.val == cur.next.val) {
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return head;
}
}
结果

6.删除已经排过序链表中重复的所有数字 82. 删除排序链表中的重复元素 II - 力扣(LeetCode)
思路:
创建一个新的头结点newhead,这个头结点指向head,同时创建两个指针cur、temp。 cur = newhead;temp = head;
temp.val与temp.next.val比较
1.相等,则记录当前的值val,如果当前的temp!=null且值为val,则让temp = temp.next。继续判断temp是否为空,且temp.val是否等于val。相等则继续temp = temp.next。不相等,则cur.next = temp
2.不相等则cur = temp;temp = temp.next
3.然后再执行上面的操作,直到temp等于空或者temp.next == null;退出循环,返回newhead.next
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null){//链表中没有节点
return head;
}
ListNode newhead = new ListNode(-1,head);
ListNode cur = newhead;
ListNode temp = head;
while(temp!=null&&temp.next!=null){
if(temp.val==temp.next.val){
int num = temp.val;//记录当前位置的值
while(temp!=null&&temp.val==num){
temp = temp.next;
}
cur.next = temp;
}
else{
// cur.next = temp;
// cur = cur.next;
cur = temp;
temp = temp.next;
}
}
return newhead.next;
}
}
结果


被折叠的 条评论
为什么被折叠?



