链接:https://ac.nowcoder.com/acm/problem/219811
来源:牛客网
题目描述
You are given an array a of n integers. You have to clearing all elements equal to k in this array.
When there is at least one element equal to k in the array, then you should make all the positive elements in the array minus one. In other words, ai=ai−1(1≤i≤n;ai>0)a_i=a_i-1(1\leq i\leq n;a_i > 0)ai=ai−1(1≤i≤n;ai>0) .
When the array does not have any element equal to k , please output the array.
输入描述:
The first line contains two integers n(1≤n≤10^6), k(1≤k≤10^9)— the length of a and the number we need to clear.
The second line contains n integers a1,a2,...,an(1≤ai≤10^9).
输出描述:
Output the array when the array does not have any element equal to k .
Please do not output extra blank spaces at the end of the output.
示例1
输入
5 1
5 2 3 4 1
输出
0 0 0 0 0
示例2
输入
6 1
1 1 4 5 1 4
输出
0 0 3 4 0 3
题目大意:给定一个含有n个整数的数组a(a中元素大于等于1),给定一个k(k>=1),如果数组中存在与k相等的元素,则将数组中所有元素减一,最多减到0,输出最后剩余的数组
初始代码(提示运行超时)
#include<iostream>
using namespace std;
int main(){
int n,k,i,j;
cin>>n>>k;
int a[n];
for(i = 0; i < n; i++){
cin>>a[i];
}
for(i = 0; i < n;){
if(a[i]==k){
for(j = 0; j < n; j++){
if(a[j]==0){
continue;
}
a[j]-=1;
}
i = 0;
}else i++;
}
for(i = 0; i < n ;i++){
if(i==0)cout<<a[i];
else cout<<" "<<a[i];
}
return 0;
}
说明思路没有问题,需要优化代码,因为出现了二阶循环,时间复杂度过大
优化思路:先将数组中所有的数排序,放入另外一个数组,将此数组排序后找到给定元素k,从k位置开始找到含k连续块,该含k连续块的max-k-1是需要为数组中全部元素减的值
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,k,i,j,max = 0,p = 0;
cin>>n>>k;
int a[n],b[n];
for(i = 0; i < n; i++){
cin>>a[i];
b[i] = a[i];
}
sort(b,b+n);
for(i = 0; i < n ;i++){
if(b[i]==k){
j = i;
break;
}
}
if(i!=n){
for(i = j; i < n;){
if(b[i]==k){
_:
if(b[i+1] == b[i]+1||b[i+1]==b[i]){
i++;
goto _;
}else {
goto __;
}
}else{
__:
max = b[i];
break;
}
}
if(max==k){
p = k;
}else p = max-k+1;
}else {
p = 0;
}
for(i = 0; i < n ;i++){
a[i] = a[i]-p;
if(a[i]<=0)a[i]=0;
if(i==0)cout<<a[i];
else cout<<" "<<a[i];
}
return 0;
}
成功ac
题目难点:1.意识到二阶循环必然超时,需要优化算法(及时break掉循环,用goto可以避免二重循环)
2.需要考虑初始数组中无k值的情况