面试题 08.06. 汉诺塔问题 & 148. 排序链表
面试题 08.06. 汉诺塔问题
在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制: (1) 每次只能移动一个盘子; (2) 盘子只能从柱子顶端滑出移到下一根柱子; (3) 盘子只能叠在比它大的盘子上。
请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。
你需要原地修改栈。
示例1:
输入:A = [2, 1, 0], B = [], C = [] 输出:C = [2, 1, 0] 示例2:
输入:A = [1, 0], B = [], C = [] 输出:C = [1, 0] 提示:
A中盘子的数目不大于14个。
思路:递归与分治
很久之前不懂的题,现在用递归还是不太懂。所以直接看的题解。
class Solution { public: void hanota(vector<int>& A, vector<int>& B, vector<int>& C) { move(A.size(), A,B,C); } void move(int n, vector<int>& A, vector<int>& B, vector<int>& C){ if(n==0) return; //将A中的n-1个先通过 →C移到→ B move(n-1, A, C, B); //A最后一个移动到C C.push_back(A.back()); A.pop_back(); //将B中n-1个通过A移动到C move(n-1, B, A, C); } };
排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
示例 1:
输入:head = [4,2,1,3] 输出:[1,2,3,4] 示例 2:
输入:head = [-1,5,3,4,0] 输出:[-1,0,3,4,5] 示例 3:
输入:head = [] 输出:[]
提示:
链表中节点的数目在范围 [0, 5 * 104] 内 -105 <= Node.val <= 105
思路:归并排序
初次接触归并排序,也是没有思路,直接看的题解。在合并函数那里的代码暂时也没看明白。(日后补课)
class Solution { public: ListNode* sortList(ListNode* head) { //一头一尾 return sortList(head, nullptr); } ListNode* sortList(ListNode* head, ListNode* tail) { if(head == nullptr) return head; //头尾相接 if(head->next == tail){ head->next = nullptr; return head; } ListNode* slow = head, *fast = head; while(fast != tail){ slow = slow->next; fast = fast->next; if(fast != tail) fast = fast->next; } ListNode* mid = slow; return merge(sortList(head,mid), sortList(mid,tail)); } ListNode* merge(ListNode* head, ListNode* tail){ //合并,需要虚拟头结点 ListNode* dummyNode = new ListNode(); ListNode* tmp = dummyNode, *tmp1 = head, *tmp2 = tail; // 开始不懂的代码 while(tmp1 && tmp2){ if(tmp1->val <= tmp2->val){ tmp->next = tmp1; tmp1 = tmp1->next; }else{ tmp->next = tmp2; tmp2 = tmp2->next; } tmp = tmp->next; } if(tmp1){ tmp->next = tmp1; }else if(tmp2){ tmp->next = tmp2; } return dummyNode->next; } };