zoukankan      html  css  js  c++  java
  • LeetCode136:只出现一次的数字与LeetCode137:只出现一次的数字ii

    Leetcode136:

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

    说明:

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

    时间O(n),空间O(1)的算法实在没想到,满脑子里都是排序或者引入map。

    看了下答案巧妙的运用了异或的性质,相同的数字异或为0,不同的数字异或异或为1的特点。

    顺便纠正了下基础,异或运算在位上的,比如1异或3,答案不是1,而是2.因为异或是在001与011间的每一位进行,异或的结果是010,也就是2。

    这样,对[a,a,c,b,c]这样的数组的每个数都进行^

    a^a^c^b^c,配合结合律变为:

    a^a^c^c^b

    其中a^a^c^c=0

    0^b=b

    Leetcode137:

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

    说明:

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

    class Solution {
    public:
        int singleNumber(vector<int>& nums) {
    		int result=0;
    		int cnt=0;
    		for(int i=0;i<32;i++)
    		{
    			int tmp=0;//[-2,-2,1,1,-3,1,-3,-3,-4,-2]
    			for(int j=0;j<nums.size();j++)
    			{
    
    				tmp+=nums[j]&1;
    				nums[j]=nums[j]>>1;
    			}
    			tmp=tmp%3;
    			result=result|(tmp<<i);
    		}
    		return result;
        }
    };

    从位的角度上来看,136题中,每一位的异或操作只是对进行二进制相加但不产生进位。

    现在有三个相同的数,只要在每一位上,令三个相同的数进行某种运算后归0,即可将不同的数的那一位凸显出来。

    因此考虑在每一位上进行三进制的相加,满了归0且不产生进位。

    在32位上,所有数的某一位全部相加后对3取余,所得结果即是不同的数的对应位。

    最后将每一位“或”起来即可。

    另外关于负数的二进制位表示与右移:

    负数的二进制表示并不是简单的将首尾改为1,比如-1的二进制表示实际上是1111....1(共32个)而不是1 000....1,不要想当然。

    另外对负数进行右移时,符号位被丢弃后又会补一个1,比如-1,右移后并不会在首尾补0而是补1,因此无论右移多少次,一直为111....1,也即一直为-1。

  • 相关阅读:
    20145310《网络对抗》Exp2 后门原理与实践
    20145310《网络对抗》逆向及Bof基础
    20144303《网络对抗》免考项目——恶意代码分析以及检测
    20144303石宇森《网络对抗》Web安全基础实践
    20144303石宇森 《网络对抗》 WEB基础实践
    20144303石宇森 《网络对抗技术》 网络欺诈技术防范
    20144303 石宇森《网络对抗》信息收集和漏洞扫描技术
    20144303石宇森《网络对抗》MSF基础应用
    20144303石宇森 《网络对抗技术》 恶意代码分析
    20144303 石宇森 《网络对抗技术》免杀原理与实践
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11141860.html
Copyright © 2011-2022 走看看