链表简单题
void deleteNode(struct ListNode *node) {
// 转换成删除下一个节点
node->val = node->next->val;
node->next = node->next->next;
}
int getDecimalValue(struct ListNode *head) {
struct ListNode *cur = head;
int res = 0;
while (cur != NULL) {
res <<= 1;
res += cur->val;
cur = cur->next;
}
return res;
}
int kthToLast(struct ListNode *head, int k) {
struct ListNode *fast = head;
struct ListNode *slow = head;
// 快指针先走k步
while (k > 0) {
fast = fast->next;
k--;
}
// 快慢指针同时走
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
return slow->val;
}
// 迭代
struct ListNode *reverseList(struct ListNode *head) {
struct ListNode *pre = NULL;
struct ListNode *next;
struct ListNode *cur = head;
// 原地反转
while (cur != NULL) {
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
// 递归
struct ListNode *reverseList(struct ListNode *head) {
// 递归出口
if (head == NULL || head->next == NULL) return head;
// 递归式
struct ListNode *newHead = reverseList(head->next); // 递归反转后面的链表
head->next->next = head; // 下个结点也就是反转后的尾节点,指向自己
head->next = NULL; // 自己作为新的尾节点
return newHead;
}
// 返回向上取整的中间节点
struct ListNode *middleNode(struct ListNode *head) {
struct ListNode *fast = head;
struct ListNode *slow = head;
// 慢指针每走一步,快指针走两步
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
// 返回两个单链表相交的起始节点
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int len1 = 0, len2 = 0;
struct ListNode *p = headA, *q = headB;
// 求长度
while (p != NULL) {
len1++;
p = p->next;
}
while (q != NULL) {
len2++;
q = q->next;
}
// 长链表先走
p = headA;
q = headB;
if (len1 > len2)
for (int i = 0; i < len1 ### len2; ++i)
p = p->next;
else
for (int i = 0; i < len2 ### len1; ++i)
q = q->next;
// p、q距离尾节点距离相同时,同时出发
while (p != NULL) {
if (p == q)return p;
p = p->next;
q = q->next;
}
return NULL;
}
// 散列
struct ListNode *removeDuplicateNodes(struct ListNode *head) {
if (head == NULL || head->next == NULL) return head; // 特殊情况单独处理
int hash[20001]; // 记录是否出现过
memset(hash, 0, sizeof(hash));
struct ListNode *p = head;
hash[head->val] = 1;
// 判断当前下个节点是否需要删除
while (p != NULL && p->next != NULL) {
if (hash[p->next->val] == 0) {
// 首次出现
hash[p->next->val] = 1;
// 指针后移
p = p->next;
} else {
// 删除已经出现过
p->next = p->next->next;
// 指针无需后移
}
}
return head;
}
// 不使用散列
// 删除链表中所有值为k的节点
struct ListNode *removeNode(struct ListNode *head, int k) {
struct ListNode *headNode = (struct ListNode *) malloc(sizeof(struct ListNode));
headNode->next = head;
struct ListNode *p = headNode;
while (p != NULL && p->next != NULL) {
if (p->next->val == k) {
// 跳过节点
p->next = p->next->next;
// 指针无需后移
} else {
// 指针后移
p = p->next;
}
}
return headNode->next;
}
struct ListNode *removeDuplicateNodes(struct ListNode *head) {
if (head == NULL || head->next == NULL) return head; // 特殊情况单独处理
struct ListNode *cur = head;
while (cur != NULL && cur->next != NULL) {
// 删除后续链表中和当前值相同的所有节点
cur->next = removeNode(cur->next, cur->val);
cur = cur->next;
}
return head;
}
// 合并升序链表(迭代)
struct ListNode *mergeTwoLists(struct ListNode *list1, struct ListNode *list2) {
struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode));
head->next = NULL; // 写完成,不然if (list1 != NULL)会报错
struct ListNode *p = head;
// 从两个链表中反复选出较小者
while (list1 != NULL && list2 != NULL) {
if (list1->val < list2->val) {
p->next = list1;
list1 = list1->next;
} else {
p->next = list2;
list2 = list2->next;
}
p = p->next;
}
// 把剩余的链表直接接上
if (list1 != NULL) p->next = list1;
if (list2 != NULL) p->next = list2;
return head->next;
}
// 递归
struct ListNode *mergeTwoLists(struct ListNode *list1, struct ListNode *list2) {
// 递归出口
if (list1 == NULL) return list2;
if (list2 == NULL) return list1;
// 递归体
if (list1->val < list2->val) {
list1->next = mergeTwoLists(list1->next, list2);
return list1;
} else {
list2->next = mergeTwoLists(list1, list2->next);
return list2;
}
}
// 返回向上取整的中间节点
struct ListNode *findMid(struct ListNode *head) {
struct ListNode *slow = head;
struct ListNode *fast = head;
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
// 原地反转
struct ListNode *reverseList(struct ListNode *head) {
struct ListNode *pre = NULL;
struct ListNode *cur = head;
struct ListNode *next;
while (cur != NULL) {
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
bool isPalindrome(struct ListNode *head) {
struct ListNode *mid = findMid(head);
mid = reverseList(mid);
struct ListNode *p = head;
struct ListNode *q = mid;
while (q != NULL) {
if (p->val != q->val) return false;
p = p->next;
q = q->next;
}
return true;
}
// 删除链表中所有值为k的节点
struct ListNode *removeElements(struct ListNode *head, int val) {
struct ListNode *headNode = (struct ListNode *) malloc(sizeof(struct ListNode));
headNode->next = head;
struct ListNode *p = headNode;
while (p != NULL && p->next != NULL) {
if (p->next->val == val) {
// 跳过节点
p->next = p->next->next;
// 指针无需后移
} else {
// 指针后移
p = p->next;
}
}
return headNode->next;
}
struct ListNode *deleteDuplicates(struct ListNode *head) {
if (head == NULL || head->next == NULL) return head;
struct ListNode *dummyHead = (struct ListNode *) malloc(sizeof(struct ListNode));
dummyHead->next = head;
struct ListNode *cur = head;
while (cur != NULL) {
while (cur->next != NULL && cur->val == cur->next->val) {
// 跳过重复节点
cur->next = cur->next->next;
}
cur = cur->next;
}
return dummyHead->next;
}
bool hasCycle(struct ListNode *head) {
if (head == NULL || head->next == NULL) return false;
struct ListNode *slow = head;
struct ListNode *fast = head->next;
// 快慢指针,若有环,快指针迟早会追过慢指针(多跑了一个环的距离)
while (fast != NULL && fast->next != NULL) {
if (slow == fast)return true;
slow = slow->next;
fast = fast->next->next;
}
return false;
}