[LeetCode-150 classic interview questions-day14]

 

Table of contents

19. Delete the Nth node from the bottom of the linked list

 82.Delete duplicate elements in sorted linked list Ⅱ

 61. Rotating linked list

 86. Separate linked lists

 146.LRU cache


19. Delete the Nth node from the bottom of the linked list

Question meaning:

Given a linked list, delete the penultimate  n node of the linked list and return the head node of the linked list.

[Input example] head = [1,2,3,4,5],n=2

[Output sample][1,2,3,5]

Problem-solving ideas:

1. Double pointers p and q, the initial hash points to the head node;

2. Move q until the element between p and q is n

3. Move p and q at the same time until q points to null at the end of the linked list

4. p.next = p.next.next

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyHead = new ListNode(0,head);
        ListNode p = dummyHead;
        ListNode q = head;
        for(int i=0; i< n; i++){
            q = q.next;
        }
        while(q != null){
            q = q.next;
            p = p.next;
        }
        p.next = p.next.next;
        ListNode ans = dummyHead.next;
        return ans;

    }
}

Time: Beat 100.00%

Memory: Beaten by 64.22%

 82.Delete duplicate elements in sorted linked list Ⅱ

Question meaning:

Given the head of a sorted linked list  head ,  delete all nodes with duplicate numbers in the original linked list, leaving only different numbers  . Returns  a sorted linked list  .

[Input example] head = [1,1,1,2,3]

[Output sample][2,3]

Problem-solving ideas:

1. Define a dumb node pointing to the head node of the linked list

2. The pointer cur points to the dumb node and traverses the linked list

3. If cur.next.val == cur.next.next.val, delete all cur.next and subsequent nodes with the same element x (x=cur.next.val);

4. Continue to remove duplicate elements until cur.next is an empty node or the element value is not equal to x

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null){
            return head;
        }
        ListNode dummy = new ListNode(0,head);
        ListNode cur = dummy;
        while(cur.next != null && cur.next.next != null){
            if(cur.next.val == cur.next.next.val){
                int x = cur.next.val;
                while(cur.next != null && cur.next.val == x){
                    cur.next = cur.next.next;//不断跳过重复值的数
                }
            }else{
                cur = cur.next;//继续往下遍历
            }
        }
        return dummy.next;//指向head
    }
}

Time: Beat 100.00%

Memory: Beaten by 86.54%

 61. Rotating linked list

Question meaning:

You are given the head node of a linked list  head , rotate the linked list, and move each node of the linked list to the right  k .

[Input example] head = [1,2,3,4,5],k=2

[Output sample][4,5,1,2,3]

Problem-solving ideas:

1. Define a dumb node pointing to the head node of the linked list

2. Traverse the linked list, count the length of the linked list, and optimize the number of moves to k%n;

3. Form a closed loop of the original linked list and calculate count = nk%n, which means that the tail node can be found by traversing count times starting from the current node;

4. Keep moving the pointer until count = 0. At this time, define a new node pointing to dummy.next as the head node of the new linked list. Dummy.next is assigned null to achieve link breaking.

 

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(k == 0 || head==null || head.next == null){
            return head;
        }
        //一次遍历,统计链表的长度n,移动k次相当于移动k%n次;
        int n = 1;
        ListNode dummy = head;
        while(dummy.next !=null){
            dummy = dummy.next;
            ++n;
        }
        int count = n - k % n;
        if(count == n){
            return head;
        }
        dummy.next = head;//形成闭环
        while(count-- > 0){
            dummy = dummy.next;
        }
        ListNode result = dummy.next;
        dummy.next = null;
        return result;

    }
}

Time: Beat 100.00%

Memory: Beaten by 68.97%

 86. Separate linked lists

Question meaning:

You are given the head node of a linked list  head and a specific value  . Please separate the linked list so that all   nodes that are  less than or equal to appear  before nodes that are greater than or equal to . x x x

You should  preserve  the initial relative position of each node in both partitions.

[Input example] head = [1,4,3,2,5,2],x=3

[Output sample][1,2,2,4,3,5]

Problem-solving ideas:

1. Use two linked lists, one to store nodes less than x, and one to store nodes greater than or equal to x, and then just splice the two linked lists.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode partition(ListNode head, int x) {
        ListNode minNext = new ListNode(0);
        ListNode minhead = minNext;
        ListNode maxNext = new ListNode(0);
        ListNode maxhead = maxNext;

        while(head!=null){
            if(head.val < x){
                minNext.next = head;
                minNext = minNext.next;
            }else{
                maxNext.next = head;
                maxNext = maxNext.next;
            }
            head = head.next;
        }
        maxNext.next = null;
        minNext.next = maxhead.next;
        return minhead.next;
    }
}

Time: Beat 100.00%

Memory: Beaten by 20.49%

 146.LRU cache

Question meaning:

Please design and implement a data structure that satisfies   LRU (least recently used) cache  constraints.

Implementation  LRUCache class:

  • LRUCache(int capacity) Initialize the LRU cache  with  a positive integer  as the capacity capacity
  • int get(int key)key Returns the value of the keyword   if  it exists in the cache, otherwise -1 .
  • void put(int key, int value) If the keyword  key already exists, change its data value  value ; if it does not exist, insert the group into the cache  key-value . If an insertion operation causes the number of keywords to be exceeded  ,  the oldest unused keyword capacity should  be evicted .

 The average time complexity that get a  function  put must run with  .O(1)

【Input sample】

["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]

【Output sample】

[null, null, null, 1, null, -1, null, -1, 3, 4]
explain
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // The cache is {1=1}
lRUCache.put(2, 2); // The cache is {1=1, 2=2}
lRUCache.get(1); // Return 1
lRUCache.put(3, 3); // This operation will invalidate keyword 2, and the cache is {1=1, 3=3}
lRUCache.get(2); // Return -1 (not found)
lRUCache.put(4, 4); // This operation will invalidate keyword 1, and the cache is {4=4, 3=3}
lRUCache.get(1); // Return -1 (not found)
lRUCache.get(3); // Return 3
lRUCache.get(4); // Return 4

Problem-solving ideas: Hash table + doubly linked list

1. A doubly linked list stores key-value pairs in the order they are used. The key-value pairs closest to the head are the most recently used, and the key-value pairs closest to the tail are the longest unused.

2. The key of the hash table cache data is mapped to its position in the doubly linked list

3. Use the hash table for positioning, find the position of the cache item in the doubly linked list, and move it to the head of the doubly linked list. If the key is not stored in the hash table, return -1 or at the head of the linked list. Create a new node.

public class LRUCache {
    private Map<Integer,DLinkedNode> cache = new HashMap<Integer,DLinkedNode>();
    private int size;
    private int capacity;
    private DLinkedNode head,tail;

    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.prev = head;
    }
    
    public int get(int key) {
        DLinkedNode node = cache.get(key);
        if(node == null){
            //链表中不存在此值
            return -1;
        }
        //存在,将其移动到双向链表的头部
        moveToHead(node);
        return node.value;
    }
    
    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);
        if(node == null){
            //如果key不存着,要创建一个新节点
            //需要判断插入之后长度是否会超过容量
            DLinkedNode newNode = new DLinkedNode(key,value);
            cache.put(key,newNode);
            addToHead(newNode);
            ++size;//每加进来一个元素,size++
            if(size > capacity){
                //删除尾部节点和哈希表中的对应项
                DLinkedNode tail = removeTail();
                cache.remove(tail.key);
                --size;
            }
        }else{
            //key存在,哈希表定位,修改value,移到头部
            node.value = value;
            moveToHead(node);
        }
    }

    private void addToHead(DLinkedNode node){
        //添加到双向链表头部
        node.prev = head;
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
    }

    private void removeNode(DLinkedNode node){
        //从当前位置移走
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private void moveToHead(DLinkedNode node){
        removeNode(node);
        addToHead(node);
    }

    private DLinkedNode removeTail(){
        DLinkedNode node = tail.prev;
        removeNode(node);
        return node;
    }
}


class DLinkedNode{
    int key;
    int value;
    DLinkedNode prev;
    DLinkedNode next;
    public DLinkedNode(){}
    public DLinkedNode(int key, int value){
        this.key = key;
        this.value = value;
    }
}
/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

Time: Defeated 23.27%

Memory: Beat 97.38%

Guess you like

Origin blog.csdn.net/qq_37998848/article/details/132488098