黑马程序员技术交流社区

标题: 关于数组去重 [打印本页]

作者: 无此姓名    时间: 2014-4-1 22:57
标题: 关于数组去重
本帖最后由 无此姓名 于 2014-4-1 23:00 编辑

这是黑马基础测试里的一个题目,感觉有点意思,和大家讨论一下。
需求数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}。
前提:在网上看到有其他办法,但目前我们课程刚进行到String类,很多知识都没学到,想到用“标志位计算元素个数”的办法。
问题:就目前我的知识水平(刚刚学完String类)不知道大家有什么好的解决办法没有。
我的代码如下

  1. package com.itheima;

  2. import java.util.Arrays;

  3. public class Test8 {

  4.         /**
  5.          *需求:数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
  6.          * @param args
  7.          */
  8.         public static void main(String[] args) {
  9.                 int arr[]={4,2,4,6,1,2,4,7,8};
  10.                 System.out.println(Arrays.toString(repeat(arr)));        //将去重后数组打印出来
  11.         }
  12.         
  13.         /*定义方法实现去重。
  14.          * 思路:
  15.          *                 1、先确定去重后数组元素的个数count,定义一个boolean类型数组来给重复的元素做标志;
  16.          *                 2、定义元素个数为count的新数组arrNew,将所有不重复的元素存入数组中。
  17.          *                 3、将arrNew返回。
  18.          * */
  19.         
  20.         public static int[] repeat(int [] arr){
  21.                 boolean flag[] = new boolean[arr.length];//定义一个和目标数组长度一样的boolean类型,此数组用作标示,用于获取不重复元素的个数的标志位
  22.                 for (int i = 0; i < flag.length; i++) {//遍历数组,查找重复的元素。循环结束后,重复的元素对应的标志位置都为true。
  23.                         if (flag[i]) //如果这个元素对应的标志位已被置为true,则返回循环继续检查下一个元素。
  24.                                         continue;
  25.                         for (int j = i+1; j < flag.length; j++) {    //后边元素和此位置上的元素比较,
  26.                                 if (arr[j]==arr[i]) {     //如果后边元素和前边元素相同,
  27.                                         flag [j]=true;   //则此重复元素对应的标志位置为true
  28.                                 }
  29.                         }
  30.                 }
  31.                
  32.                 int count=0;    //计数器,记录不重复元素的个数
  33.                 for (int i = 0; i < flag.length; i++) {    //算出不重复元素的个数,记为count,
  34.                         if (!flag[i]) {      //标志位依然为false的对应元素即为不重复的元素
  35.                                 count++;
  36.                         }
  37.                 }
  38.                
  39.                 int index=0;
  40.                 int [] arrNew = new int [count];        //定义新数组,元素个数为count。
  41.                 for (int i = 0; i < arr.length; i++) {        //将所有不重复的元素存入新数组中
  42.                         if (!flag[i]) {
  43.                                 arrNew[index++]=arr[i];
  44.                         }
  45.                 }
  46.                
  47.                 return arrNew;        //返回数组
  48.         }
  49. }
复制代码

作者: 亓华森    时间: 2014-4-2 08:24
分享一下我写的
  1. package com.itheima;

  2. /*
  3. * 5、 数组去重复,
  4. 例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
  5. */

  6. public class Test5
  7. {
  8.         public static void main(String args[])
  9.         {
  10.                 int[] arr={4,2,4,6,1,2,4,7,8};//创建并初始化数组
  11.                 for(int i=0;i<8;++i)
  12.                 {
  13.                         for(int j=i+1;j<9;++j)
  14.                         {
  15.                                 if(arr[i]==arr[j])
  16.                                 {
  17.                                         arr[j]=-1;//逐个比较数组中元素,如果出现两个元素相等,则后一个元素赋值-1
  18.                                 }
  19.                         }
  20.                 }
  21.                 for (int i=0;i<9;++i)
  22.                 {
  23.                         if(arr[i]!=-1)
  24.                         {
  25.                                 System.out.print(arr[i]+" ");}continue;//逐个输出数组元素,遇到-1的元素跳过
  26.                         }
  27.                 }
  28. }
  29.        
复制代码

作者: 1453149997    时间: 2014-4-2 12:14
本帖最后由 1453149997 于 2014-4-2 12:16 编辑

下面的内容请不要抄袭,这是我在黑马基础测试题里的解法:
  1. public class Test5 {
  2.         public static void main(String[] args) {
  3.                 //1.创建一个数组
  4.                 Integer[] arr ={4,2,4,6,1,2,4,7,8};
  5.                 //2.利用LinkedHashSet的"元素不可重复"特性去除重复元素(使用链表结构的集合主要是为了让数组元素的前后位置关系不发生变化)
  6.                 LinkedHashSet<Integer> set = new LinkedHashSet<Integer>();
  7.                 for(Integer temp:arr){
  8.                         set.add(temp);
  9.                 }
  10.                 //3.把集合转换成数组
  11.                 arr = set.toArray(new Integer[0]);
  12.                
  13.                 //4.输出去除重复元素后的数组元素
  14.                 for(int temp:arr){
  15.                         System.out.print(temp);
  16.                 }
  17.         }
  18. }
复制代码



作者: Saner    时间: 2014-4-2 12:32
思想大概就是把数组放到set里面(set的值不会重复)就可以去重了
                  Integer[] arr = {4,2,4,6,1,2,4,7,8};

        Set<Integer> set = new HashSet<Integer>();

        for(Integer i : arr)

        set.add(i);

        for(Object j: set.toArray())

        System.out.print(j + " ");
作者: 无此姓名    时间: 2014-4-2 18:20
亓华森 发表于 2014-4-2 08:24
分享一下我写的

你这个只是打印了一下不重复的元素,并没有生成新数组啊
作者: 无此姓名    时间: 2014-4-2 18:24
1453149997 发表于 2014-4-2 12:14
下面的内容请不要抄袭,这是我在黑马基础测试题里的解法:

你这用集合了,没学呢,不用集合有其他办法吗?
作者: 无此姓名    时间: 2014-4-2 18:25
Saner 发表于 2014-4-2 12:32
思想大概就是把数组放到set里面(set的值不会重复)就可以去重了
                  Integer[] arr = {4,2, ...

不用集合有其他办法吗?
作者: 一世英明    时间: 2014-4-2 19:44
群里高手很多啊!!
作者: 张治国    时间: 2014-4-2 22:42
一世英明 发表于 2014-4-2 19:44
群里高手很多啊!!

我是刚报名的,正好我的测试题就有这道题,分享一下

/**
* 5、 数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
* 思路:
* 遍历原始数组
* 定义个容器,让数组中的每个元素与这个容器中的元素比较,如果这个元素不存在,就将数组中的这个元素存储到容器中。反之,舍弃。
* 再用个容器以{4,2,6,1,7,8}的形式存储。
* 最后打印结果。
*/
public class Test5 {

        public static void main(String[] args) {
                //原始数值
                int[] nums = new int[]{4,2,4,6,1,2,4,7,8};
                //定义一个容器,
                List<Integer> list = new ArrayList<Integer>();
                //循环遍历去除数组中重复的元素
                for (int i = 0; i < nums.length; i++) {
                        if (!list.contains(nums)) {
                                list.add(nums);
                        }
                }
               
                StringBuffer sb = new StringBuffer();
                sb.append("{");
                Iterator<Integer> it=list.iterator();
                while(it.hasNext()){
                        sb.append(it.next()+",");
                       
                }
                sb.delete(sb.length()-1,sb.length());//删除最后一个元素
                sb.append("}");
                System.out.println(sb);

        }

}
作者: lwy0319    时间: 2014-4-2 22:42
无此姓名 发表于 2014-4-2 18:20
你这个只是打印了一下不重复的元素,并没有生成新数组啊

我看了下,思路差不多的,你在这个基础上在数出-1的个数在计数,再初始化新数组在放在检查非-1的放进去就好,它这个主要是给你提供了一个除了脚标也可以赋值的思路,生成的过程是可以跟你的一样的
作者: 无此姓名    时间: 2014-4-2 23:24
lwy0319 发表于 2014-4-2 22:42
我看了下,思路差不多的,你在这个基础上在数出-1的个数在计数,再初始化新数组在放在检查非-1的放进去就 ...

如果给出的数组里本身就有-1元素呢? 比如{2,3,4,5,6,-1,3,4,2}
作者: 无此姓名    时间: 2014-4-2 23:25

你这代码有问题,如果数组里本身就有-1呢? 比如{1,2,3,4,5,6,-1,1,2,3,4}
作者: lwy0319    时间: 2014-4-2 23:26
无此姓名 发表于 2014-4-2 23:24
如果给出的数组里本身就有-1元素呢? 比如{2,3,4,5,6,-1,3,4,2}

赋值之前检查下哈,如果有就赋值别的,大不了循环检查,依次减一定的数。
作者: 无此姓名    时间: 2014-4-2 23:38
lwy0319 发表于 2014-4-2 23:26
赋值之前检查下哈,如果有就赋值别的,大不了循环检查,依次减一定的数。 ...

写出来看
作者: lwy0319    时间: 2014-4-3 02:54
  1. public class Test{
  2.         public static void main(String[] args) {
  3.                 int oldA[]={4,2,4,6,1,2,4,7,8,0,0,-1,-1,-2,-2,-3};//初始化原始数组
  4.                 int x=0;//初始化新的数组长度
  5.                 int y=0;//初始化新数组的脚标
  6.                 int m=0;
  7.                 int n=0;
  8.                 int nonexistent=0;
  9.                 int a=0;
  10.                 while(a<oldA.length){
  11.                         for(int i=0;i<oldA.length;i++){
  12.                                 if(oldA[i]==nonexistent)
  13.                                         nonexistent--;
  14.                         }
  15.                         a++;
  16.                 }
  17.                         for(int i=1;i<oldA.length;i++){//嵌套循环给与数组索引编号靠后的项数相同的项赋值为nonexistent
  18.                                 for(int j=0;j<i;j++){
  19.                                         if(oldA[i]==oldA[j]){
  20.                                                 oldA[i]=nonexistent;
  21.                                         }
  22.                                         }
  23.                                 }
  24.                         for(int i=0;i<oldA.length;i++){//判断原始数组变更后的0项的个数
  25.                                 if(oldA[i]!=nonexistent){            //并从新数组长度的初值减去
  26.                                         x++;
  27.                                 }
  28.                         }
  29.                 //}
  30.                
  31.                 int newA[]=new int[x];//初始化新数组,类型,长度
  32.                 for(int i=0;i<oldA.length;i++){
  33.                         if(oldA[i]!=nonexistent){//将原始数组中的非零项加入新数组
  34.                                 newA[y++]=oldA[i];//每被赋值一次,新数组的脚标数值+1以便下次赋值用
  35.                         }
  36.                 }
  37.                 for(int i=0;i<newA.length;i++)
  38.                         System.out.print(newA[i]+" ");//循环输出新数组
  39.                 }
  40.         }
复制代码

好吧。。。满足你。。不过感觉没必要太较真。。毕竟后面很快就会学到动态数组了。马上你就是不用跟小学奥数较真的大学生了哈,另外说下还是你的方法更好一些,那个人只是给你提供一个思路,虽然代码当时没实现得很好,提取有用的地方就好了。
作者: 无此姓名    时间: 2014-4-5 10:03
lwy0319 发表于 2014-4-3 02:54
好吧。。。满足你。。不过感觉没必要太较真。。毕竟后面很快就会学到动态数组了。马上你就是不用跟小学 ...

好吧,你赢了,这题确实没什么实际用处。但是限定范围就是为了搞一搞奥数题嘛。
作者: lwy0319    时间: 2014-4-5 15:23
无此姓名 发表于 2014-4-5 10:03
好吧,你赢了,这题确实没什么实际用处。但是限定范围就是为了搞一搞奥数题嘛。 ...

你说的有道理,我最开始接触这题的时候,学习进度还不如你,我写了篇技术博客,引用了你的代码,地址:
http://blog.csdn.net/u013938806/article/details/22985985
作者: 王春涛    时间: 2014-6-26 10:24
Saner 发表于 2014-4-2 12:32
思想大概就是把数组放到set里面(set的值不会重复)就可以去重了
                  Integer[] arr = {4,2, ...

for(Integer i : arr)   这是什么用法?新手没见过
作者: chensc    时间: 2014-7-2 12:30
学习学习!
作者: 大★宝    时间: 2014-8-3 12:48
  1. package com.itheima;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. @SuppressWarnings({ "rawtypes", "unchecked" })
  5. public class Test7 {
  6.         /**
  7.          * 7、 数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
  8.          */
  9.         public static void main(String[] args) {
  10.         int[] arr = { 4, 2, 4, 6, 1, 2, 4, 7, 8 };
  11.         //创建对象
  12.         List data = new ArrayList();
  13.         //增强for
  14.         for (int num : arr) {
  15.             if (!data.contains(num)) {
  16.                 data.add(num);
  17.             }
  18.         }
  19.         //打印数组
  20.         System.out.println(data);
  21.     }
  22. }
复制代码

作者: 敲敲代码    时间: 2014-8-21 17:37
我也有这道题学习了
作者: 孤鸢    时间: 2014-8-22 23:57
本帖最后由 孤鸢 于 2014-8-23 00:19 编辑

我有个没有用集合的方法,在考试审核通过了发的,加技术分的各种可能都不放过0.0  @加分  大神
  1. public class Test8
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 int[] arr = {4,2,4,6,1,2,4,7,8};
  6.                 int len = arr.length;
  7.                 System.out.println("原数组:");
  8.                 printArray(arr,len);
  9.                
  10.                 /*
  11.                  *思路:每遇到重复的元素,就将其后面的元素向前移一位,然后将数组长度减1。
  12.                  *                这样增加了系统的开销,因为移动次数多了,但是思路很好理解,而且结果没有打乱原数的顺序
  13.                  */
  14.                 for(int i=0; i<len-1; i++)
  15.                 {
  16.                         int key = arr[i];
  17.                         for(int j=i+1; j<len; j++)
  18.                         {
  19.                                 if(arr[j] == key)
  20.                                 {
  21.                                         for(int k=j; k<len-1; k++)
  22.                                         {
  23.                                                 arr[k] = arr[k+1];                                                
  24.                                         }
  25.                                         len = len-1;
  26.                                 }
  27.                         }
  28.                 }
  29.                 System.out.println("去重复后数组:");
  30.                 printArray(arr,len);
  31.                

  32.                
  33.         }
  34.         //打印数组
  35.         public static void printArray(int[] a, int len)
  36.         {               
  37.                 for(int i=0; i<len; i++)
  38.                         System.out.print(a[i]+" ");      //这儿曾将双引号写成了单引号,死活打印不出正确数组,坑死了^_^
  39.                 System.out.println();
  40.         }
  41. }
复制代码

作者: Fightin黑马    时间: 2014-8-24 22:57
贴一下我写的吧,只是用到数组知识
package com.itheima;
//*7、 数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
思路:
        1.新建一个长度和原数组长度相同的空数组,
        2.依次取出原数组中的数和新数组的每个数做比较,如果有就下一个数做比较,没有就把数放到新数组
                并且定义一个变量记录不重复数字的个数
        3.遍历完得到的新数组中为不重复数组,但是后面会有空的位置,再新建一个数组,长度为不重复数字的个数,将第二个数组复制到新数组.
public class Test7 {
        public static void main(String[] args) {
                int[]arr1={1,2,3,4,5,6,7,8,9,9};//原始数组arr1
                int[]arr2=new int[arr1.length];//新建数组arr2用来接收不重复数字,长度和原数组相同,因为可能原数组全部都不重复.
                int count=1;//记录不重复的数字个数
                arr2[0]=arr1[0];//将第一个数放进新数组
                loop2:
                for(int i=0;i<arr1.length;i++){//取出arr1 的每个数
                        for(int j=0;j<count;j++){
                                if(arr2[j]!=arr1[i]){//如果arr2 中没有arr1 取出的数字,把这个数字放进arr2,计数器加一
                                        if(j==count-1){
                                                arr2[count]=arr1[i];
                                                count++;
                                        }
                                        continue ;//放完继续下一个arr1中的数
                                }else{
                                        continue loop2;//有重复的,直接再来一轮
                                }
                        }
                }
                int arr3[]=new int[count];//因为arr2 后面有空位,去掉空位复制新数组,新数组就是不重复的
                for(int i=0;i<count;i++){
                        arr3[i]=arr2[i];
                }
                print(arr1);//
                System.out.println();
                print(arr3);
        }
        public static void print(int arr[]){//打印数组函数
                for(int i=0;i<arr.length;i++){
                        System.out.print(arr[i]+"\t");
                }
        }

}

作者: Fightin黑马    时间: 2014-8-24 23:00
王春涛 发表于 2014-6-26 10:24
for(Integer i : arr)   这是什么用法?新手没见过

for ...each 循环,就是遍历arr数组中的每一个数
作者: 清晨    时间: 2014-9-23 16:31
挺好的不错。思维清晰
作者: 风逝    时间: 2014-11-18 15:57
  1. import java.util.List;
  2. import java.util.concurrent.CopyOnWriteArrayList;

  3. /**
  4. * 创建时间:2014-11-18 下午3:26:35
  5. *
  6. * @author zhangtianyou
  7. * @version 2.2
  8. */

  9. public class ArrayRemoveRepeat {

  10.         /**
  11.          * @param args
  12.          */
  13.         public static void main(String[] args) {
  14.                 // 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}。
  15.                 System.out.println("之前的数组");
  16.                 Integer[] src = { 4, 2, 4, 6, 1, 2, 4, 7, 8 };
  17.                 for (Integer k : src) {
  18.                         System.out.print(k + ",");
  19.                 }

  20.                 List<Integer> list = new CopyOnWriteArrayList<Integer>(src);


  21.                 int i = 0;
  22.                 while (i < list.size() - 1) {
  23.                        
  24.                         int j = i+1;
  25.                         while (j < list.size()) {
  26.                                 if (list.get(i) == list.get(j)) {
  27.                                         list.remove(j);
  28.                                         j--;
  29.                                 }
  30.                                 j++;
  31.                         }
  32.                        

  33.                         i++;
  34.                 }

  35.                 src = list.toArray(new Integer[list.size()]);
  36.                 System.out.println("\n之后的数组");
  37.                 for (Integer k : src) {
  38.                         System.out.print(k + ",");
  39.                 }
  40.         }
  41. }
复制代码

作者: 延续梦境    时间: 2015-3-2 20:21
1453149997 发表于 2014-4-2 12:14
下面的内容请不要抄袭,这是我在黑马基础测试题里的解法:

还行吧,只是感觉你这样有生成数组吗?
作者: kingowe    时间: 2015-5-18 11:49
不错,都挺厉害啊
作者: zxj35986847    时间: 2015-5-28 01:59
Saner 发表于 2014-4-2 12:32
思想大概就是把数组放到set里面(set的值不会重复)就可以去重了
                  Integer[] arr = {4,2, ...

你这样,输出的结果并不是{4,2,6,1,7,8}.而是{1,2,4,6,7,8}
作者: 喂小饱    时间: 2015-6-18 16:17
编立数组然后去掉相同的行吗?

作者: liuch111    时间: 2015-7-26 11:19
2楼写的比较好                  
作者: yonghong_cui    时间: 2015-9-24 00:42
搞了好一会。没搞出来,
作者: 范能胡    时间: 2017-11-6 10:18

你这个思想挺好的,但是如果数组里面本来就有-1的话,-1这个值也会被跳过,结果就会有误。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2