合并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 here
int 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 here
vector<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 here
if (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 here
if (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 here
if (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 here
if (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 here
if (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 here
ListNode* 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 here
if (!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 here
queue<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 here
list<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 here
if (!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 here
ListNode* cur = reverse(head);
ListNode* newHead = cur;
int index = 1; // 要加的1
while (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 here
if (!head || k == 0) return head;
ListNode* fast = head;
ListNode* slow = head;
int len = 1;
// 计算链表长度并移动fast
for (; 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;
}