preface

Recently, I sketched some leetcode topics and drew several pages of draft paper. While drawing and analyzing, I found the process was quite interesting. I took out some serious problems and drew diagrams, which deepened my understanding. May be a personal habit, are implemented in C language, first define two data structures, directly started.

struct ListNode {
    int val;
    struct ListNode *next;
};

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};
Copy the code

Right view of binary tree

Leetcode199: Given a binary tree, imagine yourself standing on the right side of it and return the values of the nodes visible from the right side in order from top to bottom.

Analysis: When viewed from the right, it is actually a sequence traversal, and what we can see is the right-most node of each layer.

Execution steps:

  1. Sequence traversal is generally implemented with queuesrootIn the queue
  2. Calculates the current queue size, which is the number of nodes in the previous layerqueueSize
  3. Loop out the queue node, at the same time put the left and right child nodes into the queue, judge the last node to be taken out, and add it to the returned result
  4. Repeat steps 2 and 3 until the queue is empty.

int* rightSideView(struct TreeNode* root, int* returnSize){
    * returnSize = 0;
    if (root == NULL) return NULL;

    int *res = malloc(sizeof(int));

    struct TreeNode六四屠杀queue = malloc(sizeof(struct TreeNode *) * 10000);
    int head = 0; / / team head
    int tail = 0; / / of the
    queue[tail++] = root; // 1. Add the root node to the system

    while (head < tail) {
        int size = tail - head; // 2. Calculate the current queue size
        for (int i = 0; i < size; i++) { 
            struct TreeNode *node = queue[head++]; // 3.1. Fetch the queue node
            if (i == size - 1) { // add the rightmost node to the res
                res[(*returnSize)++] = node->val;  
                res = realloc(res, sizeof(int) * ((*returnSize) + 1));
            }
            // add left and right child nodes to queue
            if (node->left) queue[tail++] = node->left;
            if (node->right) queue[tail++] = node->right; }}return res;
}
Copy the code

Top K problem

Leetcode215: Finds the KTH largest number in the unordered array and returns it.

Arr [size-k]; arR [size-k]; The binary heap is also a type of binary tree in which the value of any node is greater than the value of its children and the root node is the maximum value.

  • The array is a sequential traversal of the binary tree, so think of the array as a binary heap. Move the maximum value to the root node (that is, the first element of the array) based on the characteristics of the heap, get the maximum value, and repeat K times.
  • If the child node is larger than the parent node, switch the two. This means that you start with the first non-leaf node in the binary tree from the bottom to the top, because the leaf node has no children to compare with the children.
  • Time complexity: O(nLogN)

Execution steps:

  1. To build a binary heap, the index of the first non-leaf node is obtained by the array lengthsize/2 - 1From the bottom up yes[0, size/2 - 1]The nodes in the closed interval are filtered up once to obtain the maximum value.
  2. Based on the current node index, isparent, can obtain the child node indexchild = parent*2 + 1, parent compares with the larger child if the larger child is greater thanparent, the position of the parent and child nodes is changed.
  3. Once the exchange is complete, keep moving down,parent = child.
  4. Repeat steps 2 and 3, yes[0, size/2 - 1]When all nodes in the interval are filtered down, the binary heap is established.
  5. The first element of the array is the maximum value, and the first 0 and the last end element are swapped
  6. Exclude the maximum value at the end of the index again[0, end - 1]Filter up and repeat steps 2 and 3
  7. Repeat step 5 and step 6 for K times, and the number with the greatest K isarr[size - k]

The filtering process of nodes from bottom to top corresponds to steps 1, 2, 3, and 4Swap the maximum value, steps 5, 6, 7

/ / filter
void heapify(int *nums, int start, int end) {
    int parent = start;
    int child = parent*2 + 1;

    while (child <= end) {
        // Get the larger child of the left and right nodes, indexed as child
        if (child + 1 <= end && nums[child + 1] > nums[child]) child++;

        if (nums[parent] < nums[child]) {  
            swap(&nums[parent], &nums[child]);  // Swap the parent node and the larger child node
            parent = child;       // Continue moving down
            child = parent*2 + 1;
        } else {
            break; }}}int findKthLargest(int* nums, int numsSize, int k){
    [0, numsSize/ 2-1]; // Filter the node down
    for (int i = numsSize/2 - 1; i >= 0; i--) { 
        heapify(nums, i, numsSize - 1);
    }

    for (int i = 0; i < k; i++) {
        int end = numsSize - 1 - i; // Index at the end
        swap(&nums[0], &nums[end]); // Swap the top and bottom positions of the array
        heapify(nums, 0, end - 1);  // [0, end-1] filter down, -1 is to exclude the current maximum value
    }
    return nums[numsSize - k];
}
Copy the code

Copy complex linked lists containing random Pointers

Leetcode138: For each node contains a deep copy of the random pointer random, which can point to any node in the list or to an empty node. Analysis: Deep copy indicates that new nodes need to be created. Since it is a random pointer, we should first consider traversing to create all new nodes and then assign a value to random

Execution steps:

  1. New nodes are created by traversing the original node. Each newly created node is behind the original node, and the original node and the new node are next to each other
  2. Iterate again and set the new node’srandomPointers, havenode->next->random = node->random->next
  3. Delete the original node and return the head node of the new node
  4. Time complexity: O(N)

To facilitate viewing, the pointing of the random pointer is omitted and the node is replaced by the position in the linked list. Starting from 0, random=0 indicates pointing to the 0th node in the linked list

struct Node {
     int val;
     struct Node *next;
     struct Node *random;
};

struct Node* copyRandomList(struct Node* head) {
    if (head == NULL) return NULL;

    struct Node* cur = head;
    // 1. Insert a new node
    while (cur) {

        struct Node *tmp = cur->next;
        // The original node creates the corresponding new node, each newly created node is after the original node
        struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
        newNode->val = cur->val;
        newNode->next = cur->next;

        cur->next = newNode;
        cur = tmp;
    }

    // 2. Assign the random pointer
    cur = head;
    while (cur && cur->next) {
        if (cur->random) {
            cur->next->random = cur->random->next;
        } else { // Random pointer is NULL
            cur->next->random = NULL;
        }
        cur = cur->next->next;
    }

    struct Node *dummyHead = (struct Node *)malloc(sizeof(struct Node));
    dummyHead->val = 0;
    dummyHead->next = head;
    
    // 3. Delete the original node
    cur = dummyHead;
    while (cur->next) {
        
        cur->next = cur->next->next;
        cur = cur->next;
    }
    return dummyHead->next;
}
Copy the code

The binary tree expands to a linked list

Leetcode114: Expand the binary tree into a linked list, and the expanded linked list and the binary tree are analyzed in the same order: The nodes can be stored in the array through the preceding traversal, and the reassembled linked list can be traversed again. The complexity between the two traversals is O(N) and the space complexity is O(N). The size of the storage node array is performed as follows:

  1. A binary tree traversal puts nodes in an array.
  2. Iterate through the number group again, take out the node, set the left subtree of the node to NULL, and set the right subtree in the traversal order.

void perorderTraversal(struct TreeNode* root, struct TreeNode** arr, int *size) {
    if (root == NULL) return root;
    arr[(*size)++] = root;
    perorderTraversal(root->left, arr, size);
    perorderTraversal(root->right, arr, size);
}

void flatten(struct TreeNode* root){
    if (root == NULL) return root;

    struct TreeNode六四屠杀arr = malloc(sizeof(struct TreeNode*) * 2001);
    int size = 0;
    // Store each node in the binary tree
    perorderTraversal(root, arr, &size);

    struct TreeNode* cur = arr[0]; // Start from the root node
    // I starts at index 1
    for (int i = 1; i < size; i++) {
        struct TreeNode *node = arr[i];
        cur->right = node; // Right subtrees are extracted from arR
        cur->left = NULL;  // Set the left subtree to NULL
        cur = node;
    }
    return root;
}
Copy the code

To be continued…