当前位置: 首页 > news >正文

网站设计就业培训学校排名快手短链接生成

网站设计就业培训学校排名,快手短链接生成,成都网站建设公司排名,最适合穷人的四种保险题目列表 2855. 使数组成为递增数组的最少右移次数 2856. 删除数对后的最小数组长度 2857. 统计距离为 k 的点对 2858. 可以到达每一个节点的最少边反转次数 一、使数组成为递增数组的最少右移次数 这题可以直接暴力求解,枚举出每种右移后的数组,将…

题目列表

2855. 使数组成为递增数组的最少右移次数

2856. 删除数对后的最小数组长度

2857. 统计距离为 k 的点对

2858. 可以到达每一个节点的最少边反转次数

一、使数组成为递增数组的最少右移次数

这题可以直接暴力求解,枚举出每种右移后的数组,将它和排完序后的数组比较,时间复杂度为O(n^2)

代码如下

class Solution {
public:int minimumRightShifts(vector<int>& nums) {vector<int> v=nums;sort(v.begin(),v.end());for(int i=0;i<nums.size();i++){if(v==nums) return i;nums.insert(nums.begin(),nums.back());nums.pop_back();}return -1;}
};

这个能过,但是有没有更快的算法,我们观察一下这个数组,如果它要是能右移成递增数组,那么它必然是由两个递增数组构成的,且前一个数组的最小值,一定大于后一个数组的最大值,答案就是第二个数组的长度,所以我们只要试着将数组拆分成两个递增数组就行(边界条件挺多,一定要细节),时间复杂度为O(n)

代码如下

class Solution {
public:int minimumRightShifts(vector<int>& nums) {int end1=0,n=nums.size();while(end1+1<n&&nums[end1]<nums[end1+1])end1++;if(end1==n-1) return 0;int end2=end1+1;while(end2+1<n&&nums[end2]<nums[end2+1])end2++;if(end2!=n-1||nums[0]<nums[n-1]) return -1;else return n-end1-1;}
};

二、删除数对后的最小数组长度

这题还是比较难想到的,比较绕。我们需要多枚举几个例子,然后就会发现,当某个数的个数cnt大于等于数组长度n的一半时,最优的方案就是将它前后的数都与它相互抵消(因为如果还让其他数相互抵消,那么剩余的和该数相抵消的元素个数就会变小,从而该元素剩下的个数就会变多),所以答案就是cnt-(n-cnt)=2*cnt-n,那么如果没有一个数的个数大于数组长度的一半呢?

首先从最特殊的数组中数字都是唯一的情况开始讨论,那么显然,当数组长度为偶数时,答案为0,当数组长度为奇数时,答案为1,那么是不是所有的情况都符合这个规律呢?答案是,确实都符合这个规律,因为所有的数的个数都<n/2,那么我们就可以通过抵消,将数的个数全部化成1

代码如下

class Solution {
public:int minLengthAfterRemovals(vector<int>& nums) {unordered_map<int,int>cnt;int n=nums.size(),ans=n&1;//n&1,奇数为1,偶数为0for(auto x:nums)++cnt[x];for(auto [x,y]:cnt)if(y>n/2)ans=max(ans,2*y-n);return ans;}
};

当然这题如果想不到这么深,那么也可以用最基本的贪心,每次拿出出现次数最大的两个元素相抵消,直到剩下零个数或剩下一个数为止。代码如下

class Solution {
public:int minLengthAfterRemovals(vector<int>& nums) {unordered_map<int,int>cnt;int n=nums.size(),ans=n&1;for(auto x:nums)++cnt[x];priority_queue<int>q;for(auto [x,y]:cnt)q.push(y);while(q.size()>1){int x=q.top();q.pop();int y=q.top();q.pop();x--,y--;if(x)q.push(x);if(y)q.push(y);}return q.empty()?0:q.top();}
};

三、统计距离为k的点对

看到两个数的和k,以及k的数据范围,我们就要想到这题能用暴力枚举点来做,然后通过枚举到的点,求出与之相对应的点的坐标,答案加上之前出现的该点个数(用哈希表统计),代码如下

class Solution {
public:int countPairs(vector<vector<int>>& coordinates, int k) {int n=coordinates.size();unordered_map<long long,int>cnt;int ans=0;for(auto& e:coordinates){int x=e[0],y=e[1];for(int i=0;i<=k;i++){auto it=cnt.find((x^i)*1000000LL+(y^(k-i)));if(it!=cnt.end())ans+=it->second;}cnt[x*1000000LL+y]++;}return ans;}
};

 四、可以到达每一个节点的最小边反转次数

这题是换根dp,即通过根节点的最小边反转次数,来得到它孩子结点的最小边反转次数,因为它的孩子结点的反转边的个数就和它父节点的最小边反转次数相差一个它俩之间的边是否需要翻转,其它的都一样。

代码如下

class Solution {
public:vector<int> minEdgeReversals(int n, vector<vector<int>>& edges) {//建图vector<vector<pair<int,int>>>g(n);for(auto& e:edges){int x=e[0],y=e[1];g[x].push_back({y,1});//顺便记录一下边的方向,1为正,-1为逆g[y].push_back({x,-1});}vector<int>ans(n);//计算根节点的最少边反转次数function<void(int,int)>dfs=[&](int x,int fa){for(auto& [y,dir]:g[x]){if(y!=fa){ans[0]+=(dir<0);//方向反的需要反转dfs(y,x);}}};dfs(0,-1);//换根dpfunction<void(int,int)>reroot=[&](int x,int fa){for(auto& [y,dir]:g[x]){if(y!=fa){ans[y]=ans[x]+dir;reroot(y,x);}}};reroot(0,-1);return ans;}
};

http://www.yayakq.cn/news/658397/

相关文章:

  • 物流管理网站建设烟台住房和城乡建设厅网站
  • 流行的企业网站推广wordpress支持视频播放器插件
  • flash asp设计公司网站源码app开发定制外包服务商e
  • 杭州营销网站建设平台郑州企业网站建设费用
  • 网站反向代理怎么做护肤品网站建设的意义
  • 句容建设局网站黄浦区做网站
  • 中小微企业建设网站加工平台v型架子
  • 网站服务器租用价格 百度一下网店代运营费用
  • 网站怎么做框架集陕西省建设厅网站劳保统筹基金
  • 网站编程新品怎么刷关键词
  • 免费网站主机空间网站有什么到期
  • 东营网站排名凭祥网站建设
  • 网络公司做机场网站建站公司推广
  • 医疗科技网站建设第一次做网站不知道
  • 网站推广到底应该怎么做个人网站建设案例课堂
  • 毕业设计除了网站还可以做啥做网站必须要认证吗
  • 成都创意网站设计企业年金有必要交吗
  • 建设移动网站网上书店网站建设毕业设计范文
  • 建网站费用会计分录为什么几年前做的网站视频看不了
  • 易语言可以做网站吗旅游公司网站建设ppt
  • 手机如何做车载mp3下载网站微营销平台
  • 东营做网站优化多少钱免费中文企业网站模板
  • 编程自学免费网站南昌商城网站建设
  • 10个奇怪又有趣的网站广州番禺营销型网站建设
  • 做网站商城需要什么条件软件开发者能看到手机信息吗
  • 网站建设存在哪些问题互联网商城建设
  • 做淘宝头像的网站有哪些网站底部导航代码
  • 宁波网站建设模板制作网站是怎么做的
  • 网站建设招标公示可以用自己的电脑做网站主机
  • 万网云虚拟主机上传网站企业网站推广可以选择哪些方法?