Skip to content

Algorithm About LinkedList

Posted on:March 13, 2023 at 01:32 AM
Share on

It’s about the data struct of linear — linkedlist and the Algorithm on it.

Table of contents

Open Table of contents

链表

性质

关键点

时间复杂度

操作复杂度
LookupO(n)
InsertO(1)
DeleteO(1)
Append(push back)O(1)
Prepend(push front)O(1)
Note:表中都是值知道插入或删除地址,而不是仅仅只知道元素,需要查询得到地址

实战

  1. Reverse Linked List

Given the head of a singly linked list, reverse the list, and return the reversed list.

Example 1:

Input: head = [1,2,3,4,5]

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

Example 2:

Input: head = [1,2]

Output: [2,1]

Example 3:

Input: head = []

Output: []

Constraints:

The number of nodes in the list is the range [0, 5000].

-5000 <= Node.val <= 5000

Follow up: A linked list can be reversed either iteratively or recursively. Could you implement both?

class Solution {
    public ListNode reverseList(ListNode head){
      // Set the last node
      ListNode last = null;
      while(head != null){
        // copy the head next node
        ListNode nextHead = head.next;

        // reverse
        head.next = last;

        // move
        last = head;
        head = nextHead;
      }
    return last;
    }
}
  1. Reverse Nodes in k-Group

Given the head of a linked list, reverse the nodes of the list k at a time, and return the modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should remain as it is.

You may not alter the values in the list’s nodes, only nodes themselves may be changed.

Example 1:

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

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

Example 2:

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

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

Constraints:

The number of nodes in the list is n.

1 <= k <= n <= 5000

0 <= Node.val <= 1000

Follow-up: Can you solve the problem in O(1) extra memory space?

class Solution {
    public ListNode reverseKGroup(ListNode head, int k){

    // avoid the last.next rasie a NullException
    ListNode protect  = new ListNode(0,head);
    ListNode last = protect;

    // group iterator
    while(head != null){
      // 1. make group: walk back k-1 step, find the head and end of the group
      ListNode end = getEnd(head,k);
      // if the group size less than k, not change it
      if (end==null){
        break;
      }

      ListNode nextGroupHead = end.next;


      //2. reverse the group
      reverseGroup(head, nextGroupHead);

      //3.connect the small LinkList bond
      // after group
      head.next = nextGroupHead;
      //before group
      last.next = end;


      // move last
      last = head;
      head = nextGroupHead;
    }
    return protect.next;
  }

  void reverseGroup(ListNode head,ListNode stop){

    // because the first is not null, so deal first step
    ListNode last = head;
    head = head.next;
    while(head!=stop){
      ListNode nextHead = head.next;
      head.next = last;
      last = head;
      head = nextHead;
    }
  }

  ListNode getEnd(ListNode head,int k){
    while(head!=null){
      k--;
      if (k==0){
        return head;
      }
      head = head.next;
    }
    // head = null
    return null;
  }
}

AcWing 136. 邻值查找

给定一个长度为 n 的序列 A,A 中的数各不相同。

对于 A 中的每一个数 Ai,求:

min1≤j<i |Ai−Aj|

以及令上式取到最小值的 j (记为 Pi)。若最小值点不唯一,则选择使 Aj 较小的那个。

输入格式

第一行输入整数 n,代表序列长度。

第二行输入 n 个整数 A1…An,代表序列的具体数值,数值之间用空格隔开。

输出格式

输出共 n−1 行,每行输出两个整数,数值之间用空格隔开。

分别表示当 i 取 2∼n 时,对应的 min1≤j<i|Ai−Aj| 和 Pi 的值。

数据范围

n≤105,|Ai|≤109

输入样例:

3
1 5 3

输出样例:

4 1
2 1

解题思路:

关键点:

import java.util.*;

public class Solution {
    public static class Node {
        long val;
        int idx;
        Node pre;
        Node next;
    }

    static int SIZE = 100005;
    static int[] a = new int[SIZE];
    static int[] ans = new int[SIZE];
    static Integer[] rk = new Integer[SIZE];
    static Node[] pos = new Node[SIZE];
    static int n;

    /**
     * 双链表插入模版,在node后面插入新结点
     *
     * @param node
     * @param idx
     * @return
     */
    static Node addNode(Node node, int idx) {
        Node newNode = new Node();
        newNode.val = a[idx];
        newNode.idx = idx;
        node.next.pre = newNode;
        newNode.next = node.next;
        node.next = newNode;
        newNode.pre = node;
        return newNode;
    }

    /**
     * 双链表删除模版
     *
     * @param node
     */
    static void deleteNode(Node node) {
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        for (int i = 1; i <= n; i++) {
            a[i] = input.nextInt();
            rk[i] = i;
        }

        Arrays.sort(rk, 1, n + 1, Comparator.comparingInt(rki -> a[rki]));
        // 保护结点
        Node head = new Node();
        Node tail = new Node();
        head.next = tail;
        tail.pre = head;
        head.val = (long) -1e10;
        tail.val = (long) 1e10;
        for (int i = 1; i <= n; i++) {
            // 数值:a[rk[i]],下标:rk[i]
            pos[rk[i]] = addNode(tail.pre, rk[i]);
        }
        for (int i = n; i > 1; i--) {
            Node curr = pos[i];
            if (a[i] - curr.pre.val <= curr.next.val - a[i]) {
                ans[i] = curr.pre.idx;
            } else {
                ans[i] = curr.next.idx;
            }
            deleteNode(curr);
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 2; i <= n; i++) {
            sb.append(Math.abs(a[ans[i]] - a[i]));
            sb.append(" ");
            sb.append(ans[i]);
            sb.append("\n");
        }
        System.out.println(sb);
    }

}
  1. Linked List Cycle

Given head, the head of a linked list, determine if the linked list has a cycle in it.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail’s next pointer is connected to. Note that pos is not passed as a parameter.

Return true if there is a cycle in the linked list. Otherwise, return false.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 0th node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

Constraints:

The number of the nodes in the list is in the range [0, 104].

-105 <= Node.val <= 105

pos is -1 or a valid index in the linked-list.

Follow up: Can you solve it using O(1) (i.e. constant) memory?

解题思路:

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            head = head.next;
            if (head == fast) return true;
        }
        return false;
    }
}
  1. Linked List Cycle II

Given the head of a linked list, return the node where the cycle begins. If there is no cycle, return null.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail’s next pointer is connected to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter.

Do not modify the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 0th node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

Constraints:

The number of the nodes in the list is in the range [0, 104].

-105 <= Node.val <= 105

pos is -1 or a valid index in the linked-list.

Follow up: Can you solve it using O(1) (i.e. constant) memory?

解题思路:

cycle

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast!=null&&fast.next!=null){
            fast = fast.next.next;
            slow = slow.next;
            if (fast==slow){
                while(head!=slow){
                    head = head.next;
                    slow = slow.next;
                }
                return head;
            }
        }
        return null;
    }
}
  1. Merge Two Sorted Lists

You are given the heads of two sorted linked lists list1 and list2.

Merge the two lists in a one sorted list. The list should be made by splicing together the nodes of the first two lists.

Return the head of the merged linked list.

Example 1:

Input: list1 = [1,2,4], list2 = [1,3,4]
Output: [1,1,2,3,4,4]

Example 2:

Input: list1 = [], list2 = []
Output: []

Example 3:

Input: list1 = [], list2 = [0]
Output: [0]

Constraints:

The number of nodes in both lists is in the range [0, 50].

-100 <= Node.val <= 100

Both list1 and list2 are sorted in non-decreasing order.

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode protect = new ListNode(-1);
        ListNode cur = protect;
        while(list1!=null && list2!=null){
            if(list1.val <= list2.val){
                cur.next = list1;
                list1 = list1.next;
            }else{
                cur.next = list2;
                list2 = list2.next;
            }
            cur = cur.next;
        }
        cur.next = list1==null?list2:list1;
        return protect.next;
    }
}
while(head != null) {
  head = head.next;
}
ListNode last = null;
while(head!=null){
    // make a copy
    ListNode nextHead = head.next;

    // some operation

    // move
    last = head;
    head = nextHead;
}
Share on