NC4 判断链表中是否有环牛客题霸 和 NC22 合并两个有序的数组牛客题霸

75 阅读2分钟

NC4 判断链表中是否有环牛客题霸

在这里插入图片描述

  • 关键思路:创造两个指针,一个走的快(一次走两个结点),一个走的慢(一次走一个结点),若是存在环的话,两个快慢指针一定会相遇(因为在环中,两个快慢指针的距离会每次缩小1,直到相遇,画个图模拟一下);若无环,就会走到NULL;
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode * fast = head; // 初始化快指针指向头结点 一次走两个结点
        ListNode * slow = head; // 初始化慢指针指向头结点 一次走一个结点
        
        while (slow != NULL && fast != NULL && fast->next != NULL && fast->next->next != NULL) {
            // 若是慢,快指针不走到空,且快指针的下一个, 下下一个不走到空,就继续走
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {
                return true;
            }
        }
        return false;
    }
};

NC22 合并两个有序的数组牛客题霸

在这里插入图片描述

  • 有序数组的合并,我们很容易想的到双指针思想(这个跟归并排序二分后再合并数组这一步一样),但是这里要注意一下,我们还是要把数据存回A数组中,而不断的移动数字插入是很浪费效率的,题目中又说A数组有足够的空间存放B数组,且A数组的空间大小为m + n,也就是说,我们可以想到:如下画图演示;
  • 在这里插入图片描述
class Solution {
public:
    void merge(int A[], int m, int B[], int n) {
        int lenOldA = m - 1; // 原先A数组中的元素个数 - 1 即 lenOldA 指针所指向的末尾位置
        int lenB = n - 1;   //lenB指针指向B数组末尾位置
        
//         从扩充后的A数组的末尾开始填充 m + n - 1
        for (int i = m + n - 1; i >= 0; --i) {
            // 若当前B数组中的数字都用完了,就用A数组中的数字填充 or A 数组中的数字未用完且A数组的数字大
            if (lenB < 0 || (lenOldA >= 0 && A[lenOldA] >= B[lenB])) {
                A[i] = A[lenOldA--];
            }else {
                A[i] = B[lenB--];
            }
        }
    }
};