用代码实现对数组重复元素的去重-面试思考题

这道题主要是考察array_unqiue 的底层实现

php中array_unique源码为:

 PHP_FUNCTION(array_unique)
 4 {
 5     // 定义变量
 6     zval *array, *tmp;
 7     Bucket *p;
 8     struct bucketindex {
 9         Bucket *b;
10         unsigned int i;
11     };
12     struct bucketindex *arTmp, *cmpdata, *lastkept;
13     unsigned int i;
14     long sort_type = PHP_SORT_STRING;
15
16     // 解析参数
17     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
18         return;
19     }
20
21     // 设置比较函数
22     php_set_compare_func(sort_type TSRMLS_CC);
23
24     // 初始化返回数组
25     array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
26     // 将值拷贝到新数组
27     zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array), (copy_ctor_func_t) zval_add_ref, (void *)&tmp, sizeof(zval*));
28
29     if (Z_ARRVAL_P(array)->nNumOfElements <= 1) {    /* 什么都不做 */
30         return;
31     }
32
33     /* 根据target_hash buckets的指针创建数组并排序 */
34     arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->persistent);
35     if (!arTmp) {
36         zval_dtor(return_value);
37         RETURN_FALSE;
38     }
39     for (i = 0, p = Z_ARRVAL_P(array)->pListHead; p; i++, p = p->pListNext) {
40         arTmp[i].b = p;
41         arTmp[i].i = i;
42     }
43     arTmp[i].b = NULL;
44     // 排序
45     zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), php_array_data_compare TSRMLS_CC);
46
47     /* 遍历排序好的数组,然后删除重复的元素 */
48     lastkept = arTmp;
49     for (cmpdata = arTmp + 1; cmpdata->b; cmpdata++) {
50         if (php_array_data_compare(lastkept, cmpdata TSRMLS_CC)) {
51             lastkept = cmpdata;
52         } else {
53             if (lastkept->i > cmpdata->i) {
54                 p = lastkept->b;
55                 lastkept = cmpdata;
56             } else {
57                 p = cmpdata->b;
58             }
59             if (p->nKeyLength == 0) {
60                 zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
61             } else {
62                 if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
63                     zend_delete_global_variable(p->arKey, p->nKeyLength - 1 TSRMLS_CC);
64                 } else {
65                     zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
66                 }
67             }
68         }
69     }
70     pefree(arTmp, Z_ARRVAL_P(array)->persistent);
71 }

#########################################################################################################################################################

  还想深挖的给大家推荐几篇好文章:

     http://blog.csdn.net/lz610756247/article/details/51512918

  php源码注释:https://github.com/hoohack/read-php-src

#####################################################################################################

自己用php实现该函数的底层。

思路:

1.还是先对数组进行排序。

//第一步:先对数组排序,采用冒泡排序

function bubble($arr)

{

  $len = count($arr);    //计算数组元素的个数

  for($i =1 ; $i< $len ;$i++)   // 对比次数

  {

    for($j = 0;$j<$len-$j;$j++)  //循环次数

    {

      if($arr[$i] > $arr[$j])

      {

        $temp  = $arr[$i] ;

        $arr[$i] = $arr[$j];

        $arr[$j] = $temp; 

      }

    }

  }

  return $arr;

}

//主函数function  dd($arr)

{

  $data = bubble($arr);

  for($i = 0; $i < count($data);$i++)

  {

      if($data[$i] == $data[$i+1])

      {

        unset($data[$i+1]);

      }  

  }

  return $arr;

}

$arr = [2,3,42,1,23,2,4,55,73,5];

dd($arr);

######

补充:运行上述代码会包一个notice的错误,用error_reporting(E_ALL||E_NOTICE)屏蔽错误就可以了

主要原因 是$data数组是索引数组,unset以后,键会出现空缺部分,所以报错,其实不算报错,算是php的一个“提醒”。

时间: 2024-08-24 15:03:16

用代码实现对数组重复元素的去重-面试思考题的相关文章

Perl快捷删除数组重复元素,以前写过类似的博客,今天被问起时,却支支吾吾!

以前写过类似的博客: http://blog.csdn.net/three_man/article/details/34084361 今天拿出来,再好好剖析一下: 1. 构造一个含有重复元素的数组 my @arr1 = (1 .. 10); my @arr2 = (5 .. 15); # join multi array my @arr = (@arr1, @arr2); 2. 删除数组中的重复元素 sub removeRepeat { my $arrRef = shift; my %count

javascript 笔试题之删除数组重复元素

笔试时紧张没写出来,静下心后发现简单的要死. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content=&quo

前端面试高频题:删除数组重复元素的多种方法

最近在想着换工作,去了一家中关村的上市公司,面试官随便问了几个问题其中就提到了怎么删除数组元素的方法,表示这已经是第三次遇到了这个问题了,由于知识口头说说所以就随便说了下,之前用的时候都是直接找的方法库虽然知道大致是怎么写的但是还没有真正写过,网上的方法还是蛮多的这里也给大家分享一个作者写的吧,希望对初学者有所帮助: //数组去重的方法 Array.prototype.unique=function(){ //集中声明变量 var oldArr=this, newArr=[oldArr[0]],

每日一题之LeetCode移除元素 删除有序数组重复元素

这两道题若是不使用官方题解的双指针做法,就会涉及到浅复制,深复制的问题,可参考如下https://blog.csdn.net/qq_32907349/article/details/52190796 .其中,此题将要使用深复制,但这会违背题意中的不开辟新的内存空间. 1.移除元素class Solution:def removeElement(self, nums, val):i = 0for j in range(0,len(nums)): if (nums[j] != val): nums[

Js删除数组重复元素的多种方法

js对数组元素去重有很多种处理的方法,本篇文章中为网络资源整理,当然每个方法我都去实现了:写下来的目的是希望自己活学活用,下次遇到问题后方便解决. 第一种 1 function oSort(arr){ 2 var result={}; 3 var newArr=[]; 4 for(var i=0;i<arr.length;i++){ 5 if(!result[arr[i]]){ 6 console.log(result[arr[i]]); //看看输出的是什么 7 newArr.push(arr

JS Jquery去除数组重复元素

js jquery去除数组中的重复元素 第一种:$.unique() 第二种: for(var i = 0,len = totalArray_line.length;i < len;i++) { !RegExp(totalArray_line[i],"g").test(resultArray_line.join(",")) && (resultArray_line.push(totalArray_line[i])); }-----解决了V0.2

JavaScript删除数组重复元素的5个高效算法

1.遍历数组法 最简单的去重方法, 实现思路:新建一新数组,遍历传入数组,值不在新数组就加入该新数组中:注意点:判断值是否在数组的方法“indexOf”是ECMAScript5 方法,IE8以下不支持,需多写一些兼容低版本浏览器代码,源码如下: // 最简单数组去重法 function unique1(array){   var n = []; //一个新的临时数组   //遍历当前数组   for(var i = 0; i < array.length; i++){     //如果当前数组的

219. 数组重复元素2 Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k. public class Solution { public bool ContainsNearby

js 去除重复元素

方法一: 1 //数组去重的方法 2 Array.prototype.unique=function(){ 3 //集中声明变量 4 var 5 oldArr=this, 6 newArr=[oldArr[0]], 7 len=oldArr.length, 8 i=1; 9 //过滤空数组 10 if(!len) return this; 11 //过滤重复元素 12 for(;i<len;i++){ 13 newArr.indexOf(oldArr[i])<0 ? newArr.push(_