链表专题 c/c++实现 LeetCode例题讲解

C语言实现链表的增删查改以及OJ题讲解 目录 动态申请一个节点 单链表的打印 单链表的尾插 单链表的头插 单链表的尾删 单链表的头删 单链表查找 单链表在pos位置之后插入x 单链表删除pos位置之后的值 单链表的销毁 最后呢,我会挑几道关于链表的OJ题给大家讲解一下 ... 阅读详情

链表专题

转发的朋友请带上原博地址:https://blog.youkuaiyun.com/RangeLZ/article/details/97272742

首先我们都知道,链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

一般用结构体来表示。

struct ListNode {
      int val;
      struct ListNode *next;
 };

其中 v a l val val 是存储这个节点的值, ∗ n e x t *next ∗next 是存储下一个节点的位置。这样每一个节点都知道下一个节点的位置,就可以以非连续、非顺序的存储结构,把一段数据连续起来。

链表本身是个不难理解的东西,重要的是学会如何在问题中使用它。

例题

于是我们接下来就在实战中学习。

注:下面的例题讲解是学习完 Week2 链表专题 - bilibili 后的产物,若是对本博客不感兴趣的可以直接去看原视频。

  1. LeetCode 19. 删除链表的倒数第N个节点
  2. LeetCode 237. 删除链表中的节点
  3. LeetCode 83. 删除排序链表中的重复元素
  4. LeetCode 61. 旋转链表
  5. LeetCode 24. 两两交换链表中的节点
  6. LeetCode 206. 反转链表
  7. LeetCode 92. 反转链表 II
  8. LeetCode 160. 相交链表
  9. LeetCode 142. 环形链表 II
  10. LeetCode148. 排序链表

No.1 LeetCode 19. 删除链表的倒数第N个节点

原题地址:LeetCode 19. 删除链表的倒数第N个节点

题目描述

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
  • 给定的 n 保证是有效的。
进阶:
  • 你能尝试使用一趟扫描实现吗?

解题思路:

由于题目中使用的是单向链表,只能从头开始走到尾,而不能逆着走。

看到这道题的时候,我第一想法是,先把链表跑一遍,这时我们可以知道它的长度 m m m。

再然后,计算得出倒数的第 n n n 个节点是正数的第 m − n + 1 m - n + 1 m−n+1 个,这个时候我们再跑一遍就可以知道我们要删除的是哪一个节点了。

但题目的进阶要求我们只能使用一趟扫描来实现,上面的想法自然是不满足题目要求的。

由于我们的头结点 h e a d head head 也有可能被删除,于是我们要创建一个虚拟头结点 d u m m y dummy dummy ,让 d u m m y − > n e x t = h e a d ; dummy -> next = head; dummy−>next=head;

再然后,我们要用两个指针, f i r s t = d u m m y , s e c o n d = d u m m y first = dummy, second = dummy first=dummy,second=dummy

这两个指针有什么用呢,我们首先让 f i r s t first first 指针比 s e c o n d second second 指针先移动 n n n 次。

这时 f i r s t first first 指针已经指到了第 n n n 个结点,而 s e c o n d second second 指针依然指着虚拟结点 d u m m y dummy dummy 也就是第0个结点。

等到 f i r s t first first 指针比 s e c o n d second second 指针先移动 n n n 次后,我们的 s e c o n d second second 指针就可以开始和 f i r s t first first 指针一起开始移动了。

这样当 f i r s t first first 指针指到末尾的时候, s e c o n d second second 刚好到倒数第 n − 1 n - 1 n−1 个结点。

而这个结点的 n e x t next next 就是我们要删除的结点。

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        auto dummy = new ListNode(-1);
        dummy -> next = head;
        auto first = dummy, second = dummy;
        while(n--)
            first = first -> next;
        while(first -> next){
            first = first -> next;
            second = second -> next;
        }
        second -> next = second -> next -> next;
        return dummy -> next;
    }
};

No.2 LeetCode 237. 删除链表中的节点

原题地址: LeetCode 237. 删除链表中的节点

题目描述

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

现有一个链表 – head = [4,5,1,9],它可以表示为:

在这里插入图片描述

示例1:
输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例2:
输入: head = [4,5,1,9], node = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
说明:
  • 链表至少包含两个节点。
  • 链表中所有节点的值都是唯一的。
  • 给定的节点为非末尾节点并且一定是链表中的一个有效节点。
  • 不要从你的函数中返回任何结果。

解题思路:

这道题呢,怎么说呢,就是一个很简单的链表删除元素操作。

但有所不同的是,你并不知道该删除的点的上一个结点的位置。

所以你不能直接简单的将要删除的结点的上一个结点的 n e x t next next 直接改成要删除的结点的 n e x t next next,因为你无从得知要删除的结点的上一个结点在哪。

既然不能直接来删除,那就只能曲线救国了。

假设我们 A [ a ] → B [ b ] → C [ c ] A[a] \rightarrow B[b] \rightarrow C[c] A[a]→B[b]→C[c] 中要删除 B B B ,但是我们不能让 A [ a ] → C [ c ] A[a] \rightarrow C[c] A[a]→C[c]。

那么,我们可以将 B B B 结点的 v a l val val 值改成 C C C 结点的 v a l val val 值 ,于是就变成了 A [ a ] → B [ c ] → C [ c ] A[a] \rightarrow B[c] \rightarrow C[c] A[a]→B[c]→C[c]。

最后我们再将 C C C 删除就可以了,最后就是 A [ a ] → B [ c ] A[a] \rightarrow B[c] A[a]→B[c] 这样虽然没能直接删除 B [ b ] B[b] B[b] ,但是在我们查看链表的时候 b b b 已经被我们删除了,而其他数据并没有改变。

所以我们曲线救国成功。

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node -> val = node -> next -> val;
        node -> next = node -> next -> next;
        // *node = *(node -> next);       上面两行代码,可以简写成这一行代码。
    }
};

No.3 LeetCode 83. 删除排序链表中的重复元素

原题链接: LeetCode 83. 删除排序链表中的重复元素

题目描述

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例1:
输入: 1->1->2
输出: 1->2
示例2:
输入: 1->1->2->3->3
输出: 1->2->3

解题思路:

这道题也不难,题目本身是排好序的,所以重复的数字一定是紧挨在一起的。

因此我们只需要从头结点开始走,每次判断该结点和下一个结点的 v a l val val 是否相等,若相等则删除下一个结点。

这里需要注意的是,由于可能不止有一个数与该结点重复,所以删除了第一个重复的数字的结点后,还得继续判断新的结点是否相等。

只有当该结点与下一结点不相等的时候,猜移动到下一个结点的位置进行判断。

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        auto p = head;
        while(p){
            if(p -> next && p -> val == p -> next -> val)
                p -> next = p -> next -> next;
            else
                p = p -> next;
        }   
        return head;
    }
};

No.4 LeetCode 61. 旋转链表

原题链接: LeetCode 61. 旋转链表

题目描述

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

示例1:
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例2:
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NUL

解题思路:

分析题目我们可以发现,虽然题目给的示例是一次一次的移动。

但其实我们可以一次性移动完毕,因为我们发现如果是将链表每个节点向右移动 k 个位置,那么就是将最后一个的结点的 n e x t next next 变成 h e a d head head 头结点, 然后倒数第 k k k 个点就是新的头结点。

因此我们可以像例题一一样,用两个指针找到倒数第 K − 1 K - 1 K−1 个点的位置,然后将 k − 1 k-1 k−1 结点的 n e x t next next 设置为 N U L L NULL NULL 。最后将将最后一个的结点的 n e x t next next 变成 h e a d head head 头结点就行了。

但之后我发现,它的 K K K有可能会大于链表的长度,所以要先计算出链表的长度 n n n, 然后 k k k %$= n;
$ k k k 就是小于等于链表长度的了。

注意要记得判断空链表的情况,这个时候可以直接返回 N U L L NULL NULL.

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head)
            return NULL;
        int n = 0;
        for(auto p = head; p; p = p->next)
            n++;
        k %= n;
        auto first = head, second = head;
        while(k--)
            second = second -> next;
        while(second -> next){
            first = first -> next;
            second = second -> next;
        }
        second -> next = head;
        head = first -> next;
        first -> next = NULL;
        return head;
    }
};

No.5 LeetCode 24. 两两交换链表中的节点

原题链接: LeetCode 24. 两两交换链表中的节点

题目描述

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.

解题思路:

这道题的难点在于怎么将 A → B A \rightarrow B A→B 变成 A ← B A \leftarrow B A←B .

其实这个问题也不难解决,只要提前把 A A A、 B B B 以及 B B B 的下一个结点 C C C 存储下来,然后就将各个结点的 n e x t next next 更新成交换后的结点就行,然后再后移进行新的交换即可。

交换过程如图所示:

在这里插入图片描述

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        auto dummy = new ListNode(-1);
        dummy -> next = head;
        for(auto p = dummy; p->next && p->next->next; p = p->next->next){
            auto a = p->next, b = a -> next;
            p->next = b;
            a->next = b->next;
            b->next = a;
        }
        return dummy->next;
    }
};

No.6 LeetCode 206. 反转链表

原题链接:LeetCode 206. 反转链表

题目描述

反转一个单链表。

示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

解题思路:

这道题和上一道题很类似,只不过他是每一个数之间都反转。

所以交换方式和上一道题一样,但是移动方式就有一点区别了, 即 a = b , b = c ; a= b, b = c; a=b,b=c; 这样右移动一位即可,而不是像上一题移动两位。

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head)
            return NULL;
        auto a = head, b = head->next;
        while(b){
            auto c = b->next;
            b->next = a;
            a= b, b = c;
        }
        head->next = NULL;
        return a;
    }
};

No.7 LeetCode 92. 反转链表 II

原题链接:LeetCode 92. 反转链表 II

题目描述

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL

解题思路:

这道题先找到要反转范围的结点的位置后, 按照上一题的反转方法进行反转即可。

若是 m = = n m == n m==n, 可以直接返回该链表就行。

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
         if(m == n)
             return head;
        
        auto dummy = new ListNode(-1);
        dummy->next = head;
        auto a = dummy, d = dummy;
        for(int i = 1; i < m; i++)
            a = a->next;
        for(int i = 0; i < n; i++)
            d = d->next;
        auto b = a->next, c = d->next;
        for(auto p = b, q = b->next; q != c;){
            auto o = q->next;
            q->next = p;
            p = q, q = o;
        }
        b->next = c;
        a->next = d;
        return dummy->next;
    }
};

No.8 LeetCode 160. 相交链表

原题链接:LeetCode 160. 相交链表

题目描述

写一个程序,找到两个单链表相交的起始节点。如下面的两个链表:在这里插入图片描述

在节点 c1 开始相交。

示例1:

在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例2:

在这里插入图片描述

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例3:

在这里插入图片描述

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。

注意:

  • 如果两个链表没有交点,返回 null.
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。
  • 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

解题思路:

分别用两个指针 a , b a,b a,b 从两个头结点 A , B A,B A,B 开始移动,假设 a a a 先到链表末尾,那么就将 a a a 变到链表 B B B 的头结点的位置, 然后 a , b a,b a,b 继续移动。

等到 b b b 到链表末尾后,就将 b b b 变到链表 A A A 的头结点的位置,当他们相遇时,相遇的点就是相交的点。

为什么呢?

假设 A A A 链条私有部分长度为 x x x, B B B 链条私有部分长度为 y y y 、 A , B A,B A,B 链条公有部分长度为 z z z。当他们相遇时, A A A 走了 x + z + y x+z+y x+z+y 、 B B B 走了 y + z + x y+z+x y+z+x, 也就是两个链表的相交点。

如果是示例3 的情况,他们会在都等于 N U L L NULL NULL 的时候相遇,因此返回的值也是符号题目要求的。

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        auto a = headA, b = headB;
        while(a != b){
            if(a)
                a = a->next;
            else
                a = headB;
            if(b)
                b = b->next;
            else
                b = headA;
        }
        return b;
    }
};

No.9 LeetCode 142. 环形链表 II

原题链接: LeetCode 142. 环形链表 II

题目描述

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。

示例2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。

在这里插入图片描述

示例3:
输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

在这里插入图片描述

解题思路:

这道题是用的快慢指针来,首先建立两个指针 a , b a, b a,b ,两个都最初指向头结点 h e a d head head ,但是 a a a 每次移动一步、 b b b 每次移动两步。

当两个指针第一次相遇后, 将 a a a 移动到头结点 h e a d head head ,然后 a , b a,b a,b 再都以每次一步的速度同时移动,等他们再次相遇的时候的节点位置,就是我们环开始的位置。

至于是为什么呢…我最开始看到这个算法的时候很懵逼…然后证明了一下,才明白这是为什么…

在这里插入图片描述

首先先如图假设一下。

当 a a a 、 b b b 第一次相遇的时候: a a a 走了 x + y + n z x +y + nz x+y+nz ( n = 0 , 1 , 2... n = 0,1,2... n=0,1,2...)、 b b b 走了 2 x + 2 y + 2 n z 2x +2y + 2nz 2x+2y+2nz ( n = 0 , 1 , 2... n = 0,1,2... n=0,1,2...)

然后将 a a a 移动到头结点、当 a a a 、 b b b 再一次相遇的时候: a a a 走了 2 x + y + n z 2x +y + nz 2x+y+nz ( n = 0 , 1 , 2... n = 0,1,2... n=0,1,2...)、 b b b 走了 3 x + 2 y + 2 n z 3x +2y + 2nz 3x+2y+2nz ( n = 0 , 1 , 2... n = 0,1,2... n=0,1,2...)

它们相差的步数是 x + y + n z x +y + nz x+y+nz 可得 x + y = = m z x + y == mz x+y==mz( m = 0 , 1 , 2... m = 0,1,2... m=0,1,2...) ,所以在第一次相遇后再走 x x x 步就一定可以到达 J J J 点。

而刚好 a a a 从结头到 J J J 点的距离刚好为 x x x。

所以他们第二次相遇的时候,就是我们要的结果

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        auto a = head, b = head;
        while(b){
            a = a->next;
            b = b->next;
            if(b)
                b = b->next;
            else break;
            if(a == b){
                a = head;
                while(a != b ){
                    a = a->next;
                    b = b->next;
                }
                return a;
            }
        }
        return NULL;
    }
};

No.10 LeetCode148. 排序链表

原题链接: LeetCode148. 排序链表

题目描述

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例1:
输入: 4->2->1->3
输出: 1->2->3->4
示例2:
输入:-1->5->3->4->0
输出: -1->0->3->4->5

解题思路:

这道题要用到之前用的反转链表,然后再选择一种满足题目要求的算法即可。

而满足这道题的排序算法是归并排序。

那什么是归并排序呢?

归并排序就是,当我有一个如图的数组,他的左边部分和右边部分都是排好了的。
在这里插入图片描述
然后我们将他拆分成两个数组,并准备一个新的空数组来放他们。
在这里插入图片描述
然后 i i i 指向 l e f t left left 数组的第一个, j j j 指向 r i g h t right right 数组的第一个, k k k 指向 a n s ans ans 数组的第一个。

然后判断 l e f t [ i ] &lt; r i g h t [ j ] left[i] &lt; right[j] left[i]<right[j] 若 l e f t [ i ] left[i] left[i] 小一些,则将 l e f t [ i ] left[i] left[i] 放到 a n s [ k ] ans[k] ans[k] 里面。
在这里插入图片描述
若 r i g h t [ j ] right[j] right[j] 小一些,则将 r i g h t [ j ] right[j] right[j] 放到 a n s [ k ] ans[k] ans[k] 里面,
在这里插入图片描述
直到数组里面的的数字都放完为止。

而这道题就是采用的归并排序,先将 n n n 个结点分成 i i i 个数组 ( i i i 从1开始增大,直到将整个链表一分为二),然后每次两个数组进行归并排序,最后把整个串起来就可以了。

A C AC AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        int n = 0;
        for (ListNode *p = head; p; p = p->next) n ++ ;

        ListNode *dummy = new ListNode(-1);
        dummy->next = head;
        for (int i = 1; i < n; i *= 2)
        {
            ListNode *begin = dummy;
            for (int j = 0; j + i < n; j += i * 2)
            {
                ListNode *first = begin->next, *second = first;
                for (int k = 0; k < i; k ++ )
                    second = second->next;
                int f = 0, s = 0;
                while (f < i && s < i && second)
                    if (first->val < second->val)
                    {
                        begin = begin->next = first;
                        first = first->next;
                        f ++ ;
                    }
                    else
                    {
                        begin = begin->next = second;
                        second = second->next;
                        s ++ ;
                    }

                while (f < i)
                {
                    begin = begin->next = first;
                    first = first->next;
                    f ++ ;
                }
                while (s < i && second)
                {
                    begin = begin->next = second;
                    second = second->next;
                    s ++ ;
                }

                begin->next = second;
            }
        }

        return dummy->next;
    }
};

小结

这次是链表专题,整个学习的过程中感觉难点就是有点抽象。

所以学这一段的时候我就是在不断画图…

不过学到最后感觉也就那个样吧,哈哈。

力扣(Leetcode)第2题:两数相加(C语言版本) 通常,我们从左到右书写数字,例如数字123,最左边的是最高位(百位),然后是十位,最后是个位。但是在这个特殊的表示法中,链表的第一个节点将代表个位数,第二个节点代表十位数,以此类推,最左边的节点(链表的头节点)代表最低位,而最右边的节点(链表的尾节点)代表最高位。在这种表示法中,每个节点只存储一个数字(0-9),并且每个链表的第一个节点(最近个位)实际上是整个数字的最低有效位,而最后一个节点(最远离个位)是最高位。由于每个节点只存储一位数字,相加的结果可能需要进位到下一个更高的位。它们每位数字都是按照。 阅读详情

相关推荐

【AI概念】迁移学习 vs. 域自适应 vs. 域泛化|定义、核心原理、数学表达、易混淆点与工程选择建议|实际案例、工程实现细节、未来研究趋势、实际应用场景

大家好,我是爱酱。本篇将会详细梳理迁移学习(Transfer Learning)、域自适应(Domain Adaptation)、域泛化(Domain Generalization)三大常被混淆的核心概念,结合数学公式、典型算法与实际应用场景,帮助你厘清它们的本质区别、联系与工程意义。 注:本文章含大量数学算式、详细例子说明及大量代码演示,大量干货,建议先收藏再慢慢观看理解。新频道发展不易,你们的每个赞、收藏跟转发都是我继续分享的动力!

AI人工智能爱酱~你的AI学习好帮手~ 2472

leetcode刷题之链表

合并两个有序链表 参考代码 普通解法 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { publ...

qq_39621037的博客 541

深入解析ViT中的RoPE旋转位置编码:原理、实现与视觉应用

本文深入解析了ViT中的RoPE旋转位置编码原理、实现及其在视觉任务中的应用。RoPE通过旋转变换巧妙地将相对位置信息融入注意力计算,解决了传统绝对位置编码外推性差的问题,在图像分类、目标检测及生成任务中展现出更优的泛化能力和灵活性。

alice7model的博客 706

leetcode-链表

LeetCode-链表 LeetCode 206 - Reverse Linked List - 反转链表 - easy 反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题? 三步:备份、更新、移动。 /** * Definition for singly-linked list. * struct ListN

Starr 435

n8n实战:动态报表生成与企业微信自动化推送

本文详细介绍了如何利用n8n实现动态报表生成与企业微信自动化推送的全流程。通过配置n8n Form触发器、智能报表生成核心逻辑以及企业微信Webhook推送,帮助企业大幅提升数据收集与报表推送效率,实现从数据录入到报表推送的全自动化处理。

weixin_29267307的博客 307

BES (恒玄)HFP通话笔记

1.audio_developer 调试:SDK 需要打开某个算法,需要原厂打开对应宏定义编译出新的SDK,只要涉及到lib库里的功能都需要原厂手动修改编译。开发商和原厂FAE做起来都会比较累。如果没有原厂支持根本没法做,很少文档,SDK也很多问题,没法开箱即用如果要支持audio_developer上位机调试,还需改代码,如果对整个原理不清楚就没法做,没文档只能啃代码调试工具设计的也有待加强,串口通讯调试对耳机这类产品非常麻烦,本来板子就不大,还要焊接一堆线,调试还要拖着串口线。

飞天鱼 690

leetcode每日一题第四十八天

【代码】leetcode每日一题第四十八天。

Hzzzzxx的博客 294

从STM32转战小华HC32F448:手把手教你搞定串口复用与超时中断(附完整代码)

本文详细介绍了从STM32迁移到小华HC32F448的串口开发实战指南,重点解析了HC32F448的GPIO复用系统和超时中断机制。通过对比STM32的架构差异,提供了完整的串口配置代码和优化方案,帮助开发者快速掌握HC32F448的串口通信技术,适用于工业控制等应用场景。

weixin_30564901的博客 549

【C算法】链表算法

使用C语言解决链表问题

dab112的博客 1136

在没有实验数据的情况下,如何高效快速发表高影响因子论文

最新基于Citespace、vosviewer、R语言的文献计量学可视化分析技术及全流程文献可视化SCI论文高效写作方法

glldxh的博客 372

新能源汽车电机交流电流测量系统精度全链路分析

通过全链路误差建模与瓶颈分析,结合硬件选型优化与软件算法补偿,可将系统精度从4.2%提升至≤1% FS。本文所述方法论已应用于某800V电驱平台开发,实测电流控制精度达±0.8%,为高性能电机控制奠定基础。为例,深入剖析从互感器采集到CAN报文解析的全链路信号处理流程,揭示各环节误差来源及对最终精度的影响,为研发测试提供理论支撑。:±0.1%(电阻温漂与运放开环增益限制):运放增益带宽积(GBW)不足导致高频衰减。:±0.02%/℃(铁氧体材料温敏特性):±0.5%读数(磁芯饱和效应)

优快云-新能源汽车研发测试专业博主 1497

(LeetCode 热题 100) 23. 合并 K 个升序链表(小顶堆、优先队列)

【代码】(LeetCode 热题 100) 23. 合并 K 个升序链表(小顶堆、优先队列)

记录一些刷过的题并分享学习心得 458

innovus:addRepeaterByRule用法

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?addRepeaterByRule不管transition/timing violation,只根据约束的length/cap/fanout等等去给net 插buffer。

m0_61544122的博客 1093

题解 力扣 LeetCode 206 反转链表 C/C++ 三种思路

可以用迭代和递归来做,每种又可以具体写成不同样子,这里给出三种不同思路的代码 先说迭代: 遍历整个链表 第一个节点是将来的最后一个节点,令它指向 NULL 之后的每个节点指向之前的节点即可,每次反转前都要记录一下下一个节点 否则会和之后的节点断开联系 former 用来记录之前的节点 latter 用来在该次反转前记录下一个节点 p 不为 NULL 就继续执行,结束执行后返回 p 循环体上半部分结束后判断 latter,因为我们要返回 p 作为最后一个节点的地址 所以不能让 p == NULL

qwq_ovo_pwp的博客 2348

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

2024年C C++最新单链表C语言实现附加力扣题_c语言单链单题 力扣(2),一份非常适合收藏的C C++进阶面试题

要想复制一份链表比较得保证新链表的结点关系和原链表保持一致,并且新链表的每个结点的值以及结点中两个指针的指向都必须与原链表结点一样,将拷贝链表的结构构建出来后,同步拷贝链表和原链表两个指针的指向,最后将拷贝链表拆解下来,同时还原原链表结点的链接的关系,最后返回拷贝链表的头。链表的相交并不是直线的相交,而是两个链表中存在一个公共结点,这样的链表我们可以称它是相交链表,比较结点的地址,如果相同那么就是相交的,否则不是,让长距离的先走差距步,最后再同时走,如果中间相交就返回该结点,否则返回NULL。

2401_84976619的博客 1167

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

链表(典型算法思想)—— OJ例题算法解析思路

链表(典型算法思想)—— OJ例题算法解析思路

祯的博客 1451

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【C/C++】相交链表(leetcode T160)

这篇文章讲解了如何在两个单链表中找到它们的相交起始节点。文章首先分析了题目要求和示例,接着提出了解决方案——使用双指针法:通过设置两个指针在链表中同步遍历,如果指针到达链表末尾,就切换到另一个链表的头部。这样两个指针最终会在相交节点相遇,或者都为 NULL(表示无交点)。文章详细解释了为什么双指针法有效,并对时间复杂度和空间复杂度进行了分析,最后总结了思路和相关的扩展问题。

2301_76324845的博客 1209

Leetcode(力扣)题解--C++实现(一)

Leetcode(力扣)题解–C++实现(一) 文章目录Leetcode(力扣)题解--C++实现(一)题目 1 [平方数之和](https://leetcode-cn.com/problems/sum-of-square-numbers/)题目 2 [两数之和 II - 输入有序数组](https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/)题目 3 [反转字符串中的元音字母](https://leetcode-cn.com/p

qq_43419412的博客 2714

数据结构与算法——分治的思想(C++,leetcode例题讲解)

分治的意思是把一个问题分解成多个子问题来解决,以提高解决的效率。以下图为例(来源于本题的力扣官方题解),当我们合并k个升序链表时,相当于合并前k22k​项合并后的结果和后k22k​项合并后的结果。并且,当我们合并前k22k​项合并时,同样可以一分为二来合并。这样,当分到只有两个升序链表时,只需要合并这两个升序链表就可以。如果只有一个升序链表,则返回其本身。仔细思考,我们会发现,这种不断拆分的过程可以看成一个二叉树,而树的问题的解决大多使用递归,这也是我们之后代码的逻辑。

qq_73075805的博客 1009

题解 力扣 LeetCode 61 旋转链表 C/C++

时间复杂度 O(N) 1.特殊情况判断:head == NULL 2.获取链表长度 length,该数据很有用,等下会用到好几次 3.k %= length,防止 k过大出现多轮重复操作 4.找到将来的末节点和头结点,记录将来的头结点后,将来的末节点->next = NULL 举个例子: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, NULL} rotate 3 >> {8, 9, 10, 1, 2, 3, 4, 5, 6, 7, NULL} 7 是将来的末节点,8 是将来的头结点

qwq_ovo_pwp的博客 543

LeetCode 例题精讲 | 01 反转链表:如何轻松重构链表

点击关注上方“五分钟学算法”,设为“置顶或星标”,第一时间送达干货。转自面向大象编程本期例题:LeetCode 206 - Reverse Linked List[1](Easy)反转一...

程序员吴师兄的博客 444

力扣---链表2

链表因为全靠一个head和next连接了全部,所以要特别注意next的指向,在操作的时候指向了哪里,同时还要注意因为只有一个next,没有pre,也就是单链表,操作的时候容易断掉,所以要及时记录要断掉的节点!!!

2301_78138281的博客 577

力扣热题100题解(c++)—链表

链表是有一系列结点组成的,每个结点包括两个部分:1、存储数据元素的数据域;2、存储下一个节点地址的指针域。//单链表int data;// 节点数据// 指向下一个节点的指针// 构造函数{}//双链表int data;// 节点数据// 指向下一个节点的指针// 指向前一个节点的指针// 构造函数{}

weixin_50764857的博客 1098

【LeetCode刷题笔记】160.相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的 起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交:题目分析 对链表的题目大多可以使用指针迭代进行解决,链表不允许被破坏,使用双指针对链表进行遍历。 A和B可以看作为两条链表,先使用p1指针从A链表开始遍历,再使用p2指针从B链表开始遍历,哪个指针先遍历到链表结尾,就代表哪个链表更长。 使用长链表的长度减去短链表的长度为这两条链表长度差,再利用长链表指针先出发这个长度差后,短

努力让自己的能力配得上梦想. 1432

C++链表基本用法及LeetCode经典链表题目汇总

链表基本用法: 目录 链表基本用法: C++链表及基本操作 LeetCode链表经典题目汇总: 2. 两数相加 19. 删除链表的倒数第 N 个结点 21. 合并两个有序链表 23. 合并K个升序链表 24. 两两交换链表中的节点 25. K 个一组翻转链表 61. 旋转链表 92. 反转链表 II 141. 环形链表 142. 环形链表 II 160. 相交链表 328. 奇偶链表 C++链表及基本操作 1 2 ...

whocare的博客 4148

力扣---链表1

本博客用于力扣链表系列的刷题记录,跟的是代码随想录的顺序,在刷完之后,最后对链表相关的博客做规整和总结,同之前的数组。

2301_78138281的博客 749
上一篇: 二分查找算法专题 c/c++实现 LeetCode二分题讲解
下一篇: 计算机三级 数据库技术 学习笔记
爱写BUG的老冉
博客等级 码龄8年 2357粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值