六月集训(第12天)—链表

链表

1. 328. 奇偶链表

    思路:
        利用两个指针,交替连接得到两个(奇偶)链表,最后将两个链表合并。
        注意特判链表为空和只有一个元素的情况

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if (head == nullptr) return nullptr;   // 特判链表为空      
        ListNode *head1 = head;
        ListNode *head2 = head->next;
        if (head2 == nullptr) return head;      // 特判只有一个元素
        ListNode *rem_head2 = head->next;
        int cnt = 1;
        while (head1->next != nullptr && head2->next != nullptr) {
            if (cnt & 1) {
                head1->next = head2->next;
                head1 = head1->next;
            } else {
                head2->next = head1->next;
                head2 = head2->next;
            }
            cnt ^= 1;
        }
        head2->next = nullptr;
        head1->next = rem_head2;
        return head;
    }
};

2. 725. 分隔链表

    思路:
        首先可以算出每个子链表需要包含多少个链结unit_len = line_len / k;,开始的几个子链表可能会多一个元素,即开始的rest(rest = line_len % k;)个元素包含unit_len + 1个元素。遍历链表,按照规定的元素个数将对应的子链表放入答案中即可。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    vector<ListNode*> splitListToParts(ListNode* head, int k) {
        int line_len = 0;
        int rest = 0, unit_len = 0;
        vector<ListNode *> ans;
        ListNode *temp_head = head;
        while (temp_head) {
            line_len++;
            temp_head = temp_head->next;
        }
        unit_len = line_len / k;	// 每个子链表至少包含unit_len 个元素
        rest = line_len % k;	// 前rest个子链表包含unit_len + 1个元素
        while (head) {
            ans.push_back(head);
            for (int i = 1; i < unit_len; ++i) head = head->next;
            if (rest && unit_len) {
                head = head->next;
                rest--;
            }
            ListNode *temp = head;
            head = head->next;
            temp->next = nullptr;	// 尾指针置为空
        }
        int ans_size = ans.size();
        if (ans_size < k) {	/* 链表空了,需要加入空指针,让子链表的数量达到k个 */
            for (int i = ans_size; i < k; ++i) ans.push_back(nullptr);
        }
        return ans;
    }
};

3. 817. 链表组件

    思路:
        题意没看懂,卡了半天。先解释一下:链表中的连续子链中的每一个元素都在数组nums中,问这样的连续子链有多少个。
        (1) 将nums中的每个元素建立哈希映射。
        (2) 遍历链表,如果当前元素在nums中出现了,并且链表中的下一个元素也出现了,则其为连续子链的一部分,当当前元素在nums中,而其在链表中的下一个元素不在链表中,则该元素是当前连续子链的结尾,子链个数+1。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    #define maxn 10010
public:
    int numComponents(ListNode* head, vector<int>& nums) {
        bool vis[maxn];
        int cnt = 0;
        memset(vis, false, sizeof(vis));
        int nums_size = nums.size();
        for (int i = 0; i < nums_size; ++i) vis[ nums[i] ] = true;	// (1)
        while (head) {	// (2)
            if (vis[ head->val ] && (head->next ==  nullptr || !vis[ head->next->val ])) cnt++;
            head = head->next;
        }
        return cnt;
    }
};

4. 622. 设计循环队列

    思路:
        数组模拟循环链表。

class MyCircularQueue {
    vector<int> line;
    int front = 0, rear = -1;
    int line_size = 0, len_limited = 0;
public:
    MyCircularQueue(int k) {
        for (int i = 0; i < k; ++i) line.push_back(0);
        line_size = rear - front + 1;
        len_limited = k;
    }
    
    bool enQueue(int value) {
        if (isFull()) return false;
        line_size++;
        rear++;
        if (rear >= len_limited - 1) rear %= len_limited;
        line[rear] = value;
        return true;
    }
    
    bool deQueue() {
        if (isEmpty()) return false;
        line_size--;
        front++;
        if (front >= len_limited - 1) front %= len_limited;
        return true;
    }
    
    int Front() {
        if (isEmpty()) return -1;
        return line[front];
    }
    
    int Rear() {
        if (isEmpty()) return -1;
        return line[rear];
    }
    
    bool isEmpty() {
        return line_size == 0;
    }
    
    bool isFull() {
        return line_size == len_limited;
    }
};

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue* obj = new MyCircularQueue(k);
 * bool param_1 = obj->enQueue(value);
 * bool param_2 = obj->deQueue();
 * int param_3 = obj->Front();
 * int param_4 = obj->Rear();
 * bool param_5 = obj->isEmpty();
 * bool param_6 = obj->isFull();
 */
posted @ 2022-06-12 09:24  番茄元  阅读(36)  评论(0)    收藏  举报