版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
单链表翻转:
采用就地逆置, 定义三个指针变量, 一个标记现在跟在head后的节点, 一个记录现在要移动的节点, 一个记录现在要移动的节点之后的节点。
struct ListNode* reverseList(struct ListNode* head){
struct ListNode *p, *q, *r;
p = q = r = (struct ListNode *)malloc(sizeof(struct ListNode));
if (head == NULL){
return head;
}
if (head->next == NULL) {
return head;
}
p = head;
q = p->next;
r = q->next;
p->next = NULL;
while(1) {
q->next = p;
head = q;
if (r == NULL) {
break;
}
p = q;
q = r;
r = r->next;
}
return head;
}
判断循环链表:
定义两个指针,快慢指针, 快的一次走两个, 慢的一次走一个, 如果他们可以相遇, 说明是循环链表, 如果快指针走到了结尾, 则不是循环链表
bool hasCycle(struct ListNode *head) {
struct ListNode *pfast, *pslow;
pfast = pslow = (struct ListNode *)malloc(sizeof(struct ListNode));
if ((head == NULL) || (head->next == NULL)){
printf("false");
return 0;
}
pfast = head->next;
pslow = head;
while (1) {
if (pfast->next == NULL) {
printf("false");
return 0;
}
if (pfast->next->next == NULL) {
printf("false");
return 0;
}
pfast = pfast->next->next;
pslow = pslow->next;
if (pslow == pfast) {
printf("ture");
return 1;
}
}
}
删除倒数第n个节点
使用两次遍历, 方法显而易见,但如果使用一次遍历, 方法是定义两个指针, 第一个指针先向前走n个, 此时第二个指针开始走, 这样当第一个指针走到结尾时, 第二个指针走到倒数第n个节点位置。
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode *ptemp1, *ptemp2, *ppre;
int i;
ppre = ptemp1 = ptemp2 = (struct ListNode*)malloc(sizeof(struct ListNode));
ptemp1 = head;
ptemp2 = head;
for (i = 1; i < n; i++) {
if (ptemp1->next == NULL) {
return 0;
}
ptemp1 = ptemp1->next;
}
if (ptemp1->next == NULL) {
head = head->next;
return head;
}
while(ptemp1->next != NULL) {
ptemp1 = ptemp1->next;
ppre = ptemp2;
ptemp2 = ptemp2->next;
}
ppre->next = ptemp2->next;
return head;
}
单链表找中间节点
定义两个快慢指针, 比如只有三个节点, 快指针指向第三个, 慢指针指向第一个节点, 判断快的下一个是否为空, 此时为空, 让慢指针下一个为头指针, 输出该链表。
struct ListNode* middleNode(struct ListNode* head){
struct ListNode *pfast, *pslow;
int i;
if (head->next == NULL) {
return head;
}
if (head->next->next == NULL) {
return head->next;
}
pfast = pslow = (struct ListNode*)malloc(sizeof(struct ListNode));
pfast = head->next->next;
pslow = head;
for (i = 1; ; i++){
if (pfast->next == NULL) {
head = pslow->next;
return head;
}
if ((pfast->next != NULL) && (pfast->next->next == NULL)) {
head = pslow->next->next;
return head;
}
pfast = pfast->next->next;
pslow = pslow->next;
}
}
两条链表的合并
我的思路是,先寻找以那条链作为主链,比如1,2,3和2,3,4通过比较第一个我觉定以第一条作为主链,把第二条插到第一条,ptemp标记第二条目前要插入的元素,ppre标记第一条链的元素,如果是1表示插到1后
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
struct ListNode *ppre, *plater, *ptemp;
int flag = 0;
if (l1 == NULL) {
return l2;
}
if (l2 == NULL) {
return l1;
}
ppre = plater = ptemp = (struct ListNode *)malloc(sizeof(struct ListNode));
if (l1->val < l2->val) {
ppre = l1;
ptemp = l2;
while (1) {
if (ppre->next == NULL) {
ppre->next = ptemp;
return l1;
} else {
while ((ppre->next != NULL) && (ppre->next->val < ptemp->val)) {
ppre = ppre->next;
}
if (ppre->next == NULL) {
ppre->next = ptemp;
return l1;
} else {
if (ptemp->next == NULL) {
ptemp->next = ppre->next;
ppre->next = ptemp;
return l1;
} else {
plater = ptemp->next;
ptemp->next = ppre->next;
ppre->next = ptemp;
ppre = ptemp;
ptemp = plater;
}
}
}
}
} else {
ppre = l2;
ptemp = l1;
while (1) {
if (ppre->next == NULL) {
ppre->next = ptemp;
return l2;
} else {
while ((ppre->next != NULL) && (ppre->next->val < ptemp->val)) {
ppre = ppre->next;
}
if (ppre->next == NULL) {
ppre->next = ptemp;
return l2;
} else {
if (ptemp->next == NULL) {
ptemp->next = ppre->next;
ppre->next = ptemp;
return l2;
} else {
plater = ptemp->next;
ptemp->next = ppre->next;
ppre->next = ptemp;
ppre = ptemp;
ptemp = plater;
}
}
}
}
}
}
这些都是我在力扣上提交的代码