一.二进制加法
1.1题目
给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。
输入为 非空 字符串且只包含数字 1 和 0。
示例 1:
输入: a = "11", b = "10"
输出: "101"
示例 2:
输入: a = "1010", b = "1011"
输出: "10101"
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/JFETK5
1.2解题思路和代码
输入: a = "111", b = "10"
n=3
遍历for循环,i=0,i<n
(1)i=0 i < a.length() i<b.length() 所以是1+0=1; 个位的结果为1
(2)i=1 i < a.length() i<b.length() 所以是1+1=2;个位的结果为2%2=0;向前进的数是2/2=1;
(3)i=2 i < a.length() 所以是1,但是进位为1,所以1+1=2;个位的结果为2%2=0;向前进的数是2/2=1;
(4)i=3 进位为1,所以此位置是1
其中两个数某一个位置的相加,是 carry=carry+a(i)+b(i),结果这个位置的数是carry%2,向前的进位是 carry/2
class Solution {
public String addBinary(String a, String b) {
//确定两个字符串里面最大的长度
int n=Math.max(a.length(),b.length());
//carry代表进位,初始值为0,代表第一步计算个位时,carry=carry+ai+bi;
int carry=0;
StringBuffer sb=new StringBuffer();
//经过n次计算
for(int i=0;i<n;i++){
//如果a在这个位置有数,则加这个数,没有则不加
if(a.length()>i){
carry=carry+(a.charAt(a.length()-1-i)-'0');
}
//如果b在这个位置有数,则加这个数,没有则不加
if(b.length()>i){
carry=carry+(b.charAt(b.length()-1-i)-'0');
}
//将计算结果写好 各位上的值=(a(i)+b(i)+carry)%2
sb.append(carry%2);
//下一个位置的数进位是carry/2
carry=carry/2;
}
if (carry > 0) {
sb.append('1');
}
sb.reverse();
return sb.toString();
}
}
二.前 n 个数字二进制中 1 的个数
2.1题目
给定一个非负整数 n
,请计算 0
到 n
之间的每个数字的二进制表示中 1 的个数,并输出一个数组。
例1:
输入: n = 2 输出: [0,1,1] 解释: 0 --> 0 1 --> 1 2 --> 10
例 2:
输入: n = 5
输出: [0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/w3tCBm
2.2思路以及代码
n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
1的个数 | 0 | 1 | 1 | 2 | 1 | 2 | 2 | 3 | 1 | 2 | 2 | 3 | 2 | 3 | 3 | 4 | 1 |
dp[i] | 0 | 0+1 |
将这个规则带入
dp[i]=dp[i-1]+1; i为奇数
dp[i]=dp[i/2]; i为偶数
public class Solution {
public int[] CountBits(int n) {
int[] dp=new int[n+1];
dp[0]=0;
if(n>0){
dp[1]=1;
}
for(int i=2;i<=n;i++){
if(i%2==0){
dp[i]=dp[i/2];
}else{
dp[i]=dp[i-1]+1;
}
}
return dp;
}
}
三 只出现一次的数字
3.1题目
给你一个整数数组 nums
,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
示例 1:
输入:nums = [2,2,3,2] 输出:3
示例 2:
输入:nums = [0,1,0,1,0,1,100] 输出:100
3.2思路以及代码(方法1)
采用map,通过存储他的值和次数,解该题。
Java版本
class Solution {
public int singleNumber(int[] nums) {
HashMap<Integer,Integer> hashmap=new HashMap<Integer,Integer>();
int count=0;
for(int i=0;i<nums.length;i++){
if(hashmap.containsKey(nums[i])){
count=hashmap.get(nums[i]);
hashmap.put(nums[i],count+1);
}else{
hashmap.put(nums[i],1);
}
}
for(Integer i:hashmap.keySet()){
if(hashmap.get(i)==1){
return i;
}
}
return -1;
}
}
C#版本
public class Solution {
public int SingleNumber(int[] nums) {
Dictionary<int, int> map = new Dictionary<int, int>();
for(int i=0;i<nums.Length;i++){
if(map.ContainsKey(nums[i])){
int count=map[nums[i]];
map.Remove(nums[i]);
map.Add(nums[i],count+1);
}else{
map.Add(nums[i],1);
}
}
foreach (int key in map.Keys)
{
if(map[key]==1){
return key;
}
}
return -1;
}
}
c#C# Dictionary的用法_w3cschoolhttps://www.w3cschool.cn/csharp/csharp-86c42por.html可以参考上面链接Dictionary的具体方法。
3.3 思路以及代码(方法2)
使用位运算
需要了解的知识点
符号 | 描述 | 运算规则 | 实例(以四位二进制数为例) |
---|---|---|---|
& | 与 | 两个位都为1时,结果才为1。 | 0001&0001=1,0001&0000=0,0000&0000=0000 |
| | 或 | 两个位都为0时,结果才为0。 | 0001|0001=0001,0001|0000=0001,0000|0000=0000 |
^ | 异或 | 两个位相同为0,相异为1。 | 0001∧0001=0000,0001∧0000=1,0000∧0000=0 |
~ | 取反 | 0变1,1变0 | ∼0=1,∼1=0 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0。 | 0001<<k=0100,k=2,k kk是左移的位数,这里k = 2 k=2k=2 ———————————————— 版权声明:本文为CSDN博主「unique_pursuit」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/hzf0701/article/details/117359478 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,右移补1 11。 | 0100>>k=0001,k=2,k kk是右移的位数,这里k = 2 k=2k=2 |
上表的 原文链接:https://blog.csdn.net/hzf0701/article/details/117359478
Java代码如下:
class Solution {
public int singleNumber(int[] nums) {
int ans=0;
for(int i=0;i<32;i++){
int total=0;
for(int num:nums){
total=total+((num>>i)&1);
}
if(total%3!=0){
ans=ans|(1<<i);
}
}
return ans;
}
}
C#代码如下
public class Solution {
public int SingleNumber(int[] nums) {
int ans=0;
for(int i=0;i<32;i++){
int total=0;
foreach(int num in nums){
total=total+((num>>i)&1);
}
if(total%3!=0){
ans=ans|(1<<i);
}
}
return ans;
}
}