zoukankan      html  css  js  c++  java
  • leetcode136-寻找数组中仅出现一次的数字


    文章首发于taskhub

    1. 仅出现一次与均出现两次

    题目描述:在给定的非空数组中,仅有一个数字出现一次,其余数字均出现两次,如[1,2,2,3,3]或[1,1,2,3,3]
    解题思路:1)分类讨论,利用数组特性;2)利用异或XOR的特性

    1.1 分类讨论法

    • 当切片长度为1时,直接返回
    • 当排序后的切片前两位数字不相等时,直接返回
    • 当排序后的切片前两位数字相等时,从第0位元素开始每次取两个相邻的元素,判断两者是否相等,若不等则可知元素组合的第一个元素即为仅出现一次的元素
    • 该方法不需要占用额外的内存空间,时间复杂度为o(n)
    // golang实现
    func singleNumber(nums []int) int {
        //对切片进行排序
        sort.Ints(nums)
        // 排除长度为1的情况
       // 当前两位数字相同时,即[1,1,2,2,3]或[1,1,2,3,3]等情况,只需比较对应位置的相邻两数是否相等
        if len(nums)!=1 && nums[0] == nums[1]{
            // 遍历第0,2,4...组数字,当某组数字不相等时,则第i个数即为出现一次的数字
            // 由题意可知,数组长度为奇数,因此i只能遍历到倒数三个数,否则将溢出
            for i:=0;i<len(nums)-2;i+=2{
                if nums[i] != nums[i+1]{
                    return nums[i]
                }
            }
            // 当两两组合均相等时,数组最后一位元素即为仅出现一次的数字
            return nums[len(nums)-1]
        }else{
            return nums[0]
        }
    

    1.2 异或位运算

    • 任意数与0进行异或,其结果为该数本身,0 XOR a = a
    • 两个相同的数进行异或,其结果为0, a XOR a = 0
    • 使用异或方法不需要对数组进行排序
    		// golang实现
        func singleNumber(nums []int) int {
            single := 0
            for _, num := range nums {
                single ^= num
            }
            return single
        }
    

    2. 仅出现一次与均出现三次

    2.1 分类讨论法

    • 分类讨论法与1.1类似,将两两比较组合更改为每三个元素一组
    • 需要注意数组遍历的边界
    // golang实现
    func singleNumber(nums []int) int {
        sort.Ints(nums)
        if len(nums)!=1 && nums[0] == nums[1] && nums[1]==nums[2]{
            for i:=1;i<len(nums)-2;i+=3{
                if nums[i-1] != nums[i]{
                    return nums[i-1]
                }
            }
            return nums[len(nums)-1]
        }else{
            return nums[0]
        }
    }
    

    2.2 位运算组合

    • 由于异或结果无法区分出现1次和出现3次等奇数个元素的情况,需要使用两个位掩模对异或结果进行处理
    • seenOnce记录出现一次的数字,seenTwice记录出现两次的数字
    • 异或法参考官方题解leetcode
    // golang实现
    func singleNumber(nums []int) int {
        var seenOnce,seenTwice = 0,0
            for _,num := range nums{
                seenOnce = ^seenTwice & (seenOnce ^ num)
                seenTwice = ^seenOnce & (seenTwice ^ num)
            }
        return seenOnce
    }
    
    
  • 相关阅读:
    一网友推荐的书:框架设计(第2版):CLR Via C#
    线程与WinForm设计,防冻结,卡住窗体
    通用数据库操作辅助类DbHelper
    高级着色器语言(High Level Shader Language,简称HLSL)
    无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型
    根据RGB,计算灰度值
    温故而知新:WinForm/Silverlight多线程编程中如何更新UI控件的值
    [原创视频]PHP在netbeans中的简单使用
    自己封装的ASP.NET的SQLITE数据库的操作类
    《JavaScript征途》读后感
  • 原文地址:https://www.cnblogs.com/litchi99/p/13600068.html
Copyright © 2011-2022 走看看