problem:
Given An array of numbers nums
, in which exactly-elements appear only once and all the other elements appear exactly Twice. Find the elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5]
, return [3, 5]
.
Note:
- The order of the result is not important. The above example, is
[5, 3]
also correct.
- Your algorithm should run in linear runtime complexity. Could implement it using only constant space complexity?
Credits:
Special thanks to @jianchao. Li.fighter for adding the problem and creating all test cases.
Analysis:
The Sort A array is always a good beginning to find duplciates in a array. But it would at least take O (NLOGN) time in sorting the array. Solution1: Basic idea:step1: Sort the entire array.step2:in the sorted form,ifa element does not has neighors share the same value wit it. It must is the single element we want to find. Note:take Care The first and last element, it may incure out of bound exception. Public int[] Singlenumber (int[] nums) { if(Nums = =NULL|| Nums.length <= 1) return New int[0]; Arrays.sort (Nums); int[] ret =New int[2]; intCount = 0; for(inti = 0; i < nums.length; i++) { BooleanIs_single =true; if(I! = 0) Is_single= Is_single && (nums[i]! = nums[i-1]); if(I! = nums.length-1) Is_single= Is_single && (nums[i]! = nums[i+1]); if(is_single) Ret[count++] =Nums[i]; } returnret;} Wrong logic:if You use thedefaultValue of flag as "true", you must take care for the logic you is going to implment. (| | or &&) Initially, I have implemented following problemetic logic------------------------------------------------------------------- for(inti = 0; i < nums.length; i++) { BooleanIs_single =true; if(I! = 0) Is_single= Is_single | | (Nums[i]! = nums[i-1]); if(I! = nums.length-1) Is_single= Is_single | | (Nums[i]! = nums[i+1]); if(Is_single) {Ret[count]=Nums[i]; Count++; } }-------------------------------------------------------------------in the above code, the Is_single would alway istrue, since the intialdefaultIstrueand I use "| | |"To pass around logic. What I meant to DoIs "once it had a neighor, it should return false, and pass to the value". the change is Easy:is_single= Is_single && (nums[i]! = nums[i-1]); Even though the above solution is clear, there could a very elegant and genius solution for Thisproblem. But it requires strong understand of bit operation. Key:the Magic Rule of XOR. A^ A = 0; a^ B ^ a = 0; a^ B ^ C ^ a = b ^C; After the XOR operation, all numbers appear even times, would is removed from theFinalXOR value. what' s more, after "a ^ b ^ c ^ a = b ^ C", the set bits of "b ^ C" would only contain the digits that B is different from C.solving Step:step1: XOR all elements in the array.intXOR = 0; for(inti = 0; i < nums.length; i++) {XOR^=nums[i];} Step2: Get the rightmost bit of the set Bit.right_most_bit= XOR & (~ (xor-1) ); Step3: Divide the nums array into and set based on the set bit. (thus the single numbers:b, C would is placed into and different set). Then the XOR at each set and get those the numbers. for(inti = 0; i < nums.length; i++) { if((Nums[i] & right_most_bit) = = 0) {ret[0] ^=Nums[i]; } Else{ret[1] ^=Nums[i]; }}skills:1. How to get the rightmost set bit?Right_most_bit= XOR & (~ (xor-1)); Reason:the XOR-1 would turn the rightmost set bit into 0, and bits after it becomes 1.' 1000001000 ' = ' 1000000111 ' the Not"~" operation would turn all bits into opposite bit (note the rightmost bitset have already been setted into 0)' 1000000111 ' = ' 0111111000 ' the' & 'operation would filter the setbit out.' 0111111000 ' 1000001000 ' 0000001000 ' 2. The set bit could is used a proper indicator to divide the original array into the sets.if((Nums[i] & right_most_bit) = = 0) {ret[0] ^=nums[i];} Else{ret[1] ^=nums[i];} Note the form of set bit:' 0000001000 ', only the number share the same bit would not equal to "000000000 ... (integer:0) "
Solution:
Public classSolution { Public int[] Singlenumber (int[] nums) { if(Nums = =NULL|| Nums.length = = 0) return New int[0]; int[] ret =New int[2]; intXOR = 0, right_most_bit = 0; for(inti = 0; i < nums.length; i++) {XOR^=Nums[i]; } right_most_bit= XOR & (~ (xor-1)); for(inti = 0; i < nums.length; i++) { if((Nums[i] & right_most_bit) = = 0) {ret[0] ^=Nums[i]; } Else{ret[1] ^=Nums[i]; } } returnret; }}
[leetcode#260]single number III