4.链表 | 左程云算法笔记

343 阅读2分钟

反转单链表或双向链表

class Solution {

    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }
    
//    反转单链表
    public  Node reverseList(Node head) {
        Node pre = null;
        Node next = null;
        while (head != null){
            next = head.next;
            head.next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }


    public static class DoubleNode {
        public int value;
        public DoubleNode last;
        public DoubleNode next;

        public DoubleNode(int data) {
            this.value = data;
        }
    }
//    反转双向链表
    public static DoubleNode reverseList(DoubleNode head) {
        DoubleNode pre = null;
        DoubleNode next = null;
        while (head != null) {
            next = head.next;
            head.next = pre;
            head.last = next;
            pre = head;
            head = next;
        }
        return pre;
    }
    
}

打印两个有序链表的公共部分

public class Code03_PrintCommonPart {

   public static class Node {
      public int value;
      public Node next;
      public Node(int data) {
         this.value = data;
      }
   }

   public static void printCommonPart(Node head1, Node head2) {
      System.out.print("Common Part: ");
      while (head1 != null && head2 != null) {
         if (head1.value < head2.value) {
            head1 = head1.next;
         } else if (head1.value > head2.value) {
            head2 = head2.next;
         } else {
            System.out.print(head1.value + " ");
            head1 = head1.next;
            head2 = head2.next;
         }
      }
      System.out.println();
   }

   public static void printLinkedList(Node node) {
      System.out.print("Linked List: ");
      while (node != null) {
         System.out.print(node.value + " ");
         node = node.next;
      }
      System.out.println();
   }

   public static void main(String[] args) {
      Node node1 = new Node(2);
      node1.next = new Node(3);
      node1.next.next = new Node(5);
      node1.next.next.next = new Node(6);

      Node node2 = new Node(1);
      node2.next = new Node(2);
      node2.next.next = new Node(5);
      node2.next.next.next = new Node(7);
      node2.next.next.next.next = new Node(8);

      printLinkedList(node1);
      printLinkedList(node2);
      printCommonPart(node1, node2);

   }

}

判断一个链表是否为回文结构

class Solution {

    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }

//    把所有节点先全部都放到栈里,再一个个去对比判断相等
    public static boolean isPalindrome1(Node head) {
        Stack<Node> stack = new Stack<>();
        Node cur = head;
        while (cur != null){
            stack.push(cur);
            cur = cur.next;
        }

        while (head != null){
            if (head.value != stack.pop().value) return false;
            head = head.next;
        }
        return true;
    }

//    用快慢指针只把一半的节点放进栈中,然后从头对比
    public static boolean isPalindrome2(Node head) {
        if(head == null || head.next == null) return true;
        Node fast = head;
        Node slow = head.next;
        while (fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        Stack<Node> stack = new Stack<>();
        while (slow != null){
            stack.push(slow);
            slow = slow.next;
        }

        while (!stack.isEmpty()){
            if (head.value != stack.pop().value) return false;
            head = head.next;
        }
        return true;
    }

//    只用三个变量 不用其他辅助空间,空间复杂度O(1)
    public static boolean isPalindrome3(Node head) {
      if(head == null || head.next == null) return true;
      Node n1 = head;
      Node n2 = head;
//      此时n1在链表的中点,n2为右半部分的第一个节点
      while (n2.next != null && n2.next.next != null){
          n1 = n1.next;
          n2 = n2.next.next;
      }
//      翻转右半部分
      n2 = n1.next;
      Node n3 = null;
      n1.next = null;
      while (n2 != null){
          n3 = n2.next;
          n2.next = n1;
          n1 = n2;
          n2 = n3;
      }

//      从左右半部分的两头开始对比判断 n1为右半部分的最后一个节点
        n3 = n1;
        n2 = head;
        boolean result = true;
        while (n1 != null && n2 != null){
            if (n1.value != n2.value){
                result = false;
                break;
            }
            n1 = n1.next;
            n2 = n2.next;
        }
//        最后把翻转的右半部分再复原
        n1 = n3.next;
        n3.next = null;
        while (n1 != null){
            n2 = n1.next;
            n1.next = n3;
            n3 = n1;
            n1 = n2;
        }
        return result;
    }


    public static void printLinkedList(Node node) {
        System.out.print("Linked List: ");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {

        Node head = null;
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(2);
        head.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(2);
        head.next.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

    }

}

将单向链表按某值划分成左边小,中间相等,右边大的形式

class Solution {

    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }

    public static Node listPartition1(Node head, int pivot) {
        if (head == null) return head;

//        i为节点总数,把所有节点放到help数组中
        int i = 0;
        Node cur = head;
        while (cur != null){
            i++;
            cur = cur.next;
        }
        Node[] help = new Node[i];
        i = 0;
        cur = head;
        for (i = 0; i< help.length; i++) {
            help[i] = cur;
            cur = cur.next;
        }
        arrPartition(help,pivot);
        //把排序好的help数组节点再恢复成链表
        for (int j = 1; j < help.length; j++) {
            help[j - 1].next = help[j];
        }
        help[help.length - 1].next = null;
        return help[0];
    }

    //通过荷兰国旗的方式排序
    public static void arrPartition(Node[] help, int pivot) {
        int small = -1;
        int big = help.length;
        int index = 0;
        while (index != big){
            if (help[index].value < pivot){
                swap(help,++small,index++);
            }else if (help[index].value > pivot){
                swap(help,--big,index);
            }else {
                index++;
            }
        }
    }


    public static Node listPartition2(Node head, int pivot) {
        Node sH = null; // small head
        Node sT = null; // small tail
        Node eH = null; // equal head
        Node eT = null; // equal tail
        Node bH = null; // big head
        Node bT = null; // big tail
        Node next = null; // save next node
        // every node distributed to three lists
        while (head != null) {
            next = head.next;
            head.next = null;
            if (head.value < pivot) {
                if (sH == null) {
                    sH = head;
                    sT = head;
                } else {
                    sT.next = head;
                    sT = head;
                }
            } else if (head.value == pivot) {
                if (eH == null) {
                    eH = head;
                    eT = head;
                } else {
                    eT.next = head;
                    eT = head;
                }
            } else {
                if (bH == null) {
                    bH = head;
                    bT = head;
                } else {
                    bT.next = head;
                    bT = head;
                }
            }
            head = next;
        }
        // small and equal reconnect 如果有小于区域
        if (sT != null) {
            sT.next = eH;
            eT = eT == null ? sT : eT;
        }
        // all reconnect
        if (eT != null) {
            eT.next = bH;
        }
        return sH != null ? sH : eH != null ? eH : bH;
    }

    public static void swap(Node[] nodeArr, int a, int b) {
        Node tmp = nodeArr[a];
        nodeArr[a] = nodeArr[b];
        nodeArr[b] = tmp;
    }

    public static void printLinkedList(Node node) {
        System.out.print("Linked List: ");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head1 = new Node(7);
        head1.next = new Node(9);
        head1.next.next = new Node(1);
        head1.next.next.next = new Node(8);
        head1.next.next.next.next = new Node(5);
        head1.next.next.next.next.next = new Node(2);
        head1.next.next.next.next.next.next = new Node(5);
        printLinkedList(head1);
//         head1 = listPartition1(head1, 4);
        head1 = listPartition2(head1, 5);
        printLinkedList(head1);

    }

}

复制含有随机指针节点的链表

public class Solution {

    public static class Node {
        public int value;
        public Node next;
        public Node rand;

        public Node(int data) {
            this.value = data;
        }
    }

//    用哈希表存储key为老节点 value为新节点
    public static Node copyListWithRand1(Node head) {
        HashMap<Node,Node> hashMap = new HashMap<>();
        Node cur = head;
        while (cur != null){
            hashMap.put(cur,new Node(cur.value));
            cur = cur.next;
        }
        cur = head;
        while (cur != null){
            hashMap.get(cur).next = hashMap.get(cur.next);
            hashMap.get(cur).rand = hashMap.get(cur.rand);
            cur = cur.next;
        }
        return hashMap.get(head);
    }


    public static Node copyListWithRand2(Node head) {
         if (head == null) return head;
//         现在每个老节点后边复制一个新节点 1->1`->2->2`->3....
        Node cur = head;
        Node next = null;
        while (cur != null){
            next = cur.next;
            cur.next = new Node(cur.value);
            cur.next.next = next;
            cur = next;
        }

//        处理新节点的rand
        cur = head;
        Node curCopy = null;
        while (cur != null){
            next = cur.next.next;
            curCopy = cur.next;
            curCopy.rand = cur.rand != null ? cur.rand.next : null;
            cur = next;
        }

//        再把老节点和新节点再分别拆开
         Node result = head.next;
         cur = head;
         while (cur != null){
             next = cur.next.next;
             curCopy = cur.next;
             cur.next = next;
             curCopy.next = next != null ? next.next : null;
             cur = next;
         }
         return result;
    }

    public static void printRandLinkedList(Node head) {
        Node cur = head;
        System.out.print("order: ");
        while (cur != null) {
            System.out.print(cur.value + " ");
            cur = cur.next;
        }
        System.out.println();
        cur = head;
        System.out.print("rand:  ");
        while (cur != null) {
            System.out.print(cur.rand == null ? "- " : cur.rand.value + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = null;
        Node res1 = null;
        Node res2 = null;
        printRandLinkedList(head);
        res1 = copyListWithRand1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRand2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(4);
        head.next.next.next.next = new Node(5);
        head.next.next.next.next.next = new Node(6);

        head.rand = head.next.next.next.next.next; // 1 -> 6
        head.next.rand = head.next.next.next.next.next; // 2 -> 6
        head.next.next.rand = head.next.next.next.next; // 3 -> 5
        head.next.next.next.rand = head.next.next; // 4 -> 3
        head.next.next.next.next.rand = null; // 5 -> null
        head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4

        printRandLinkedList(head);
        res1 = copyListWithRand1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRand2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");

    }


}