首尾交換連結串列

BetterCbx發表於2020-10-22

1->2->3->4->5 ==> 1->5->2->4->3

使用線性表

將節點依次放入集合中,通過索引交換

 /**
     * 將連結串列的節點放入順序表中,這樣方便獲取最後一個節點
     * 1->2->3->4
     * 1->4->2->3
     */
    public void recordList(ListNode head){
        if (head==null) return;
        List<ListNode> list=new ArrayList<>();
        ListNode node=head;
        while (node!=null){
            list.add(node);
            node=node.next;
        }
        int i=0,j=list.size()-1;
        while (i<j){
            list.get(i).next=list.get(j);
            i++;
            if (i==j){
                break;
            }
            list.get(j).next=list.get(i);
            j--;
        }
        list.get(i).next=null; //避免形成環形連結串列
    }

使用棧

/**
     * https://leetcode-cn.com/problems/reorder-list/solution/zhong-pai-lian-biao-by-leetcode-solution/
     */
    public void recordList2(ListNode head){
        if (head==null) return;
        Deque<ListNode> stack=new ArrayDeque<>();
        ListNode cur=head;
        while (cur!=null){
            stack.push(cur);
            cur=cur.next;
        }
        cur=head;
        ListNode stack_cur=new ListNode(Integer.MAX_VALUE);

        while (cur.next!=stack_cur.next){
            stack_cur=stack.poll();
            stack_cur.next=cur.next;
            cur.next=stack_cur;
            cur=cur.next.next;
        }

        stack_cur.next=null; //防止出現環形問題
    }

中間節點,加逆序,加合併連結串列

/**
         * 1 -> 2 -> 3 -> 4 -> 5 -> 6
         第一步,將連結串列平均分成兩半
         1 -> 2 -> 3
         4 -> 5 -> 6

         第二步,將第二個連結串列逆序
         1 -> 2 -> 3
         6 -> 5 -> 4

         第三步,依次連線兩個連結串列
         1 -> 6 -> 2 -> 5 -> 3 -> 4
         尋找連結串列中點 + 連結串列逆序 +合併連結串列
         * @param head
         */
        public void recordList3(ListNode head){
               ListNode middle=middleNode(head);
               ListNode middleNext=middle.next;
               //反轉後半段連結串列
            middle.next=null;
            //這是後半段連結串列
            ListNode afterNode= reverseList(middleNext);
          //然後進行一次交錯插入操作
             mergeList(head,afterNode);
        }

    private void mergeList(ListNode head, ListNode afterNode) {
              ListNode tempH;
              ListNode tempA;
              while (head!=null&&afterNode!=null){
                      tempH=head.next;
                      tempA=afterNode.next;
                      head.next=afterNode;
                      head=tempH;
                      afterNode.next=head;
                      afterNode=tempA;
              }
    }

    public ListNode middleNode(ListNode head) {
        if (head==null) return null;
        ListNode[] res=new ListNode[100];
        int index=0;
        while (head!=null){
            res[index++]=head;  //index指向陣列最後一個元素的後一個位置
            head=head.next;
        }
        return res[index/2];
    }


    public ListNode reverseList(ListNode head) {
        ListNode dummy=new ListNode(-100);
        dummy.next=head;  //dummy模擬帶頭結點的連結串列
        if (dummy.next==null||dummy.next.next==null){
            //只有一個節點或者沒有節點
            return head;
        }
        ListNode temp=dummy.next;
        while (temp.next!=null){
            temp=temp.next; //找到尾結點
        }
        ListNode last=temp;

        while (dummy.next!=last) {
            //相當於尾插法,一直往尾部插入頭元素
            ListNode p=dummy.next;
            dummy.next=p.next;
            p.next=last.next;
            last.next=p;
        }
        return dummy.next;

    }

相關文章