[路飞]_程序员必刷力扣题: 只出现一次的数字

130 阅读2分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

只出现一次的数字

力扣链接

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。 请你找出并返回那个只出现了一次的元素。

示例 1:

输入:nums = [2,2,3,2]
输出:3

示例 2:

输入:nums = [0,1,0,1,0,1,100]
输出:100

提示:

1 <= nums.length <= 3 * 104 -231 <= nums[i] <= 231 - 1 nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次  

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

哈希表

思路

要找到只出现一次的数字,那么我们可以遍历所有的值,并在哈希表中统计同一个值出现的次数, 当遍历完所有的值以后,我们就能得到一个统计结果。 再遍历这个结果,找到出现次数等于1的值,就得到了只出现一次的数字。

if(nums.length===1) return nums[0] 
    var map = {} for(let i = 0;i<nums.length;i++){ 
        var item = nums[i] 
        if(!map[item]){ 
            map[item] = 1 
        }else{ 
            map[item]++ 
        } 
    } 
    for(var key in map){ 
        if(map[key]===1){ 
            return key
        } 
     }
 }

对比法(进阶不实用额外空间)

思路

这里我们用另一种方法来解题,上一中解法我们需要创建一个哈希表,使用了额外空间。

在不使用额外空间的情况下,我们可以通过双循环对比来做 外层循环依次获取到每一个值nums[i]与 内层循环nums[j]对比,如果两者相等且i!==j ,那就证明这个值出现了第二次,直接break跳过此次循环 当i!==j,同时nums[i]不等于nums[j] 且整个循环遍历完毕,nums[i]并没有再次出现,则返回nums[i]

这里需要注意的是,如何判断遍历完毕,这里有两种情况 正常情况下j===len-1 则遍历结束。 但是因为要满足i!==j的条件, 所以当只出现一次的数字在数组末尾时,需要另外处理 此时只需要j遍历到len-2的位置就结束了遍历

var singleNumber = function(nums) {
    if(nums.length===1return nums[0]
    var len = nums.length
    for(let i = 0 ;i<nums.length;i++){
        for(let j = 0 ;j<nums.length;j++){
            if(i!==j&&nums[i]===nums[j]){
                break;
            }
            if(i!==j&&nums[i]!==nums[j]){
                if(i===len-1&&j===len-2){
                    return nums[i]
                }
                if(i!==len-1&&j===len-1){
                    return nums[i]
                }
            }
        }
    }
};