目录
1、反转链表的描述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0\leq n\leq10000≤n≤1000
要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ /** * * @param pHead ListNode类 * @return ListNode类 */ struct ListNode* ReverseList(struct ListNode* pHead ) { // write code here if (NULL == pHead) return pHead; //两个指针移动的应用(经典) #if 0 //定义两个结构体指针进行偏移 struct ListNode* p = pHead; struct ListNode* q = NULL; //定义一个新的链表结构体指针 struct ListNode* pre = NULL; //头结点带数据 while (p) { q = p->next;//必须为 p,因为两个指针都需要移动 p->next = pre;//断掉p,q两个结点连接 pre = p;//新的链表指针发挥作用,由于 p 要移动,所以需要保存 p 的指向的内容 p = q;//p开始向下移动(根据q方向的路线移动,画图体会最佳) } return pre; #endif #if 0 //同上,栈区不断开辟和释放 结构体指针,不建议 struct ListNode* fast = pHead, *slow = NULL; while (fast) { struct ListNode* t = fast->next; fast->next = slow; slow = fast; fast = t; } return slow; #endif #if 1 //堆区不断开辟新节点的头插法,弄懂临时变量很重要很重要(p=q;) struct ListNode *p = (struct ListNode*)malloc(sizeof(struct ListNode)); if(NULL==p){ perror("old_malloc"); return NULL; } p->val = pHead->val; p->next = NULL; pHead = pHead->next; while(pHead){ struct ListNode *q = (struct ListNode*)malloc(sizeof(struct ListNode)); if(NULL==q){ perror("new_malloc"); free(p); p = NULL; return NULL; } q->val = pHead->val; q->next = p; p = q; pHead = pHead->next; } return p; #endif }
2、合并两个排序的链表描述
输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
数据范围: 0 \le n \le 10000≤n≤1000,-1000 \le 节点值 \le 1000−1000≤节点值≤1000
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6},转换过程如下图所示:
或输入{-1,2,4},{1,3,4}时,合并后的链表为{-1,1,2,3,4,4},所以对应的输出为{-1,1,2,3,4,4},转换过程如下图所示:
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ /** * * @param pHead1 ListNode类 * @param pHead2 ListNode类 * @return ListNode类 */ struct ListNode* Merge(struct ListNode* pHead1, struct ListNode* pHead2 ) { // write code here if (NULL == pHead1 && NULL == pHead2) return NULL; if (NULL == pHead1 && NULL != pHead2) return pHead2; if (NULL != pHead1 && NULL == pHead2) return pHead1; #if 1 struct ListNode* head_new = (struct ListNode*)malloc(sizeof(struct ListNode)),*p1; p1 = head_new; while (pHead1 != NULL && pHead2 != NULL) { if (pHead1->val <= pHead2->val) { p1->next = pHead1; p1 = p1->next; pHead1 = pHead1->next; } else { p1->next = pHead2; p1 = p1->next; pHead2 = pHead2->next; } } //等价三目运算符 if (pHead1 == NULL) { p1->next = pHead2; } else { p1->next = pHead1; } return head_new->next; #endif #if 0 //无法实现,因为q(p)=temp时会导致两个头,即-2,-1都指向1 //【-2| 】-》【1| 】-》【2| 】-》【3| 】 // | // p,q(new) //【-1| 】-》【4| 】-》【5| 】-》【6| 】 // | // q(old),temp //可看上面那段代码 struct ListNode* temp = NULL; struct ListNode* p = pHead1; struct ListNode* q = pHead2; int flag = 0; if (p->val <= q->val) flag = 0; else flag = 1; while (p) { if (p->val <= q->val) { temp = p->next; p->next = q; p = temp; } else { temp = q->next; q->next = p; q = temp; } } if (flag == 0) return pHead1; else return pHead2; #endif #if 0 struct ListNode* p = pHead1; struct ListNode* q = pHead2; struct ListNode* res = (struct ListNode*)malloc(sizeof(struct ListNode)); struct ListNode* new = res; if (NULL == res) { perror("res_malloc"); return NULL; } while (NULL != p && NULL != q) { struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode)); if (NULL == node) { perror("node_malloc"); return NULL; } if (p->val >= q->val) { node->val = q->val; q = q->next; } else { node->val = p->val; p = p->next; } res->next = node; res = res->next; } res->next = (p == NULL) ? q : p; // 当其中一个循环完毕后,将另一个直接赋值过去,另外链表判空也可省略 return new; #endif }