(leetcode) titleID136 【只出现一次的数字】

题目136:[只出现一次的数字]
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:
    你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:
    输入: [2,2,1]
    输出: 1
示例 2:
    输入: [4,1,2,1,2]
    输出: 4

思路

- [1]哈希计数法:循环计数
    - 用一个数组$arr来保存每个数的出现个数  键(每个数) => 值(出现次数)
    - 然后循环找出来次数为1的 键
    - 然后返回键,就是只出现一次的数;
- [2]数组去重法
    - 额外数组$arr来保存
    - 遍历当前数组中每一个元素;
    - 如果某个元素是新出现的加入到$arr中;
    - 如果某个元素已经在$arr,那么就删除;
    - 最后留在$arr数组中的值就是只有一个的。
 - [3]异或法
    - 看啦官网题解
    - 如果我们对 0 和二进制位做 XOR 运算,得到的仍然是这个二进制位;
        `a XOR 0 = a`
    - 如果我们对相同的二进制位做 XOR 运算,返回的结果是 0;
        `a XOR a = 0`
    - XOR 满足交换律和结合律;
    - 所以我们只需要将所有的数进行 XOR 操作,得到那个唯一的数字。

  - [4]内置函数
    - array_count_values() 返回一个数组: 数组的键是 array (数组的值必须是字符或者数字 )里单元的值; 数组的值是 array 单元的值出现的次数
    - array_flip() 对数组进行键值互换
    - 因为只有一个数字是出现一次的,所以那么最后也就是数组的第2个单元 也就是数组下标为1的值;
    - array_search — 在数组中搜索给定的值,如果成功则返回首个相应的键名
    - array_keys — 返回数组中部分的或所有的键名

Code

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer
     */
     //执行用时 :24 ms, 在所有 php 提交中击败了97.55%的用户
     //内存消耗 :17.3 MB, 在所有 php 提交中击败了66.24%的用户
     //哈希法  对每个元素进行计数
    function singleNumber($nums) {
        $arr = [];
        foreach ($nums as $value) {
            if(!isset($arr[$value])) {//防止Notice 数组键名未定义
                $arr[$value] = 1;//第一次出现
            }else{
                $arr[$value]++;//后续再次出现
            }
        }
        foreach ($arr as $key => $value) {
            if($value === 1) {//找到只出现一次的值
                return $key;
            }
        }
        return 0;
    }

    //执行用时 :24 ms, 在所有 php 提交中击败了97.55%的用户
    //内存消耗 :17.4 MB, 在所有 php 提交中击败了26.75%的用户
    //数组去重法:和第一种其实差别不是特别大,只不过这最后数组就只剩一个值。
    function singleNumber2($nums) {
        $arr = [];
        foreach ($nums as $value) {
            if(!isset($arr[$value])) {
                $arr[$value] = 1;//第一次出现就1
            }else{
                unset($arr[$value]);//第二次出现就删除
            }
        }
        //下面这个循环为了取出来 数组中最后的一个元素,感觉怪异
        foreach ($arr as $key => $value) {
            return $key;
        }
    }

    //异或法
    //执行用时 :32 ms, 在所有 php 提交中击败了70.95%的用户
    // 内存消耗 :17.5 MB, 在所有 php 提交中击败了8.92%的用户
    function singleNumber3($nums) {
        $re = 0;
        foreach ($nums as $value) {
            $re ^= $value;//进行异或运算
        }
        return $re;
    }

//【函数法】//
    //函数法
    //执行用时 :32 ms, 在所有 php 提交中击败了70.95%的用户
    //内存消耗 :17.5 MB, 在所有 php 提交中击败了18.79%的用户
    function singleNumber4($nums) {
        $nums = array_count_values($nums);//统计 各个单元出现的次数 返回的数组是 键=>出现的次数
        $nums = array_flip($nums);//互换键值
        return $nums[1];//由于出现的只有一次
    }

    //函数法
    //执行用时 :28 ms, 在所有 php 提交中击败了88.07%的用户
    //内存消耗 :17.1 MB, 在所有 php 提交中击败了93.95%的用户
    function singleNumber5($nums) {
       //计算数组元素出现个数
       $nums = array_count_values($nums);
       // php数组根据值为1的 获取键名
       $nums = array_keys($nums,1);
       return $nums[0];
    }

    //函数法
    function singleNumber6($nums) {
        //计算数组元素出现个数
        $nums = array_count_values($nums);
        // 在数组$nums中搜索给定的值1,如果成功则返回首个相应的键名
        return array_search(1,$nums);
    }
}

$obj  = new Solution();
$nums = [4,1,2,1,2];
$re   = $obj->singleNumber1($nums);
var_dump($re);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值