合并k个有序链表
https://www.nowcoder.com/share/jump/9321389651694169697706
递归调用一下合并2个有序链表就OK:
ListNode* merge2Lists(ListNode* pHead1, ListNode* pHead2) {ListNode* dummy = new ListNode(0);ListNode* cur = dummy;ListNode* cur1 = pHead1;ListNode* cur2 = pHead2;while (cur1 != nullptr && cur2 != nullptr) {if (cur1->val <= cur2->val) {cur->next = cur1;cur1 = cur1->next;} else {cur->next = cur2;cur2 = cur2->next;}cur = cur->next;}if (cur1 == nullptr && cur2 != nullptr) cur->next = cur2;else if (cur2 == nullptr && cur1 != nullptr) cur->next = cur1;return dummy->next;}ListNode* mergeKLists(vector<ListNode*>& lists) {if (lists.size() == 0) return nullptr;;// write code hereint k = lists.size();ListNode* newList = merge2Lists(lists[0], lists[1]);for (int i = 2; i < k; i++) {newList = merge2Lists(newList, lists[i]);}return newList; }
单链表排序
题目没说不可以直接修改链表的值,所以用vector存值排序后直接改就行。。。
ListNode* sortInList(ListNode* head) {// write code herevector<int> vals;ListNode* cur = head;while (cur != nullptr) {vals.push_back(cur->val);cur = cur->next;}cur = head;sort(vals.begin(), vals.end());for (int i = 0; i < vals.size(); i++) {cur->val = vals[i];cur = cur->next;}return head;}
其实一开始想到的是另一种,就是用小根堆把每个节点排一下序,然后构造个新链表每次都取小根堆堆顶的节点,再弹出更新:
这个写法也可以过,就是写优先级队列的时候语法不好记:
auto comp = [](ListNode* a, ListNode* b){return a->val > b->val;};
priority_queue<ListNode*, vector<ListNode*>, decltype(comp)> pq(comp);
auto comp = [](ListNode * a, ListNode * b) {return a->val > b->val;
};
priority_queue<ListNode*, vector<ListNode*>, decltype(comp)> nodeQue(comp);
ListNode* sortInList(ListNode* head) {// write code hereif (head == nullptr || head->next == nullptr) return head;auto comp = [](ListNode * a, ListNode * b) {return a->val > b->val;};priority_queue<ListNode*, vector<ListNode*>, decltype(comp)> nodeQue(comp);ListNode* cur = head;while (cur != nullptr) {nodeQue.push(cur);cur = cur->next;}ListNode* dummy = new ListNode(0);cur = dummy;while (!nodeQue.empty()) {cur->next = nodeQue.top();nodeQue.pop();cur = cur->next;}cur->next = nullptr;return dummy->next;}
判断链表是否回文
翻转一半链表:
ListNode* reverse(ListNode* head) {ListNode* pre = nullptr;ListNode* cur = head;while (cur != nullptr) {ListNode* temp = cur->next;cur->next = pre;pre = cur;cur = temp;}return pre;}bool isPail(ListNode* head) {// write code hereif (head == nullptr || head->next == nullptr) return true;ListNode* fast = head;ListNode* slow = head;while (fast && fast->next) {fast = fast->next->next;slow = slow->next;}ListNode* halfNodes = reverse(slow);ListNode* cur = head;while (halfNodes) {if (cur->val != halfNodes->val) return false;cur = cur->next;halfNodes = halfNodes->next;} return true;}
或者翻前翻后用一个vector存储当前的值再比较就行:
ListNode* reverse(ListNode* head) {ListNode* pre = nullptr;ListNode* cur = head;while (cur != nullptr) {ListNode* temp = cur->next;cur->next = pre;pre = cur;cur = temp;}return pre;}bool isPail(ListNode* head) {// write code hereif (head == nullptr || head->next == nullptr) return true;ListNode* cur = head;vector<int> valList;while (cur) {valList.push_back(cur->val);cur = cur->next;}ListNode* pre = reverse(head);for (int i = 0; i < valList.size(); i++) {if (pre->val != valList[i]) return false;pre = pre->next;}return true;}
删除有序链表的重复元素
美团一面的题呜呜呜,这个题没做出来我是真该死啊
ListNode* deleteDuplicates(ListNode* head) {// write code hereif (head == nullptr || head->next == nullptr) return head;ListNode* dummy = new ListNode(0);dummy->next = head;ListNode* cur = head;while (cur && cur->next) {if (cur->val == cur->next->val) cur->next = cur->next->next;else cur = cur->next;}return dummy->next;}
删除有序链表重复元素Ⅱ
用map存val出现次数,画图认真理,可以推出来的:
ListNode* deleteDuplicates(ListNode* head) {// write code hereif (head == nullptr || head->next == nullptr) return head;ListNode* dummy = new ListNode(0);dummy->next = head;ListNode* cur = head;ListNode* pre = dummy;unordered_map<int, int> valMap;valMap[cur->val]++;while (cur && cur->next) {if (valMap[cur->next->val] == 1) {pre->next = cur->next->next;cur = pre;}else {valMap[cur->next->val]++;pre = cur;cur = cur->next;}}return dummy->next;}
链表奇偶重排
直接改值,比较简单的方法:
ListNode* oddEvenList(ListNode* head) {// write code hereListNode* dummy = new ListNode(0);dummy->next = head;ListNode* cur = head;vector<int> valList;while (cur) {valList.push_back(cur->val);cur = cur->next;}cur = head;for (int i = 0; i < valList.size(); i += 2) {cur->val = valList[i];cur = cur->next;}for (int i = 1; i < valList.size(); i += 2) {cur->val = valList[i];cur = cur->next;}return dummy->next;}
一个比较巧妙的方法,开辟一个奇数节点链表和一个偶数节点链表,然后奇数尾连接偶数头:
ListNode* oddEvenList(ListNode* head) {// write code hereif (!head || !head->next) return head;ListNode* odd = head;ListNode* even = head->next;ListNode* connect = even;//记录偶数节点的起点while (even && even->next) {//while (odd && odd->next)可能会导致遗漏一些偶数位置上的节点odd->next = even->next;odd = odd->next;even->next = odd->next;even = even ->next;}odd->next = connect;//奇偶相连return head;}
链表重排
https://www.nowcoder.com/share/jump/9321389651694178928216
用栈实现,只要每次cur移动的时候取一下栈顶元素就行:
void reorderList(ListNode *head) {if (!head || !head->next) return;stack<ListNode*> st;ListNode* cur = head;while (cur) {st.push(cur);cur = cur->next;}cur = head;int size = st.size();while (st.size() > size/2) {ListNode* temp1 = cur->next;cur->next = st.top();st.pop();cur->next->next = temp1;cur = temp1;}cur->next->next = nullptr;return;}
环形链表/约瑟夫问题
https://www.nowcoder.com/share/jump/9321389651694182994267
用队列模拟更容易理解:
int ysf(int n, int m) {// write code herequeue<int> people;for (int i = 1; i <= n; i++) {people.push(i);}while (people.size() > 1) {for (int i = 1; i < m; i++) {//只要在这个循环里,说明都没报到m,都需要从队列头到队列尾people.push(people.front());people.pop();}people.pop();//出循环了,表示当前就是报m的时候了,此时直接pop,不需要再加入队列}return people.front();}
用双向链表list
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param n int整型 * @param m int整型 * @return int整型*/int ysf(int n, int m) {// write code herelist<int> people;for (int i = 1; i <= n; i++) {people.push_back(i);}auto it = people.begin();//迭代器it记录当前报数的人while (people.size() > 1) {for (int i = 1; i < m; i++) {it++;if (it == people.end()) {//当当前这个it是队尾的后一个元素时,重置为开头,实现环it = people.begin();}}//这个循环结束后,it在报到m的位置it = people.erase(it);//删除报到m的人,迭代器更新if (it == people.end()) {//重新判断迭代器的位置,实现环it = people.begin();}}return people.back();}
};
链表插入排序
https://www.nowcoder.com/share/jump/9321389651694184440161
ListNode* insertionSortList(ListNode* head) {// write code hereif (!head || !head->next) return head;ListNode* dummy = new ListNode(0);ListNode* cur = head;while (cur) {ListNode* pre = dummy;while (pre->next && pre->next->val < cur->val) {pre = pre->next;}ListNode* temp = cur->next;cur->next = pre->next;pre->next = cur;cur= temp;}return dummy->next;}
单链表+1
https://www.nowcoder.com/share/jump/9321389651694185573227
ListNode* plusOne(ListNode* head) {// write code hereListNode* cur = reverse(head);ListNode* newHead = cur;int index = 1; // 要加的1while (cur && index) {int sum = cur->val + index;cur->val = sum % 10;index = sum / 10;if (!cur->next && index) {cur->next = new ListNode(index);break;}cur = cur->next;}return reverse(newHead);}
旋转链表
ListNode* rotateLinkedList(ListNode* head, int k) {// write code hereif (!head || k == 0) return head;ListNode* fast = head;ListNode* slow = head;int len = 1;// 计算链表长度并移动fastfor (; fast->next; len++) {fast = fast->next;}// 计算实际需要移动的步数k %= len;if (k == 0) return head;// 移动slow到正确的位置for (int i = 0; i < len - k - 1; i++) {slow = slow->next;}// 进行旋转操作ListNode* newHead = slow->next;slow->next = nullptr;fast->next = head;return newHead;}