LeetCode:Given a singly linked list L: L 0→L 1→…→L n-1→L n, reorder it to: L 0→L n →L 1→L n-1→L 2...

题目描述:

链表:

变换成为:

两种思路:

1、第一种比较容易想到,也比较简单,但是就是复杂度比较高,即使能在牛客网的LeetCode上能通过。就是把所有的元素都存储起来呗,然后新建一个链表,循环取第一个,最后一个,第一个,最后一个直到结束为止,并将这写元素插入到新的链表中,程序如下:

import java.util.LinkedList;
public class Solution {
    public void reorderList(ListNode head) {
        if(head==null || head.next==null){
			return ;
		}
        //用java提供的数据结果存储所有的链表元素。
		LinkedList<ListNode> list=new LinkedList<ListNode>();
		while(head!=null){
			list.add(head);
			head=head.next;
		}
        //新建一个链表。
		ListNode newHead=new ListNode(0);
		ListNode cur=newHead;
		boolean flag=true;
		while(!list.isEmpty()){
			if(list.size()==1){
				list.getFirst().next=null;
			}
			if(flag){
				cur.next=list.removeFirst();//第一个取出后,后来的也就变成了第一个。
			}else{
				cur.next=list.removeLast();//同理最后一个取出后,倒数第二个也就变成了最后一个。
			}
			cur=cur.next;
			flag=!flag;//这个的意思是从取第一个然后取最后一个。
		}
		
		head=newHead.next;//新建链表的时候带表头了,所以返回表头的next.
    }
}

这种方法没有什么技巧,就是暴力去新建链表,没有什么难度。而且耗时耗空间,真正的机试不一定能通过。

2、第二种方法,比较有技巧,刚开始我也想到了,但是我想的比较麻烦,就是将链表从中间分开,然后将前半部分的链表倒过来,也就是都变成尾,尾变成头,然后和后一部分链表开始合并就是下:

链表:1->2->3->4->5->6->7->8->9->0

找到中间位置分开:1->2->3->4->5     6->7->8->9->0

然后把前半部分链表倒过来:5->4->3->2->1

然后和后半部分合并,这个时候注意一个问题哦,新的链表必须采用尾插法新建,因为5和6在新链表的最后面,这个方法逻辑上没什么问题但是我最后么有实现,很尴尬的。(问题的根本在于链表元素的个数是偶数还是奇数,这时候的前半部分的头,在新链表中的位置不好确定,需要条件判断,比较麻烦,但如果后半部分链表倒置就不一样了,肯定是从两个链表的头开始。这里看不懂可以评论问我呀,哈哈哈
但是这个时候如果,把后半部分链表倒过来是不是比较好呢?
倒过来后:0->9->8->7->6 
前半部分为: 1->2->3->4->5

这个时候就不用尾插法新建链表了,是不是很方便,哈哈,程序如下:

public class Solution {
    public void reorderList(ListNode head) {
        if(head == null || head.next == null || head.next.next == null)
            return;
        ListNode slow = head;
        ListNode fast = head;
        //快慢指针找到中间结点
        while(fast != null && fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        //断开链表,fast指向后半部分链表,head仍然是头结点,之前前半部分链表
        fast = slow;
        slow = slow.next;
        fast.next = null;
        //翻转链表
        ListNode lastHead = ReverseNode(slow);
        ListNode newHead = head;
        head = head.next;
        //合并链表
        while(head != null && lastHead != null){
            newHead.next = lastHead;
            lastHead = lastHead.next;
            newHead = newHead.next;
            newHead.next = head;
            head = head.next;
            newHead = newHead.next;
        }
        if(head != null)
            newHead.next = head;
        if(lastHead != null)
            newHead.next = lastHead;
    }
    private ListNode ReverseNode(ListNode head){
        ListNode prev = null;
        ListNode curr = head;
        while(curr != null && curr.next != null){
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        curr.next = prev;
        return curr;
    }
}

欢迎批评指正,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值