深信服笔试
最大排序序列
输入一个数n表示数组长度,再输入n个无重复的数表示数组的内容。
求最大排序连续上升子段的长度(某个连续子数组排序后两两之间只相差1)。
n∈[1,5000]
每个元素∈[1,1e9]
输入
5
3 1 2 4 6
输出
4
思想:用哈希表存储每个端点值对应连续区间的长度,
若数已在哈希表中:跳过不做处理;若是新数加入:取出其左右相邻数已有的连续区间长度 left 和 right,计算当前数的区间长度为:cur_length = left + right + 1,根据 cur_length 更新最大长度 max_length的值,更新区间两端点的长度值。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int l,r,len,ans=0;
unordered_map<int,int>mp;
for(auto &x:nums)
{
if(mp[x]) continue;
l=mp[x-1];
r=mp[x+1];
len=l+r+1;
ans=max(ans,len);
mp[x]=len;
mp[x-l]=len;
mp[x+r]=len;
}
return ans;
}
};
病毒入侵
小绿需要按顺序,去入侵n个主机,每个主机上的杀毒设备有自己的辨识度ai],如果小绿的伪装度v与杀毒设备的辨识度a[j]绝对值不超过x(主机的辨识精确度),即|a[i]-v|<=x,则病毒可以入侵成功当前主机。
现给定n个主机的辨识度,问小绿最少需要变化多少次伪装度(伪装度可以取任意值),才能按照顺序,成功入侵所有主机。注意,小绿初始时的伪装度可以取任意值,且不记入小绿变化的伪装次数。
输入描述
给定正整数n和x,分别表示主机数和主机的辨识精确度。接下来是n个正整数a[i],分别表示这n个主机的辨识度。
输出描述
输出一个整数,表示小绿最少需要变化多少次伪装度,才能入侵n个主机。
测试数据
5 4
4 9 6 7 8
0
说明
小绿将初始伪度设置为6,由于4,9,6,8,8与6的绝对值都不超过4,因此小绿可以成功入侵这些主机,需要变换0次。
//每次取小区间,迭代更新
#include<bits/stdc++.h>
using namespace std;
vector<int>nums;
int n,x;
void solve(vector<int>&nums)
{
cin>>n>>x;
nums.resize(n);
for(int i=0;i<n;i++) cin>>nums[i];
}
int main()
{
ios::sync_with_stdio(0);
solve(nums);
int ans=0;
int l=nums[0]-x;
int r=nums[0]+x;
for(int i=1;i<n;i++)
{
int a=nums[i]-x;
int b=nums[i]+x;
if(a>r || b<l)
{
l=a,r=b;
ans+=1;
}
else
l=max(a,l),r=max(b,r);
}
cout<<ans;
return 0;
}
LIZHI笔试
丑数
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
思想:这个题用三指针,第一个丑数是1,以后的丑数都是基于前面的小丑数分别乘2,3,5构成的。我们每次添加进去一个当前计算出来个三个丑数的最小的一个,并且是谁计算的,谁指针就后移一位。
class Solution {
public:
int nthUglyNumber(int n) {
vector<int>dp(n+2);
dp[0]=1;
int a2=0,a3=0,a5=0;
for(int i=1;i<n;i++)
{
dp[i]=min(dp[a2]*2,min(dp[a3]*3,dp[a5]*5));
if(dp[i]==dp[a2]*2) a2++;
if(dp[i]==dp[a3]*3) a3++;
if(dp[i]==dp[a5]*5) a5++;
}
return dp[n-1];
}
};