题目描述力扣https://leetcode.cn/problems/LGjMqU/
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln-1 → Ln
请将其重新排列后变为:L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解题思路1
此种思路是自己看题解之前的思路:将后半段的链表进行反转并设置两个指针,在寻找中间结点时,采用了第一遍进行计数,第二遍采用结点遍历的方式,这种方法比较笨~,同时在反转链表方面,我选择了栈空间,但事实上不需要栈空间也能进行反转,且所需的空间复杂更低,而在当时的思路下,我也将前半段的结点信息存入了LinkedList中,也是比较笨~(可以直接遍历,优化的方法大家直接看第二种即可)
代码实现1
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public void reorderList(ListNode head) {
//第一遍遍历查看链表中的个数
int count=0;
ListNode cur=head;
while(cur!=null){
count++;
cur=cur.next;
}
//如果是1直接返回
if(count==1){
return;
}
//重新遍历放入栈中
LinkedList<ListNode>stack1=new LinkedList<>();
Stack<ListNode>stack2=new Stack<>();
//重新遍历
cur=head;
for(int i=0;i<count/2;++i){
//前半段入栈
stack1.offer(cur);
cur=cur.next;
}
//后半段入栈
while(cur!=null){
stack2.push(cur);
cur=cur.next;
}
stack1.pop();
cur=head;
//栈中取出
while(stack1.size()!=0||!stack2.empty()){
if(!stack2.empty()){
cur.next=stack2.pop();
cur=cur.next;
}
if(stack1.size()!=0){
cur.next=stack1.pop();
cur=cur.next;
}
}
//最后解除循环
cur.next=null;
}
}
解题思路2
优化后的实现思路就比较明了了:通过前后指针进行遍历寻找中间结点,通过双指针进行里链表的反转,同时使用两个结点通过遍历就实现了链表的拼接,无需设计到额外的使用空间
代码实现2
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public void reorderList(ListNode head) {
//分为三步对此进行求解 1.寻找中点2.翻转后半段链表3.进行合并
ListNode mid=findMiddle(head);
ListNode corret=mid.next;
mid.next=null;
ListNode head2= reverse(corret);
merge(head,head2);
}
public ListNode findMiddle(ListNode head){
if(head==null){
return null;
}
ListNode slow=head;
ListNode fast=head;
while(fast.next!=null&&fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
public ListNode reverse(ListNode head){
if(head==null){
return null;
}
ListNode cur=head;
ListNode pre=null;
//进行循环
while(cur!=null){
ListNode next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
public ListNode merge(ListNode head1 ,ListNode head2){
if(head1==null){
return head2;
}
if(head2==null){
return head1;
}
ListNode next1;
ListNode next2;
while(head1!=null&&head2!=null){
next1=head1.next;
next2=head2.next;;
head1.next=head2;
head1=next1;
head2.next=head1;
head2=next2;
}
return head1;
}
}
题目描述力扣https://leetcode.cn/problems/LGjMqU/
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln-1 → Ln
请将其重新排列后变为:L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入: head = [1,2,3,4]
输出: [1,4,2,3]
示例 2:输入: head = [1,2,3,4,5]
输出: [1,5,2,4,3]
提示:
链表的长度范围为 [1, 5 * 104]
1 <= node.val <= 1000
解题思路
该题目存在两种解题思路:1.将链表存放于数组中,利用双指针进行遍历判断2.使用递归思路进行解决,由于我对递归思路不太熟悉,所以这题使用递归思路来解决:定义一个中间结点从从前往后进行遍历与递归变更结点的进行照应,对比两个结点的值是否相等,相等递归方进行回溯,中键结点向下遍历,不相等直接返回FALSE即可
实例代
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
//定义从顶向下遍历的结点
private ListNode tmpNode;
public boolean isPalindrome(ListNode head) {
tmpNode=head;
return recursiveCheck(head);
}
boolean recursiveCheck(ListNode cur){
if(cur!=null){
if(!recursiveCheck(cur.next)){
return false;
}
if(tmpNode.val!=cur.val){
return false;
}
tmpNode=tmpNode.next;
}
return true;
}
}