码迷,mamicode.com
首页 > 其他好文 > 详细

Leetcode(easy Bit)

时间:2020-11-04 19:20:25      阅读:49      评论:0      收藏:0      [点我收藏+]

标签:位置   tmp   sort   hat   次数   改变   算数   rtb   ndt   

Leetcode(easy Bit)

leetcode位运算的简单的题目总结

136 只出现一次的数字

题目:给定一个非空整数数组,除了某一个元素只出现一次之外,其余每个元素均出现了两次,找出那个只出现一次的元素。
说明:你的算法应该具有线性时间复杂度,而且尽量不使用额外空间

解题思路:用到了位运算中的异或操作,两个相同的数字异或结果是0,数字与0异或的结果还是这个数字,并且异或操作满足交换律与结合律。

时间复杂度O(n) 因为对nums进行了一次的遍历
空间复杂度O(1) 没有占用额外的内存空间

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

169 多数元素

题目:给定一个大小为n的数组,找到其中的多数元素,多数元素指的是在数组中出现次数严格大于一半的元素。
保证数组是非空的,并且给定的数组总是存在多数元素

解题思路1:投票 时间复杂度O(n) ,空间复杂度O(1)
解题思路2: 排序 时间复杂度O( n * log n) ,空间复杂度O(1)
解题思路3: Hash表 时间复杂度O(n) ,空间复杂度O(n)
解题思路4:分治算法 时间复杂度O(n * log n) ,空间复杂度O(log n)
解题思路5: 位运算 时间复杂度O(n) ,空间复杂度O(1)

// 投票算法
class Solution{
	public int majorElement(int[] nums){
		int vote = 0;
		int res = 0;
		for(int i = 0;i<nums.length;i++){
			if(vote == 0){
				res = nums[i];
				vote++;
			}else{
				if(res == nums[i]) vote++;
				else vote--;
			}
		}
		return res;
	}
}
// 分治算法
class Solution{
	private int countInRange(int[] nums,int num,int lo,int hi){
		int count = 0;
		for(int i = lo;i<=hi;i++) if(nums[i] == num) count++;
		return count;
	}
	private int majorityElementRec(int[] nums,int lo,int hi){
		// base case : the only element in an array of size 1 is the majority element
		if(lo == hi) return nums[lo];
		// recurse on left and right halves of this slice
		int mid = (hi-lo)/2+lo;
		int left = majorityElementRec(nums,lo,mid);
		int right = majorityElementRec(nums,mid+1,hi);
		// if the two halves agree on the majority element return it
		if(left == right) return left;
		// otherwise count each element and return the winner
		int leftCount = countInRange(nums,left,lo,hi);
		int rightCount = countInRange(nums,right,lo,hi);
		return leftCount>rightCount?left:right;
	}
	public int majorElement(int[] nums){
		return majorityElementRec(nums,0,nums.length-1);
	}
}
//位运算:思路由于众数出现的次数大于n/2,那么众数对应的二进制每一个为1的位数出现的次数一定大于n/2
class Solution{
	public int majorElement(int nums){
		int result = 0;
		int k = nums.length>>1;
		for(int i = 0;i<32;i++){
			// count 用于记录将数字转换成为二进制数之后每一位对应到数组中数字出现1的数量
			int count = 0;
			for(int num:nums){
				count+=num>>i&1;
				if(count>k){
					result+=1<i;
					break;
				}
			}
		}
		return result;
	}
}

190 颠倒二进制位

Waring:在Java语言中,是没有无符号整数类型的,在JAVA中所有的整数类型都是有符号的整数类型。

题目:颠倒给定的32位无符号整数的二进制位

解题思路:

class Solution{
	// you need treat n as unsigned value
	public int reverseBits(int n){
		int result = 0;
		for(int i = 0;i<=32;i++){
			// 将给定的二进制数,由低到高位依次取出
			int tmp = n>>i;
			tmp = tmp&1;
			// 反转,右移31-i位
			tmp=tmp<<(31-i);
			// 更新result
			result|=tmp;
		}
		return result;
	}
}

231 2的幂

题目 给定一个整数,编写一个函数来判断他是否是2的幂次方

解题思路1 : 位运算 如果一个整数是2的幂次方,那么他的32位二进制表示只能出现一个1,并且n不能是负数 时间复杂度O(1) 空间复杂度O(1)
解题思路2: 连续除法 判断余数 时间复杂度O(log n) 空间复杂度O(1)

// 连续除法
class Solution{
	public boolean isPowerOfTwo(int n){
		if(n==0) return false;
		while(n%2==0) n/=2;
		return n==1;
	}
}
// 位运算
class Solution{
	public boolean isPowerOfTwo(int n){
		return n>0 && (n&(n-1)) == 0;
	}
}

268 丢失的数字

题目:给定一个包含[0,n]中n个数的数组nums,找出这个范围内没有出现在数组中的元素

解题思路:异或

class Solution{
	public int missingNumber(int[] nums){
		int res = 0;
		for(int i = 1;i<nums.length+1;i++) res^=i;
		for(int num:nums) res^=num;
		return res;
	}
}

342 4的幂

题目:给定一个整数(32位有符号整数) 编写一个函数用来判断他是否是4的幂次方

解题思路:位运算,要清楚4的幂次方在二进制表示中的特点 二进制表示有以下特点:只有一个1,且1的位置在偶数位置上 判断是否在偶数位置上,只需要与全部在奇数位置上的数字进行与运算,判断其是否为0

奇数位置全部是1,且偶数位置都是0的数字是0xaaaaaaaa(16进制)
偶数位置全部是0,且奇数位置全部都是1的数组是ox55555555(16进制)

class Solution{
	public boolean isPowerOfFour(int num){
		return (num>0) && ((num&(num-1))==0) && ((num & 0xaaaaaaaa) == 0);
	}
}

371 两整数之和

题目要求:不使用运算符+或者- 计算两整数之和

解题思路 分析进位与数值位 a+b的进位为(a&b)<<1 ,a+b的数值位为 a^b 5+7 = 12 数值位为2 进位是10
5:101 7:111 ,,,101^111 = 010 = 2,,,,101&111<<1 = 1010,,,, 1010 ^ 010 = 1000 ,,,, 1010&010<<1 = 100

class Solution{
	public int getSum(int a,int b){
		// 结束条件:进位为0
		while(b!=0){
			// 计算数值位
			int temp = a^b;
			// 计算进位
			b = (a&b)<<1;
			a = temp;
		}
		return a;
		
	}
}

389 找不同

题目:给定两个字符串s,t。其中t是s添加一个字符得到的 找到这个添加的字符

解题思路:异或

class Solution{
	public char findTheDifference(String s ,String t){
		char res = 0;
		int lens = s.length();
		for(int i = 0;i<lens;i++) res^=s.charAt(i)^t.chatAt(i);
		res^=t.charAt(lens);
		return res;
	}
}

401 二进制手表

这个题我认为学习的内容在于了解到了Java的方法bitCount()用于计算一个数字的二进制数字的1的个数

class Solution{
	public List<String> readBinaryWatch(int num){
		List<String> times = new ArrayList<>();
		for(int h = 0;h<12;h++) for(int m = 0;m<60;m++) if(Integer.bitCount(h) + Integer.bitCount(m) == num) times.add(String.format("%d:%02d",h,m));
	}
} 

405 数字转换成为16进制数字

题目:给定一个整数,编写一个算法将这个整数转换成为16进制数

解题思路:利用位运算,一次取后面四位,然后对照16进制换算数组,进行换算,无符号右移4位直到num=0

class Solution{
	public String toHex(int num){
		char[] hex = "0123456789abcdef".toCharArray();
		String s = new String();
		while(num!=0){
			int end = num&15;
			s = hex[end]+s;
			num>>>=4;
		}
		if(s.length()==0) s = "0";
		return s;
	} 
}

461 汉明距离

题目:两个整数之间的汉明距离指的是这两个数字对应的二进制位不同位置的数目。

解题思路:首先两者异或 不同数字的异或结果为1,然后再去计算异或结果中1的位数。

class Solution{
	public int hammingDistance(int x,int y){
		int xor = x^y;
		int res = 0;
		while(xor!=0){
			res++;
			xor&=(xor-1);
		}
		return res;
	}
}

476 数字的补数

题目:给定一个正整数,输出他的补数。补数是对该数的二进制表示取反

解题思路:创造一个与给定数二进制位数相同的全部是1 的新的二进制数,然后用这个全部为1的二进制数与原有的数进行异或。异或操作会把原来是1的变为0,原来是0的变为1。

class Solution{
	public int findComplement(int num){
		int tmp = 1;
		while(tmp<num){
			tmp<<=1;
			tmp+=1;
		}
		return tmp^num;
	}
}

693 交替位二进制数

题目:给定一个整数,检查他是否为交替二进制数。换句话说就是他的二进制数相邻的两个位数永远不想等

解题思路:每次取二进制数的最后一位,并保存上次取的二进制数,判断二者是否相等,不想等的话,将数字无符号右移。

class Soluton{
	public boolean hasAlternatingBits(int n){
		int pre = n&1;
		n>>>=1;
		while(n!=0){
			if((n&1)==pre) return false;
			pre = n&1;
			n>>>=1;
		}
		return true;
	}
}

762 二进制表示中质数个计算置位

1290 二进制链表转整数

给一个单链表的引用节点,链表中的节点值不是1就是0,请返回该链表的十进制数字。

class Solution{
	public int getDecimalValue(ListNode head){
		int flag = 0;
		int res = 0;
		int len = 0;
		ListNode pre = head;
		while(pre != null){
			len++;
			pre=pre.next;
		}
		pre =head;
		while(pre!=null){
			if(pre.val == 1) res+=Mtah.pow(2,len-flag-1);
			flag++;
			pre = pre.next;
		}
		return res;
	}
}

1342 将数字变成0的操作次数

class Solution{
	public int numberOfSteps(int num){
		int res = 0;
		while(num!=0){
			if(num%2==1){
				res++;
				num-=1
			}else{
				res++;
				num/=2;
			}
		}
		return res;
	}
}

1356 根据数字二进制下1的数目排序

class Solution{
	public int[] sortByBits(int[] arr){
		Map<Integer,List<Integer>> map = new TreeMap<>();
		int[] res = new int[arr.length];
		for(int num:arr){
			int temp = helper(num);
			if(!map.cnotainsKey(temp)){
				map.put(temp,new LinkedList<>());
				map.get(temp).add(sum);
			}
			else{
				map.get(temp).add(num);
			}
		}
		int i = 0;
		for(int key:map.keySet()){
			Collections.sort(map.get(key));
			for(int num:map.get(key)){
				res[i++] = num;
			}
		}
		return res;
	}
	public int helper(int num){
		int res = 0;
		while(num!=0){
			res++;
			num&=(num-1);
		}
		return res;
	}
}

1486 数组异或操作

没有意思的一题

Offer 15 二进制中1的个数

同上

Offer 39 数组中出现次数超过一半的数字

同上

面试题 05.01 插入

class Solution{
	// N = 1024 10000000000 M = 19 10011 i=2 j=6 res = 1100 100001001100
	public int insertBits(int N,int M,int i ,int j){
		int mask = (1<<(j-i+1)-1)<<i; // i = 2 j = 6 : 100000 -> 011111 -> 1111100
		mask~=mask; // 0000011
		N&=mask; // 10001111100
		M=M<<i; // 1001100
		return M|N; // 100001001100
	}
}

面试题 05.03 翻转数位

题目:给定一个32位整数num,你可以将一个数从0变为1,请编写一个程序,找出你能够获得的最长的一串1的长度

class Solution{
	public int reverseBits(int num){
		if(num == -1) return 32;
		String s = Integer.toBinaryString(num);
		String[] arr = s.split("0");
		if(arr.length < 1) return arr.length+1;
		int max = arr[0].length();
		int res = max+1;
		for(int i = 1;i<arr.length;i++){
			if(arr[i-1].length() + arr[i].length() > max){
				max = arr[i-1].length()+arr[i].length();
				res=max+1;
			}
		}
		return res;
	}
}

面试题 05.06 整数转换

题目:编写一个方法,确定需要改变几个位才能将整数A变成整数B

class Solution{
	public int convertInteger(int A,int B){
		int xor = A^B;
		int res = 0;
		while(xor!=0){
			res++;
			xor&=(xor-1);
		}
		return res;
	}
}

面试题 05.07 配对交换

题目:编写一个方法,交换某个整数的奇数位与偶数位

class Solution{
	public int exchangeBits(int num){
		int odd = num&0x55555555;
		int even = num&0xaaaaaaaa;
		odd = odd<<1;
		even = even>>>1;
		return odd|even;
	}
}

面试题 16.07 最大数值

题目:编写一个方法,找出两个数字a和b中最大的哪一个。不能使用if-else或者其他比较运算符

class Solution{
	public int maximum(int a,int b){
		long c = a;
		long b = b;
		int res = (int)(Math.abc(c-d) + c + d/2);
		return res;
	}
}

面试题 17.01 不用加号的加法

同上

面试题 17.04 消失的数字

同上

面试题 17.10 主要元素

同上

Leetcode(easy Bit)

标签:位置   tmp   sort   hat   次数   改变   算数   rtb   ndt   

原文地址:https://www.cnblogs.com/botak/p/13926478.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!