链表经典问题(附部分代码和测试)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32768743/article/details/81948196
  • 基本的插入、删除、遍历操作
  • 实现栈
  • 找倒数第n个节点

双指针实现

  • 扩展1:找两个链表的合并节点
  • 扩展2:从表尾开始找模结点

  • 判环

快慢指针实现(Floyd环判定算法)

  • 扩展1:求环长
  • 扩展2:找中间节点
  • 反转链表
  • 扩展1:逐对反转
  • 扩展2:每K个节点反转
  • 约瑟夫环
  • 复制链表(节点含兄弟指针)

散列表辅助

附:

public class ListNode {
    private int data;
    private ListNode next;

    public ListNode(int data) {
        this.data = data;
    }

    public ListNode(int data, ListNode next) {
        this.data = data;
        this.next = next;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public ListNode getNext() {
        return next;
    }

    public void setNext(ListNode next) {
        this.next = next;
    }

    @Override
    public String toString() {
        ListNode head = this;
        ListNode it = this;
        StringBuilder msg = new StringBuilder();
        while (it != null) {
            msg.append(it.data);
            if (it.next != null && it.next != head && it.next != it) {
                msg.append("->");
            }
            it = it.next;
            if (it == head) break;
        }
        return msg.toString();
    }

    public static int listLength(ListNode headNode) {
        int length = 0;
        ListNode currentNode = headNode;
        while (currentNode != null) {
            length++;
            currentNode = currentNode.next;
        }
        return length;
    }

    public static ListNode insertInLinkedList(ListNode headNode, ListNode nodeToInsert, int position) {
        if (headNode == null) return nodeToInsert;
        int size = listLength(headNode);
        if (position > size + 1 || position < 1) {
            System.out.println("Position of node to insert is invalid. The valid inputs are 1 to " + (size + 1));
            return headNode;
        }
        if (position == 1) {
            nodeToInsert.next = headNode;
            return nodeToInsert;
        }
        ListNode previousNode = headNode;
        int count = 1;
        while (count < position) {
            previousNode = previousNode.next;
            count++;
        }
        ListNode currentNode = previousNode.next;
        nodeToInsert.next = currentNode;
        previousNode.next = nodeToInsert;
        return headNode;
    }

    public static ListNode deleteNodeFromLinkedList(ListNode headNode, int position) {
        int size = listLength(headNode);
        if (position > size || position < 1) {
            System.out.println("Position of node to delete is invalid. The valid inputs are 1 to " + size);
            return headNode;
        }
        if (position == 1) {
            ListNode currentNode = headNode.next;
            headNode = null;
            return currentNode;
        }
        ListNode previousNode = headNode;
        int count = 1;
        while (count < position) {
            previousNode = previousNode.next;
            count++;
        }
        ListNode currentNode = previousNode.next;
        previousNode.next = currentNode.next;
        currentNode = null;
        return headNode;
    }

    public static void deleteLinkdedList(ListNode head) {
        ListNode auxilaryNode, iterator = head;
        while (iterator != null) {
            auxilaryNode = iterator.next;
            iterator = null;
            iterator = auxilaryNode;
        }
    }

    public static ListNode nthNodeFromEnd(ListNode head, int nthNode) {
        if (head == null) return null;
        if (nthNode <= 0) return null;
        ListNode node = head, prev = null;
        for (int count = 1; count < nthNode; count++) {
            if (node != null) node = node.next;
        }
        while (node != null) {
            prev = (prev == null) ? head : prev.next;
            node = node.next;
        }
        return node;
    }

    public static boolean doesLinkedListContainsLoop(ListNode head) {
        if (head == null) return false;
        ListNode fastNode = head, slowNode = head;
        while (fastNode.next != null && fastNode.next.next != null) {
            fastNode = fastNode.next.next;
            slowNode = slowNode.next;
            if (fastNode == slowNode) {
                return true;
            }
        }
        return false;
    }

    public static ListNode reverseList(ListNode head) {
        ListNode temp = null, nextNode = null;
        while (head != null) {
            nextNode = head.next;
            head.next = temp;
            temp = head;
            head = nextNode;
        }
        return temp;
    }

    public static ListNode findIntersectingNode(ListNode list1, ListNode list2) {
        if (list1 == null || list2 == null) {
            return null;
        }
        int count1 = 0, count2 = 0;
        ListNode it = list1;
        while (it != null) {
            count1++;
            it = it.next;
        }
        it = list2;
        while (it != null) {
            count2++;
            it = it.next;
        }
        ListNode head1 = list1, head2 = list2;
        int diffCount = count1 - count2;
        if (count1 < count2) {
            head1 = list2;
            head2 = list1;
            diffCount = count2 - count1;
        }
        for (int i = 0; i < diffCount; i++) {
            head1 = head1.next;
        }
        while (head1 != null && head2 != null) {
            if (head1 == head2) return head1;
            head1 = head1.next;
            head2 = head2.next;
        }
        return null;
    }

    public static ListNode findMiddle(ListNode head) {
        if (head == null) return null;
        ListNode slowNode = head, fastNode = head;
        while (fastNode.next != null && fastNode.next.next != null) {
            slowNode = slowNode.next;
            fastNode = fastNode.next.next;
        }
        return slowNode;
    }

    public static void printListFromEnd(ListNode head) {
        if (head == null) return;
        printListFromEnd(head.next);
        System.out.print(head.data + " ");
    }

    public static boolean isLinkedListLengthEven(ListNode listHead) {
        while (listHead != null && listHead.next != null) {
            listHead = listHead.next.next;
        }
        return listHead == null;
    }

    public static ListNode mergeList(ListNode a, ListNode b) {
        ListNode result = null;
        if (a == null) return b;
        if (b == null) return a;
        if (a.data < b.data) {
            result = a;
            result.next = mergeList(a.next, b);
        } else {
            result = b;
            result.next = mergeList(a, b.next);
        }
        return result;
    }

    public static ListNode reversePairRecursive(ListNode head) {
        if (head == null || head.next == null) return head;
        int temp = head.data;
        head.data = head.next.data;
        head.next.data = temp;
        reversePairRecursive(head.next.next);
        return head;
    }

    public static ListNode reversePairIterative(ListNode head) {
        if (head == null || head.next == null) return head;
        ListNode it = head;
        while (it != null && it.next != null) {
            int temp = it.data;
            it.data = it.next.data;
            it.next.data = temp;
            it = it.next.next;
        }
        return head;
    }

    private static boolean hasEnoughNode(ListNode head, int k) {
        if (head == null) return false;
        ListNode currentNode = head;
        for (int i = 0; i < k; i++) {
            currentNode = currentNode.next;
            if (currentNode == null) return false;
        }
        return true;
    }

    public static ListNode reverseList(ListNode head, int k) {
        if (head == null) return null;
        // 如果链表不足k个节点,不用反转
        if (k == 1 || !hasEnoughNode(head, k)) return head;
        ListNode result = null;
        // 当前头节点,反转后变成尾节点
        ListNode currentHead = head;
        // 连接反转后的头节点
        ListNode lastTail = null;
        ListNode currentNode = head;
        do {
            // 反转这部分的链表
            ListNode newHead = null;
            for (int i = 0; i < k; i++) {
                ListNode t = currentNode.next;
                currentNode.next = newHead;
                newHead = currentNode;
                currentNode = t;
            }
            if (result == null) result = newHead;
            if (lastTail != null) lastTail.next = newHead;
            lastTail = currentHead;
            currentHead.next = currentNode;
            currentHead = currentHead.next;
        } while (hasEnoughNode(currentHead, k));

        return result;
    }

    public static int getJosephusPosition(int n, int m) {
        ListNode head = new ListNode(1);
        ListNode tail = head;
        for (int i = 1; i < n; i++) {
            tail.next = new ListNode(i + 1);
            tail = tail.next;
        }
        tail.next = head;
        ListNode it = tail;
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < m - 1; j++) it = it.next;
            it.next = it.next.next;
        }
        return it.data;
    }

    public static ListNode modularNodes(ListNode head, int k) {
        ListNode modularNode = null;

        if(k<=0) return null;
        for(int i = 1;head!=null;head=head.next){
            if(i%k==0){
                modularNode = head;
            }
            i++;
        }
        return modularNode;
    }

    public static void main(String[] args) {
        ListNode next = new ListNode(3);
        ListNode head = new ListNode(1, new ListNode(2, next));
        next.setNext(head);
        System.out.println(head.toString());
    }
}

测试

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import static org.junit.Assert.*;

public class ListNodeTest {
    private ListNode head;
    private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
    private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();

    @Before
    public void setUp() throws Exception {
        head = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4,new ListNode(5)))));
        System.setOut(new PrintStream(outContent));
        System.setErr(new PrintStream(errContent));
    }
    @After
    public void tearDown(){
        System.setOut(null);
        System.setErr(null);
    }
    @Test
    public void testFindMiddle() {
        ListNode result = ListNode.findMiddle(head);
        Assert.assertEquals(3,result.getData());
    }
    @Test
    public void testFindMiddle_1() {
        head = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
        ListNode result = ListNode.findMiddle(head);
        Assert.assertEquals(2,result.getData());
    }
    @Test
    public void testPrintListFromEnd(){
        ListNode.printListFromEnd(head);
        Assert.assertEquals("5 4 3 2 1 ",outContent.toString());
    }
    @Test
    public void testIsLinkedListLengthEven(){
        boolean result = ListNode.isLinkedListLengthEven(head);
        Assert.assertFalse(result);
    }
    @Test
    public void testIsLinkedListLengthEven_1(){
        head = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
        boolean result = ListNode.isLinkedListLengthEven(head);
        Assert.assertTrue(result);
    }
    @Test
    public void testMergeList(){
        ListNode b = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
        ListNode newHead = ListNode.mergeList(head,b);
        print(newHead);
        Assert.assertEquals("1 1 2 2 3 3 4 4 5 ",outContent.toString());
    }
    @Test
    public void testReversePairRecursive(){
        ListNode newHead = ListNode.reversePairRecursive(head);
        print(newHead);
        Assert.assertEquals("2 1 4 3 5 ", outContent.toString());
    }
    @Test
    public void testReversePairRecursive_1(){
        ListNode head = new ListNode(1,new ListNode(2));
        ListNode newHead = ListNode.reversePairRecursive(head);
        print(newHead);
        Assert.assertEquals("2 1 ", outContent.toString());
    }
    @Test
    public void testReversePairRecursive_2(){
        ListNode head = new ListNode(1,new ListNode(2, new ListNode(3)));
        ListNode newHead = ListNode.reversePairRecursive(head);
        print(newHead);
        Assert.assertEquals("2 1 3 ", outContent.toString());
    }
    @Test
    public void testReversePairIterative(){
        ListNode newHead = ListNode.reversePairIterative(head);
        print(newHead);
        Assert.assertEquals("2 1 4 3 5 ", outContent.toString());
    }
    @Test
    public void testReverseBlockOfKNodesInLinkedList_1(){
        ListNode newHead= ListNode.reverseList(head,1);
        print(newHead);
        Assert.assertEquals("1 2 3 4 5 ", outContent.toString());
    }
    @Test
    public void testReverseBlockOfKNodesInLinkedList_2(){
        ListNode newHead= ListNode.reverseList(head,2);
        print(newHead);
        Assert.assertEquals("2 1 4 3 5 ", outContent.toString());
    }
    @Test
    public void testReverseBlockOfKNodesInLinkedList_3(){
        head = new ListNode(3,new ListNode(4, new ListNode(5)));
        ListNode newHead= ListNode.reverseList(head,2);
        print(newHead);
        Assert.assertEquals("4 3 5 ", outContent.toString());
    }
    @Test
    public void testReverseBlockOfKNodesInLinkedList_4(){
        ListNode newHead= ListNode.reverseList(head,3);
        print(newHead);
        Assert.assertEquals("3 2 1 4 5 ", outContent.toString());
    }
    @Test
    public void testGetJosephusPosition(){
        int result = ListNode.getJosephusPosition(3,2);
        Assert.assertEquals(3,result);
    }
    @Test
    public void testGetJosephusPosition_2(){
        int result = ListNode.getJosephusPosition(9,4);
        Assert.assertEquals(1,result);
    }
    @Test
    public void testGetJosephusPosition_3(){
        int result = ListNode.getJosephusPosition(9,1);
        Assert.assertEquals(9,result);
    }
    @Test
    public void testGetJosephusPosition_4(){
        int result = ListNode.getJosephusPosition(1,10);
        Assert.assertEquals(1,result);
    }
    @Test
    public void testGetJosephusPosition_5(){
        int result = ListNode.getJosephusPosition(8,5);
        Assert.assertEquals(3,result);
    }
    @Test
    public void testGetJosephusPosition_6(){
        int result = ListNode.getJosephusPosition(6,6);
        Assert.assertEquals(4,result);
    }
    @Test
    public void testGetJosephusPosition_7(){
        int result = ListNode.getJosephusPosition(2,1);
        Assert.assertEquals(2,result);
    }
    @Test
    public void testGetJosephusPosition_8(){
        int result = ListNode.getJosephusPosition(3,1);
        Assert.assertEquals(3,result);
    }
    private void print(ListNode head){
        ListNode it = head;
        while(it!=null){
            System.out.print(it.getData()+" ");
            it = it.getNext();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_32768743/article/details/81948196