LeetCode 136.137. 260.Single Number ⅠII III

来源:互联网 发布:数值模拟软件 编辑:程序博客网 时间:2024/04/30 07:00

Single Number Ⅰ:

Given an array of integers, every element appears twice except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

分析:此系列问题都是考察对位运算的掌握程度。对于Ⅰ,异或操作是解决问题的最简便途径,异或操作有两个相关的性质:1、两个相等的数异或为0;2、0与任何数异或仍为0.

本题解法之一就是将数组中的数据依次异或,即可得到出现一次的数据;

代码:

public class Solution {    public int singleNumber(int[] nums) {        if(nums.length == 1){            return nums[0];        }        for(int i = 1; i < nums.length; i++){            nums[0] = nums[0] ^ nums[i];        }        return nums[0];            }}


本题还可利用HashSet集合中不能存储重复数据这一特性来解,当数据加入失败时证明此数据出现第两次,将原先加入的数据也移除,最后便可得到值出现以此的数据。

代码:

public class Solution {    public int singleNumber(int[] nums) {               HashSet<Integer> set = new HashSet<Integer>();        for(int n : nums){            if(!set.add(n)){                set.remove(n);            }        }        Iterator<Integer> it = set.iterator();        return it.next();    }}

Single Number II:

Given an array of integers, every element appears three times except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

分析:与本系列第一题不同的是:其他数据出现三次,奇数次不能使用上题的两种解法。入手点依然是位运算:统计二进制下各个位1的个数,因为数组中只有一个数字出现一次,其他数字均出现三次,则统计出某位数字的个数不是3的倍数,则证明所求的数字在该位上是1;将每一位出现1的个数统计好存放在数组中,取余后即可得到所求数字的二进制的每一位,将此数组转化为整型数据即为所求。

代码:

public class Solution {    public int singleNumber(int[] nums) {        int [] numsOfBits = new int[32];        int res = 0;        for(int i = 0; i < 32; i++){            for(int j = 0; j <nums.length; j++){                numsOfBits[i] +=  (nums[j] >> i) & 1;            }                        res |= (numsOfBits[i] % 3) << i;        }                return res;    }}

Single Number III:

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

For example:

Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].

Note:

  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

分析:本题要求线性复杂度,位运算是首先要想到的。与题目一不同,本题有两个数出现一次,那么找到两个数的不同是关键。由题目一的启发,异或可以得到两个数字存在的不同位,利用两个数字在某一位的差别,可以将数组分成两部分分别用题目一的方法来求得两个数:

代码:

public class Solution {    public int[] singleNumber(int[] nums) {        int result[] = {0,0};        int temp = nums[0];        for(int i = 1; i < nums.length; i++){            temp = temp ^ nums[i];        }        int difference = temp & (~(temp - 1));        for(int i = 0; i < nums.length; i++){            if((difference & nums[i]) == 0){                result[0] = result[0] ^ nums[i];            }else{                result[1] = result[1] ^ nums[i];            }        }                return result;    }}

int difference = temp & (~(temp - 1));
这条语句表示取出两个数最小的不同位用来分割数组。

0 0