代码随想录打卡 Day 1

代码随想录打卡 Day 1

1.二分法

leetcode编号:704.二分查找

【题目描述】

在一个有序无重复有元素的数组nums中,寻找一个元素target,如果找到乐就返回对应的下标,如果没有找到就返回-1。

【题目分析】

二分法的前提是数组为有序数组,题目中同时强调无重复元素。两者都是使用二分法的前提条件。

二分法需要注意的主要就是区间的定义。区间的定义就是不变量--在while循环中,每一次的边界处理的定义来操作,即所谓的”循环不变量“规则。

常见的二分法写法一般有左闭右闭的区间 $[left,right]$和左闭右开的区间$[left,right)$。在编写代码时,必须时刻按照区间定义来实现函数。

下面以左闭右闭区间来实现该算法:

int binarySearch(vector<int>& nums, int target) {int left=0, right=nums.size()-1;while(left<=right){			//由于区间是左右闭区间,所以边界条件为left<=rightint mid = left + (right-left)/2;  if(nums[mid]<target){    //target在左半区间的处理left = mid+1;}else if (nums[mid]>target){ //target在右半区间的处理right = mid-1;}else {return mid;}}//未找到目标值return -1;}

2.移除元素

leetcode编号:27.移除元素

【题目描述】

原地移除数组中所有等于val的元素,要求不能使用额外的辅助空间,即空间复杂度为$O(1)$.

返回移除后的新数组的size

【题目分析】

暴力解法

不难想出,本体的一个暴力解法是使用两个for循环,第一个for循环循环数组元素,第二个for循环更新数组,其时间复杂度为$O(n^2)$。暴力解的代码如下:

int removeElement(vector<int>& nums,int val){int size=nums.size()for (int i= 0; i < size;i++){if(nums[i] == val){ //发现val值的元素,将数组元素集体向前移动一位for (int j = i+1;j<size;j++){nums[j-1] = nums[j];}i--; //找到元素后下标i以后的数值都向前移动一位size--; //数组的长度-1}}return size;
}

快慢指针法

但是,快慢指针法通过一个快指针和一个慢指针在一个for循环内完成两个for循环的工作。其中两个指针相对有序。

int removeElement(vector<int>& nums, int val) { //双指针法移除数组元素int Slow = 0;for(int Fast = 0; Fast < nums.size(); Fast++){if(val != nums[Fast]){ //Fast未指向值为val的元素时,Slow与Fast同时向后移动//Fast指向值为val的元素时,Fast向后移动,Slow不动nums[Slow] = nums[Fast]; //略去val元素Slow++;}}return Slow; //Slow表示元素个数
}

3.长度最小的子数组

leetcode题号:209.长度最小的子数组

【题目描述】

在一个正整数数组nums中找到最小长度的连续子数组,使子数组元素之和大于或等于s.返回满足条件的连续子数组的最小长度,如果没有找到则返回0.

【题目分析】

暴力解法

暴力解法同样是使用两个for循环,不断寻找符合条件的子数组,时间复杂度为$O(n^2)$

滑动窗口法

数组操作中另一个重要方法是滑动窗口法,所谓的滑动窗口,就是不断调节子数组的起始和终止位置,从而得到我们想要的答案。实现滑动窗口,主要确定:

  • 窗口内的元素是什么? —在本问中,窗口内的元素就是数值和大于等于s的长度最小的连续子数组

  • 如何移动窗口的起始位置? —在本问中,当当前窗口内元素总和大于等于s时,窗口向前移动

  • 如何移动窗口的终止位置?—在本问中。窗口结束位置就是for循环遍历数组的指针。

    本题使用滑动窗口法的CPP代码如下,通过该方法,不断调节子数组的起始位置,从而将时间复杂度将为$O(n^2)$:

    int findShortestSubArray2(vector<int>& nums, int k) { // 滑动窗口 时间复杂度为O(N)int result = INT32_MAX;int sum =0;int subLength = 0;for (int i=0, j=0; j<nums.size(); j++){sum += nums[j];while( sum >= k){subLength = j-i+1;result = min(result, subLength);sum -= nums[i++];}}return result == INT32_MAX ? 0 : result;}
    

4.有序数组的平方

leetcode题号:977:有序数组的平方

【题目描述】

给你一个按 非递减顺序排序的整数数组 nums,返回 每个数字的平方组成的新数组,要求也按非递减顺序 排序。

【题目分析】

同样,一个简单的想法是先将nums数组自平方,然后使用快速排序将nums数组进行排序,时间复杂度为$O(nlogn)$。

本题也可以使用双指针法进行操作,利用双指针将nums元素按照元素绝对值重新排序,然后对nums每个元素平方处理。由于给出的nums数组是非递减顺序排序的整数数组,这就给按绝对值重新排序带来了一定便利性。

vector<int> sortedSquare(vector<int>& nums) {vector<int> ans(nums.size());//ans为返回的数组int i=0;int j=nums.size()-1; //i与j为两个指针int k=nums.size()-1; while (i<j){if(abs(nums[i])<abs(nums[j])){ans[k--]=nums[j];j--;}else{ans[k--]=nums[i];i++;}}for (int i = 0; i < nums.size(); i++){ans[i]=ans[i]*ans[i];}return ans;
}

不难看出,该解法时间复杂度为$O(n)$,空间复杂度为$O(n)$.

5.区间和

【题目描述】

给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。

【题目分析】

最直观的想法便是使用循环将所有区间的和都累加一边,该解法的时间复杂度为$O(m*n)$,其中$n$为数组长度,$m$为查询次数.如果查询次数非常大,时间复杂度也会非常大.

接下来,引入了前缀和这一想法,其思想史重复利用计算过的子数组之和,从而降低区间查询所需要的累加次数,在设计计算区间的问题时非常有用.通过创建辅助数组$p[n]$,就可以将区间和从循环转换为简单的数组元素相减.同时需要注意的是,使用前缀和时,需要注意下标.如$[2,5]$的元素和为 $p[5]-p[1]$.

利用前缀和,本题的时间复杂度为$O(n)$,空间复杂度为$O(n)$

int main(){int n;int a,b;cin>>n;vector<int> arr(n);for (int i = 0; i < n; i++){cin>>arr[i];}vector<int> preSum(n);preSum[0]=arr[0];for (int i = 1; i < n; i++){preSum[i]=preSum[i-1]+arr[i];}while(cin >> a >> b){int sum;if (a==0){sum=preSum[b];}else{sum=preSum[b]-preSum[a-1];}cout<<sum<<endl;}
} 

总结

对于以数组为基础数据结构的算法题,常见的技巧有:

  1. 边界条件:对于数组遍历时,必须坚持“循环不变量”的原则,按照统一的规则进行循环
  2. 双指针法:其常见场景包括查找成对元素,移除重复元素,合并有序数等,包括同向双指针法和异向双指针法.
  3. 滑动窗口:其方法主要用于连续子数组或者字串问题,通过一定规则动态调整窗口的大小与位置,在使用过程中,必须明白窗口元素以及何时调整窗口.
  4. 前缀和法:利用辅助数组,可以通过相减快速得到子数组的和,对于频繁查找子数组和的场景很有必要.

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

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

相关文章

【分布式框架】XXL-RPC v1.8.0

一、Release Notes 1、【重构】针对 “Core/核心模块” 进行架构模块化重构,拆分 Provider、Invoker、Serializer、Remoting、Registry 和 Boot 等六个核心模块:Provider:定位为服务提供者,提供RPC服务端能力,包括RCP/HTTP Server、业务Service扫描维护、服务执行等能力。…

解决U盘不能传输大文件的问题

将“文件系统”改成“NTFS”,默认一般是FAT32,然后点击格式化即可。注意U盘不要有重要数据避免数据丢失

网站打开不稳定,如何排查和解决?

网站打开不稳定可能由多种因素引起,包括服务器性能、网络问题、代码错误等。以下是详细的排查步骤和解决方案,帮助您找到并解决问题:检查服务器性能:CPU和内存使用情况:使用 top 或 htop 命令查看服务器的CPU和内存使用情况。如果资源占用过高,可能导致网站响应缓慢或无法…

服务器配置显示异常,带宽和内存与预期不符

关于您提到的服务器配置显示异常的问题,我们非常理解您的困惑。根据您的描述,您发现服务器的带宽从原来的8M变成了4M,内存也从4G变成了2G。为了帮助您更好地解决这个问题,我们需要进行以下几个步骤的排查和确认。 首先,请确保您登录的是正确的服务器账号和密码。有时由于多…

如何处理服务器端口888突然无法访问的问题

关于您提到的服务器端口888突然无法访问的问题,我们非常理解您的困扰。根据您的描述,宝塔面板因存在致命漏洞,为了保障数据安全,我们在安全组中暂时阻止了888端口。以下是详细的解决方案和建议,帮助您尽快恢复正常访问。 首先,强烈建议您立即更新宝塔面板的安全补丁。这是…

如何解决服务器空间扩容后FTP无法上传文件及宝塔面板容量未更新的问题?

您好,根据您的描述,在升级服务器空间容量后,您遇到了FTP无法上传文件以及宝塔面板显示的容量未更新的问题。以下是详细的解决方案和建议:确认磁盘扩容是否成功:首先,确保服务器提供商确实已经完成了磁盘扩容操作。可以通过服务商的管理控制台或联系技术支持确认扩容状态。…

如何解决云服务器网络访问异常的问题?

您好,根据您的描述,云服务器出现了网络访问异常的情况,严重影响了业务的正常运行。以下是详细的分析和解决方案:确认网络连接状态:使用命令行工具(如ping、traceroute)测试服务器与外部网络的连通性,确定是否存在网络中断或延迟过高的问题。 检查服务器的本地网络配置(…

如何正确开启服务器上的某个端口?

在服务器上正确开启某个特定端口(如465端口)是一项常见但又容易出错的任务。为了确保端口能够顺利打开并正常工作,以下是详细的步骤指南和注意事项:理解端口作用:首先明确要开启的端口用途。例如,465端口主要用于SMTPS协议,即通过SSL加密发送电子邮件。确保该端口确实是…

如何优化数据库查询速度,特别是使用多个CONTAINS条件时?

您好,当您在数据库查询中使用多个CONTAINS条件时,查询速度可能会显著下降。为了优化这种查询,您可以采取以下几种方法: 首先,确保数据库中有适当的索引。索引是提高查询速度的关键。对于包含全文搜索条件的查询,创建全文索引是非常有效的。以MySQL为例,您可以使用以下命…

如何找回宝塔面板的登录网址?

如果您忘记了宝塔面板的登录网址,可以通过以下步骤来找回或重新设置:检查服务器IP地址: 宝塔面板的默认访问地址通常是 http://<服务器IP>:8888 或者 https://<服务器IP>:8888。您可以登录到您的服务器提供商控制台,找到您服务器的公网IP地址。查看宝塔面板安装…

如何解决宝塔面板无法打开的问题?

当您遇到宝塔面板无法打开的情况时,可能是由多种原因引起的。以下是一些常见的排查步骤和解决方案,帮助您快速恢复宝塔面板的正常访问:检查服务器状态: 首先确认服务器是否正常运行。您可以登录到服务器提供商的控制台,查看服务器的状态。如果服务器处于关机或重启状态,请…

服务器流量增大速度太快怎么办?

当您发现服务器流量增大速度过快时,这可能是由多种原因引起的,包括但不限于恶意流量、内容被频繁请求或存储容量不足。为了有效应对这种情况,以下是详细的解决方案和预防措施:分析流量来源:使用流量监控工具(如AWStats、Google Analytics等)详细分析流量来源。找出哪些页…