数组相关题目总结

33.搜索旋转排序数组

这题如果数组不进行循环平移那用二分做就很简单,平移后其实也可以用二分做,重点在于二分里面如何check。平移后数组可以分成两段各自升序的数组,并且第一段值大于第二段值。check的时候分两种情况,一种是target >= nums[0],这时候target只可能出现在第一段上,所以二分到第二段时可以直接return true。第二种情况是target < nums[0],这时候target只可能出现在第二段上,所以二分到第一段时可以直接return false。

class Solution {
public:int search(vector<int>& nums, int target) {int ans = -1, l = 0, r = nums.size()-1;while(l <= r){int mid = l+r>>1;if(target >= nums[0]){if(nums[mid] >= target || nums[mid] < nums[0]){ans = mid;r = mid-1;}else l = mid+1;}else{if(nums[mid] >= target && nums[mid] < nums[0]){ans = mid;r = mid-1;}else l = mid+1;}}if(ans == -1 || nums[ans] != target) return -1;return ans;}
};

31.下一个排列

这道题可以找找规律,53421->54123以及54132->54213这两个例子可以看出来每个排列尾部总有一个降序序列,然后这个降序序列左边第一个数字一定会被改变,并且是与降序序列中某个数字进行了交换,交换以后后面的降序序列需要重新排序为升序。

class Solution {
public:void nextPermutation(vector<int>& nums) {/*5342154123541325421354231*/int index = nums.size()-1;while(index > 0 && nums[index] <= nums[index-1])index--;if(index == 0){sort(nums.begin(), nums.end());return;}for(int i = nums.size()-1; i >= 0; i--){if(nums[i] > nums[index-1]){swap(nums[i], nums[index-1]);sort(nums.begin()+index, nums.end());break;}}}
};

88.合并两个有序数组

简单的归并操作。

class Solution {
public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {vector<int> a(nums1.size());int idx1 = 0, idx2 = 0;for(int i = 0; i < a.size(); i++){if(idx1 == m) a[i] = nums2[idx2++];else if(idx2 == n) a[i] = nums1[idx1++];else if(nums1[idx1] > nums2[idx2]) a[i] = nums2[idx2++];else a[i] = nums1[idx1++];}nums1 = a;}
};

56.合并区间

比较经典的题目了,按左端点排序,然后遍历一遍区间,维护出当前合并区间的最右端点,如果某个新区间左端点大于当前的最右端点,那就没法合并了,反之可以合并进去。

class Solution {
public:vector<vector<int>> merge(vector<vector<int>>& intervals) {sort(intervals.begin(), intervals.end());vector<vector<int>> res;int mxr = -0x3f3f3f3f, mnl = 0x3f3f3f3f;for(int i = 0; i < intervals.size(); i++){if(intervals[i][0] <= mxr){mxr = max(mxr, intervals[i][1]);}else{if(mxr != -0x3f3f3f3f) res.push_back({mnl, mxr});mnl = intervals[i][0];mxr = intervals[i][1];}}res.push_back({mnl, mxr});return res;}
};

162.寻找峰值

如果只有一个峰值那就是三分,但这里有多个峰值。其实二分也能做,根据mid左右的值来判断收缩到哪个区间,如果mid-1、mid、mid+1位置的值是递增的,那选择右区间更好一些,如果是递减的那就左区间。

class Solution {
public:int findPeakElement(vector<int>& nums) {int l = 0, r = nums.size()-1;while(l <= r){int mid = l+r>>1;int lnum = mid?nums[mid-1]:0x80000000;int rnum = mid<nums.size()-1?nums[mid+1]:0x80000000;if(nums[mid] >= lnum && nums[mid] >= rnum)return mid;else if(nums[mid] >= lnum && nums[mid] <= rnum)l = mid+1;elser = mid-1;}return 0;}
};

4.寻找两个正序数组的中位数

这道题直接归并的话复杂度是O(n),但题目要求log级的复杂度,所以这样肯定行不通。正解的话需要先了解怎么求第k小数,如果有两个升序数组,可以比较它们第k/2个元素大小,如果nums1[k/2] < nums2[k/2],那么nums1[0~k/2]一定都不可能是第k小数,因为此时如果把两数组归并起来那nums1[0~k/2]都排在nums2[k/2]前面,都达不到第k小的位置。这样就可以把nums1[0~k/2]这些元素排除掉,由于排除了k/2+1个元素,找第k小就相当于在剩下的元素中找第k-(k/2+1)小。当某个数组中元素全被排除掉或者k = 1时达到终态,此时退出递归。因为每次都排除掉一半的元素,所以时间复杂度是O(logn)。

实现的时候有些细节要注意,比如k/2时可以直接下取整,访问nums[k/2]可能会越界,这时候直接取它最后一个元素,vector的size()方法返回无符号数,运算时需要转为带符号数。

class Solution {
public:int findTopK(vector<int>& nums1, int st1, vector<int>& nums2, int st2, int k){if(st1 > (int)nums1.size()-1) return nums2[st2+k-1];if(st2 > (int)nums2.size()-1) return nums1[st1+k-1];if(k == 1) return min(nums1[st1], nums2[st2]);int mid = k/2-1;int a = st1+mid>nums1.size()-1?nums1.size()-1:st1+mid;int b = st2+mid>nums2.size()-1?nums2.size()-1:st2+mid;if(nums1[a] > nums2[b])return findTopK(nums1, st1, nums2, b+1, k-(b-st2+1));else   return findTopK(nums1, a+1, nums2, st2, k-(a-st1+1));}double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {if((nums1.size()+nums2.size())&1)return findTopK(nums1, 0, nums2, 0, (nums1.size()+nums2.size()+1)/2);else{int a = findTopK(nums1, 0, nums2, 0, (nums1.size()+nums2.size())/2);int b = findTopK(nums1, 0, nums2, 0, (nums1.size()+nums2.size())/2+1);return (a+b)/2.0;}}
};

215.数组中的第K个最大元素

类似快速排序的思路,快排中对数组进行一趟操作可以保证第一个元素最终处在正确的位置,也就是其左边的元素均小于等于它,右边的元素均大于等于它。利用这个特性寻找第k大理想情况下可以每趟排除一半的数据量,平均时间复杂度是n+n/2+n/4+n/8+...+1 = O(n)。但这种方法在数据升序时会退化到O(n^2),为了避免退化在每次选取基准元素时应该随机选取。即使加入了随机化,当数组元素值全相同时还是会退化到O(n^2),这时候可以用双路或三路快排。

还有一种方法是用优先队列,维护一个长度为k的升序的优先队列,这种方法时间复杂度为O(nlogk)。

//优先队列做法
class Solution {
public:int findKthLargest(vector<int>& nums, int k) {priority_queue<int, vector<int>, greater<int>> q;for(int i = 0; i < nums.size(); i++){q.push(nums[i]);if(q.size() > k) q.pop();}return q.top();}
};
//快排做法
class Solution {
public:int findTopK(vector<int>& nums, int l, int r, int k){int x = rand()%(r-l+1)+l;swap(nums[x], nums[l]);int i = l, j = r;while(i < j){while(nums[i] <= nums[j] && i < j) j--;swap(nums[i], nums[j]); while(nums[i] <= nums[j] && i < j) i++;swap(nums[i], nums[j]); }if(k <= r-i) return findTopK(nums, i+1, r, k);else if(k == r-i+1) return nums[i];else return findTopK(nums, l, i-1, k-(r-i+1));}int findKthLargest(vector<int>& nums, int k) {srand(time(NULL));return findTopK(nums, 0, nums.size()-1, k);}
};

34.在排序数组中查找元素的第一个和最后一个位置

两次二分就出来了。

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {vector<int> res;int ans = -1, l = 0, r = nums.size()-1;while(l <= r){int mid = l+r>>1;if(nums[mid] >= target){ans = mid;r = mid-1;}else l = mid+1;}if(ans != -1 && nums[ans] != target) res.push_back(-1);else res.push_back(ans);ans = -1, l = 0, r = nums.size()-1;while(l <= r){int mid = l+r>>1;if(nums[mid] <= target){ans = mid;l = mid+1;}else r = mid-1;}if(ans != -1 && nums[ans] != target) res.push_back(-1);else res.push_back(ans);return res;}
};

283.移动零

遍历一遍数组就行了。

class Solution {
public:void moveZeroes(vector<int>& nums) {int len = 0;for(int i = 0; i < nums.size(); i++)if(nums[i]) nums[len++] = nums[i];for(int i = len; i < nums.size(); i++)nums[i] = 0;}
};

153.寻找旋转排序数组中的最小值

分两种情况,一种是旋转完仍然升序,直接返回第一个元素,另一种是分成了两段升序的数组,这时候二分就行了,check条件也很明显。

class Solution {
public:int findMin(vector<int>& nums) {if(nums[0] <= nums[nums.size()-1]) return nums[0];int ans = -1, l = 0, r = nums.size()-1;while(l <= r){int mid = l+r>>1;if(nums[mid] < nums[0]){ans = mid;r = mid-1;}else l = mid+1;}return nums[ans];}
};

136.只出现一次的数字

思维题,全部按位异或。

class Solution {
public:int singleNumber(vector<int>& nums) {int ans = 0;for(int i = 0; i < nums.size(); i++)ans ^= nums[i];return ans;}
};

55.跳跃游戏

一开始想的是dp+区间和,过了以后发现还有更简单的方法。直接维护当前能跳到的最远位置,如果走到了最远位置以外那就return false。

//dp+区间和做法
class Solution {
public:bool canJump(vector<int>& nums) {vector<int> dp(nums.size());dp[nums.size()-1] = 1;for(int i = nums.size()-2; i >= 0; i--){int r = min((int)nums.size()-1, i+nums[i]);int sum = dp[i+1]-(r==nums.size()-1?0:dp[r+1]);if(sum) dp[i] = dp[i+1]+1;else dp[i] = dp[i+1];}if(nums.size() == 1) return true;return dp[0]!=dp[1];}
};
//更好的dp做法
class Solution {
public:bool canJump(vector<int>& nums) {int mx = 0;for(int i = 0; i < nums.size(); i++) {if(i > mx) return false;mx = max(mx, i+nums[i]);}return true;}};

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

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

相关文章

简洁高效的短链接:优化互联网体验

title: 简洁高效的短链接&#xff1a;优化互联网体验 date: 2024/2/18 13:24:24 updated: 2024/2/18 13:24:24 tags: 短链接长网址缩短美观简洁分享优化点击率提升数据统计用户体验 在互联网时代&#xff0c;我们经常遇到需要分享长网址的情况。长网址不仅不美观&#xff0c;而…

【二维比较函数】有n个区间,对于每个区间,求该区间与其他区间的相交的最小值

题目 #include <bits/stdc++.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn = 1e6 + 5, inf = 1e18 + 5, maxm = 4e4 + 5, mod = …

Mysql开启bin-log日志

目录 一、安装配置 二、mysqlbinlog命令 一、安装配置 yum -y install mariadb mariadb-server#安装mysql数据库#默认配置文件/etc/my.cnfvim /etc/my.cnflog-binmariadb-bin #开启二进制日志 systemctl restart mariadb#会在/car/lib/mysql/产生二进制日志文件&#xff0…

返乡创业者:直播电商-连州农产品的新舞台

摘要&#xff1a;在广东省连州市&#xff0c;“连州年味直播争霸赛”为返乡创业者提供了展示才华的平台&#xff0c;将农特产品的故事传达给全国消费者。返乡创业者通过直播电商模式&#xff0c;挑战旧有销售渠道的局限性&#xff0c;探索农产品从田间到餐桌的新路径。 正文&a…

防火墙(三) -----------------关于iptables规则的保存

一、关于iptables规则的保存 之前写的iptables的设置&#xff0c;但是都是临时生效的&#xff0c;一旦电脑重启&#xff0c;那么就会失效&#xff0c;如何永久保存&#xff0c;需要借助iptables-save命令&#xff0c;开机生效需要借助iptables-restore命令&#xff0c;并写入规…

P1106 删数问题题解

题目 键盘输入一个高精度的正整数N&#xff08;不超过250位&#xff09;&#xff0c;去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的N和k&#xff0c;寻找一种方案使得剩下的数字组成的新数最小。 输入输出格式 输入格式 输入两行正整数…

图像处理与计算机视觉算法

图像处理与计算机视觉算法是实现对图像和视频内容分析、理解和操作的一系列技术。这些算法可以分为多个类别,包括但不限于以下几个主要方面: 预处理: 像素操作:灰度化、二值化、直方图均衡化等,用于改善图像的对比度和亮度分布。去噪:高斯滤波、中值滤波、自适应滤波等,…

【C++搜索】DFS:拆分自然数

题目描述 “天下熙熙&#xff0c;皆为利来&#xff1b;天下攘攘&#xff0c;皆为利往”&#xff0c;监狱里的暗势力划分地盘的目的无非是为了获取利益&#xff0c;他们分配利益的方式是基于这样一个准则&#xff1a;设总利益为自然数&#xff2e;&#xff0c;则任何一个大于1的…

AB测试最小样本量

1.AB实验过程 常见的AB实验过程&#xff0c;分流-->实验-->数据分析-->决策&#xff1a;分流&#xff1a;用户被随机均匀的分为不同的组实验&#xff1a;同一组内的用户在实验期间使用相同的策略&#xff0c;不同组的用户使用相同或不同的策略。数据收集&#xff1a;…

HOOPS发布全新CAD文件支持以及改进的API性能版本!增加了对Navisworks和C#支持!

全球工程软件开发工具包的领先提供商Tech Soft 3D今天宣布推出HOOPS Exchange 2024&#xff08;支持30多种文件格式的领先CAD数据转换SDK&#xff09;和HOOPS Publish 2024&#xff0c;用于发布交互式3D PDF、3D HTML和3D CAD数据的领先工具包。 HOOPS Exchange现在支持Navisw…

C++day6

模拟跟随导演去动物园&#xff1a; #include <iostream>using namespace std; class Animal { private:string name; public:Animal(){}Animal(string name):name(name){}virtual void perform(){cout << name << "为我们讲解,说&#xff1a;" &…

php 数组函数

php 数组函数 1. 常用的php数组函数 1. 常用的php数组函数 array_pop() 删除数组中最后一个元素 array_push() 将一个或多个元素插入到数组的末尾 array_keys <?php $arr array("刘岩" > 30, "范冰冰" > 31, "娜扎" > 31);$…

~汉诺塔~(C语言)~

引言 汉诺塔&#xff08;Hanoi Tower&#xff09;&#xff0c;又称河内塔&#xff0c;源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从上面开始按大小顺序重新摆放在…

npm run serve启动报错npm ERR! Missing script: “serve“

启动项目的时候用npm run serve发现报了以下的错误 解决方法&#xff1a; 1.一般情况下&#xff0c;这个问题是因为package.json文件里面确实没有 这里没有可能因为你的脚手架版本比较低&#xff0c;如果不想换&#xff0c;可以用 这里面有的 npm run dev去启动也是可以的 n…

精工电联:定制精工线缆,赋能科技互联---致力于为客户提供卓越的连接线缆和连接器产品

精工电联 “定制精工线缆 &#xff0c;赋能科技互联”&#xff0c;精工电联致力于为高科技产业提供全方位、多维度的集成线缆解决方案。凭借深厚的研发实力和丰富的行业经验&#xff0c;精工电联已经成功地在工控设备、医疗设备、人工智能、新能源领域、轨道交通和超声波设备等…

Vue3之ElementPlus中Table选中数据的获取与清空方法

Vue3之ElementPlus中Table选中数据的获取与清空方法 文章目录 Vue3之ElementPlus中Table选中数据的获取与清空方法1. 点击按钮获取与清空选中表格的数据1. 用到ElementPlus中Table的两个方法2. 业务场景3. 操作案例 1. 点击按钮获取与清空选中表格的数据 1. 用到ElementPlus中…

分享一个学英语的网站

名字叫&#xff1a;公益大米网​​​​​​​ Freerice 这个网站是以做题的形式来记忆单词&#xff0c;题干是一个单词&#xff0c;给出4个选项&#xff0c;需要选出其中最接近题干单词的选项。 答对可以获得10粒大米&#xff0c;网站的创办者负责捐赠。如图 触发某些条件&a…

Web APIs - 06

正则表达式 正则表达式是一种字符串匹配的规则 使用场景&#xff1a; 例如验证表单&#xff1a;手机号表单要求用户只能输入11位的数字 (匹配)过滤掉页面内容中的一些敏感词(替换)&#xff0c;或从字符串中获取我们想要的特定部分(提取)等 正则基本使用 定义规则 const reg…

手把手教你绘制自定义控件

主要是注意两点,一点是在控件构造函数中设置一些属性,另一点是重写OnPaint方法,参考代码那如下: class SelfControl:Control{public SelfControl(){//this.SetStyle(ControlStyles.ResizeRedraw, true);//空间大小改变时,控件会重绘//this.SetStyle(ControlStyles.UserPai…

代码随想录算法训练营第三十四天 860.柠檬水找零 、 406.根据身高重建队列、452. 用最少数量的箭引爆气球

代码随想录算法训练营第三十四天 | 860.柠檬水找零 、 406.根据身高重建队列、452. 用最少数量的箭引爆气球 860.柠檬水找零 题目链接&#xff1a;860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; class Solution {public boolean lemonadeChange(int[] bills) {//…