简单记录牛客top101算法题(初级题C语言实现)BM17 二分查找 BM21 旋转数组的最小数字 BM23 二叉树的前序遍历

1. BM17 二分查找

   要求:给定一个 元素升序的、无重复数字的整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标(下标从 0 开始),否则返回 -1。

输入:[-1,0,3,4,6,10,13,14],13
返回值:6
说明:13     出现在nums中并且下标为6   

1.1 自己的整体思路

  1. 使用二分法,先定义三个指针,左指针,右指针,中间指针。
  2. 比较中间指针对应数值与目标数值是否相等,如果相等直接返回该点索引;如果目标值大于中间值,则移动左指针,另其为中间指针加上1;如果目标值小于中间值,则移动右指针,另其为中间指针减1。
  3. 直到左指针大于右指针,结束整个循环,这时是没有找到与目标值对应的索引的。
#include <stdbool.h>
#include <stdlib.h>
int search(int* nums, int numsLen, int target ) {// write code hereint n_pre = 0;                           //首指针位置int n_next = numsLen - 1;                //尾部指针位置int n_mid = (n_pre + n_next) / 2;        //中间指针位置if (numsLen == 0) {                      //数组为空的情况return -1;}while ( nums[n_mid] != target ) {        //中间值是否等于目标值if ( nums[n_mid] < target) {         //目标值在中间右侧n_pre = n_mid + 1;                //更新左索引n_mid = (n_pre + n_next)/2;       //更新中间索引}else {n_next = n_mid - 1;                //更新右索引n_mid = (n_pre + n_next)/2;       //更新中间索引}if ( n_pre > n_next ) {                //左指针大于右指针,结束整个循环return -1;}}return n_mid;
}

  开始上面的结束条件写成了这样的了:

    if ( n_pre == n_next ) {                  //没有找到,最终两个索引会重合   会出现在右边的情况,不是一直到最后都会重合的if (nums[n_pre ] == target) {return n_pre ;}else {return -1;}}

  认为两个指针一定会重合,只要判断重合时候的情况就能结束整个循环,但是未通过所有的测试。

1.2 其他的方法(标准判断方法)

  判断条件是左索引是否大于右索引。

int search(int* nums, int numsLen, int target ) {// write code hereif(numsLen == 0) return -1;int left=0, right=numsLen-1;while(left<=right) {int mid = left+(right-left)/2;if(nums[mid]==target) return mid;if(nums[mid]<target) left=mid+1;if(nums[mid]>target) right=mid-1;}return -1;
}

2. BM21 旋转数组的最小数字

   要求:有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

输入:[3,4,5,1,2]
返回值:1

  这个题开始使用的分类讨论的情况,情况太多了,最后也没有写出来,下面是参考大佬的写法:
核心思想:

1.计算中间位置 mid,并与 right 指针所指向的元素进行比较:
 如果 rotateArray[mid] > rotateArray[right],说明最小值在 mid 右侧,将 left 更新为 mid + 1。
 如果 rotateArray[mid] < rotateArray[right],说明最小值在 mid 左侧或就是 mid,将 right 更新为 mid。
 如果 rotateArray[mid] == rotateArray[right],无法确定最小值在哪一侧,但是可以排除 right 指针所指向的元素,将 right 向前移动一位,缩小搜索范围。
2. 循环继续,直到 left 和 right 指针相邻或重合。最终,right 指向的位置即为最小值所在位置。

int minNumberInRotateArray(int* rotateArray, int rotateArrayLen ) {int left=0, right=rotateArrayLen-1;while(left<right) {int mid = left+(right-left)/2;if(rotateArray[mid]>rotateArray[right]) left=mid+1;         //说明最小值在右边else if(rotateArray[mid]<rotateArray[right]) right=mid;     //说明最小值在左边else right--;    //22212或者10111                            //不能说明在左边还是右边,但是肯定不是右值,索引减去1再进行比较                        //关注右边,从右边出发}return rotateArray[right];
}

3. BM23 二叉树的前序遍历

   要求:给你二叉树的根节点 root ,返回它节点值的前序遍历。
                    在这里插入图片描述

输入:{1,#,2,3}
返回值:[1,2,3]

3.1 自己的整体思路

  1. 使用二叉树的前序遍历方法,递归完成二叉树元素的访问。
  2. 这里访问二叉树的元素,需要传一个变量(接收数组的索引地址),因为最后结果需要返回该索引值。

具体代码如下:

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
void visit_root(struct TreeNode* p ,int *arr, int *a){         //访问二叉树的元素,存到数组中去*(arr + *a) = p->val;//arr[*a] = p->val;    //写成这样也是可以的// *a++;               //这样是错的,优先级不一样,++的优先级要高(*a)++;          //索引加1}void  Preorder(struct TreeNode* p , int *arr, int *a){        //遍历二叉树if (p != NULL) {visit_root(p , arr, a);Preorder(p->left,  arr, a);    //递归左子结点         //这行代码为空的时候,才会运行到下一行Preorder(p->right, arr, a );   //递归右子结点}
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){//前序遍历 先根,再左,再右struct TreeNode* cur =  root;                           //接收根结点int*  result = (int *)malloc(100 * sizeof(int));        //申明一个100的空数组int a = 0;                                              //接收数组的索引int *i = &a;                                            //接收a的地址Preorder(cur, result, i);                               //遍历二叉树 *returnSize = *i;                                       //必须给行号 ,卡了半天return result;
}

3.2 大佬的方法

  1. 先判断二叉树有多少元素,这样再动态申请多大的内存。
  2. 遍历二叉树即可。
int TreeSize(struct TreeNode* root)
{if(root==NULL){return 0;}return TreeSize(root->left)+TreeSize(root->right)+1;
}
void preorder(struct TreeNode* root, int* a,int *i) 
{if(root==NULL){return ;}a[*i]=root->val;++(*i);preorder(root->left,a,i);preorder(root->right,a,i); 
}
int* preorderTraversal(struct TreeNode* root, int* returnSize ) 
{  int i=0; int size=TreeSize(root);int* a=(int*)malloc(size*sizeof(int));preorder(root,a,&i);*returnSize=size;return a;
}

3.3 小结

3.3.1 malloc函数

   malloc(memory allocation)函数是用于动态分配内存的标准库函数之一。它是在程序运行时从堆(heap)中申请一块指定大小的内存空间,以供程序使用。
   malloc函数的原型如下:
size:要分配的内存空间的大小,以字节为单位。通常使用sizeof运算符来计算要分配的空间大小,以确保正确性。
返回值:malloc函数返回一个void指针,指向已分配内存块的起始地址。由于返回类型是void *,您需要将这个通用指针转换为适当类型的指针,然后才能访问和操作分配的内存。

void *malloc(size_t size);

   举例分配一个包含10个int元素的数组:

 int *array = (int *)malloc(10 * sizeof(int));

注意:

  1. malloc分配的内存块是未初始化的,其中的值是不确定的。您应该确保在使用之前将其初始化。
  2. 在使用完分配的内存后,必须使用free函数释放它,以避免内存泄漏。
  3. 在调用malloc后,应该检查返回的指针是否为NULL,以防止内存分配失败。
  4. malloc函数分配的内存是在堆上,与局部变量不同,不会在函数退出后销毁,需要手动释放。

3.3.2 *和++的优先级

++操作符的优先级比*操作符更高,因此会先执行++操作,然后再执行*操作。下面的a是一个int型变量指针
*a++;       //指针会往下加1,再去该地址里面的值,地址变了
(*a)++;     //取指针a对应的变量值,把变量值加1,地址没变

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

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

相关文章

【云原生】K8S存储卷:PV、PVC详解

目录 一、emptyDir存储卷二、hostPath存储卷三、nfs共享存储卷四、PVC 和 PV4.1 NFS使用PV和PVC4.2创建动态PV 一、emptyDir存储卷 容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。首先&#xff0c;当容器崩溃时&#xff0c;ku…

UG NX二次开发(C++)-PK函数创建一条圆弧曲线

文章目录 1、前言2、创建一个项目3、添加头文件4、在do_it中添加创建圆曲线的源代码5、调用dll6、再创建一个长方体验证1、前言 采用PK进行UG NX二次开发,现在看到的文章很多是直接创建实体,然后在UG NX的视图区显示出来,对于创建圆曲线的文章不多,本文讲一下PK函数创建圆…

Git 代码分支规范

目的 俗话说&#xff1a;没有规矩&#xff0c;不成方圆。遵循一个好的规章制度能让你的工作事半功倍。同时也可以展现出你做事的认真的态度以及你的专业性&#xff0c;不会显得杂乱无章&#xff0c;管理困难。Git分支规范也是一样。当遵循了某种约定的Git分支&#xff0c;在代…

若依框架浅浅介绍

由若依官网所给介绍可知 1、文件结构介绍 在ruoyi-admin的pom.xml文件中引入了ruoyi-framework、ruoyi-quartz和ruoyi-generatior模块&#xff0c;在ruoyi-framework的pom.xml文件中引入了ruoyi-system模块。 2、技术栈介绍 前端&#xff1a;Vue、Element UI后端&#xff1a…

第1章:绪论

科学、技术、工程、应用 科学&#xff1a;是什么、为什么技术&#xff1a;怎么做工程&#xff1a;怎样做的多快好省应用&#xff1a;怎么使用 定义 机器学习&#xff1a;利用经验改善系统自身的性能。 研究 智能数据分析&#xff08;数据分析算法&#xff09; 典型的机器…

电脑ip地址怎么改 ip地址怎么改到别的城市

一、ip地址怎么改到别的城市 1.ip地址怎么改到别的城市&#xff0c;1、重启WIFI路由设备 一般手机或电脑在家或公司上网时都是接入到路由器的WIFI网络,再由路由器分配上网IP地址,如果要更换上网IP那么重启路由器设备后,路由器会向网络运营商进行宽带的重新拨号,此时手机或电脑设…

【【verilog 典型电路设计之加法器树乘法器】】

verilog 典型电路设计之加法器树乘法器 加法器树乘法器 加法器树乘法器的设计思想是“移位后加”&#xff0c;并且加法运算采用加法器树的形式。乘法运算的过程是&#xff0c;被乘数与乘数的每一位相乘并且乘以相应的权值&#xff0c;最后将所得的结果相加&#xff0c;便得到了…

selenium.webdriver Python爬虫教程

文章目录 selenium安装和使用 selenium安装和使用 pip install selenium 下载对应的浏览器驱动 实例化浏览器 from selenium import webdriverbrowser webdriver.Chrome()元素定位 控制浏览器

HTB-Keeper

HTB-Keeper 信息收集80端口 lnorgaardroot 信息收集 80端口 80主页给了一个跳转的链接 跟随链接后到了一个登陆界面。 尝试搜索默认密码。 通过账号root:password登录。不知道为什么我登陆了两次才成功。 通过搜索在Admin->Users->Select里面发现了用户信息。 lno…

WS2812B————动/静态显示

一&#xff0c;系统架构 二&#xff0c;芯片介绍 1.管脚说明 2.数据传输时间 3.时序波形 4.数据传输方法 5.常用电路连接 三&#xff0c;代码展示及说明 驱动模块 在驱动模块首先选择使用状态机&#xff0c;其中包括&#xff0c;空闲状态&#xff0c;复位清空状态&#xff0c…

怎么把图片表格转换成word表格?几个步骤达成

在处理文档时&#xff0c;图片表格的转换是一个常见的需求。而手动输入表格是非常耗时的&#xff0c;因此&#xff0c;使用文本识别软件来自动转换图片表格可以大大提高工作效率。在本文中&#xff0c;我们将介绍如何使用OCR文字识别技术来将图片表格转换为Word表格。 OCR文字识…

15.3 【Linux】循环执行的例行性工作调度

相对于 at 是仅执行一次的工作&#xff0c;循环执行的例行性工作调度则是由 cron &#xff08;crond&#xff09; 这个系统服务来控制的。刚刚谈过 Linux 系统上面原本就有非常多的例行性工作&#xff0c;因此这个系统服务是默认启动的。另外&#xff0c; 由于使用者自己也可以…

栈和队列--受限制的线性表

目录 和队列的定义和特点 1.1栈的定义和特点、 1.2队列的定义和特点 1.3栈和队列的应用 2.栈的表示和操作的实现 2.1栈的类型定义 2.2顺序栈的表示和实现 2.2.1初始化 2.2.2入栈 2.2.3出栈 2.2.4取栈顶元素 2.3链栈的表示和实现 2.2.1初始化 2.2.2入栈 2.2.3出栈…

Java-运算符和控制语句(下)(基于c语言的补充)

输出到控制台 System.out.println(msg); // 输出一个字符串, 带换行 System.out.print(msg); // 输出一个字符串, 不带换行 System.out.printf(format, msg); // 格式化输出 从键盘输入 使用 Scanner 读取字符串/整数/浮点数 首先需要导入util包 自动导入util包 这里把回车看…

如何选择最佳的文件传输协议?(FTP、TFTP、Raysync)

在数字化时代&#xff0c;通过互联网传输文件是一项常见的任务。因此&#xff0c;选择适合您企业需求的文件传输协议非常重要。 文件传输协议是发送方和接收方之间的一套规则和信息。它的作用就像网络两端都能理解的一种语言&#xff0c;使得数据可以正确输出并带有正确的文件…

【高频面试题】JVM篇

文章目录 一、JVM组成1.什么是程序计数器2.什么是Java堆&#xff1f;3.能不能介绍一下方法区(元空间&#xff09;4.你听过直接内存吗5.什么是虚拟机栈6.垃圾回收是否涉及栈内存&#xff1f;7.栈内存分配越大越好吗&#xff1f;8.方法内的局部变量是否线程安全&#xff1f;9.什么…

NIO 非阻塞式IO

NIO Java NIO 基本介绍 Java NIO 全称 Java non-blocking IO&#xff0c;是指 JDK 提供的新 API。从 JDK1.4 开始&#xff0c;Java 提供了一系列改进的输入/输出的新特性&#xff0c;被统称为 NIO&#xff08;即 NewIO&#xff09;&#xff0c;是同步非阻塞的。NIO 相关类都被…

netty学习分享 二

操作系统IO模型与实现原理 阻塞IO 模型 应用程序调用一个IO函数&#xff0c;导致应用程序阻塞&#xff0c;等待数据准备好。如果数据没有准备好&#xff0c;一直等待….数据准备好了&#xff0c;从内核拷贝到用户空间,IO函数返回成功指示。 当调用recv()函数时&#xff0c;系…

釉面陶瓷器皿SOR/2016-175标准上架亚马逊加拿大站

亲爱的釉面陶瓷器皿和玻璃器皿制造商和卖家&#xff0c;亚马逊加拿大站将执行SOR/2016-175法规。这是一份新的法规&#xff0c;规定了含有铅和镉的釉面陶瓷器和玻璃器皿需要满足的要求。让我们一起来看一看&#xff0c;为什么要实行SOR/2016-175法规&#xff1f;这是一个保护消…

使用SpringAop切面编程通过Spel表达式实现Controller权限控制

目录 参考一、概念SpEL表达式 二、开发引入包定义注解定义切面定义用户上下文 三、测试新建Service在方法上注解新建Service在类上注解运行 参考 SpringBoot&#xff1a;SpEL让复杂权限控制变得很简单 一、概念 对于在Springboot中&#xff0c;利用自定义注解切面来实现接口…