算法学习day27

一、寻找重复数(链表中找环)

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

题意:

给定大小为n+1的整数数组nums,元素的范围在[1,n]中,必然有一个重复的数字。如何通过找环的思想处理这道题?当我们将数组的值和下标对应在一起的时候,有一个值是对应两个下标的。因此在这里一定会形成环。

eg:[1,3,4,2,2]。以下标0为起始,nums[i]作为下一个下标。

1.下标为0,下一个下标为nums[0]=1,1不仅为下一个下标,也为当前的值。

2.下标为1,下一个下标为nums[1]=3,

3.下标为3,下一个下标为nums[3]=2;

4.下标为2,下一个下标为nums[2]=4;

5.下标为4,下一个下标为nums[4]=2;

现在有两个位置的下标可以到达2,因此就有环出现了。

思路:

通过之前环形链表II的思路:快慢指针相遇代表有环,然后头结点到入口的距离=相遇点到入口的距离。这样就可以找到入口,也就是重复的数。

代码:
class Solution {public int findDuplicate(int[] nums) {int slow=0;int fast=0;slow=nums[slow];fast=nums[nums[fast]];while(slow!=fast){slow=nums[slow];fast=nums[nums[fast]];}//slow和fast一定会相遇的 题目中给出来了int head=0;while(slow!=head){head=nums[head];slow=nums[slow];}return head;}
}

二、分段链表(奇偶链表、分割链表)

题意:

就是根据某种要求将链表重新拼接起来。比如说:将所有索引为奇数的节点索引为偶数的节点分别组合在一起,然后返回重新排序的列表。又或者说,将链表中元素>=k的都放到后面,<k的都放到前面。

思路:做这种题的思路就是,重新建立一个newHead,把另一组的节点都放到newHead后面,然后两段链表连起来就行。

比如说:奇偶链表:如果(下标值+1)%2==0,说明是偶数节点;偶数节点.next=null;然后把偶数节点放到newHead后面。循环完之后,把newHead.next放到cur的后面就行了

代码:
class Solution {public ListNode oddEvenList(ListNode head) {ListNode dummyHead=new ListNode();dummyHead.next=head;ListNode cur1=dummyHead;ListNode newHead=new ListNode();ListNode cur2=newHead;int index=1;while(cur1.next!=null){if(index%2==0){ListNode temp=cur1.next;cur1.next=cur1.next.next;temp.next=null;cur2.next=temp;cur2=cur2.next;index++;}else{cur1=cur1.next;index++;}}cur1.next=newHead.next;return dummyHead.next;}
}

三、相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

思路:如果两个单链表有相交的节点。那么从0开始到相交节点的距离一定是一样的。

但是问题在于两个链表的起始节点位置不一样。eg:A从位置1出发,B从位置0出发。

那么如何才能让他们走的距离是一样的。假如A到相交节点的距离是:x;B到相交节点的距离是:y。

相交链表的长度是c; x+c+y=y+c=x。这样的距离一定是相等的。

A走到null(x+c)就去headB继续走(y);

B走到null(y+c)就去headA继续走(x); 

直到A和B相等

代码:
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode A=headA,B=headB;while(A!=B){A=A==null?headB:A.next;B=B==null?headA:B.next;}return A;}
}

四、供暖器(二分查找)

现在,给出位于一条水平线上的房屋 houses 和供暖器 heaters 的位置,请你找出并返回可以覆盖所有房屋的最小加热半径。

思路:

这道题中的思路就是:遍历每一个房屋houses,找距离它最近的供暖器,然后计算出半径。然后取一个能满足所有房屋都能被供暖的半径。

有三种情况:

1.房屋在最左边,左边没有供暖器了,只有右边有,那么半径等于右边第一个供暖器的位置-房屋的位置

2.房屋在最右边,右边没有供暖器了,只有左边有,那么半径等于左边第一个供暖器的位置-房屋的位置

3.房屋的左右都用供暖器,找距离它最近的供暖器,然后计算半径。难点:如何找到距离该房屋最近的供暖器?找到下标比它大的第一个供暖器,然后找到第一个比他小的供暖器,比较两个就行了

使用二分法找下标比它大的第一个供暖器

代码:
class Solution {public int findRadius(int[] houses, int[] heaters) {//先对供暖器的位置进行升序排Arrays.sort(heaters);int res=Integer.MIN_VALUE;int d=0;for(int i=0;i<houses.length;i++){//房屋的左边没有供暖器if(houses[i]<=heaters[0])d=heaters[0]-houses[i];//房屋的右边没有供暖器else if(houses[i]>=heaters[heaters.length-1])d=houses[i]-heaters[heaters.length-1];else{int left=0;int right=heaters.length-1;while(left<right){int mid=(left+right)>>1;//右移 取中间值if(heaters[mid]<houses[i])left=mid+1;else right=mid;}d=Math.min(heaters[left]-houses[i],houses[i]-heaters[left-1]);}res=Math.max(res,d);}return res;}
}

五、有效的完全平方数(二分法)

解法一:数学规律

对于一个完全平方数而言,可以写成这样的形式:num=1+3+5+...+(2∗n−1)

class Solution {public boolean isPerfectSquare(int num) {int n=1;while(num>0){num-=n;n+=2;}return num==0;}
}
解法二:二分法

要从0->n中获取一个数字使得n^2=num,使用二分法是比较合适的。

注意:在判断n^2和num是否相等时,为了防止溢出使用mid和num/mid进行判断;

mid<num/mid;说明目标值在右边区域中,left=mid+1;

mid>num/mid;说明目标值在左边区域中,right=mid;

mid==num/mid:有可能是精度缺失后相等,因此要特别注意(num%mid==0)

class Solution {public boolean isPerfectSquare(int num) {if(num==1)return true;int left=0,right=num;while(left<right){int mid=left+(right-left)/2;if(num/mid>mid)left=mid+1;else if(num/mid<mid)right=mid;else{if(num%mid!=0)return false;return true;}}return false;}
}

六、有序数组中的单一元素

给你一个仅由整数组成的有序数组,其中每个元素都会出现两次唯有一个数只会出现一次

请你找出并返回只出现一次的那个数。必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。

思路:

如何将这道题和二分法联系起来?  根据题意我们可以发现规律:

在没有出现单个元素之前,奇数下标的值一定和它的前一个下标值相等;偶数下标的值一定和它下一个下标的值相等。

如果下标mid满足上面的规律,那么mid之前的数字都满足,更新left=mid+1;

如果下标mid不满足上面的规律,那么mid之后的数字都不满足,更新right=mid;

代码:
class Solution {public int singleNonDuplicate(int[] nums) {//奇数下标:如果前面没有单个数字 一定和前一个值相等//偶数下标:如果前面没有单个数字 一定和后一个值相等int size=nums.length;int left=0,right=size-1;while(left<right){int mid=left+(right-left)/2;if(mid%2==0){if(mid+1<size&&nums[mid]==nums[mid+1]){left=mid+1;}else{right=mid;}}else{if(mid-1>=0&&nums[mid-1]==nums[mid]){left=mid+1;}else{right=mid;}}}return nums[left];}
}

七、在排序数组中查找元素的第一个位置和最后一个位置(好题)

解法一:二分查找target后,while循环寻找最左边和最右边
class Solution {public int[] searchRange(int[] nums, int target) {int left=0;int right=nums.length-1;int[] res=new int[]{-1,-1};while(left<right){int mid=left+(right-left)/2;if(nums[mid]>target)right=mid;else if(nums[mid]<target)left=mid+1;else{//找到target寻找最左边和最右边int start=mid;int end=mid;while(start>=0&&nums[start]==target)start--;while(end<nums.length&&nums[end]==target)end++;res[0]=start+1;res[1]=end-1;break;}}return res;}
}
解法二:

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]

思路:

以往我们使用二分搜索target的时候,当nums[mid]==target的时候,就返回mid了。此时就找到了数组中哪一个下标的值为target。

但是如果让我们找元素的第一个位置,就需要我们把右边相等的元素都筛除掉。那么应该如何删除?(只有在更新右边区域的时候才能筛除掉右边元素)所以只有当nums[i]>=target的时候,right=mid; (这样mid之后相等的元素就被筛除掉了) else left=mid+1

如果让我们找元素的最后一个位置,就需要我们把左边相等的元素都筛除掉。那么应该如何删除?

 当nums[mid]<=target的时候,left=mid  else right=mid-1;

注意:1.在找元素最后一个位置的时候,如果mid=(left+right)/2 此时如果left+1=right 那么mid一直会是left,会一直陷入循环中,此时就必须把mid=(left+right+1)/2
代码:
class Solution {public int[] searchRange(int[] nums, int target) {int[] res = new int[] { -1, -1 };if (nums.length == 0)return res;int left = 0;int right = nums.length - 1;// 先找target左边第一个元素while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] >= target) right = mid;else left = mid + 1;}// 此时找到了左边第一个元素 leftif (nums[left] != target)return res;res[0] = left;left = 0;right = nums.length - 1;while (left < right) {//是为了防止当left+1=right的时候 之前是mid=(left+right)/2 2left+1/2=left//此时mid就一直会是left 一直循环int mid = left + (right - left+1) / 2;if (nums[mid] <= target) left = mid;else right = mid - 1;}res[1] = right;return res;}
}

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

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

相关文章

[Git][认识Git]详细讲解

目录 1.什么是仓库&#xff1f;2.认识工作区、暂存区、版本库3.认识 .git1.index2.HEAD && master3.objects4.总结 1.什么是仓库&#xff1f; 仓库&#xff1a;进⾏版本控制的⼀个⽂件⽬录 2.认识工作区、暂存区、版本库 工作区&#xff1a;在电脑上写代码或⽂件的⽬录…

Java Excel复杂表头,表头合并单元格

Java Excel复杂表头&#xff0c;表头合并单元格 效果预览 一、maven依赖 <!--操作excel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.1</version><scope>test</…

【C++标准模版库】vector的介绍及使用

vector 一.vector的介绍二.vector的使用1.vector 构造函数2.vector 空间增长3.vector 增删查改4.vector 迭代器的使用1.正向迭代器2.反向迭代器 5.victor 迭代器失效问题&#xff08;重点&#xff09; 三.vector不支持 流提取与流插入四.vector存储自定义类型1.存储string2.存储…

大数据环境安装Elasticsearch Kibana可视化

1、用yum安装&#xff0c;配置仓库和镜像。 2、用离线软件包&#xff0c;rpm安装。 服务器环境CentOS7.9 因为云安装&#xff0c;配置镜像版本一直没有成功&#xff0c;改为直接下载软件安装。 官方网址&#xff1a;https://www.elastic.co/cn/downloads/elasticsearch 因为要…

linux用户组练习

准备工作 [rootlocalhost ~]# watch -n 1 tail -n 5 /etc/group使用watch 动态监控 1.建立用户组 shengcan&#xff0c;其id 为2000 2.建立用户组 caiwu&#xff0c;其id 为 2001 3.足建立用户组 jishu&#xff0c;其id 为 2002 4.建立用户lee&#xff0c;指定其主组id为sh…

【开源】嵌入式Linux(IMX6U)应用层综合项目(1)--云平台调试APP

目录 1.简介 1.1功能介绍 1.2技术栈介绍 1.3演示视频 1.4硬件介绍 2.软件设计 2.1连接阿里云 2.2云平台调试UI 2.3Ui_main.c界面切换处理文件 2.4.main函数 3.结尾&#xff08;附网盘链接&#xff09; 1.简介 此文章并不是教程&#xff0c;只能当作笔者的学习分享&…

江协科技51单片机学习- p31 LCD1602液晶屏驱动

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

端到端自动驾驶:挑战与前沿

End-to-end Autonomous Driving: Challenges and Frontiers 端到端自动驾驶&#xff1a;挑战与前沿 Abstract The autonomous driving community has witnessed a rapid growth in approaches that embrace an end-to-end algorithm framework, utilizing raw sensor input …

OpenSPG安装部署

文章目录 前言一、安装前准备安装docker安装docker compose 二、安装服务端下载 docker-compose.yml 文件启动服务端 三、安装客户端拉取镜像克隆OpenSPG源码 案例 前言 OpenSPG是以SPG框架为基础设计和实现的知识图谱开放引擎&#xff0c;它为领域图谱构建提供了明确的语义表…

常见病症之中医药草一枝黄花

常见病症之中医药草一枝黄花 1. 源由2. 一枝黄花植物描述药用部分主要成分药理作用使用方法注意事项 3. 常用方剂3.1 一枝黄花汤3.2 一枝黄花解毒汤 4. 着凉感冒主要方剂加味处方使用方法注意事项 5. 补充资料 1. 源由 注&#xff1a;仅供参考&#xff0c;建议在中医师指导下使…

电商兴农,柳湖新篇:特色产品助力乡村发展

在 2024 年这个充满希望与活力的年份&#xff0c;电商兴农的热潮如同一股春风&#xff0c;吹进了柳湖这片充满生机的土地。玄鹤洞油茶、醋&#xff0c;食家巷特色传统面点、陇原雪陇强面粉、陇源香亚麻籽油等特色产品&#xff0c;以及众多农家的积极参与&#xff0c;共同书写了…

欧科云链7月安全月报 | 私钥泄露损失约占总损失88%,超2.6亿美元

7 月全网累计造成损失约 2.9 亿美元&#xff0c;因私钥泄露所造成损失占总损失的 88.31%&#xff0c;其中 WazirX 因多签钱包私钥泄露&#xff0c;造成约 2.35 亿美元的损失&#xff0c;为 7 月最大安全事件。 最大安全事件-私钥泄漏 7 月 18 日&#xff0c;WazirX 多签钱包私…

免账户免权限免费获取 A股 全市场股票ETF指数 分钟级数据

日期 2024/8/2 意外发现的&#xff0c;抛砖引玉&#xff0c;测试了下&#xff0c;其他券商的也可以。 可以直接获取 1m 5m 1day 级别的数据&#xff0c;全A股市场的都可以。期货未测试。 需要 其他的级别的分数数据可以自行合成。 原理 券商版qmt获取行情数据时&#xff0c;不…

Java 设计模式之策略模式 (Strategy Pattern) 详解

Java 设计模式之策略模式 (Strategy Pattern) 详解 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;旨在定义一系列算法&#xff0c;将每个算法封装起来&#xff0c;并使它们可以互相替换&#xff0c;从而使得算法的变化不会影响使用算法的…

高并发内存池

高并发内存池 一、项目介绍二、什么是内存池1.池化技术2.内存池3.内存池主要解决的问题3.1内碎片3.2外碎片3.3内存池的解决方案 4.malloc 三、定长内存池1.定长内存池设计2.成员属性3.析构和构造4.New和Delete5.性能测试 四、高并发内存池整体框架设计五、申请内存设计1.Thread…

利用Qt实现调用文字大模型的API,文心一言、通义千问、豆包、GPT、Gemini、Claude。

利用Qt实现调用文字大模型的API&#xff0c;文心一言、通义千问、豆包、GPT、Gemini、Claude。 下载地址: AI.xyz 1 Qt实现语言大模型API调用 视频——Qt实现语言大模型API调用 嘿&#xff0c;大家好&#xff01;分享一个最近做的小项目 “AI.xyz” 基于Qt实现调用各家大模型…

八股文-基础知识-int和Integer有什么区别?

引言 在Java编程实践中&#xff0c;基本数据类型int与包装类Integer扮演着不可或缺的角色&#xff0c;它们间的转换与使用策略深刻影响着程序的性能与内存效率。本文旨在深入探究int与Integer的区别&#xff0c;涵盖其在内存占用、线程安全、自动装箱与拆箱机制等方面的表现。…

tomato靶场

扫描网址端口 访问一下8888 我们用kali扫描一下目录 访问这个目录 产看iofo.php源码&#xff0c;发现里面有文件包含漏洞 访问/etc/passwd/发现确实有文件包含漏洞 远程连接2211端口 利用报错&#xff0c;向日志文件注入木马&#xff0c;利用文件包含漏洞访问日志文件 http:/…

嵌入式Linux系统中LCD屏驱动框架基本实现

大家好,今天主要给大家分享一下,如何使用linux系统中LCD屏驱动框架Framebuffer编写具体的代码。 第一:如何编写字符设备驱动程序 1、驱动框架基本操作: 驱动主设备号 * 构造file_operations结构体,填充open/read/write等成员函数 * 注册驱动:register_chrdev(major, name…

【参会邀请】第四届区块链技术与信息安全国际会议(ICBCTIS 2024)诚邀相聚江城!

我们诚挚地邀请您参与第四届区块链技术与信息安全国际会议&#xff08;ICBCTIS 2024&#xff09;。本届会议将于2024年8月17日~19日在中国武汉召开。会议将围绕区块链技术与信息安全等相关研究领域&#xff0c;特邀国内外数位在此领域学术卓越的学者专家做相关致辞与报告&#…