剑指offer----C语言版----第一天

news2024/12/26 11:17:03

目录

1. 数组中重复的数字Ⅰ

 1.1 题目描述

1.2 思路一

1.3 思路二

 1.4 思路三(最优解)


1. 数组中重复的数字Ⅰ

原题:剑指 Offer 03. 数组中重复的数字 - 力扣(LeetCode)https://leetcode.cn/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

 1.1 题目描述

给你一个数组,大小为N,数组里面的值的介于 [ 0, N-1 ],要求你找出数组中任意一个重复的数字。

1.2 思路一

 我们选用一个时间复杂度为O(N*logN)的排序算法对数组进行排序,例如快速排序,堆排序,归并排序。然后再去遍历排序好的数组,找出重复的数字。解题的时间复杂度:O(N*logN),空间复杂度:O(1)。

我这里自己写了快速排序的代码,如果大家嫌麻烦可以使用C语言的库函数qsort来对数组进行排序,底层逻辑也是快速排序,但是在数据量比较小的时候用的是插入排序,库函数嘛,效率的优化是最高的。

cplusplus.com - The C++ Resources Networkhttps://legacy.cplusplus.com/大家可以使用这个来查看C语言的标准库函数。

//数字交换
void Swap(int* pa, int* pb)
{
    int temp =*pa;
    *pa = *pb;
    *pb = temp;
}

//快速排序优化算法:三数取中间
int GetMidIndex(int* arr, int left, int right)
{
	int mid = (left + right) >> 1;
	if (arr[mid] > arr[left])
	{
		if (arr[left] > arr[right])
		{
			return left;
		}
		else if (arr[mid] > arr[right])
		{
			return right;
		}
		else
		{
			return mid;
		}
	}
	// arr[mid] < arr[left]
	else
	{
		if (arr[right] > arr[left])
		{
			return left;
		}
		else if (arr[mid] > arr[right])
		{
			return mid;
		}
		else
		{
			return right;
		}
	}
}



void QuickSort(int* arr, int left,int right)
{
	if (left >= right)
	{
		return;
	}
	int index = GetMidIndex(arr, left, right);
	int begin = left;
	int end = right;
	Swap(&arr[index], &arr[begin]);
	int pivot = begin;
	
	int key = arr[begin];
	while (begin < end)
	{
		//找小的
		while (begin < end && arr[end] >= key)
		{
			--end;
		}
		arr[pivot] = arr[end];
		pivot = end;
		//找大的
		while (begin < end && arr[begin] <= key)
		{
			++begin;
		}
		arr[pivot] = arr[begin];
		pivot = begin;
	}
	pivot = begin;
	arr[pivot] = key;

    QuickSort(arr, left, pivot - 1);
    QuickSort(arr, pivot + 1, right);

}

int findRepeatNumber(int* nums, int numsSize){
    assert(nums);
    int left = 0;
    int right = numsSize - 1;
    QuickSort(nums, left, right);
    int i = 0;
    for(i = 0; i < numsSize - 1; i++)
    {
        if(nums[i] == nums[i + 1])
        {
            return nums[i];
        }
    }
    return -1;
}

1.3 思路二

我们可以利用一个简单的哈希表:开辟一个同样大小的数组arr,并将数组arr初始化为0,然后遍历原来的数组nums,将nums数组的值对应到arr相应下标的位置,让他的值加一,如果再遍历过程中遇到arr的值大于1,则找到了该重复的数字。该解题方法的时间复杂度:O(N),空间复杂度O(N),以空间换时间。

int findRepeatNumber(int* nums, int numsSize){
    int* arr = (int*)calloc(numsSize, sizeof(int));
    int i = 0;
    for(i = 0; i < numsSize; i++)
    {
        arr[nums[i]] += 1;
        if(arr[nums[i]] > 1)
        {
            free(arr);
            arr = NULL;
            return nums[i];
        }
    }
    free(arr);
    arr = NULL;
    return -1;
}

 1.4 思路三(最优解)

我们分析题目可以得到如下规律:数组大小是N,数值范围是N-1,如果说该数组没有重复的元素,那么数组中每一个下标都可以对应与其下标相同的数字,如果说有重复的数字,那么,会出现一个下标有多个与其下标相等的数字,或者出现没有与其下标相等的数字。

利用这一特性,我们可以遍历该数组,扫描到下标 i 时,首先比较这个数 m 与下标 i 是否相等,如果相等,继续扫描下一个元素。如果不相等,将m与下标为 m 的数进行比较,如果相等则找到一个重复的数字,如果不相等将 m 交换到下标为 m 的位置,对交换过来的数字继续重复上述判断即可,直到找到重复的数字。

解题的时间复杂度:O(N),空间复杂度O(1)。

下面以一组例子来演示方便理解:

void Swap(int* pa, int* pb)
{
    int temp = *pa;
    *pa = *pb;
    *pb = temp;
}

int findRepeatNumber(int* nums, int numsSize){
    int i=0;
    for(i = 0; i < numsSize; i++)
    {
        while(nums[i] != i)
        {
            if(nums[i] == nums[nums[i]])
            {
                return nums[i];
            }
            Swap(&nums[i],&nums[nums[i]]);
        }
    }
    return -1;
}

 

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

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

相关文章

Python语言快速入门上

目录 1、前言 2、变量和常量 1&#xff09;Python对象模型 2&#xff09;Python变量 二、运算符和表达式 【运算符和表达式】 【位运算符】 【逻辑运算符】 【成员运算符】 【身份运算符】 【常用内置函数】 【基本输入输出】 【模块导入与使用】 【Python代码编…

【PCB专题】Allegro导出3D文件

在PCB布局时,已经决定了大部分器件要放置的位置。如接口、主要的芯片、模块等。因为放置好器件后可能与结构干涉,如果没有发现,那么不得不在Layout的后期调整器件位置,增加工作量。所以前期布局基本确定后就需要导出3D文件给结构工程师,由他查看是否有器件与结构、螺丝孔等…

全志Tina Linux Display 开发指南支持百问网T113 D1-H哪吒DongshanPI-D1s V853-Pro等开发板

1 概述 让显示应用开发人员了解显示驱动的接口及使用流程&#xff0c;快速上手&#xff0c;进行开发&#xff1b;让新人接手工作时能快速地了解驱动接口&#xff0c;进行调试排查问题。sunxi 平台DE1.0/DE2.0。与显示相关的应用开发人员&#xff0c;及与显示相关的其他模块的开…

操作系统期末考试必会题库1——引言+用户界面

1.请简要描述操作系统的定义及其功能。 操作系统定义&#xff1a; 是计算机系统中的一个系统软件&#xff0c;是一些程序模块的集合 &#xff0c;它们管理和控制计算机系统中的软硬件资源&#xff0c;合理的组织计算机的工作流程&#xff0c;以便有效的利用这些资源为用户提供一…

Linux用户权限详解

为什么有人冲了钱就能享受至尊VIP待遇&#xff1f;为什么冲了黄钻、绿钻、紫钻就会享受一些特殊活动呢&#xff1f;我们起初都是一群普通用户&#xff0c;为什么有些人就能通过某些手段得到一些异于常人的服务呢&#xff1f;这其中的奥秘是什么呢&#xff1f;接下来带大家了解这…

【Vue】course_1

一、vue简介 Vue是一款用于构建用户界面的 JavaScript 框架。 它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。 无论是简单还是复杂的界面&#xff0c;Vue 都可以胜任。 二、vue3选项式…

ASEMI肖特基二极管MBR30100CT和MBR40200PT有什么区别

编辑-Z 别看ASEMI肖特基二极管MBR30100CT和MBR40200PT两种型号从名字上看很像&#xff0c;其实他们的参数和封装都是不一样的&#xff0c;具体MBR30100CT和MBR40200PT有什么区别呢&#xff1f; 肖特基二极管MBR30100CT参数&#xff1a; 型号&#xff1a;MBR30100CT 封装&…

[开源工具]使用Fiddler/Postman简单计算QPS[新手开箱可用]

使用Fiddler/Postman简单计算QPS1.什么是QPS?2.怎么计算QPS?3.如何使用Fiddler/Postman得到一个API接口的QPS?3.1Fiddler使用3.2Postman使用4.如何得到本机的核心数?5.根据公式计算QPS?6.扩展计算单机可支撑PV(理论值)?1.什么是QPS? qps即每秒查询率&#xff0c;是对一…

Postfix + Extmail 企业邮件服务器搭建

ExtMail套件用于提供从浏览器中登录、使用邮件系统的Web操作界面&#xff0c;而Extman套件用于提供从浏览器中管理邮件系统的Web操作界面。它以GPL版权释出&#xff0c;设计初衷是希望设计一个适应当前高速发展的IT应用环境&#xff0c;满足用户多变的需求&#xff0c;能快速进…

数据预处理和特征工程-sklearn

数据挖掘的五大流程&#xff1a; 获取数据数据预处理 数据预处理是从数据中检测&#xff0c;纠正或删除损坏&#xff0c;不准确或不适用于模型的记录的过程。 数据预处理的目的&#xff1a;让数据适应模型&#xff0c;匹配模型的需求特征工程 特征工程是将原始数据转换为更能代…

NLP 中文智能纠错 API 数据接口

NLP 中文智能纠错 API 数据接口 专注于中文语句智能纠错&#xff0c;基于 NLP&#xff0c;多模型参与纠错。 1. 产品功能 秒级 NLP 智能纠错性能&#xff1b;NLP 加载多个模型进行纠错处理&#xff1b;返回纠正字符以及对应位置索引&#xff1b;底层模型以及语料库持续更新集…

正大国际期货:五十句期货投资理念

1.许多期货投资人交易时没有计划。交易前&#xff0c;他们既不设定风险限度&#xff0c;也不设定盈利目标。即使是制定了计划&#xff0c;他们总是“半路出家”&#xff0c;并不坚持既定的计划&#xff0c;尤其是在出现亏损的情况下。结果往往是过量操作&#xff0c;把自己逼在…

Android 操作系统简介

Android 操作系统简介1. 起源2. 操作系统市场占有率3. Android 系统架构3.1 Linux Kernel3.2 Hardware Abstraction Layer (HAL)3.3 运行时 系统库3.3.1 Android Runtime3.3.1 Native C/C Libraries3.4 Java API Framework3.5 System Apps1. 起源 安卓&#xff08;Android&…

程序员年底如何升职加薪?这份涨薪指南来了!

年底了&#xff0c;这个时间节点对于各个公司来说都很重要。 今年大家也知道情况&#xff0c;互联网整体行情都不太好&#xff0c;国外也不好过&#xff0c;硅谷裁员大刀阔斧&#xff0c;实实在在的 感受到了寒意。 能顺利熬到年底的程序员&#xff0c;现在就会关心“公司会普调…

一分钟搞定Netty 三大组件,如果搞不定,再看3遍

1. 三大组件简介 Channel 与 Buffer Java NIO 系统的核心在于&#xff1a;通道 (Channel) 和缓冲区 (Buffer)。通道表示打开到 IO 设备 (例如&#xff1a;文件、套接字) 的连接。若需要使用 NIO 系统&#xff0c;需要获取用于连接 IO 设备的通道 以及用于容纳数据的缓冲区。然…

黑客使用虚假 DDoS 保护页面分发恶意软件

WordPress 网站被黑客入侵后显示欺诈性 Cloudflare DDoS 保护页面&#xff0c;这些页面被用于分发恶意软件&#xff08;例如 NetSupport RAT 和 Raccoon Stealer&#xff09;。 “最近针对 WordPress 网站的 JavaScript 注入激增&#xff0c;通过弹出虚假的 DDoS 阻止提示&…

DaVinci:跟踪器 - 窗口

调色页面&#xff1a;跟踪器Color&#xff1a;Tracker跟踪器 - 窗口 Tracker - Window&#xff0c;是 DaVinci Resolve 提供的一款强大的跟踪工具。可以利用窗口调板所设置的窗口区域&#xff0c;通过自动分析之后&#xff0c;在此区域内产生许多如云状分布的特征点&#xff08…

Java8 Stream详细用法介绍

Java8 Stream详细用法介绍一、Stream概述1.1、流的定义1.2、流与集合1.3、流的特性1.4、Stream的创建1.5、Stream操作分类二、Stream API 使用2.1 中间操作2.1.1、filter() 过滤2.1.2、map与flatMap 映射2.1.3、sorted() 排序2.2 终止操作2.2.1、forEach() 遍历2.2.2、collect(…

ThinkPHP 多应用模式下访问其他应用忽略入口文件

目录 问题描述&#xff1a; 解决方法&#xff1a; 1.配置两个域名分别指向项目public目录 2.项目全局配置域名绑定应用 问题描述&#xff1a; 使用TP6.0做多应用项目开发&#xff0c;分为前端Api和后台管理 项目中已配置地址重写规则 Api为默认应用&#xff0c;可忽略入…

Allegro如何手动和自动10度走线操作指导

Allegro如何手动和自动10度走线操作指导 PCB上有时需要10度走线,可以有效的避免玻纤效应的产生,尤其是在应对高速设计的时候,Allegro支持10度走线如下图 具体操作如下 选择setup Parameter选择route