[算法]删除已排序数组中的重复元素

时间:2021-09-04 11:10:00

删除已排序数组中的重复元素

代码功能:

  1. 统计已排序数组中重复元素的个数int morethan2(int[] a)
  2. 获取删除了重复元素的新数组int[] deletemul(int[] a,int sum)

完整源码:

public class D{
public static void main(String args[]){
int[] a = {1,1,1,1,1,1,1,1,1,1,1};
int[] b = {1,1,1,1,2,2,2,3,3,3,4};
System.out.println(a.length);
System.out.println(morethan2(a));
System.out.println(b.length);
System.out.println(morethan2(b));

deletemul(a,morethan2(a));
System.out.println("");
deletemul(b,morethan2(b));


}
public static int morethan2(int[] a){
int step = 1;
int sum = 0;
for(int i=0;i<a.length-1;i+=step)
{
int index = 1;
while((i+index<a.length)&&(a[i]==a[i+index]))
{
index++;
}
step = index;
if(index>1)
{
sum += (index-1);
}
}
return sum;
}
public static int[] deletemul(int[] a,int sum)
{
int[] newlist = new int[a.length-sum];
int step2 = 1;
for(int i=0,j=0;j<newlist.length;i+=step2,j++)
{
int index2 = 1;
while(((i+index2)<a.length)&&(a[i]==a[i+index2]))
{
index2++;
}
step2 = index2;

newlist[j] = a[i];
System.out.print(newlist[j]);
}
return newlist;
}

}

输出结果:

———–OUTPUT———–
11
10
11
7
1
1234

———–OUTPUT———–
11 > System.out.println(a.length); 输出数组a的原始长度
10 > System.out.println(morethan2(a)); 输出数组a中重复元素的个数
11 > System.out.println(b.length);
7 > System.out.println(morethan2(b));
1 > deletemul(a,morethan2(a)); 剔除了重复元素后的a数组输出
1234 > deletemul(b,morethan2(b)); 剔除了重复元素后的b数组输出

代码说明:

计算重复元素部分

利用输入数组已经排好序的特性,以下代码可以实现计算出每次步进的距离step,

for(int i=0;i<a.length-1;i+=step){
int index = 1;
while((i+index<a.length)&&(a[i]==a[i+index]))
{
index++;
}
step = index;
...
...
}

如果某一次步进次数变得大于1次(本身的存在就是1次),就说明这个值存在重复,把重复的次数(大于1的部分index-1)累加到变量sum,

if(index>1) 
{
sum += (index-1);
}

获取剔除重复元素的数组部分

原始输入数组a以i+=step步进向前,存储剔除重复元素后的数组b以 j++ 步进向前

 for(int i=0,j=0;j<newlist.length;i+=step2,j++)
{
...

newlist[j] = a[i];

...

}

以数组int[] b = {1,1,1,1,2,2,2,3,3,3,4}; 举例,可以看到i以及j的变量值得变化分别是:

i 0     j 0
i 4 j 1
i 7 j 2
i 10 j 3

代码心得:

  1. 数组一旦声明长度就固定不变了,所以根本不能删除元素,要么就是在某些场合将元素值置为某个特殊值(比如零),要么就是【把元素提出来放到新的数组里】,所以一开始遇到“删除”这个任务,我就觉得应该是不能再元数组上瞎弄的;

  2. 虽然不能对数组进行粗暴的增、删,但是排序却可以很容易实现;

  3. 观察了一下排好序的数组,无论是升序还是降序,可以看见拥有相同值得元素都被放到“一块”去了,那么只要在提数据的时候只提一次不就好了;

  4. 既然数组元素长度是不变的, 那么用来存放数据的新数组的长度就要先确定,新数组的长度很容易想到就是【原始数组的长度减去重复元素的个数】(即:old[] ={1 1 1 2 2 3 4} new[]={1 2 3 4} //长度从7变成了3 重复的元素个数是3)

  5. 视线回到代码的话,就是对应每次多余的步进次数,因为没有重复的时候步进次数是1,重复的时候需要重复的次数就是步进次数减去1sum += (index-1);

  6. 但是“只提一次”这个怎么用代码体现?我想到的是【跳过后面重复的元素】,所以写出了newlist[j] = a[i];来体现这种跳过效果。

    反思

    这次的代码感觉非常不鲁棒,并且重复代码很多,感觉很笨重,还需努力。