【牛客刷题】链表专项 Ⅱ()

合并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
用队列模拟更容易理解:

扫描二维码关注公众号,回复: 16640319 查看本文章
    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;
    }

猜你喜欢

转载自blog.csdn.net/weixin_43785314/article/details/132765963
今日推荐