【OJ】关于顺序表的经典题目(移除数组中指定元素的值、数组去重、合并两个有序的数组)

news2024/11/16 4:24:56

文章目录

  • 前言
  • 题目1:移除数组中指定的元素
    • 题目描述
    • 解题思路
      • 方法1 :暴力法
      • 方法2:双指针法
  • 题目2:数组去重
    • 题目描述
    • 解题思路
      • 双指针法
  • 题目3:合并两个有序的数组
    • 题目描述
    • 解题思路
      • 方法1:暴力破解法
      • 方法2:从后往前

前言

通过有关顺序表的知识讲解,相信大家或多或少都对顺序表有一定的了解。

那么在本文中,我们将会给出几道有关于顺序表(个人觉得于数组的相关性较大)经典的代码练习题,并且总结一些做题的经验,呈现给大家。
哈哈哈

题目1:移除数组中指定的元素

题目链接:移除元素 - LeetCode

题目描述

题目表述
示例

解题思路

方法1 :暴力法

相信很多人看到这道题的时候,会不自觉的这样想:我先遍历题目所给的数组,在遍历的过程中,将每个数组中的每个元素与题目所给的那个val进行比较。如果不相等的话,我就把那个元素赋值到我新建的数组中。

由于这个想法比较简单,这里我就不画图进行讲解了。

实现的代码如下:

//方法1:暴力法
#include<stdlib.h>
int removeElement(int* nums, int numsSize, int val) {
    
    //创建一个与题目所给数组一样大小的空间
    int* newnums = (int*)malloc(sizeof(int)*numsSize);

    if (newnums == NULL)
    {
        perror("malloc fail");
        exit(1);
    }
    //开始进行删除数据
    int i = 0;
    int count = 0;
    while (i < numsSize)
    {
        if (nums[i] != val)
        {
            newnums[count++] = nums[i];
        }
        i++;
    }

   
    return count;
}

方法2:双指针法

图解

相信经过上面的描述,已经对双指针的用法有了初步的感觉了!如果还不会的话,不用担心,本文后面的题目仍会用到双指针法的。

实现的代码如下:

int removeElement(int* nums, int numsSize, int val) {

    //创建两个指针,但对于数组来说下表的移动也可以相当是指针的移动
    int src = 0, dst = 0;

    while (src < numsSize)
    {
        if (nums[src] != val)
        {
            nums[src++] = nums[dst++];
        }
        else
        {
            src++;
        }
    }

    return dst;

}

题目2:数组去重

题目链接:数组去重 - LeetCode

题目描述

题目描述
案例演示

解题思路

这题的难点在于原地删除重复出现的元素,这个就意味着我们无法像上面那道题一样创建新数组去完成了。

那该怎么办呢?在仔细看一下条件,题目还说了数组的元素是非严格递增排列的。但是我们有前面移除数组元素题目做铺垫,这两道题的共性都在于删除元素。

那我们可以先用双指针法来尝试做一下这道题!

思路

解题过程

这里你会发现,指针src就像一个侦察兵,dst指针就像一个大本营。当指针src发现前面有埋伏时,它就会跟大本营说,前面有埋伏,你不要过来,让我看看还有哪个地方时没有敌人的埋伏的。当发现没有埋伏是,大本营就会根据src传递的信息记录下这个没有埋伏的地方!

看到这里,你会发现:噢,双指针法真的能解决这个问题。但是你再仔细思考一下,如果数组是乱序的话,还能不能这样做?
很显然是不能的,因为dst指针指向的位置一旦被赋值之后,dst指针就会往下挪动一个位置。那假如,src在数组很后面的位置找到了dst之前那个位置的值,那就没有办法检测到了。

双指针法

代码实现:

//双指针法
int removeDuplicates(int* nums, int numsSize)
{
    int dst = 0, src = 1;

    while (src < numsSize)
    {
        if (nums[dst] == nums[src])
        {
            //说明,src位置的元素是重复出现的。我们就要记录下来这个位置。
            //做法就是,我们可以先不动dst位置,等到值不一样的时候,再移动并赋值。
            src++;
        }
        else
        {
            nums[++dst] = nums[src++];
        }
    }

    return dst+1;
}

可能有的读者这里会问,能不能在nums[dst] == nums[src]的时候,将dst和src指针都移动一个位置。答案是不能!
自己画图就可以理解这一点了。

也许看到这里,你会说双指针法很好用!确实,它非常的好用!


题目3:合并两个有序的数组

题目链接:合并两个有序的数组 - LeetCode

题目描述

题目描述
案例演示

解题思路

按照题目的要求给了我们两个非递减顺序排列的数组。目的就是让我们合并它们,并且合并之后数组是按照非递减顺序排列的。

那该怎么做呢?我们在没有思路时,可以先去看一下题目给出的一些案例。不过我相信有一个方法是大家都能想到的,这里我姑且叫它暴力破解法

方法1:暴力破解法

将两个有序数组合并成一个数组之后,在使用排序算法,将它变成有序的!没错这个方法的确可行。

代码实现如下:

//思路:先将两个数组合并之后,再排序
#include<stdlib.h>
int compare_int(const void* x, const void* y)
{
	return *((int*)x) - *((int*)y);
}

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {

	//申请一块地址空间,用于存放两个数组合并之后的数组
	int* nums = (int*)malloc(sizeof(int) * (m + n));
	if (nums == NULL)
	{
		perror("malloc fail");
		exit(1);
	}
	int count = 0;
	for (int i = 0; i < m; i++)
	{
		nums[count++] = nums1[i];
	}

	for (int i = 0; i < n; i++)
	{
		nums[count++] = nums2[i];
	}

	//这里使用qsort函数进行排序
	qsort(nums,m+n,sizeof(int),compare_int);

}

方法2:从后往前

前置
思路分析
过程
代码实现:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    
    int n1 = m -1 , n2 = n - 1;
    int end = n1 + n2 + 1;
    
    
    while(n1 >= 0 && n2 >= 0)
    {
        if(nums1[n1] > nums2[n2])
        {
            nums1[end--] = nums1[n1--];
        }
        else
        {
            nums1[end--] = nums2[n2--];
        }
    }

    //循环退出之后,一定有个数组还未遍历完。
    //如果是nums1这个数组未遍历完,其实可以不用给它单独处理
    //因为,题目要求返回的是nums1

    //如果是nums2的话,那就要给它处理一下
    while(n2 >= 0)
    {
        nums1[end--] = nums2[n2--];
    }
    //}
    
}

到这里,我们习题就已经全部讲完了。

本文主要讲解了一种解题方法:双指针法,针对这个方法,我会还会再出题目的讲解的!

如果觉得本文讲的还不错的话,麻烦给偶点个赞吧!!!

哈哈哈

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

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

相关文章

SAP F110 批量付款付款参考(KIDNO)和分配字段(ZUONR)带入会计凭证

SAP F110 批量付款付款参考(KIDNO)和分配字段(ZUNOR)带入会计凭证 财务有个要求需要将付款建议的付款参考和分配字段写入最后的ZP凭证 最后的效果大概就是这样的 折腾了很久, 1、先是想到的GGB1的替代,但是试验了很久都没有搞定,貌似很多人遇到了这个情况。 2、然后…

初识爬虫4

1.理解代理ip&#xff0c;正向代理和反向代理 2.代理ip分类&#xff0c;根据匿名度分类&#xff1a;透明&#xff0c;匿名&#xff0c;高匿 3.防止频繁向同一个域名发送请求被封ip,需使用代理ip # -*- coding: utf-8 -*- import requestsurl https://www.baidu.comproxies {…

Facebook如何通过AI改变你的社交体验?

在当今数字化的社交媒体环境中&#xff0c;Facebook作为全球最大的社交平台之一&#xff0c;正在通过引入和优化人工智能&#xff08;AI&#xff09;技术&#xff0c;改变用户的社交体验。人工智能不仅帮助Facebook增强了内容推荐和信息过滤的精准度&#xff0c;还让平台具备了…

故障恢复(残次版)

视频地址 一&#xff1a;文件系统故障修复案例 模拟搞坏磁盘中的某一块 dd if/dev/zero of/dev/sdb1 bs1k count10(默认4K)1.修补分区中每个组中坏掉的超级块部分 查看超级块的备份块 dumpe2fs 磁盘位置 如&#xff1a; dumpe2fs /dev/sdb1使用备份超级块进行修复&#x…

Netty笔记01-Netty的基本概念与用法

文章目录 1. 概述1.1 Netty 是什么&#xff1f;1.2 Netty 的特点1.3 Netty 的作者1.4 Netty 的地位1.5 Netty 的优势1.6 Netty 的工作原理1.7 Netty 的应用场景1.8 Netty 的重要组件 2. 第一个程序2.1 目标2.2 服务器端2.3 客户端2.4 流程梳理&#x1f4a1; 提示 1. 概述 1.1 …

【香菇的程序人生】七夕舔狗反诈指南:技术篇

本文设计技术分析及部分参考网站仅供技术研究及自我保护&#xff0c;请勿用于其他用途&#xff01; 另外&#xff0c;为什么本文只针对"舔狗"呢?因为舔狗不愿面对事实&#xff0c;本文将从科学技术角度给其指点迷津~ 文章目录 1. 你的女神/男神保熟吗1.1 AI 换脸请谨…

关于ADC单次扫描和连续扫描的操作指导(STM32F103ZET6正点原子版)作者 江汉大学 计科224尹伦能

STM32CubeMX环境配置 1 ADC1配置 选中ADC1&#xff0c;然后勾选IN0&#xff0c;其余设置均默认不变&#xff08;此为单次扫描&#xff0c;若是连续扫描&#xff0c;只需要将上图中的Continuous Conversion Mode由Disabled变为Enabled即可&#xff09;。 2 RCC及时钟配置 选中…

分析 ECharts 图表渲染导致的内存泄漏问题 - 附解决方案

一. 引言 在今年某个可视化大屏项目中&#xff0c;出现了一个问题。项目在运行一段时间后&#xff0c;页面出现了崩溃&#xff0c;而且是大概运行几天之后&#xff0c;因为大屏项目是部署到客户现场大屏&#xff0c;长时间运行不关闭。报错问题如下图所示&#xff1a; 由于这个…

重磅发布!DeepSeek-V2.5:融合通用与代码能力的全新开源模型

前沿科技速递&#x1f680; 在人工智能飞速发展的今天&#xff0c;通用对话与代码生成的融合已经成为开发者高效工作的关键工具。近日&#xff0c;DeepSeek 团队正式发布了全新的 DeepSeek-V2.5 模型&#xff0c;一个强大的开源模型&#xff0c;它将通用语言处理与代码生成能力…

Python爱心射线

系列目录 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…

高效录屏攻略:电脑视频录制时声音同步捕获技巧,轻松搞定高清音质

在当今数字化时代&#xff0c;无论是在线教育、远程工作还是内容创作&#xff0c;录制视频已经成为我们生活中不可或缺的一部分。但是&#xff0c;很多人在录制视频时都会遇到一个问题&#xff1a;如何同时录制声音&#xff1f;如果你也在为此烦恼&#xff0c;那么这篇文章将为…

OpenCV通过鼠标提前ROI(C++实现)

文章目录 鼠标绘制矩形提取ROI任意形状绘制提前ROI 废话不多说&#xff0c;直接上代码 鼠标绘制矩形提取ROI #include <iostream> #include <opencv2\opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/core/core.hpp>us…

算法_优先级队列---持续更新

文章目录 前言最后一块石头重量题目要求题目解析代码如下 数据流中的第K大元素题目要求题目解析代码如下 前K个高频单词题目要求题目解析代码如下 数据流的中位数题目要求题目解析代码如下 前言 本文将会向你分享优先级队列相关的题目&#xff1a;最后一块石头重量、数据流中的…

【运维自动化-作业平台】脚本版本管理如何使用

在蓝鲸作业平台中&#xff0c;执行脚本是最常见的功能之一&#xff0c;支持快速录入脚本执行和引用脚本执行&#xff0c;引用的脚步即单独写好的&#xff0c;并且由定期管理更新的脚本&#xff0c;主要有业务脚本和公共脚本两种。快速脚本 手动页面编写的脚本&#xff0c;没有…

将小写字母转换为大写字母(c 语言)

2.我们第一步输入字符串&#xff0c;第二步进行筛选将字符串中所以下标为奇数位置上的字母转换成大写&#xff0c;如果该位置不是字母&#xff0c;则不转换。 #include <stdio.h> #include <string.h> void fun( char *ss ) {int i 0;while (*ss ! \0){if (i % 2…

ACL 2024:交叉领域情感分析——论文阅读笔记

前言 阅读了一篇ABSA的论文&#xff0c;在这里写下自己的一些理解小笔记&#xff0c;可能有点小乱&#xff0c;原文在这下面&#xff1a; 论文链接&#xff1a;Refining and Synthesis: A Simple yet Effective Data Augmentation Framework for Cross-Domain Aspect-based Sen…

swoole协程 是单线程的,还是多线程的

Swoole 协程本质上是单线程的&#xff0c;但它可以在多个线程中运行。因此&#xff0c;Swoole 协程既可以看作是单线程的&#xff0c;也可以在多线程的环境下运行&#xff0c;这取决于你如何使用 Swoole。 理解 Swoole 协程的运行模式 1 单线程中的协程&#xff1a; 在一个单…

构建常态化安全防线:XDR的态势感知与自动化响应机制

当前&#xff0c;网络安全威胁日益复杂多变&#xff0c;企业正面临前所未有的严峻挑战。为有效应对这些挑战&#xff0c;态势感知与自动化响应机制在提升网络安全运营效率与防御效果中扮演着至关重要的角色。它们能够实时监测网络状态&#xff0c;智能分析潜在威胁&#xff0c;…

浏览器中的JavaScript核心BOM(浏览器对象模型)重点掌握对象之History对象的属性与方法

History对象是用来把网页浏览历史用类似栈的方式进行表示。 这定义听起来非常的抽象&#xff0c;其实History对象的作用就跟浏览器的前进和后退很像&#xff0c;我们来用几幅图来理解一下。首先我们先回顾一下浏览器的返回上一个页面 和 跳转到下一个页面 这两个功能。 就类似…

【计算机网络】网络通信中的端口号

文章目录 一、引入端口号二、端口号的作用三、端口号的确定 在TCP/IP协议中&#xff0c;传输层有两个重要的协议&#xff1a;TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;。TCP用于提供可靠的数据传输&#xff0c;而UDP则适合用于广播…