【问题标题】:Array remove duplicate elements数组删除重复元素
【发布时间】:2011-03-22 00:11:17
【问题描述】:

我有一个未排序的数组,如果存在元素的所有重复项,最好的方法是什么?

例如:

a[1,5,2,6,8,9,1,1,10,3,2,4,1,3,11,3]

所以在该操作之后数组应该看起来像

 a[1,5,2,6,8,9,10,3,4,11]

【问题讨论】:

  • 这是作业吗?如果没有,许多语言(至少脚本语言)都内置了这个。Ruby:[1, 2, 3, 2, 3, 1].uniq
  • 使用一个临时字典,您可以在读取元素时在其中插入元素,以便在字典中已有元素时将其删除。
  • @jtbandes 这不是家庭作业.. 我想知道合适的算法。 @pascal 使用临时字典意味着使用额外的内存(存储)?
  • 是的,例如,请参阅 Matthew 的回答。
  • 另外,如果你是 C++ 用户..那么在 C++ STL cplusplus.com/reference/algorithm/unique 中使用 unique()

标签: algorithm arrays data-structures


【解决方案1】:

如果您不需要保留原始对象,您可以循环它并创建一个新的唯一值数组。在 C# 中,使用 List 来访问所需的功能。这不是最有吸引力或最智能的解决方案,但它确实有效。

int[] numbers = new int[] {1,2,3,4,5,1,2,2,2,3,4,5,5,5,5,4,3,2,3,4,5};
List<int> unique = new List<int>();

foreach (int i in numbers)
     if (!unique.Contains(i))
          unique.Add(i);

unique.Sort();
numbers = unique.ToArray();

【讨论】:

    【解决方案2】:

    您可以在 python 中使用“in”和“not in”语法,这使得它非常简单。

    虽然复杂度高于散列方法,但因为“不在”相当于线性遍历以找出该条目是否存在。

    li = map(int, raw_input().split(","))
    a = []
    for i in li:
        if i not in a:
            a.append(i)
    print a
    

    【讨论】:

      【解决方案3】:
      public class RemoveDuplicateArray {
          public static void main(String[] args) {
              int arr[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 9 };
              int size = arr.length;
              for (int i = 0; i < size; i++) {
                  for (int j = i+1; j < size; j++) {
                      if (arr[i] == arr[j]) {
                          while (j < (size) - 1) {
                              arr[j] = arr[j + 1];
                              j++;
                          }
                          size--;
                      }
                  }
              }
              for (int i = 0; i < size; i++) {
                  System.out.print(arr[i] + "  ");
              }
          }
      
      }
      

      输出 - 1 2 3 4 5 6 7 9

      【讨论】:

        【解决方案4】:
        Time O(n) space O(n) 
        
        #include <iostream>
            #include<limits.h>
            using namespace std;
            void fun(int arr[],int size){
        
                int count=0;
                int has[100]={0};
                for(int i=0;i<size;i++){
                    if(!has[arr[i]]){
                       arr[count++]=arr[i];
                       has[arr[i]]=1;
                    }
                }
             for(int i=0;i<count;i++)
               cout<<arr[i]<<" ";
            }
        
            int main()
            {
                //cout << "Hello World!" << endl;
                int arr[]={4, 8, 4, 1, 1, 2, 9};
                int size=sizeof(arr)/sizeof(arr[0]);
                fun(arr,size);
        
                return 0;
            }
        

        【讨论】:

          【解决方案5】:
          import java.util.ArrayList;
          import java.util.Arrays;
          import java.util.Collection;
          import java.util.HashMap;
          import java.util.HashSet;
          import java.util.List;
          import java.util.Set;
          
          public class testing {
              public static void main(String[] args) {
                  EligibleOffer efg = new EligibleOffer();
                  efg.setCode("1234");
                  efg.setName("hey");
                  EligibleOffer efg1 = new EligibleOffer();
                  efg1.setCode("1234");
                  efg1.setName("hey1");
                  EligibleOffer efg2 = new EligibleOffer();
                  efg2.setCode("1235");
                  efg2.setName("hey");
                  EligibleOffer efg3 = new EligibleOffer();
                  efg3.setCode("1235");
                  efg3.setName("hey");
                  EligibleOffer[] eligibleOffer = { efg, efg1,efg2 ,efg3};
                  removeDupliacte(eligibleOffer);
              }
          
              public static EligibleOffer[] removeDupliacte(EligibleOffer[] array) {
                  List list = Arrays.asList(array);
                  List list1 = new ArrayList();
                  int len = list.size();
                  for (int i = 0; i <= len-1; i++) {
                      boolean isDupliacte = false;
                      EligibleOffer eOfr = (EligibleOffer) list.get(i);
                      String value = eOfr.getCode().concat(eOfr.getName());
                      if (list1.isEmpty()) {
                          list1.add(list.get(i));
                          continue;
                      }
                      int len1 = list1.size();
                      for (int j = 0; j <= len1-1; j++) {
                          EligibleOffer eOfr1 = (EligibleOffer) list1.get(j);
                          String value1 = eOfr1.getCode().concat(eOfr1.getName());
                          if (value.equals(value1)) {
                              isDupliacte = true;
                              break;
                          }
                          System.out.println(value+"\t"+value1);
                      }
                      if (!isDupliacte) {
                          list1.add(eOfr);
                      }
                  }
                  System.out.println(list1);
                  EligibleOffer[] eligibleOffer = new EligibleOffer[list1.size()];
                  list1.toArray(eligibleOffer);
                  return eligibleOffer;
              }
          }
          

          【讨论】:

            【解决方案6】:

            我的解决方案(O(N))不使用额外的内存,但数组必须排序(我的类使用插入排序算法,但没关系。):

              public class MyArray
                    {
                        //data arr
                        private int[] _arr;
                        //field length of my arr
                        private int _leght;
                        //counter of duplicate
                        private int countOfDup = 0;
                        //property length of my arr
                        public int Length
                        {
                            get
                            {
                                return _leght;
                            }
                        }
            
                        //constructor
                        public MyArray(int n)
                        {
                            _arr = new int[n];
                            _leght = 0;
                        }
            
                        // put element into array
                        public void Insert(int value)
                        {
                            _arr[_leght] = value;
                            _leght++;
                        }
            
                        //Display array
                        public void Display()
                        {
                            for (int i = 0; i < _leght; i++) Console.Out.Write(_arr[i] + " ");
                        }
            
                        //Insertion sort for sorting array
                        public void InsertSort()
                        {
                            int t, j;
                            for (int i = 1; i < _leght; i++)
                            {
                                t = _arr[i];
                                for (j = i; j > 0; )
                                {
                                    if (_arr[j - 1] >= t)
                                    {
                                        _arr[j] = _arr[j - 1];
                                        j--;
                                    }
                                    else break;
                                }
                                _arr[j] = t;
                            }
                        }
            
                        private void _markDuplicate()
                        {
                            //mark duplicate Int32.MinValue
                            for (int i = 0; i < _leght - 1; i++)
                            {
                                if (_arr[i] == _arr[i + 1])
                                {
                                    countOfDup++;
                                    _arr[i] = Int32.MinValue;
                                }
                            }
                        }
            
                        //remove duplicates O(N) ~ O(2N) ~ O(N + N)
                        public void RemoveDups()
                        {
                            _markDuplicate();
                            if (countOfDup == 0) return; //no duplicate
                            int temp = 0;
            
                            for (int i = 0; i < _leght; i++)
                            {
                                // if duplicate remember and continue
                                if (_arr[i] == Int32.MinValue) continue;
                                else //else need move 
                                {
                                    if (temp != i) _arr[temp] = _arr[i];
                                    temp++;
                                }
                            }
                            _leght -= countOfDup;
                        }
                    }
            

            和主要的

            static void Main(string[] args)
            {
                 Random r = new Random(DateTime.Now.Millisecond);
                 int i = 11;
                 MyArray a = new MyArray(i);
                 for (int j = 0; j < i; j++)
                 {
                    a.Insert(r.Next(i - 1));
                 }
            
                 a.Display();
                 Console.Out.WriteLine();
                 a.InsertSort();
                 a.Display();
                 Console.Out.WriteLine();
                 a.RemoveDups();
                 a.Display();
            
                Console.ReadKey();
            }
            

            【讨论】:

              【解决方案7】:

              这是我用 C++ 创建的代码段,试试看

              #include <iostream>
              
              using namespace std;
              
              int main()
              {
                 cout << " Delete the duplicate" << endl; 
              
                 int numberOfLoop = 10;
                 int loopCount =0;
                 int indexOfLargeNumber = 0;
                 int largeValue = 0;
                 int indexOutput = 1;
              
                 //Array to hold the numbers
                 int arrayInt[10] = {};
                 int outputArray [10] = {};
              
                 // Loop for reading the numbers from the user input
                 while(loopCount < numberOfLoop){       
                     cout << "Please enter one Integer number" << endl;
                     cin  >> arrayInt[loopCount];
                     loopCount = loopCount + 1;
                 }
              
              
              
                  outputArray[0] = arrayInt[0];
                  int j;
                  for (int i = 1; i < numberOfLoop; i++) {            
                      j = 0;
                      while ((outputArray[j] != arrayInt[i]) && j < indexOutput) {
                          j++;
                      }
                      if(j == indexOutput){
                         outputArray[indexOutput] = arrayInt[i];
                         indexOutput++;
                      }         
                  }
              
                 cout << "Printing the Non duplicate array"<< endl;
              
                 //Reset the loop count
                 loopCount =0;
              
                 while(loopCount < numberOfLoop){ 
                     if(outputArray[loopCount] != 0){
                      cout <<  outputArray[loopCount] << endl;
                  }     
              
                     loopCount = loopCount + 1;
                 }   
                 return 0;
              }
              

              【讨论】:

                【解决方案8】:
                    indexOutput = 1;
                    outputArray[0] = arrayInt[0];
                    int j;
                    for (int i = 1; i < arrayInt.length; i++) {            
                        j = 0;
                        while ((outputArray[j] != arrayInt[i]) && j < indexOutput) {
                            j++;
                        }
                        if(j == indexOutput){
                           outputArray[indexOutput] = arrayInt[i];
                           indexOutput++;
                        }         
                    }
                

                【讨论】:

                  【解决方案9】:

                  对照其他元素检查每个元素

                  天真的解决方案是检查每个元素与其他元素。这很浪费,并且会产生 O(n2) 解决方案,即使您只是“前进”。

                  排序然后删除重复项

                  更好的解决方案是对数组进行排序,然后检查每个元素到它旁边的元素以查找重复项。选择一个有效的排序,这是 O(n log n)。

                  基于排序的解决方案的缺点是无法维持顺序。然而,一个额外的步骤可以解决这个问题。将所有条目(在唯一的排序数组中)放入具有 O(1) 访问权限的哈希表中。然后遍历原始数组。对于每个元素,检查它是否在哈希表中。如果是,则将其添加到结果中并从哈希表中删除。您最终将得到一个结果数组,该数组具有原始顺序,每个元素与其第一次出现的位置相同。

                  整数的线性排序

                  如果您正在处理某个固定范围的整数,则可以使用基数排序做得更好。例如,如果假设这些数字都在 0 到 1,000,000 的范围内,则可以分配大约 1,000,001 的位向量。对于原始数组中的每个元素,根据其值设置相应的位(例如,值 13 会导致设置第 14 位)。然后遍历原始数组,检查是否在位向量中。如果是,则将其添加到结果数组中并从位向量中清除该位。这是 O(n) 并且以空间换时间。

                  哈希表解决方案

                  这使我们找到了最好的解决方案:这种排序实际上是一种分散注意力的方法,尽管很有用。创建具有 O(1) 访问权限的哈希表。遍历原始列表。如果它不在哈希表中,请将其添加到结果数组中并将其添加到哈希表中。如果它在哈希表中,则忽略它。

                  这是迄今为止最好的解决方案。那为什么剩下的呢?因为像这样的问题是关于使你拥有(或应该拥有)的知识适应问题,并根据你对解决方案所做的假设来改进它们。发展一个解决方案并理解其背后的想法比重复一个解决方案有用得多。

                  此外,哈希表并不总是可用的。以嵌入式系统或空间非常有限的东西为例。您可以在少数操作码中实现快速排序,远远少于任何哈希表。

                  【讨论】:

                  • 在问题中,结果数组似乎保留了输入数组的顺序。
                  • 人们应该明确表示,哈希表只给你预期恒定时间,而不是保证恒定时间。
                  • 虽然 hashtable 不允许你添加重复的项目,但如果你把 hashtable 中的所有数字相加,然后简单地打印出来,你可以达到相同的结果。上面使用一些 if 条件并使逻辑更复杂的意义何在?
                  • @GökhanAkduğan 提到的最明显的原因:排序的重要性、缺乏哈希表可用性、空间限制。
                  • 如果发现重复,为什么要从哈希表中删除?重复也可能意味着三胞胎、四胞胎等。我不会从哈希表中删除该值。
                  【解决方案10】:

                  将数字视为键。

                  for each elem in array:
                  if hash(elem) == 1 //duplicate
                    ignore it
                    next
                  else
                    hash(elem) = 1
                    add this to resulting array 
                  end
                  
                  如果你知道数字范围等数据并且它是有限的,那么你可以用零初始化那个大数组。
                  array flag[N] //N is the max number in the array
                  for each elem in input array:
                    if flag[elem - 1] == 0
                      flag[elem - 1] = 1
                      add it to resulatant array
                    else
                      discard it //duplicate
                    end
                  

                  【讨论】:

                    【解决方案11】:

                    这可以使用基于哈希表的集合在摊销 O(n) 中完成。

                    伪代码:

                    s := new HashSet
                    c := 0
                    for each el in a
                      Add el to s.
                        If el was not already in s, move (copy) el c positions left.
                        If it was in s, increment c. 
                    

                    【讨论】:

                      【解决方案12】:

                      使用 Set 实现。
                      HashSet,TreeSetLinkedHashSet(如果是 Java)。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2013-05-20
                        • 2011-07-03
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-03-23
                        • 2010-10-13
                        相关资源
                        最近更新 更多