《慕课网玩转算法面试》笔记及习题解答5.1.~5.3
来源:互联网 发布:c语言标准库函数 手册 编辑:程序博客网 时间:2024/06/05 09:29
链表问题
处理链表的问题,我们通常可以多设立指针来保存信息
LeetCode 206 翻转链表
思路:使用三个指针分别指向当前节点和前后节点, 改变链表的链接方向并右移,注意终止条件和终止时指向头节点的指针应该为pre, cur已经为指向头节点之后的NULL指针
ListNode* reverseList(ListNode* head) { ListNode* pre = NULL; ListNode* cur = head; while( cur != NULL ) { ListNode* next = cur->next; cur->next = pre; pre = cur; cur = next; } return pre; }
练习题:
LeetCode 92
Reverse a linked list from position m to n. Do it in-place and in one-pass.
思路:设置一个虚拟头节点避免头节点的判断操作,先将指针移动到变动区域的前一个节点,使用头插法修改区域内的节点顺序
ListNode* reverseBetween(ListNode* head, int m, int n) { ListNode* dummyHead = new ListNode(-1); dummyHead->next = head; ListNode* pre = dummyHead; for(int i = 0; i < m-1; i++) pre = pre->next; ListNode* cur = pre->next; for(int i = 0; i < n-m; i++){ ListNode* nextNode = cur->next; cur->next = nextNode->next; nextNode->next = pre->next; pre->next = nextNode; } ListNode *delNode = dummyHead; ListNode* returnNode = dummyHead->next; delete delNode; return returnNode; }
LeetCode 83
Given a sorted linked list, delete all duplicates such that each element appear only once.
For example,
Given 1->1->2
, return 1->2
.
Given 1->1->2->3->3
, return 1->2->3
.
思路:遍历,没啥别的
ListNode* deleteDuplicates(ListNode* head) { ListNode* dummyHead = new ListNode(-1); dummyHead->next = head; ListNode* curNode = head; while(curNode && curNode->next){ if(curNode->val == curNode->next->val){ ListNode* delNode = curNode->next; curNode->next = curNode->next->next; delete delNode; }else{ curNode = curNode->next; } } ListNode* resNode = dummyHead->next; delete dummyHead; return resNode; }
LeetCode 86
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
思路:头插法,注意此时的“头”应该是从左往右第一个大于x的点的左侧。比如1->4->3->2->5->2 ,那么“头”就是应该是1,然后以4为cur节点向右移动,每次碰到小于x的点就插在“头”后面,并移动“头”到4的前面。
ListNode* partition(ListNode* head, int x) { ListNode* dummyHead = new ListNode(-1); dummyHead->next = head; ListNode* pre = dummyHead; while(pre->next && pre->next->val < x) pre = pre->next; ListNode* cur = pre->next; while(cur && cur->next){ if(cur->next->val < x){ ListNode* moveNode = cur->next; cur->next = moveNode->next; moveNode->next = pre->next; pre->next = moveNode; pre = pre->next; } else cur = cur->next; } ListNode* resNode = dummyHead->next; delete dummyHead; return resNode; }
LeetCode 328
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.
You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.
Example:
Given 1->2->3->4->5->NULL
,
return 1->3->5->2->4->NULL
.
ListNode* oddEvenList(ListNode* head) { if(head == NULL || head->next == NULL) return head; ListNode* even_head = head->next; ListNode* odd = head; ListNode* even = even_head; while(even && odd && even->next && odd->next) { odd->next = even->next; even->next = odd->next->next; odd = odd->next; even = even->next; } odd->next = even_head; return head; }
LeetCode 2
思路:遍历两个链表,注意进位,遍历完链表后需要判断最后一个位是否有进位
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode* dummyHead = new ListNode(-1); ListNode* cur = dummyHead; int nextBit = 0; while(l1 && l2){ int sum = l1->val + l2->val + nextBit; nextBit = sum / 10; sum %= 10; cur->next = new ListNode(sum); cur = cur->next; l1 = l1->next; l2 = l2->next; } while(l1){ int sum = l1->val + nextBit; nextBit = sum / 10; sum %= 10; cur->next = new ListNode(sum); cur = cur->next; l1 = l1->next; } while(l2){ int sum = l2->val + nextBit; nextBit = sum / 10; sum %= 10; cur->next = new ListNode(sum); cur = cur->next; l2 = l2->next; } if(nextBit) cur->next = new ListNode(nextBit); return dummyHead->next; }
LeetCode 445
思路:和LeetCode 2差不多,还是要注意进位,因为是倒序,可以考虑用两次stack,其实用stack+头插法也可以,这里就贴个stack+头插法(两次stack的提交被覆盖了找不到= =)
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { stack<int> s1,s2; while(l1){ s1.push(l1->val); l1 = l1->next; } while(l2){ s2.push(l2->val); l2 = l2->next; } int nextBit = 0; ListNode* newHead = new ListNode(-1); while(!s1.empty() && !s2.empty()) { int sum = s1.top() + s2.top() + nextBit; nextBit = sum / 10; sum %= 10; ListNode* newNode = new ListNode(sum); newNode->next = newHead->next; newHead->next = newNode; s1.pop(); s2.pop(); } while(!s1.empty()){ int sum = s1.top() + nextBit; nextBit = sum / 10; sum %= 10; ListNode* newNode = new ListNode(sum); newNode->next = newHead->next; newHead->next = newNode; s1.pop(); } while(!s2.empty()){ int sum = s2.top() + nextBit; nextBit = sum / 10; sum %= 10; ListNode* newNode = new ListNode(sum); newNode->next = newHead->next; newHead->next = newNode; s2.pop(); } if(nextBit != 0){ ListNode* newNode = new ListNode(nextBit); newNode->next = newHead->next; newHead->next = newNode; } return newHead->next; }
LeetCode 203
思路:简历一个虚拟的头节点可以简化逻辑,每次访问当前节点的next节点判断
ListNode* removeElements(ListNode* head, int val) { ListNode* dummyHead = new ListNode(-1); dummyHead->next = head; ListNode* curNode = dummyHead; while(curNode->next) { if(curNode->next->val == val){ ListNode* delNode = curNode->next; curNode->next = curNode->next->next; delete delNode; } else{ curNode = curNode->next; } } ListNode* returnNode = dummyHead->next; delete dummyHead; return returnNode; }
练习题
LeetCode 82
思路:扫描两次,第一次用哈希表记录每个数字的次数,第二次删除次数大于1的节点,如果只遍历一次,也可以考虑用两个指针前后遍历,不过我没实现,感觉应该可行
ListNode* deleteDuplicates(ListNode* head) { unordered_map<int,int> record; ListNode* cur = head; while(cur) { record[cur->val]++; cur = cur->next; } ListNode* dummyHead = new ListNode(-1); dummyHead->next = head; ListNode* curNode = dummyHead; while(curNode->next) { if( record[curNode->next->val] > 1 ) { ListNode * delNode = curNode->next; curNode->next = curNode->next->next; delete delNode; } else{ curNode = curNode->next; } } ListNode *resNode = dummyHead->next; delete dummyHead; return resNode; }
LeetCode 21
思路:两个指针遍历,注意节点移动时的先后顺序即可,最好画个图
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode* dummyHead1 = new ListNode(-1); dummyHead1->next = l1; ListNode* dummyHead2 = new ListNode(-1); dummyHead2->next = l2; ListNode* curNode1 = dummyHead1; ListNode* curNode2 = dummyHead2; while(curNode1->next && curNode2->next){ //两个指针遍历两个链表 if(curNode1->next->val <= curNode2->next->val ) //l1的当前节点较小则直接移动 curNode1 = curNode1->next; else{//l2的当前节点较小则直接移动到l1的当前节点之前,注意前后顺序,最好画图 ListNode *moveNode = curNode2->next; curNode2->next = moveNode->next; moveNode->next = curNode1->next; curNode1->next = moveNode; curNode1 = curNode1->next; } } while(curNode2->next) //当l2还有节点时,做同样操作,l1还有则无所谓 { ListNode *moveNode = curNode2->next; curNode2->next = moveNode->next; moveNode->next = curNode1->next; curNode1->next = moveNode; curNode1 = curNode1->next; } ListNode *resNode = dummyHead1->next; delete dummyHead1; delete dummyHead2; return resNode; }
- 《慕课网玩转算法面试》笔记及习题解答5.1.~5.3
- 《慕课网玩转算法面试》笔记及习题解答1
- 《慕课网玩转算法面试》笔记及习题解答2
- 《慕课网玩转算法面试》笔记及习题解答3.5~3.6
- 《慕课网玩转算法面试》笔记及习题解答3.1 ~3.4
- 《慕课网玩转算法面试》笔记及习题解答3.7 ~3.8
- 《慕课网玩转算法面试》笔记及习题解答4
- 《慕课网玩转算法面试》笔记及习题解答5.4.~5.6
- 《慕课网玩转算法面试》笔记及习题解答6.4.~6.6
- 《慕课网玩转算法面试》笔记及习题解答6.7
- 《慕课网玩转算法面试》笔记及习题解答7.1~7.3
- 《慕课网玩转算法面试》笔记及习题解答7.4~7.6
- 《慕课网玩转算法面试》笔记及习题解答8.1~8.3
- 《慕课网玩转算法面试》笔记及习题解答8.4~8.5
- 《慕课网玩转算法面试》笔记及习题解答9.3
- 《慕课网玩转算法面试》笔记及习题解答9.4
- 《慕课网玩转算法面试》笔记及习题解答9.8
- 随机排列算法及《算法导论》5.3节习题解答
- html相关
- spring boot
- 使用ccache加速xcode编译过程
- 暑假集训test10
- POJ-3190 Stall Reservations(贪心)
- 《慕课网玩转算法面试》笔记及习题解答5.1.~5.3
- [A-frame学习文档笔记]JavaScriptEvents DOM APIs的简单使用
- flask-login 源码解析
- JSP获取屏幕可用宽高
- 基于fpga的nor flash控制器
- 函数参数
- python qrcode 生成二维码
- java并发编程之读写锁
- 泛型