The sword refers to the second edition of the offer interview question 18: delete a node in a linked list (java)

Topic 1 Description:
Given the head pointer of a singly linked list and a node pointer, define a function to delete the node in O(1) time.

Analysis:
To delete a node in a singly linked list, the most conventional method is undoubtedly to start from the head node of the linked list, traverse sequentially to find the node to be deleted, and delete the node in the linked list.
For example, in the linked list shown in Figure a, if we want to delete node i, we can traverse sequentially from the head node a of the linked list, and find that m_PNext of node h points to node i to be deleted, so we suspect that m_PNext of node h points to the lower part of i A node is j. After the pointer is adjusted, we can safely delete node i and ensure that the linked list is not broken. Since this idea requires sequential search, the time complexity is naturally O(n).
write picture description here
The reason to start the search from the beginning is because we need to get the node before the deleted node. In a singly linked list, there is no pointer to the previous node in the node, so it has to search sequentially from the head node of the linked list.
Is it necessary to get the previous node of the deleted node? the answer is negative. We can get the next node of the node to be deleted in a very respectable way. If we copy the content of the next node to the node to be deleted to overwrite the original content, and then delete the next node, is that equivalent to deleting the node to be deleted currently?
We still use the previous example to analyze this idea. For the node i we want to delete, first copy the content of the next node j of i to i, and then point the pointer of i to the next node of node j. At this time, if the node j is deleted again, the effect is just to delete the node i (Figure c)
. There is another problem with the above problem; if the node to be deleted is at the end of the linked list, then it has no next node, what should I do? We let it start from the head node of the linked list, traverse sequentially to get the pre-order node of the node, and complete the deletion operation.
The last thing to note is that if there is only one node in the linked list, and we want the head node (also the tail node) of the linked list, we need to set the head node of the linked list to NULL after deleting the node.

code show as below:

/**
 * 在O(1)时间内删除链表节点
 */
public class DeleteNodeOfO1 {

    /**
     * @param head 链表的头结点
     * @param toBeDeleted 待删除的节点
     */
    public void deleteNode(ListNode head, ListNode toBeDeleted){
        //参数校验
        if(head == null || toBeDeleted == null){
            return ;
        }

        //链表中只有一个节点,那么待删除的节点既是头结点,又是尾结点
        if(head == toBeDeleted && head.nextNode == null){
            head = null;
        }else{
            //待删除的节点是尾节点
            if(toBeDeleted.nextNode == null){
                ListNode temp = head;
                while(temp.nextNode != toBeDeleted){
                    temp = temp.nextNode;
                }
                temp.nextNode = null;
            }else{          //待删除的节点不是尾节点
                toBeDeleted.nodeValue = toBeDeleted.nextNode.nodeValue;
                toBeDeleted.nextNode = toBeDeleted.nextNode.nextNode;
            }
        }
    }

    /**
     * 打印链表
     * @param head 链表的头结点
     */
    public void printList(ListNode head){
        ListNode temp = head;
        while(temp != null){
            System.out.print(temp.nodeValue + "  ");
            temp = temp.nextNode;
        }
    }

    public static void main(String[] args) {
        DeleteNodeOfO1 test = new DeleteNodeOfO1();

        ListNode head = new ListNode();
        ListNode temp1 = new ListNode();
        ListNode temp2 = new ListNode();
        ListNode temp3 = new ListNode();

        head.nodeValue = 1;
        temp1.nodeValue = 2;
        temp2.nodeValue = 3;
        temp3.nodeValue = 4;
        head.nextNode = temp1;
        temp1.nextNode = temp2;
        temp2.nextNode = temp3;
        temp3.nextNode = null;

        System.out.println("删除前的链表:");
        test.printList(head);

        System.out.println("-----------------------");

        test.deleteNode(head, temp3);       //执行删除操作
        System.out.println("删除后的链表:");
        test.printList(head);

    }
}

class ListNode{
    int nodeValue;
    ListNode nextNode;
}

The total average time complexity is [(n-1)*1+O(n)]/n, and the result is still O(1).

Description of topic 2:
In a sorted linked list, there are duplicate nodes, please delete the duplicate nodes in the linked list, the duplicate nodes are not retained, and the pointer to the head of the linked list is returned.
For example:
input linked list: 1->2->3->3->4->4->5
Processing result: 1->2->5

Analysis:
1. Create a new head node to prevent the first node from being deleted.
2. Save the previous node of the current node, loop through the entire linked list, if the value of the current node is equal to the value of the next node, compare the value of the current node with the value of the next.next node until it is not equal or null, Finally, the previous node pre of the current node is pointed to the last node that is not equal.
3. If the current node is not equal to the next node, directly move the node pointer all one bit backwards.

code show as below:

/**
 * 删除链表中的重复节点
 */
public class DeleteNodeOfDuplication {

    public ListNode deleteDuplication(ListNode head) {
        if (head == null) {
            return null;
        }

        ListNode preNode = new ListNode(); // 前一个节点
        ListNode tmp = preNode;
        preNode.nextNode = head;
        ListNode nowNode = head; // 当前节点

        while(nowNode != null){
            //判断是否存在重复节点,是否应该删除
            if(nowNode.nextNode != null && nowNode.nodeValue == nowNode.nextNode.nodeValue){
                while(nowNode.nextNode != null && nowNode.nodeValue == nowNode.nextNode.nodeValue){
                    nowNode = nowNode.nextNode;
                }
                preNode.nextNode = nowNode.nextNode;        //删除相应的重复节点
            }else{      //preNode指针移动
                preNode = nowNode;
            }
            nowNode = nowNode.nextNode;
        }

        return tmp.nextNode;
    }

    public static void main(String[] args) {
        DeleteNodeOfDuplication test = new DeleteNodeOfDuplication();

        ListNode head = new ListNode();
        ListNode temp1 = new ListNode();
        ListNode temp2 = new ListNode();
        ListNode temp3 = new ListNode();
        ListNode temp4 = new ListNode();
        ListNode temp5 = new ListNode();
        ListNode temp6 = new ListNode();

        head.nodeValue = 1;
        temp1.nodeValue = 2;
        temp2.nodeValue = 3;
        temp3.nodeValue = 4;
        temp4.nodeValue = 5;
        temp5.nodeValue = 6;
        temp6.nodeValue = 7;
        head.nextNode = temp1;
        temp1.nextNode = temp2;
        temp2.nextNode = temp3;
        temp3.nextNode = temp4;
        temp4.nextNode = temp5;
        temp5.nextNode = temp6;
        temp6.nextNode = null;

        System.out.println("删除前的链表:");
        test.printList(head);

        System.out.println();
        System.out.println("-----------------------");

        ListNode resultList = test.deleteDuplication(head); // 执行删除操作
        System.out.println("删除后的链表:");
        test.printList(resultList);
    }

    /**
     * 打印链表
     * 
     * @param head
     *            链表的头结点
     */
    public void printList(ListNode head) {
        ListNode temp = head;
        while (temp != null) {
            System.out.print(temp.nodeValue + "  ");
            temp = temp.nextNode;
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325609017&siteId=291194637