2-8按值劃分鏈表

題目描述

  • 給定一個鏈表頭節點和一個整數pivot,將這個鏈表調整爲左邊都是小於pivot的節點,中間都是等於pivot的節點,右邊都是大於pivot的節點。

解題方法1

  • 我們可以申請一個node引用類型的數組,將原鏈表的節點都存放到這個數組中。
  • 然後在數組中根據pivot調整位置,最後再把數組中節點按順序依次相連即可。
  • 現在最主要的問題就是,具體如何對節點數組進行調整。
  • 可以定義三個變量 left=-1,index=0,right=len。
  • 0-left表示小於pivot的區域,left+1—index表示等於pivot的區域,right-len-1表示大於pivot的區域。
  • 使用index進行遍歷:
  • 如果arr[index] < pivot,將左區域擴大一個單位來放置該元素,把arr[left+1]和arr[index]交換。同時令left、index加1,繼續遍歷下一個位置。
  • 如果arr[index] > pivot,將右區域擴大一個單位來放置該元素,把arr[index]和arr[right-1]交換,令right減1,同時,index位置的值被更新,繼續從該位置遍歷。
  • 如果arr[index] == pivot,直接令index加1,繼續遍歷下一個位置。
  • index與right相遇時退出循環。
public class Test {
    public static void main(String[] args) throws Exception {
         int[] arr = {5,5,5,1,2,9};
         Node head = create(arr);
         fun(head,5);
         for(Node p=head.next;p!=null;p=p.next){
             System.out.println(p.val);
         }
    }
    //根據pivot對鏈表進行劃分
   public static void fun(Node head,int pivot){
        if(head.next==null || head.next.next==null){
            return;
        }
        //求鏈表長度
        int len=0;
        for(Node p=head.next;p!=null;p=p.next){
            len++;
        }
        //把所有節點存儲到一個node數組中
        Node[] arrnode = new Node[len];
        Node p =head.next;
        for(int i=0;i<len;i++) {
           arrnode[i] = p;
           p=p.next;
        }
        partarr(arrnode,pivot);
        //把調整後的node數組還原爲鏈表
       p=head;
       for(Node node:arrnode){
           p.next = node;
           p=p.next;
       }
       p.next = null;
   }
   //傳入一個node數組,對其進行一趟劃分
    public static void partarr(Node[] arrnode,int pivot){
         int left = -1;
         int right = arrnode.length;
         int index = 0;
         while(index<right){
             if(arrnode[index].val<pivot){
                 left++;
                 Node temp = arrnode[left];
                 arrnode[left] = arrnode[index];
                 arrnode[index] = temp;
                 index++;
             }
             else if(arrnode[index].val>pivot){
                 right--;
                 Node temp = arrnode[index];
                 arrnode[index] = arrnode[right];
                 arrnode[right] = temp;
             }
             else{
                 index++;
             }
         }
    }
    //創建單鏈表
    public static Node create(int[] arr){
        Node head = new Node(0); //頭節點
        Node newnode = null; //指向新節點
        Node tail = head; //指向鏈表尾節點
        for(int a:arr){
            newnode = new Node(a);
            newnode.next = tail.next;
            tail.next = newnode;
            tail = newnode;
        }
        return head;
    }
}
class Node{
    int val;
    Node next;
    Node(int val){
        this.val = val;
    }
}

解題方法2

  • 進階要求鏈表順序不能變,而且空間複雜度爲1。
  • 我們可以利用鏈表本身的空間,定義三個node引用表示三個鏈表的頭節點和尾節點。然後遍歷鏈表節點,利用尾插法把每個節點連到對應的子鏈表之後。
  • 這樣經過一次遍歷就可以把三種類型的節點保存到三個鏈表之中。
  • 最後將三個鏈表依次首尾連接即可。
public class Test {
    public static void main(String[] args) throws Exception {
         int[] arr = {8,9,5,5};
         Node head = create(arr);
         fun(head,5);
         for(Node p=head.next;p!=null;p=p.next){
             System.out.println(p.val);
         }
    }
    //根據pivot對鏈表進行劃分
   public static void fun(Node head,int pivot){
        if(head.next==null || head.next.next==null){
            return;
        }
        Node left=null;
        Node mid = null;
        Node right = null;
        Node leftlast = null;
        Node midlast = null;
        Node rightlast = null;
        //將鏈表節點拆成三個鏈表
        for(Node p=head.next;p!=null;){
            Node temp = p.next;
            if(p.val < pivot){
                if(left==null){
                    left = p;
                    leftlast = p;
                }
                else{
                    p.next = leftlast.next;
                    leftlast.next = p;
                    leftlast = p;
                }
            }
            else if(p.val > pivot){
                if(right==null){
                    right = p;
                    rightlast = p;
                }
                else{
                    p.next = rightlast.next;
                    rightlast.next = p;
                    rightlast = p;
                }
            }
            else{
                if(mid==null){
                    mid = p;
                    midlast = p;
                }
                else{
                    p.next = midlast.next;
                    midlast.next = p;
                    midlast = p;
                }
            }
            p = temp;
        }

        //將三個子鏈表首尾連接
       //1 1 1
       if(left!=null && mid!=null && right!=null) {
           head.next = left;
           leftlast.next = mid;
           midlast.next = right;
           rightlast.next = null;
       }
       // 1 0 0
       if(left!=null && mid==null && right==null){
           head.next=left;
           leftlast.next = null;
       }
       // 0 1 0
       if(left==null && mid!=null && right==null){
           head.next = mid;
           midlast.next = null;
       }
       // 0 0 1
       if(left==null && mid==null && right!=null){
           head.next = right;
           rightlast.next = null;
       }
       // 1 1 0
       if(left!=null && mid!=null && right==null){
           head.next = left;
           leftlast.next = right;
           rightlast.next = null;
       }
       // 1 0 1
       if(left!=null && mid==null && right!=null){
           head.next=left;
           leftlast.next = right;
           rightlast.next =null;
       }
       // 0 1 1
       if(left==null && mid!=null && right!=null){
           head.next=mid;
           midlast.next = right;
           rightlast.next =null;
       }
   }


    //創建單鏈表
    public static Node create(int[] arr){
        Node head = new Node(0); //頭節點
        Node newnode = null; //指向新節點
        Node tail = head; //指向鏈表尾節點
        for(int a:arr){
            newnode = new Node(a);
            newnode.next = tail.next;
            tail.next = newnode;
            tail = newnode;
        }
        return head;
    }
}
class Node{
    int val;
    Node next;
    Node(int val){
        this.val = val;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章