leetcode刷题(2):链表

news2024/12/24 8:06:45

文章目录

    • 1. 两数相加
      • 1.1 解题思路
      • 1. 2 c++ 实现
    • 2 删除排序链表中的重复元素 ||
      • 2.1 解题思路
      • 2.2 c++ 实现
    • 3 旋转链表
      • 3.1 解题思路
      • 3.2 c++ 实现
    • 4 剑指 Offer 06: 从尾到头打印链表
      • 4.1 解题思路
      • 4.2 c++ 实现
    • 5 剑指 Offer 24. 反转链表
      • 5.1 解题思路
      • 5.2 c++实现
    • 21. 合并两个有序链表
      • 解题思路
      • c++ 实现
    • 147. 对链表进行插入排序
    • 114. 二叉树展开为链表

1. 两数相加

  • 题目:给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

  • 要求:请你将两个数相加,并以相同形式返回一个表示和的链表
    你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
    在这里插入图片描述

  • 提示:

    • 每个链表中的节点数在范围 [1, 100] 内
    • 0 <= Node.val <= 9
    • 题目数据保证列表表示的数字不含前导零

1.1 解题思路

要求: 返回一个新链表,存储两个逆序的链表之和,返回的新链表也是逆序排列
思路

  • 从链表的头开始按位加,就可以计算出结果
  • 根据加法原则:对应位置的计算结果为:两数之和对10取余数,同时 两数之和与10相除取整,为向前进位的数字。

1. 2 c++ 实现

  • 解题1:
class Solution{
public:
    ListNode* addTwoNumber(ListNode* l1,ListNode* l2)
    {
		ListNode* dummy = new ListNode(-1);
		ListNode p = dummy;
		bool carry =false;
		
		while (l1 || l2)
		{
			int sum =0;
			if (l1 != nullptr)
			{
				sum +=l1->val;
				l1 =l1->next;
			}
			
			if (l2 != nullptr)
			{
				sum +=l2->val;
				l2 =l2->next;
			}
			if (carry)
			{
				sum ++;
			}
			
			p->next = new ListNode(sum%10);
			p =p->next;
			if (sum >10)
			{
				carry = true;
			}
			else
			{
				carry = false;
			}
		}
		if (sum >10)
		{
		   p->next = new ListNode(1);
		}
		return dummy->next;
	}
}
  • 改进版
/**
 * 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* addTwoNumbers(ListNode* l1, ListNode* l2)
   {
   		//1. 创建一个dummy节点
   		ListNode* dummy = new ListNode(-1);
   		ListNode* p = dummy;
   		int t =0;
	   while(l1 || l2 || t)
	   {
	   	 if(l1)
	   	 {
	   	 	t += l1->val;
	   	 	l1 = l1->next;
	   	 }
	   	 if(l2)
	   	 {
	   	 	t += l2->val;
	   	 	l2 = l2->next;
	   	 }
		
		 p->next = new ListNode(t % 10);
		 p = p->next;
		 t = t/10;
	   }
	   return dummy ->next;
   }
};

2 删除排序链表中的重复元素 ||

对应为leetcode 82题,中等难度

题目: 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表
示例
在这里插入图片描述
提示

  • 链表中节点数目在范围 [0, 300] 内
  • -100 <= Node.val <= 100
  • 题目数据保证链表已经按升序 排列

2.1 解题思路

  • 链表已排序,重复元素都是连续的
  • 找到两个值相同的连续节点p1,p2,假设值都为x
  • 遍历节点,如果节点p->next值等于x(因为p为dummy节点,所以从p->next开始遍历),则删除该节点:p->next = p->next->next;

2.2 c++ 实现

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head ==nullptr || head->next ==nullptr) return nullptr;
        ListNode* dummy = new ListNode(-1);
        dummy ->next =head;
        ListNode* p=dummy;

        while (p->next && p->next->next)
        {
              if(p->next->val == p->next->next->val)
              {
                  int x =p->next->val;
                  while (p->next && p->next->val==x)
                  {
                      p->next =p->next->next;
                  }
              }
              else
              {
                  p = p->next;
              }
        }
        return dummy->next;
    }
};

3 旋转链表

对应为leetcode 61题,中等难度
题目给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置
示例:
在这里插入图片描述

3.1 解题思路

  • 移动k个位置,计算旋转数据
  • 利用旋转数据,构建链表

参考:LeetCode-轮转数组的三种方法(189)

3.2 c++ 实现

  • 解题1(击败55%)
class Solution {
public:
    void reverse(vector<int>&nums,int left,int right) 
        {
            while(left < right)
            {
                int tmp = nums[left];
                nums[left] =nums[right];
                nums[right] = tmp;
                left++;
                right--;
            }
        }

    ListNode* rotateRight(ListNode* head, int k) {
        if(head==nullptr) return nullptr;
        
        ListNode* dummy = new ListNode(-1);
        ListNode* p= dummy;
        vector<int> res;
        
        
        while(head)
        {
            res.push_back(head->val);
            head = head->next;
        }

        int len= res.size();

        reverse(res,0,len-1);
        reverse(res,0,k%len-1);
        reverse(res,k%len,len-1);

        for(auto val:res)
        {
            p->next = new ListNode(val);
            p = p->next;
        }
        
        return dummy->next;
    }

    
};
  • 解题2(击败88.54%)

每旋转一次,得到的新数组:
数组中第一个元素,为原来最后一个元素
数组中1-len-1的元素,对应原来0-(len-2)元素,相当于对原来0~len-2元素向右平移1次

class Solution {
public:
    // void reverse(vector<int>&nums,int left,int right) 
    //     {
    //         while(left < right)
    //         {
    //             int tmp = nums[left];
    //             nums[left] =nums[right];
    //             nums[right] = tmp;
    //             left++;
    //             right--;
    //         }
    //     }
    // 每旋转一次,得到的新数组:数组中第一个元素,为原来最后一个元素
    // 数组中1-len-1的元素,对应原来0~len-2元素,相当于对原来0~len-2元素向右平移1次
    void rotate3(vector<int>& nums,int k) {
        for(int i=0;i<k%nums.size();i++) {
            int temp=nums[nums.size()-1];
            for(int j=nums.size()-2;j>=0;j--) {
                nums[j+1]=nums[j];
            }
            nums[0]=temp;
        }

    }


    ListNode* rotateRight(ListNode* head, int k) {
        if(head==nullptr) return nullptr;

        ListNode* dummy = new ListNode(-1);
        ListNode* p= dummy;
        vector<int> res;
        
        
        while(head)
        {
            res.push_back(head->val);
            head = head->next;
        }

        int len= res.size();

        rotate3(res,k);

        // reverse(res,0,len-1);
        // reverse(res,0,k%len-1);
        // reverse(res,k%len,len-1);

        for(auto val:res)
        {
            p->next = new ListNode(val);
            p = p->next;
        }
        
        return dummy->next;
    }

    
};

4 剑指 Offer 06: 从尾到头打印链表

题目:输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

示例

示例 1:
输入:head = [1,3,2]
输出:[2,3,1]

4.1 解题思路

  • 获得链表所有的值
  • 利用reverse反转

4.2 c++ 实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        vector<int> res;

        while(head)
        {
            res.push_back(head->val);
            head=head->next;
        }

        reverse(res.begin(),res.end());

        return res;
    }
};

5 剑指 Offer 24. 反转链表

题目:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
== 示例==:

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

5.1 解题思路

5.2 c++实现

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        vector<int> res;
        ListNode *p= head;
        ListNode *q = head; 
        while(p)
        {
            res.push_back(p->val);
            p=p->next;
        }

        reverse(res.begin(),res.end());
        
        for(int i = 0;i < res.size();i++)
        {    
            q->val = res[i];
            q = q->next; 
        }
        return head;
    }
};

21. 合并两个有序链表

题目:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
== 示例==:
在这里插入图片描述

解题思路

  • 新链表是通过拼接给定的两个链表的所有节点组成的,所以不能单纯用值来构建链表,而是需要基于两个链表的节点构建
  • 如果两个链表都非空,比较两个链表的值,将值小的节点,赋给新的节点
  • 随着遍历,其中一个链表为空,另一个为非空,此时将非空的链表节点,分配给新链表

c++ 实现

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        // ListNode* dummy = new ListNode();
        ListNode dummy(-1);
        ListNode* p = &dummy;

        while(l1&&l2)
        {
            if(l1->val <= l2->val)
            {
                p->next = l1;
                l1 = l1->next;
            }
            else
            {
                p->next = l2;
                l2 = l2->next;
            }
            p = p->next;

        }

        while(l1)
        {
            p->next = l1;
            l1 = l1 ->next;
            p = p->next;
        }

        while(l2)
        {
            p->next = l2;
            l2 =l2->next;
            p = p->next;
        }

        return dummy.next;
    }
};

147. 对链表进行插入排序

114. 二叉树展开为链表

题目: 给你二叉树的根结点 root ,请你将它展开为一个单链表

展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。

== 示例==:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1499938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【传输层】进程之间基于网络的通信(湖科大慕课自学笔记)

进程之间基于网络的通信 我们正式进入运输层的学习&#xff0c;先介绍进程之间基于网络的通信&#xff0c;我们在之前的学习中&#xff0c;已经介绍了物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;它们共同解决并实现了主机到主机的通信 举例如下图所示&#x…

DDS技术概述及测试策略与方案

随着车载通信技术的快速发展&#xff0c;传统的通信技术在满足车载通信需求方面面临着一些挑战。车载通信对实时性、可靠性以及通信带宽的需求越来越高&#xff0c;同时车载通信环境存在多路径衰落、信号干扰等问题&#xff0c;这些都给通信技术的选择和应用带来了一定的挑战。…

VMware 集群-虚拟机配置反亲和性(互斥)

简介 博客&#xff1a;https://songxwn.com/ 为实现应用系统的冗余&#xff0c;经常会双机或者多机部署&#xff08;如数据库集群等&#xff09;。在VMware 集群里面&#xff0c;要保证不同应用集群的节点虚拟机在不同的物理宿主机上&#xff0c;防止单个宿主机故障&#xff…

Web Servlet

目录 1 简介2 创建Servlet项目并成功发布运行3 新加Servlet步骤4 Servlet项目练习5 Servlet运行原理6 操作 HTTP Request头的方法(部分方法示例)7 操作 HTTP Response头的方法(部分方法示例)8 两种重定向(页面跳转)方法9 Cookie9.1 Cookie工作原理9.2 cookie构成9.3 Servlet 操…

Unity DropDown 组件 详解

Unity版本 2022.3.13f1 Dropdown下拉菜单可以快速创建大量选项 一、 Dropwon属性详解 属性&#xff1a;功能&#xff1a;Interactable此组件是否接受输入&#xff1f;请参阅 Interactable。Transition确定控件以何种方式对用户操作进行可视化响应的属性。请参阅过渡选项。Nav…

个人商城系统开源(展示宣传)

原文地址&#xff1a;个人商城系统开源&#xff08;展示宣传&#xff09; - Pleasure的博客 下面是正文内容&#xff1a; 前言 由于近期实在没有什么话题可写和一些有趣的项目教程可以分享。所以我只能决定将我自己亲手编写的一个迷你商城系统进行开源。 也就是放在我博客右边…

Unity UGUI之Scrollbar基本了解

Unity的Scrollbar组件是用于在UI中创建滚动条的组件之一。滚动条通常与其他可滚动的UI元素&#xff08;如滚动视图或列表&#xff09;一起使用&#xff0c;以便用户可以在内容超出可见区域时滚动内容。 以下是Scrollbar的基本信息和用法: 1、创建 在Unity的Hierarchy视图中右…

Android屏幕共享-硬编码硬解码

Android屏幕共享-硬编码硬解码 说起Android之间的屏幕共享&#xff0c;第一次接触会比较陌生&#xff0c;不过大家多少有了解过ffmpeg&#xff0c;看上去是不是很熟悉&#xff1f;ffmpeg是一套处理音视频的开源程序&#xff0c;但对于C了解较少的同学&#xff0c;编译起来很复杂…

掌握这几个技术点,你也能开发出爆款ARPG游戏!

在众多ARPG游戏的发售下&#xff0c;游戏市场温度迅速升高&#xff0c;今年很可能会成为一个“ARPG手游大年”&#xff0c;或许会再次出现“神仙打架”的情况。 ARPG作为一种非常经典且流行的游戏类型, 已经诞生过无数经典的作品,比如魂系,暗黑破坏神系列,塞尔达传说系列&#…

网页在特殊日子一键变灰

<template> <div :class"{ grayscale: isGrayscale }"> <!-- 你的页面内容放在这里 --> </div> </template> <script> export default { data() { return { // 存储哀悼日的数组 aidaoriDates:["0404", &q…

Filter过滤器+JWT令牌实现登陆验证

一、背景 我们需要在客户端访问服务器的时候给定用户一定的操作权限&#xff0c;比如没有登陆时就不能进行其他操作。如果他需要进行其他操作&#xff0c;而在这之前他没有登陆过&#xff0c;服务端则需要将该请求拦截下来&#xff0c;这就需要用到过滤器&#xff0c;过滤器可以…

高速缓冲存储器(Cache)

程序访问的局部性原理 程序访问的局部性原理包括时间局部性和空间局部性。 时间局部性&#xff1a;指在最近的未来要用到的信息&#xff0c;很可能是现在正在使用的信息&#xff0c;因为程序中存在循环。空间局部性&#xff1a;指在最近的未来要用到的信息&#xff0c;很可能…

简析内部审计数字化转型的方法和路径【小落送书(第6期)】

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

利用IP地址信息提升网络安全

在计算机网络中&#xff0c;IP地址是用于唯一标识网络设备的重要标识符。然而&#xff0c;由于网络中存在大量设备&#xff0c;有时会出现IP地址冲突的情况&#xff0c;即两个或多个设备在同一网络中使用了相同的IP地址&#xff0c;这可能导致网络连接故障和通信中断。本文将介…

基于PHP的医院绩效管理系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 PHP技术简介 3 1.2 Bootstrap框架简介 3 1.3 MVC技术模式简介 3 1.4 Ajax技术简介 3 1.5 MySQL数据库简介 4 1.6本章小结 4 2 系统需求分析 5 2.1系统分析 5 2.2需求分析 8 2.2.1用户需求分析 8 2.2.2管理员需求分析 10 2…

知识付费开发:开启智慧的新篇章

在数字化时代的浪潮下&#xff0c;知识的获取与分享方式正在发生深刻变革。传统的知识传递模式逐渐被知识付费开发的新模式所取代&#xff0c;它以其独特的魅力和巨大的潜力&#xff0c;正在引领着智慧的新潮流。 知识付费开发&#xff0c;是以用户为中心&#xff0c;以知识为…

Spring Boot工程集成验证码生成与验证功能教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

基于SSM技术的宠物寄存系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术介绍 3 1.1 开发技术语言 3 1.1.1 Java 3 1.1.2 Ajax 3 1.1.3 JavaScript 3 1.2 开发框架 4 1.2.1 Spring 4 1.2.2 Spring MVC 4 1.2.3 Mybatis 4 1.2.4 Bootstrap 5 1.3 MySQL数据库 5 1.4 本章小结 6 2 系统分析 7 2.1 系统的需…

针对ETC系统的OBE-SAM模块设计方案

ETC&#xff08;Electrical Toll Collection&#xff09;不停车收费是目前世界上最先进的路桥收费方式。通过安装在车辆挡风玻璃上的车载单元与安装在收费站 ETC 车道上的路侧单元之间的微波专用短程通讯&#xff0c;利用计算机联网技术与银行进行后台结算处理&#xff0c;从而…

ubuntu上通过apt-get 安装指定版本的ecal

在ubuntu上想通过apt get直接安装ecal不自己编译源码安装的话&#xff0c; ecal官网给出的安装指令是 2. Installing eCAL — Eclipse eCAL™ sudo add-apt-repository ppa:ecal/ecal-latest sudo apt-get update sudo apt-get install ecal 要指定版本的时候 按照提示&…