数据结构:力扣刷题3

简介: 数据结构:力扣刷题3

目录

题一:反转链表

思路一:

思路二:

题二:移除链表元素

思路一:

思路二:

题三:链表的中间节点

思路一:

题四:链表中倒数第k个结点

思路一:

题五:合并两个有序链表

思路一:

简化后:

本人实力有限可能对一些地方解释的不够清晰,可以自己尝试读代码,望海涵!


题一:反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

思路一:

三个变量n1=NULL,n2=head,n3,如果n2不为NULL,则n3=n2->next,循环如果n2为NULL,就停下来,当n3为空时n3就不进行变化,最后n1会停在最后一个位置,这个时候逆置完成。

struct ListNode* reverseList(struct ListNode* head)
{
  struct ListNode* n1,*n2,*n3;
  n1 = NULL;
  n2 = head;
  if(n2)
  n3 = n2->next;
  while(n2)
  {
      n2->next = n1;
      n1 = n2;
      n2 = n3;
    if(n3)
      n3 = n3->next;
  }
  return n1;
}

思路二:

struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode* newhead = NULL;
    struct ListNode* cur = head;
    while(cur)
    {
        struct ListNode* next = cur->next;
        //头插新节点,更新头
        cur->next = newhead;
        newhead = cur;
        cur = next;
    }
    
    return newhead;
}

题二:移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

思路一:

分别定义结构体指针类型的n1=head,n2=NULL,在链表上进行n1->val == val,不同则不改变,相同则跳过这个结构体指针地址,指向下一个结构体的地址,然后free释放值相同的地址,循环操作到指向NULL地址,当然,如果第一个位置就与val相同,则,跳过这个地址,指向下一个地址。

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* n1 = head, * n2 = NULL;
    while (n1)
    {
        if (n1->val == val)
        {
            if (head == n1)
            {
                head = n1->next;
                free(n1);
                n1 = head;
            }
            else
            {
                n2->next = n1->next;
                free(n1);
                n1 = n2->next;
            }
        }
        else
        {
            n2 = n1;
            n1 = n1->next;
        }
    }
    return head;
}

思路二:

开辟一个newnode,n1=head,n2=NULL;让原链表中与val不相同的位置放到新开辟的结构体指针中,依次放入,最后将newnode的最后一个地址的next==NULL,完成移除。

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* n1 = head;
    struct ListNode* newnode = NULL;
    struct ListNode* n2 = NULL;
    while (n1)
    {
        if (n1->val == val)
        {
            struct ListNode* tail = n1->next;
            free(n1);
            n1 = tail;
        }
        else
        {
            if (n2 == NULL)
            {
                n2 = n1;
                newnode = n2;
            }
            else
            {
                n2->next = n1;
                n2 = n2->next;
            }
            n1 = n1->next;
        }
    }
    if (n2)
        n2->next = NULL;
    return newnode;
}

题三:链表的中间节点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

思路一:

分别定义快慢两个指针,快指针一次前进两个地址,慢指针一次前进一个地址,当奇数时快指针的next为NULL时,当链表为偶数时判断条件为地址为NULL,停下来,此时慢指针就在链表中间节点上。

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast && fast->next)
    {
        
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

题四:链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

思路一:

分别定义快慢两个指针,快指针fast先前进k个地址,然后fast和slow开始同时每次前进一个地址,一直到fast的地址为NULL时,停下来,这时的slow就是倒数第k个节点。排除倒数第0个和传递的指针为NULL的两种情况,直接return NULL。

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) 
{
    
    struct ListNode* fast = pListHead;
    struct ListNode* slow = pListHead;
       //方法一:
        while(k--)
        {
            if(fast)
                fast = fast->next;
            else
                return NULL;
        }
//方法二:
//if (pListHead == NULL)
//{
//    return NULL;
//}
//if (k == 0)
//{
//    return NULL;
//}
//for (int i = 0; i < k; i++)
//{
//    if (fast == NULL)
//    {
//        return NULL;
//    }
//    fast = fast->next;
//
//}
    while(fast)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}

题五:合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

思路一:

创建一个新的结构体指针newnode=NULL,n1=list1,n2=list2,写一个tail=NUL来遍历newnode,先判断list1和list2是否为空,为空则返回另一方,均不为空则,则按如下图循环放入newnode,循环到有一方为NULL,做一个判断将另一方在newnode后接上。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;
    struct ListNode* n1 = list1;
    struct ListNode* n2 = list2;
    struct ListNode* newnode = NULL;
    struct ListNode* tail = NULL;
    while(n1 && n2)
    {
        if(n1->val >= n2->val)
        {
            if(tail == NULL)
            {
                tail = n2;
                newnode = tail;
                n2 = n2->next;
            }
            else
            {
                tail->next = n2;
                tail = tail->next;
                 n2 = n2->next;
            }
        }
        else
        {
            if(tail == NULL)
            {
                tail = n1;
                newnode = tail;
                n1 = n1->next;
            }
            else
            {
                tail->next = n1;
                tail = tail->next;
                n1 = n1->next;
            }
        }
    }
    if(n1)
    {
        tail->next = n1;
    }
    if(n2)
    {
        else
        tail->next = n2;
    }
    return newnode;
}

简化后:

/*
解题思路:
此题可以先创建一个空链表,然后依次从两个有序链表中选取最小的进行尾插操作进行合并。
*/
typedef struct ListNode Node;
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
        if(l1 == NULL)
            return l2;
        else if(l2 == NULL)
           return l1;
             
        Node* head = NULL, *tail = NULL;
        //创建空链表
      head = tail = (Node*)malloc(sizeof(Node));
        tail->next = NULL;
        while(l1 && l2)
        {
            // 取小的进行尾插
            if(l1->val < l2->val)
            {
                tail->next = l1;
                tail = tail->next;
                l1 = l1->next;
            }
            else
            {
                tail->next = l2;
                tail = tail->next;
                l2 = l2->next;
            }
        }
        //剩余元素直接拼接
        if(l1)
            tail->next = l1;
        else
            tail->next = l2;
        Node* list = head->next;
        free(head);
        return list;
}

本人实力有限可能对一些地方解释的不够清晰,可以自己尝试读代码,望海涵!

目录
相关文章
|
3月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
4月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
125 2
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
43 1
|
3月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
2月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
96 0
|
2月前
力扣(LeetCode)数据结构练习题(2)
力扣(LeetCode)数据结构练习题(2)
32 0
|
2月前
|
存储
力扣(LeetCode)数据结构练习题
力扣(LeetCode)数据结构练习题
57 0
|
4月前
|
算法 Python
【Leetcode刷题Python】 LeetCode 2038. 如果相邻两个颜色均相同则删除当前颜色
本文介绍了LeetCode 2038题的解法,题目要求在一个由'A'和'B'组成的字符串中,按照特定规则轮流删除颜色片段,判断Alice是否能够获胜,并提供了Python的实现代码。
58 3
|
4月前
|
算法 Python
【Leetcode刷题Python】剑指 Offer 33. 二叉搜索树的后序遍历序列
本文提供了一种Python算法,用以判断给定整数数组是否为某二叉搜索树的后序遍历结果,通过识别根节点并递归验证左右子树的值是否满足二叉搜索树的性质。
27 3
|
4月前
|
Python
【Leetcode刷题Python】50. Pow(x, n)
本文介绍了LeetCode第50题"Pow(x, n)"的解法,题目要求实现计算x的n次幂的函数,文章提供了递归分治法的详细解析和Python实现代码。
30 1