跟孙哥学java
1.指定区间反转
反转链表Ⅱ 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4 输出:[1,4,3,2,5]
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
//定义虚拟节点指向头节点
ListNode dummyNode=new ListNode(-1,head);
ListNode pre=dummyNode;
//让cur指向反转前的节点
for(int i=1;i<left;i++){
pre=pre.next;
}
ListNode cur=pre.next;
ListNode next;
//将位于left-right节点反转
for(int i=0;i<right-left;i++){
next=cur.next;
cur.next=next.next;
next.next=pre.next;
pre.next=next;
}
return dummyNode.next;
}
}
方法二:穿针引线法
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
//穿针引线法
//1. 先找到要反转的链表的头结点
ListNode dummyNode=new ListNode(-1,head);
ListNode pre=dummyNode;
for(int i=0;i<left-1;i++){
pre=pre.next;
}
//2.找到反转链表的尾节点
ListNode cur=pre;
for (int i=0;i<right-left+1;i++){
cur=cur.next;
}
ListNode needReverse=pre.next;
ListNode back=cur.next;
cur.next=null;
reverse(needReverse);
ListNode leftNode=pre.next;
pre.next=cur;
leftNode.next=back;
return dummyNode.next;
}
private void reverse(ListNode needReverse) {
ListNode pre=new ListNode();
ListNode cur=needReverse;
while (cur!=null){
ListNode next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
}
}
2.两两交换链表中的节点
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode cur=head;
//只有一个节点或没有节点直接返回
if(cur==null|| cur.next==null){
return cur;
}
//第二个节点必是交换的链表的头结点
ListNode res=cur.next;
//定义虚拟头结点,指向头结点
ListNode pre=new ListNode(-1,cur);
//当前节点为空或只有一个节点了,直接返回,无法交换了
while (cur!=null&&cur.next!=null){
//后节点
ListNode next=cur.next;
//让pre指向后节点
pre.next=next;
//当前cur指向next.next
cur.next=next.next;
//next指向cur,交换了两个节点
next.next=cur;
//让pre变为下一组要交换的节点的头结点
pre=cur;
//cur后移动
cur=cur.next;
}
return res;
}
}
3.单链表加1
:::info leetcode369 用个非空单链表来表示一个非负整数,然后将这个整数加一。你可以假设这个整数除了0本身,没有任何前导的0。这个整数的各个数位按照高位在链表头部、低位在链表尾部的顺序排列。 :::
基于链表反转实现如果这里不使用栈,使用链表反转来实现该怎么做呢?很显然,我们先将原始链表反 转,这方面完成加1和进位等处理,完成,之后再次反转。
public class Solution {
public static void main(String[] args) {
ListNode listNode=new ListNode(9,new ListNode(9,new ListNode(9)));
ListNode node = ListAddOne(listNode);
}
public static ListNode ListAddOne(ListNode head){
head= reverseList(head);
ListNode cur=head;
while (cur!=null){
cur.val=cur.val+1;
if(cur.val==10){
cur.val=0;
if(cur.next==null){
cur.next=new ListNode(1);
break;
}
cur=cur.next;
}else {
break;
}
}
return reverseList(head);
}
private static ListNode reverseList(ListNode head) {
ListNode new_head=null;
while (head!=null){
ListNode next = head.next;
head.next=new_head;
new_head=head;
head=next;
}
return new_head;
}
}
4.链表加法
两数相加Ⅱ 给你两个 **非空 **链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例1:
输入:l1 = [7,2,4,3], l2 = [5,6,4] 输出:[7,8,0,7]
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
l1=reverseList(l1);
l2=reverseList(l2);
int i=0;
ListNode ans=new ListNode(-1);
ListNode cur=ans;
while (l1!=null&&l2!=null){
int val= l1.val+l2.val+i;
if(val>=10){
int x= val%10;
cur.next=new ListNode(x);
i=1;
}else {
cur.next=new ListNode(val);
i=0;
}
l1=l1.next;
l2=l2.next;
cur=cur.next;
}
while (l1!=null){
int val=l1.val+i;
if(val==10){
i=1;
cur.next=new ListNode(0);
}else {
i=0;
cur.next=new ListNode(val);
}
cur=cur.next;
l1=l1.next;
}
while (l2!=null){
int val=l2.val+i;
if(val==10){
i=1;
cur.next=new ListNode(0);
}else {
i=0;
cur.next=new ListNode(val);
}
cur=cur.next;
l2=l2.next;
}
if(i==1){
cur.next=new ListNode(1);
}
ListNode node=ans.next;
ans.next=null;
return reverseList(node);
}
public ListNode reverseList(ListNode head){
ListNode newHead=null;
while (head!=null){
ListNode next=head.next;
head.next=newHead;
newHead=head;
head=next;
}
return newHead;
}
}
5.再论链表的回文序列问题
234.回文链表 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:head = [1,2,2,1] 输出:true
示例 2:
输入:head = [1,2] 输出:false
在上一关介绍链表回文串的时候,我们介绍的是基于栈的,相对来说比较好理解,但是除此之外还有可以使用链 表反转来进行,而且还可以只反转一半链表,这种方式节省空间。 我们姑目称之为“快慢指针+一半反转”法。 这个实现略有难度,主要是在while循环中pre.next=prepre和orepre=pre两行实现了一边遍历一边将 访问过的链表给反转了,所以理解起来有些难度,如果不理解可以在学完链表反转之后再看这个问题。