链表中等题(上)
// 辗转相除
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;
}
void deleteNode(struct ListNode *node) {
// 替死鬼
node->val = node->next->val;
node->next = node->next->next;
}
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;
}
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;
}
// 中偏右的中点
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;
}
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;
}
// 递归生成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);
}
// 保存左右子树到栈中,再修改左右指针
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;
}
}
}
// 保存先序遍历的节点,再遍历一遍节点并同时修改
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;
}
// 空间换时间
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;
}
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;
}
// 从右往左删
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);
}
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;
}
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
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 有其他做法
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;
}
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;
}
// 返回中偏左
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;
}
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;
}
};
// 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;
}
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;
}
// 需要保留相对位置
// 分到两个链表上,再合起来
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;
}
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;
}
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;
}
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;
}
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);
}
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;
}
// todo 带头尾节点的循环双链表
// 分成左右两个链表
// 不保留相对位置
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;
}