1反转整个链表
1.1题目详情
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
1.2递归
class Solution {
public ListNode reverseList(ListNode head) {
//递归终止条件
if(head==null||head.next==null) return head;
//进入递归,最后返回最后一个节点,即为反转后的头节点
ListNode newHead=reverseList(head.next);
//当前节点的下一个节点的下一个节点指向当前节点
head.next.next=head;
head.next=null;
return newHead;
}
}
1.3迭代
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode prev=null;
ListNode next=null;
ListNode curr=head;
while(curr!=null){
next=curr.next;
curr.next=prev;
prev=curr;
curr=next;
}
return prev;
}
}
1.4递归和迭代总结
1.4.1递归,就是在运行的过程中调用自己。
构成递归需具备的条件:
1. 子问题须与原始问题为同样的事,且更为简单;
2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
1.4.2 迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。
1.4.3递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换.能用迭代的不用递归,
2反转链表指定区间的节点
2.1题目详情
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
2.2递归
class Solution {
//保存第n+1个节点,因为反转之后原头节点的下一个节点变为第n+1个节点
ListNode node=null;
//反转前n个节点
public ListNode reverseN(ListNode head,int n){
if(n==1){
node=head.next;
return head;
}
ListNode last=reverseN(head.next,n-1);
head.next.next=head;
head.next=node;
return last;
}
public ListNode reverseBetween(ListNode head, int left, int right) {
if(left==1){
//相当于反转前right个节点
return reverseN(head,right);
}else{
head.next=reverseBetween(head.next,left-1,right-1);
return head;
}
}
}
2.3迭代
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode pre=null;
ListNode beginNode=null;
ListNode endNode=null;
ListNode temp=head;
int count=1;
while(temp!=null){
if(left-1==count){
beginNode=temp;
}
if(right+1==count){
endNode=temp;
break;
}
temp=temp.next;
count++;
}
ListNode prev=endNode;
ListNode next=null;
//beginNode==null说明left=1,即开始反转的节点为头节点
ListNode curr=beginNode==null?head:beginNode.next;
while(curr!=endNode){
next=curr.next;
curr.next=prev;
prev=curr;
curr=next;
}
if(beginNode==null) return prev;
beginNode.next=prev;
return head;
}
}
3k个一组反转链表
3.1题目详情给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
3.2递归加迭代
class Solution {
//反转[start,end)
public ListNode reverse(ListNode start,ListNode end){
ListNode prev=end;
ListNode next=null;
ListNode curr=start;
while(curr!=end){
next=curr.next;
curr.next=prev;
prev=curr;
curr=next;
}
return prev;
}
public ListNode reverseKGroup(ListNode head, int k) {
ListNode startNode=head;
ListNode endNode=head;
for(int i=0;i<k;i++){
//节点总数小于k,不进行反转,直接返回start节点
if(endNode==null) return startNode;
endNode=endNode.next;
}
//反转后的节点成为新的头节点
ListNode newHead=reverse(startNode,endNode);
//原头节点的下一个节点为下一次反转后的头节点
startNode.next=reverseKGroup(endNode,k);
return newHead;
}
}