链表中等题(上)

链表中等题(上)

2807. 在链表中插入最大公约数

// 辗转相除
int gcd(int a, int b) {
    if (a % b == 0) return b;
    return gcd(b, a % b);
}

struct ListNode *insertGreatestCommonDivisors(struct ListNode *head) {
    if (head->next == NULL) return head;
    struct ListNode *p = head;
    while (p->next != NULL) {
        int value = gcd(p->val, p->next->val);
        struct ListNode *node = (struct ListNode *) malloc(sizeof(struct ListNode));
        node->val = value;
        node->next = p->next;
        p->next = node;
        p = p->next->next;
    }
    return head;
}

237. 删除链表中的节点

void deleteNode(struct ListNode *node) {
    // 替死鬼
    node->val = node->next->val;
    node->next = node->next->next;
}

2181. 合并零之间的节点

struct ListNode *mergeNodes(struct ListNode *head) {
    struct ListNode *p = head->next;
    struct ListNode *pre = head;
    int tempSum = 0;
    while (p != NULL) {
        if (p->val != 0) {
            tempSum += p->val;
        } else {
            // 把小区间的节点和放到前一个值为0的节点中
            pre->val = tempSum;
            // 跳过区间中的所有节点
            pre->next = p;
            tempSum = 0;
            if(p->next == NULL) 
                // 删掉最后一个值为0的节点
                pre->next = NULL;
            else
                pre = p;
        }
        p = p->next;
    }
    return head;
}

面试题 04.03. 特定深度节点链表

struct ListNode **listOfDepth(struct TreeNode *tree, int *returnSize) {
    struct ListNode **res = (struct ListNode **) malloc(sizeof(struct ListNode *) * 100);
    *returnSize = 0;

    // 循环队列
    const int size = 100;
    struct TreeNode *queue[size];
    int front = 0, rear = 0;
    queue[rear++] = tree;

    while (front != rear) {
        // 这一层的元素个数
        int count = (rear - front + size) % size;
        // 临时的链表头节点
        struct ListNode *tempHead = (struct ListNode *) malloc(sizeof(struct ListNode));
        struct ListNode *pre = tempHead;
        while (count-- > 0) {
            // 出队
            struct TreeNode *treeNode = queue[(front++) % size];
            struct ListNode *node = (struct ListNode *) malloc(sizeof(struct ListNode));
            node->val = treeNode->val;
            node->next = nullptr;
            pre->next = node;
            pre = node;
            // 下层元素入队
            if (treeNode->left != nullptr) queue[(rear++) % size] = treeNode->left;
            if (treeNode->right != nullptr) queue[(rear++) % size] = treeNode->right;
        }
        res[(*returnSize)++] = tempHead->next;
    }

    return res;
}

2130. 链表最大孪生和

// 中偏右的中点
struct ListNode *findMid(struct ListNode *head) {
    if (head == NULL || head->next == NULL)return head;
    struct ListNode *slow = head, *fast = head;
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

// 反转链表
struct ListNode *reverseList(struct ListNode *head) {
    struct ListNode *cur = head;
    struct ListNode *pre = NULL;
    struct ListNode *next;
    while (cur != NULL) {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}

int pairSum(struct ListNode *head) {
    struct ListNode *mid = findMid(head);
    struct ListNode *newMid = reverseList(mid);
    printf("%d %d\n", mid->val, newMid->val);
    int maxSum = 0;
    while (newMid != NULL) {
        if (head->val + newMid->val > maxSum)
            maxSum = head->val + newMid->val;
        head = head->next;
        newMid = newMid->next;
    }
    return maxSum;
}

1669. 合并两个链表

struct ListNode *mergeInBetween(struct ListNode *list1, int a, int b, struct ListNode *list2) {
    struct ListNode *slow = list1, *fast = list1;
    // 循环结束时,slow在下标a-1的位置
    while (--a > 0) {
        slow = slow->next;
    }
    // fast在下标b+1的位置
    while (b-- >= 0) {
        fast = fast->next;
    }

    slow->next = list2;
    while (list2->next != NULL) {
        list2 = list2->next;
    }
    list2->next = fast;
    return list1;
}

109. 有序链表转换二叉搜索树

// 递归生成AVL
struct TreeNode *generate(int *array, int left, int right) {
    int mid = ((right - left) >> 1) + left;
    struct TreeNode *node = (struct TreeNode *) malloc(sizeof(struct TreeNode));
    node->val = array[mid];
    node->left = generate(array, left, mid - 1);
    node->right = generate(array, mid + 1, right);
    return node;
}

// 转成数组,再递归生成AVL
struct TreeNode *sortedListToBST(struct ListNode *head) {
    if (head == nullptr) return nullptr;
    int len = 0;
    struct ListNode *p = head;
    while (p != nullptr) {
        len++;
        p = p->next;
    }

    int array[len];
    p = head;
    for (int i = 0; i < len; ++i) {
        array[i] = p->val;
        p = p->next;
    }

    return generate(array, 0, len - 1);
}
struct TreeNode *sortedListToBST(struct ListNode *head) {
    // 空节点
    if (head == NULL) return NULL;
    struct TreeNode *node = (struct TreeNode *) malloc(sizeof(struct TreeNode));
    // 只有一个节点
    if (head->next == NULL) {
        node->val = head->val;
        node->left = NULL;
        node->right = NULL;
        return node;
    }

    // 中偏右的中间节点
    struct ListNode *slow = head, *fast = head, *pre = NULL;
    while (fast != NULL && fast->next != NULL) {
        pre = slow;
        slow = slow->next;
        fast = fast->next->next;
    }
    // 断开链表,分成两部分
    pre->next = NULL;
    // slow为中间节点
    node->val = slow->val;
    // 递归处理两端链表,作为左右子树
    node->left = sortedListToBST(head);
    node->right = sortedListToBST(slow->next);
    return node;
}
// todo
struct ListNode *pre;

struct TreeNode *inorder(int left, int right) {
    if (left > right) return NULL;
    int mid = left + ((right - left) >> 1);
    struct TreeNode *node = (struct TreeNode *) malloc(sizeof(struct TreeNode));

    // 构建左子树
    struct TreeNode *leftNode = inorder(left, mid - 1);
    // 构建当前节点
    node->val = pre->val;
    pre = pre->next;
    // 构建右子树
    struct TreeNode *rightNode = inorder(mid + 1, right);
    // 左右子树接到当前节点
    node->left = leftNode;
    node->right = rightNode;

    return node;
}

struct TreeNode *sortedListToBST(struct ListNode *head) {
    // 空节点
    if (head == NULL) return NULL;
    struct TreeNode *node = (struct TreeNode *) malloc(sizeof(struct TreeNode));
    // 只有一个节点
    if (head->next == NULL) {
        node->val = head->val;
        node->left = NULL;
        node->right = NULL;
        return node;
    }
    // 计算链表长
    int len = 0;
    struct ListNode *temp = head;
    while (temp != NULL) {
        len++;
        temp = temp->next;
    }
    // 从头节点开始
    pre = head;
    return inorder(0, len - 1);
}

114. 二叉树展开为链表

// 保存左右子树到栈中,再修改左右指针
void flatten(struct TreeNode *root) {
    if (root == NULL) return;
    struct TreeNode *stack[2000];
    int top = 0;
    struct TreeNode *temp, *pre = NULL;
    stack[top++] = root;

    while (top != 0) {
        root = stack[--top];
        temp = root;
        // 先压右,后压左
        if (root->right != NULL) stack[top++] = root->right;
        if (root->left != NULL) stack[top++] = root->left;

        temp->left = NULL;
        if (pre != NULL) pre->right = temp;
        pre = temp;
    }
}
// todo
// 神似morris
void flatten(struct TreeNode *root) {
    while (root != NULL) {
        if (root->left != NULL) {
            struct TreeNode *rightMost = root->left;
            while (rightMost->right != NULL)
                rightMost = rightMost->right;
            // 把右子树接到左子树的最右边的节点上
            rightMost->right = root->right;
            // 把追加过的左子树移到右子树的位置
            // 下一步访问的其实还是左节点,保证了先序
            root->right = root->left;
            root->left = NULL;
        }
        root = root->right;
    }
}
struct TreeNode *pre;

// 先序序列倒过来访问的递归写法(后序遍历递归写法的改写)
void dfs(struct TreeNode *root) {
    if (root == nullptr) return;
    dfs(root->right);
    dfs(root->left);
    root->left = nullptr;
    root->right = pre;
    pre = root;
}

void flatten(struct TreeNode *root) {
    pre = nullptr;
    dfs(root);
}
// 先序序列倒过来访问的迭代写法(后序遍历迭代写法的改写)
void flatten(struct TreeNode *root) {
    if (root == NULL) return;
    struct TreeNode *stack[2000];
    int top = 0;
    struct TreeNode *pre = NULL;

    while (top != 0 || root != nullptr) {
        while (root != nullptr) {
            stack[top++] = root;
            root = root->right;
        }

        root = stack[--top];
        if (root->left != nullptr && pre != root->left) {
            // 左子树不空且未被访问过
            stack[top++] = root;
            root = root->left;
        } else {
            // 左子树已经访问,可以处理当前节点
            root->left = NULL;
            root->right = pre;
            pre = root;
            root = nullptr;
        }
    }
}
// 保存先序遍历的节点,再遍历一遍节点并同时修改

116. 填充每个节点的下一个右侧节点指针

struct Node *connect(struct Node *root) {
    if(root == NULL ) return root;
    const int size = 2049;
    struct Node *queue[size];
    int front = 0, rear = 0;
    queue[rear++] = root;
    struct Node *pre, *cur = root;

    // 层序遍历的时候修改next
    while (front != rear) {
        int count = (rear - front + size) % size;
        pre = NULL;
        while (count-- > 0) {
            cur = queue[(front++) % size];
            if (pre != NULL) pre->next = cur;
            pre = cur;
            if (cur->left != NULL) queue[(rear++) % size] = cur->left;
            if (cur->right != NULL) queue[(rear++) % size] = cur->right;
        }
        pre->next = NULL;
    }

    return root;
}
void dfs(struct Node *root) {
    if (root == NULL) return;
    struct Node *left = root->left;
    struct Node *right = root->right;
    // left从上往下沿着左子树的最右侧走
    // right从上往下沿着右子树的最左侧走
    while (left != NULL) {
        // left同一层的右边就是right
        left->next = right;
        left = left->right;
        right = right->left;
    }
    dfs(root->left);
    dfs(root->right);
}

struct Node *connect(struct Node *root) {
    dfs(root);
    return root;
}
// todo
struct Node *connect(struct Node *root) {
    // 利用已经初始化好的next指针
    if (root == NULL) return NULL;
    // 第k层最左节点
    struct Node *leftMost = root;
    root->next = NULL;

    // 一层一层往下,遍历当前层时处理下一层的next
    while (leftMost->left != NULL) {
        struct Node *cur = leftMost;
        // 更新到下一层的最左节点
        leftMost = leftMost->left;
        struct Node *pre = NULL;

        // 遍历第k层为第k+1层初始化next
        while (cur != NULL) {
            // 连接父节点的孩子
            cur->left->next = cur->right;
            // 连接相邻父节点的孩子
            if (pre != NULL) pre->right->next = cur->left;
            pre = cur;
            cur = cur->next;
        }
        pre->right->next = NULL;
    }
    return root;
}

382. 链表随机节点

// 空间换时间
typedef struct {
    int data[10001];
    int count;
} Solution;


Solution *solutionCreate(struct ListNode *head) {
    Solution *solution = (Solution *) malloc(sizeof(Solution));
    solution->count = 0;
    while (head != NULL) {
        solution->data[solution->count++] = head->val;
        head = head->next;
    }
    return solution;
}

int solutionGetRandom(Solution *obj) {
    int index = (rand() % obj->count);
    return obj->data[index];
}

void solutionFree(Solution *obj) {
    free(obj);
    obj = NULL;
}
typedef struct {
    struct ListNode *head;
} Solution;


Solution *solutionCreate(struct ListNode *head) {
    Solution *solution = (Solution *) malloc(sizeof(Solution));
    solution->head = head;
    return solution;
}

// 蓄水池采样
int solutionGetRandom(Solution *obj) {
    struct ListNode *cur = obj->head;
    int res = 10001;
    int count = 0;
    while (cur != NULL) {
        count++;
        if (res == 10001) res = cur->val;
        // count<=m时,直接放入池子
        // count>m时,以m/count的概率决定要不要放入池子,m为要从池子中选出的数字个数,此题为1
        if (rand() % count == 0) res = cur->val;
        cur = cur->next;
    }
    return res;
}

void solutionFree(Solution *obj) {
    free(obj);
    obj = NULL;
}

24. 两两交换链表中的节点

struct ListNode *swapPairs(struct ListNode *head) {
    if (head == NULL || head->next == NULL) return head;
    struct ListNode *newHead = (struct ListNode *) malloc(sizeof(struct ListNode));
    newHead->next = head;
    struct ListNode *pre = newHead, *right, *nextNode;

    while (pre->next != NULL && pre->next->next != NULL) {
        // 要交换的右边的这个节点
        right = pre->next->next;
        // 下一对要交换的两个节点的左节点
        nextNode = right->next;
        right->next = pre->next;
        pre->next = right;
        right->next->next = nextNode;
        // pre更新到下对节点的前一个节点
        pre = pre->next->next;
    }

    return newHead->next;
}
// 递归
struct ListNode *swapPairs(struct ListNode *head) {
    if (head == nullptr || head->next == nullptr) return head;
    struct ListNode *nextNode = head->next->next;
    struct ListNode *right = head->next;
    right->next = head;
    head->next = swapPairs(nextNode);
    return right;
}

2487. 从链表中移除节点

// 从右往左删
struct ListNode *removeNodes(struct ListNode *head) {
    if (head == NULL || head->next == NULL)return head;
    // 递归处理后续节点
    struct ListNode *nextNode = removeNodes(head->next);
    // 处理当前节点
    if (head->val < nextNode->val) return nextNode;
    head->next = nextNode;
    return head;
}
// 用栈模拟从右往左删
struct ListNode *removeNodes(struct ListNode *head) {
    int len = 0;
    struct ListNode *p = head;
    while (p != NULL) {
        len++;
        p = p->next;
    }
    struct ListNode *stack[len];
    int top = 0;
    p = head;
    // 链表全都压栈
    for (int i = 0; i < len; ++i) {
        stack[top++] = p;
        p = p->next;
    }

    // 出栈
    struct ListNode *pre = stack[--top];
    while (top > 0) {
        struct ListNode *node = stack[--top];
        if (node->val >= pre->val) {
            node->next = pre;
            pre = node;
        }
    }

    return pre;
}
struct ListNode *reverseList(struct ListNode *head) {
    struct ListNode *cur = head, *next, *pre = NULL;
    while (cur != NULL) {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}

// 转化成删除节点a左边有更大值节点b的节点(删的是a
struct ListNode *removeNodes(struct ListNode *head) {
    if (head->next == NULL)return head;

    // 先反转
    struct ListNode *newHead = reverseList(head);

    struct ListNode *cur = newHead->next, *pre = newHead;
    while (cur != NULL) {
        printf("%d ", cur->val);
        if (cur->val >= pre->val) {
            pre->next = cur;
            pre = cur;
        }
        cur = cur->next;
    }
    // 单独处理最后的
    pre->next = NULL;
    
    // 再反转
    return reverseList(newHead);
}

147. 对链表进行插入排序

struct ListNode *insertionSortList(struct ListNode *head) {
    if (head->next == NULL) return head;
    // 增加一个头节点
    struct ListNode *dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyHead->next = head;
    // 有序序列中最后一个
    struct ListNode *lastSorted = head;

    while (lastSorted->next != NULL) {
        // 需要调整位置的节点
        struct ListNode *cur = lastSorted->next;
        if (cur->val >= lastSorted->val) {
            lastSorted = lastSorted->next;
        } else {
            // 从头往后找插入位置
            struct ListNode *pre = dummyHead;
            while (pre->next->val <= cur->val) {
                pre = pre->next;
            }
            lastSorted->next = cur->next;
            cur->next = pre->next;
            pre->next = cur;
        }
    }
    return dummyHead->next;
}

117. 填充每个节点的下一个右侧节点指针 II

struct Node *connect(struct Node *root) {
    if(root == NULL ) return root;
    const int size = 2049;
    struct Node *queue[size];
    int front = 0, rear = 0;
    queue[rear++] = root;
    struct Node *pre, *cur = root;

    // 层序遍历的时候修改next
    while (front != rear) {
        int count = (rear - front + size) % size;
        pre = NULL;
        while (count-- > 0) {
            cur = queue[(front++) % size];
            if (pre != NULL) pre->next = cur;
            pre = cur;
            if (cur->left != NULL) queue[(rear++) % size] = cur->left;
            if (cur->right != NULL) queue[(rear++) % size] = cur->right;
        }
        pre->next = NULL;
    }

    return root;
}
// todo
// 利用已经初始化好的next指针
struct Node *connect(struct Node *root) {
    if (root == NULL) return NULL;
    // 第k层最左节点
    struct Node *leftMost = root;
    // 手动处理第一层
    root->next = NULL;

    // 一层一层往下,遍历当前k层时处理k+1层的next
    while (leftMost != NULL) {
        printf("leftMost=%d ", leftMost->val);
        // cur在k层
        struct Node *cur = leftMost;
        leftMost = NULL;
        // pre在k+1层
        struct Node *pre = NULL;

        while (cur != NULL) {
            // 更新leftMost
            if (leftMost == NULL) {
                if (cur->left != NULL)
                    leftMost = cur->left;
                else if (cur->right != NULL)
                    leftMost = cur->right;
            }

            // 遍历第k层为第k+1层初始化next
            if (cur->left != NULL && cur->right != NULL) {
                cur->left->next = cur->right;
                if (pre != NULL) pre->next = cur->left;
                pre = cur->right;
            } else if (cur->left == NULL && cur->right != NULL) {
                if (pre != NULL) pre->next = cur->right;
                pre = cur->right;
            } else if (cur->left != NULL && cur->right == NULL) {
                if (pre != NULL) pre->next = cur->left;
                pre = cur->left;
            }
            cur = cur->next;
        }
        // 最后一层时,pre是null
        if (pre != NULL) pre->next = NULL;
    }
    return root;
}
// 加了虚拟头节点,减少判断逻辑
// 利用已经初始化好的next指针
struct Node *connect(struct Node *root) {
    if (root == NULL) return NULL;
    struct Node *dummyHead = (struct Node *) malloc(sizeof(struct Node));
    // cur在k层
    struct Node *cur = root;

    // 一层一层往下,遍历当前k层时处理k+1层的next
    while (cur != NULL) {
        dummyHead->next = NULL;
        // pre在k+1层
        struct Node *pre = dummyHead;

        // 遍历第k层为第k+1层初始化next
        while (cur != NULL) {
            if (cur->left != NULL) {
                pre->next = cur->left;
                pre = pre->next;
            }
            if (cur->right != NULL) {
                pre->next = cur->right;
                pre = pre->next;
            }
            cur = cur->next;
        }
        cur = dummyHead->next;
    }
    return root;
}
// todo DFS

2326. 螺旋矩阵 IV

int **spiralMatrix(int m, int n, struct ListNode *head, int *returnSize, int **returnColumnSizes) {
    // 二级指针模板
    int **res = (int **) malloc(sizeof(int *) * m);
    *returnColumnSizes = (int *) malloc(sizeof(int) * m);
    *returnSize = m;
    for (int i = 0; i < m; ++i) {
        res[i] = (int *) malloc(sizeof(int) * n);
        (*returnColumnSizes)[i] = n;
    }
    // 初始化二维数组
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            res[i][j] = -1;
        }
    }

    struct ListNode *cur = head;
    int i = 0, j = 0;
    while (cur != NULL) {
        // 从左往右
        while (cur != NULL
               && j < n
               && res[i][j] == -1) {
            res[i][j++] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        j--;
        i++;

        // 从上往下
        while (cur != NULL
               && i < m
               && res[i][j] == -1) {
            res[i++][j] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        i--;
        j--;

        // 从右往左
        while (cur != NULL
               && j >= 0
               && res[i][j] == -1) {
            res[i][j--] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        j++;
        i--;

        // 从下往上
        while (cur != NULL
               && i >= 0
               && res[i][j] == -1) {
            res[i--][j] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        i++;
        j++;
    }

    return res;
}
int **spiralMatrix(int m, int n, struct ListNode *head, int *returnSize, int **returnColumnSizes) {
    int **res = (int **) malloc(sizeof(int *) * m);
    *returnColumnSizes = (int *) malloc(sizeof(int) * m);
    *returnSize = m;
    for (int i = 0; i < m; ++i) {
        res[i] = (int *) malloc(sizeof(int) * n);
        (*returnColumnSizes)[i] = n;
    }
    // 初始化二维数组
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            res[i][j] = -1;
        }
    }

    struct ListNode *cur = head;
    int i = 0, j = 0;
    while (cur != NULL) {
        // 从左往右
        while (cur != NULL
               && j < n
               && res[i][j] == -1) {
            res[i][j++] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        j--;
        i++;

        // 从上往下
        while (cur != NULL
               && i < m
               && res[i][j] == -1) {
            res[i++][j] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        i--;
        j--;

        // 从右往左
        while (cur != NULL
               && j >= 0
               && res[i][j] == -1) {
            res[i][j--] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        j++;
        i--;

        // 从下往上
        while (cur != NULL
               && i >= 0
               && res[i][j] == -1) {
            res[i--][j] = cur->val;
            printf("%d ", cur->val);
            cur = cur->next;
        }
        i++;
        j++;
    }

    return res;
}
// todo 有其他做法

138. 随机链表的复制

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

    // 遍历原链表,在每个节点后面插入新节点
    while (pre != NULL) {
        struct Node *node = (struct Node *) malloc(sizeof(struct Node));
        node->val = pre->val;
        // 接在原节点的后面
        node->next = pre->next;
        pre->next = node;
        pre = pre->next->next;
    }

    pre = head;
    while (pre != NULL) {
        // 修改random指针
        if (pre->random != NULL)
            pre->next->random = pre->random->next;
        else
            pre->next->random = NULL;
        pre = pre->next->next;
    }

    pre = head;
    struct Node *res = head->next, *cur = head->next;
    while (cur != NULL && cur->next != NULL) {
        // 改回原链表节点的next指针
        pre->next = pre->next->next;
        pre = pre->next;
        // 新链表的节点从原链表中分离出来,串在一起
        cur->next = cur->next->next;
        cur = cur->next;
    }
    // 原链表尾节点的next指针
    pre->next = NULL;
    return res;
}

143. 重排链表

struct ListNode *findMid(struct ListNode *root) {
    if (root->next == NULL) return NULL;
    struct ListNode *slow = root, *fast = root;
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

struct ListNode *reverseList(struct ListNode *root) {
    struct ListNode *cur = root, *pre = NULL, *next;
    while (cur != NULL) {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}

void reorderList(struct ListNode *head) {
    if (head->next == NULL) return;
    struct ListNode *mid = findMid(head);
    struct ListNode *l1 = head;
    struct ListNode *l2 = reverseList(mid);

    while (l1->next != mid) {
        struct ListNode *temp = l2->next;
        l2->next = l1->next;
        l1->next = l2;
        l1 = l1->next->next;
        l2 = temp;
    }
    l1->next = l2;
}

148. 排序链表

// 返回中偏左
struct ListNode *findMid(struct ListNode *head) {
    if (head == NULL && head->next == NULL) return head;
    struct ListNode *slow = head, *fast = head->next;
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

// 归并
struct ListNode *merge(struct ListNode *l1, struct ListNode *l2) {
    if (l1 == NULL || l2 == NULL) return l1 == NULL ? l2 : l1;
    struct ListNode *dummyHead = (struct ListNode *) malloc(sizeof(struct ListNode));
    struct ListNode *pre = dummyHead;
    while (l1 != NULL && l2 != NULL) {
        if (l1->val < l2->val) {
            pre->next = l1;
            l1 = l1->next;
        } else {
            pre->next = l2;
            l2 = l2->next;
        }
        pre = pre->next;
    }

    if (l1 != NULL) pre->next = l1;
    if (l2 != NULL) pre->next = l2;
    return dummyHead->next;
}

// 拆分成两个链表,进行归并排序
struct ListNode *divide(struct ListNode *head) {
    if (head == NULL || head->next == NULL) return head;
    struct ListNode *mid = findMid(head);
    struct ListNode *right = mid->next;
    mid->next = NULL;
    struct ListNode *l1 = divide(head);
    struct ListNode *l2 = divide(right);
    return merge(l1, l2);
}

struct ListNode *sortList(struct ListNode *head) {
    return divide(head);
}
// todo
// 归并
struct ListNode *merge(struct ListNode *l1, struct ListNode *l2) {
    if (l1 == NULL || l2 == NULL) return l1 == NULL ? l2 : l1;
    struct ListNode *dummyHead = (struct ListNode *) malloc(sizeof(struct ListNode));
    struct ListNode *pre = dummyHead;
    while (l1 != NULL && l2 != NULL) {
        if (l1->val < l2->val) {
            pre->next = l1;
            l1 = l1->next;
        } else {
            pre->next = l2;
            l2 = l2->next;
        }
        pre = pre->next;
    }

    if (l1 != NULL) pre->next = l1;
    if (l2 != NULL) pre->next = l2;
    return dummyHead->next;
}

// 归并排序(迭代)
struct ListNode *sortList(struct ListNode *head) {
    // 统计链表长
    int len = 0;
    struct ListNode *temp = head;
    while (temp != NULL) {
        len++;
        temp = temp->next;
    }

    struct ListNode *dummyHead = (struct ListNode *) malloc(sizeof(struct ListNode));
    dummyHead->next = head;

    // 步长每次乘二
    for (int gap = 1; gap < len; gap <<= 1) {
        struct ListNode *pre = dummyHead;
        struct ListNode *cur = dummyHead->next;

        // 每次从一组元素的首个元素节点开始(两个子链表为一组)
        while (cur != NULL) {
            // 长度为gap的子链表l1
            struct ListNode *l1 = cur;
            int i = 1;
            while (i < gap && cur->next != NULL) {
                cur = cur->next;
                i++;
            }

            // 子链表l2
            struct ListNode *l2 = cur->next;
            // 把l2从l1后面断开
            cur->next = NULL;

            // 找到子链表l2的末尾,l2可能是最后一个子链表并且长度小于等于gap
            // l2后面可能还有
            cur = l2;
            i = 1;
            while (i < gap && cur != NULL && cur->next != NULL) {
                cur = cur->next;
                i++;
            }


            struct ListNode *next = NULL;
            // l2后面还有节点时
            if (cur != NULL) {
                // 下一组的起点(两个子链表为一组)
                next = cur->next;
                // 断开,l2变成完成的一条链表
                cur->next = NULL;
            }

            // 把这组的两个子链表合并
            pre->next = merge(l1, l2);
            // pre移到合并后的最后一个节点,等待接上下一组合并后的首个节点
            while (pre->next != NULL) {
                pre = pre->next;
            }
            // 进入下一组的归并
            cur = next;
        }
    }

    return dummyHead->next;
}

LCR 155. 将二叉搜索树转化为排序的双向链表

class Solution {
public:
    Node *res = nullptr;
    Node *pre = nullptr;

    void inorder(Node *root) {
        if (root == nullptr)return;
        inorder(root->left);
        if (pre == nullptr) {
            res = root;
        } else {
            pre->right = root;
            root->left = pre;
        }
        pre = root;
        inorder(root->right);
    }

    // 中序线索化,区别只有头尾节点的处理不同
    Node *treeToDoublyList(Node *root) {
        if (root == nullptr) return nullptr;
        inorder(root);
        pre->right = res;
        res->left = pre;
        return res;
    }
};

328. 奇偶链表

// todo
struct ListNode *oddEvenList(struct ListNode *head) {
    if (head == NULL) return head;
    struct ListNode *headOfEven = head->next;
    struct ListNode *odd = head;
    struct ListNode *even = head->next;
    while (even != NULL && even->next != NULL) {
        // 连接奇数节点
        odd->next = even->next;
        odd = odd->next;
        // 连接偶数节点
        even->next = odd->next;
        even = even->next;
    }
    // 最后一个奇数节点连接偶数的头节点
    odd->next = headOfEven;
    return head;
}

1019. 链表中的下一个更大节点

int *nextLargerNodes(struct ListNode *head, int *returnSize) {
    int len = 0;
    // 遍历获取链表长度
    struct ListNode *cur = head;
    while (cur != nullptr) {
        len++;
        cur = cur->next;
    }
    *returnSize = len;
    int *res = (int *) calloc(len, sizeof(int));

    // 把链表转成数组
    int list[len];
    cur = head;
    for (int i = 0; i < len; ++i) {
        list[i] = cur->val;
        cur = cur->next;
    }

    // 单调递增栈(从栈顶到栈底递增),栈中存放的是元素在temp数组中的下标
    int stack[len];
    int top = 0;
    for (int pos = 0; pos < len; ++pos) {
        if (top == 0) {
            // 栈空直接入栈
            stack[top++] = pos;
        } else {
            // 比栈顶小,直接入栈;比栈顶大,先把比当前元素小的出栈,再入栈
            while (top > 0 && list[pos] > list[stack[top - 1]]) {
                // 当前的元素list[pos]就是第一个比list[stack[top-1]]大的元素,在res中记录下当前元素
                res[stack[top - 1]] = list[pos];
                top--;
            }
            stack[top++] = pos;
        }
    }

    return res;
}

86. 分隔链表

// 需要保留相对位置
// 分到两个链表上,再合起来
struct ListNode *partition(struct ListNode *head, int x) {
    if (head == NULL || head->next == NULL) return head;
    struct ListNode *l1 = (struct ListNode *) malloc(sizeof(struct ListNode));
    l1->next = NULL;
    struct ListNode *pre1 = l1;
    struct ListNode *l2 = (struct ListNode *) malloc(sizeof(struct ListNode));
    l2->next = NULL;
    struct ListNode *pre2 = l2;

    struct ListNode *cur = head;
    while (cur != NULL) {
        if (cur->val < x) {
            pre1->next = cur;
            pre1 = pre1->next;
        } else {
            pre2->next = cur;
            pre2 = pre2->next;
        }
        cur = cur->next;
    }
    pre1->next = l2->next;
    pre2->next = NULL;
    return l1->next;
}

1721. 交换链表中的节点

struct ListNode *swapNodes(struct ListNode *head, int k) {
    struct ListNode *slow = head, *fast = head;
    struct ListNode *node1, *node2;

    // 正数第k个
    for (int i = 1; i < k; ++i)
        fast = fast->next;
    node1 = fast;
    // 倒数第k个
    while (fast->next != NULL) {
        slow = slow->next;
        fast = fast->next;
    }
    node2 = slow;

    // 交换
    int temp = node1->val;
    node1->val = node2->val;
    node2->val = temp;
    return head;
}

1472. 设计浏览器历史记录


struct MyListNode {
    char *val;
    struct MyListNode *next;
    struct MyListNode *pre;
};

typedef struct {
    struct MyListNode *head;
    struct MyListNode *cur;
} BrowserHistory;


BrowserHistory *browserHistoryCreate(char *homepage) {
    BrowserHistory *obj = (BrowserHistory *) malloc(sizeof(BrowserHistory));
    // 头节点
    obj->head = (struct MyListNode *) malloc(sizeof(struct MyListNode));
    obj->head->pre = NULL;
    obj->head->val = NULL;
    // homepage节点
    struct MyListNode *node = (struct MyListNode *) malloc(sizeof(struct MyListNode));
    node->val = homepage;
    node->next = NULL;
    node->pre = obj->head;
    obj->head->next = node;
    obj->cur = node;
    return obj;
}


// 接到双向链表表尾
void browserHistoryVisit(BrowserHistory *obj, char *url) {
    struct MyListNode *node = (struct MyListNode *) malloc(sizeof(struct MyListNode));
    node->val = url;
    node->next = NULL;
    node->pre = obj->cur;
    obj->cur->next = node;
    obj->cur = node;
}

char *browserHistoryBack(BrowserHistory *obj, int steps) {
    while (steps > 0 && obj->cur->pre != obj->head) {
        steps--;
        obj->cur = obj->cur->pre;
    }
    return obj->cur->val;
}

char *browserHistoryForward(BrowserHistory *obj, int steps) {
    while (steps > 0 && obj->cur->next != NULL) {
        steps--;
        obj->cur = obj->cur->next;
    }
    return obj->cur->val;
}

void browserHistoryFree(BrowserHistory *obj) {
    free(obj);
    obj = NULL;
}
struct MyListNode {
    char *val;
    struct MyListNode *next;
};

typedef struct {
    struct MyListNode *head;
    struct MyListNode *cur;
} BrowserHistory;

BrowserHistory *browserHistoryCreate(char *homepage) {
    BrowserHistory *obj = (BrowserHistory *) malloc(sizeof(BrowserHistory));
    // 头节点
    obj->head = (struct MyListNode *) malloc(sizeof(struct MyListNode));
    obj->head->val = NULL;
    // homepage节点
    struct MyListNode *node = (struct MyListNode *) malloc(sizeof(struct MyListNode));
    node->val = homepage;
    node->next = NULL;
    obj->head->next = node;
    obj->cur = node;
    return obj;
}

// 接到链表表尾
void browserHistoryVisit(BrowserHistory *obj, char *url) {
    struct MyListNode *node = (struct MyListNode *) malloc(sizeof(struct MyListNode));
    node->val = url;
    node->next = NULL;
    obj->cur->next = node;
    obj->cur = node;
}

// 单链表,快慢指针定位
char *browserHistoryBack(BrowserHistory *obj, int steps) {
    struct MyListNode *slow = obj->head->next, *fast = obj->head->next;
    while (steps > 0 && fast != obj->cur) {
        fast = fast->next;
        steps--;
    }
    while (fast->next != NULL && fast != obj->cur) {
        slow = slow->next;
        fast = fast->next;
    }
    obj->cur = slow;
    return slow->val;
}

char *browserHistoryForward(BrowserHistory *obj, int steps) {
    while (steps > 0 && obj->cur->next != NULL) {
        steps--;
        obj->cur = obj->cur->next;
    }
    return obj->cur->val;
}

void browserHistoryFree(BrowserHistory *obj) {
    free(obj);
    obj = NULL;
}
typedef struct {
    char **stack;
    // 栈中元素个数
    int size;
    int top;
} BrowserHistory;


BrowserHistory *browserHistoryCreate(char *homepage) {
    BrowserHistory *obj = (BrowserHistory *) malloc(sizeof(BrowserHistory));
    obj->stack = (char **) malloc(sizeof(char *) * 5001);
    obj->size = 1;
    obj->top = 0;
    obj->stack[0] = homepage;
    return obj;
}

void browserHistoryVisit(BrowserHistory *obj, char *url) {
    obj->stack[++obj->top] = url;
    obj->size = obj->top + 1;
}

char *browserHistoryBack(BrowserHistory *obj, int steps) {
    int index = obj->top - steps;
    if (index >= 0) {
        // index没超下界,就更新top
        obj->top = index;
    } else {
        obj->top = 0;
    }
    return obj->stack[obj->top];
}

char *browserHistoryForward(BrowserHistory *obj, int steps) {
    int index = obj->top + steps;
    // index没超上界,就更新top
    if (index < obj->size)
        obj->top = index;
    else
        obj->top = obj->size - 1;
    return obj->stack[obj->top];
}

void browserHistoryFree(BrowserHistory *obj) {
    free(obj);
    obj = NULL;
}

817. 链表组件

int numComponents(struct ListNode *head, int *nums, int numsSize) {
    int len = 0;
    struct ListNode *cur = head;
    while (cur != NULL) {
        len++;
        cur = cur->next;
    }
    // 初始化哈希表
    int *hash = (int *) calloc(len + 1, sizeof(int));
    for (int i = 0; i < numsSize; ++i)
        hash[nums[i]] = 1;

    int res = 0;
    bool flag = false;
    cur = head;
    while (cur != NULL) {
        // 每个组件的末尾为分界点:当前节点在nums中,但下个节点为空或者不在nums中
        if (hash[cur->val] == 1 && (cur->next == NULL || hash[cur->next->val] == 0)) res++;
        cur = cur->next;
    }
    return res;
}

445. 两数相加 II

struct ListNode *reverseList(struct ListNode *head) {
    struct ListNode *pre = NULL, *next, *cur = head;
    while (cur != NULL) {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}

// 先反转两个链表,再从低位往高位计算,记录进位
struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) {
    struct ListNode *n1 = reverseList(l1);
    struct ListNode *n2 = reverseList(l2);
    struct ListNode *dummyHead = (struct ListNode *) malloc(sizeof(struct ListNode));
    dummyHead->next = NULL;
    struct ListNode *pre = dummyHead;

    // 进位
    int carry = 0;
    while (n1 != NULL && n2 != NULL) {
        struct ListNode *node = (struct ListNode *) malloc(sizeof(struct ListNode));
        node->next = NULL;
        // 计算
        node->val = (n1->val + n2->val + carry) % 10;
        carry = (n1->val + n2->val + carry) / 10;
        // 拼接
        pre->next = node;
        pre = pre->next;
        n1 = n1->next;
        n2 = n2->next;
    }
    while (n1 != NULL) {
        struct ListNode *node = (struct ListNode *) malloc(sizeof(struct ListNode));
        node->next = NULL;
        node->val = (n1->val + carry) % 10;
        carry = (n1->val + carry) / 10;
        pre->next = node;
        pre = pre->next;
        n1 = n1->next;
    }
    while (n2 != NULL) {
        struct ListNode *node = (struct ListNode *) malloc(sizeof(struct ListNode));
        node->next = NULL;
        node->val = (n2->val + carry) % 10;
        carry = (n2->val + carry) / 10;
        pre->next = node;
        pre = pre->next;
        n2 = n2->next;
    }
    // 进位可能导致最后多出一位
    if (carry == 1) {
        struct ListNode *node = (struct ListNode *) malloc(sizeof(struct ListNode));
        node->next = NULL;
        node->val = 1;
        pre->next = node;
    }
    return reverseList(dummyHead->next);
}

725. 分隔链表

struct ListNode **splitListToParts(struct ListNode *head, int k, int *returnSize) {
    struct ListNode **res = (struct ListNode **) malloc(sizeof(struct ListNode *) * k);
    *returnSize = k;

    // 统计长度
    struct ListNode *cur = head;
    int len = 0;
    while (cur != NULL) {
        len++;
        cur = cur->next;
    }
    // 置空
    for (int i = 0; i < k; ++i) res[i] = NULL;

    // 每组的最少元素个数
    int base = len / k;
    // 前i组的元素数要加一
    int i = len - base * k;

    cur = head;
    int index = 0;
    while (cur != NULL) {
        res[index++] = cur;
        int size = base;
        // 前i组的元素数要加一
        if (i-- > 0) size++;
        while (--size > 0) {
            cur = cur->next;
        }
        // 记录下一组的首节点
        struct ListNode *temp = cur->next;
        // 断开
        cur->next = NULL;
        cur = temp;
    }
    return res;
}

1670. 设计前中后队列

// todo 带头尾节点的循环双链表
// 分成左右两个链表

面试题 02.04. 分割链表

// 不保留相对位置
struct ListNode *partition(struct ListNode *head, int x) {
    struct ListNode *dummyHead = (struct ListNode *) malloc(sizeof(struct ListNode));
    dummyHead->next = head;
    struct ListNode *cur = head;
    struct ListNode *pre = dummyHead;

    while (cur != NULL) {
        struct ListNode *next = cur->next;
        if (cur->val < x) {
            // 小于x时把大的元素头插到链表前面
            pre->next = next;
            // 头插法
            cur->next = dummyHead->next;
            dummyHead->next = cur;
            // 避免全都小于x时,dummyHead和pre始终重合
            if (pre == dummyHead) pre = pre->next;
        } else {
            // 大于x时直接后移
            pre = cur;
        }
        cur = next;
    }

    return dummyHead->next;
}
posted @ 2024-01-07 02:48  n1ce2cv  阅读(20)  评论(0编辑  收藏  举报