位运算

Posted white-loub

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位运算相关的知识,希望对你有一定的参考价值。

题目一:找出唯一成对的数

  1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

 

解题思路:这里使用的原理是连续的数字异或可以消除重复,A ^ A=0, A ^ A ^ A=A,我们的题目中有两个元素重复,用不包含重复元素的数组对原数组进行逐一异或就会消去原来不重复的元素,而最终保留那个重复的元素。如“1,2,3,4,5,6,4,7,8,9,10”,我们使用“1,2,3,4,5,6,7,8,9,10”和其进行异或,由于“4”共异或三次,所以最终被保留,即为原数组中重复的元素。这里有一个特殊的点,就是这里给出了数组是1-1000连续的数并且只有唯一一个元素值重复,所以才能构造进行异或两次的解法。  若题目允许使用辅助空间,则可使用桶排的方法实现。

 

代码编写(c++):

遇到的问题:

1·在Java中想要获取数组的长度,非常简单,但是在C++中却不太一样,下面记录一下C++中获取数组长度的方法。

int num[] = { 0,1,2,3,4,5,6,7,8,9,10 };
int len = sizeof(num) / sizeof(num[0]);//这样得到的 len 的值等于11 

 

2·C++中没有自带的random函数,要实现随机数的生成就需要使用rand()和srand()。

rand()的内部实现是用线性同余法做的,所以生成的并不是真正的随机数,而是在一定范围内可看为随机的伪随机数。srand()可用来设置rand()产生随机数时的随机数种子。通过设置不同的种子,我们可以获取不同的随机数序列。也就是说,rand()每次生成的随机数相同,若要不同,则要借助srand()。

产生一定范围随机数的通用表示公式是:

要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。

 

3.代码原码(未添加桶排):

#include <iostream>
#include <bits/stdc++.h>
#include <ctime>
using namespace std;

int main(){
    int N = 10;
    srand((int)time(0));
    int arr[] = {1,2,3,4,5,6,7,8,9,10,(rand() % 10)+1};
    int arr_len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < arr_len; i++){
        cout<<arr[i]<< ;
    } 
    int res = 0;
    for(int i = 0;i < arr_len;i++){
        res=res^arr[i];
    }
    for(int i = 1;i <= N;i++){
        res=res^i;
    }
    cout<<endl<<res;
}

 

用于参考的他人代码(java):

import java.util.Random;
 
public class 唯一成对的数 {
 
    public static void main(String[] args) {
         
        int N = 11;
        int [] arr = new int[N];
        for (int i = 0; i < arr.length-1; i++) {
            arr[i] = i+1;
        }
        // 最后一个数,是随机数
        arr[arr.length-1] = new Random().nextInt(N-1)+1;
        // 随机下标
        int index = new Random().nextInt(N);
        swap(arr, index, arr.length-1);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+ "  ");
        }
        System.out.println();
        int x1=0;
        for(int i=1;i <= N -1;i++){
            x1 = (x1^i);   // 求得1到N-1这些连续的数的异或
        }
        for(int i=0;i < N ;i++){
            x1 = (x1^arr[i]);  // 再与原来的数组arr异或,这样重复的数就有三个,不重复的数有两个,异或消除重复后,剩下的就是重复的数了
        }
        System.out.println(x1);
        System.out.println("使用辅助空间实现============");
        int []helper = new int[N];
        for (int i = 0; i < helper.length; i++) {
            helper[arr[i]]++;
        }
        for (int i = 0; i < helper.length; i++) {
            if (helper[i]==2) {
                System.out.println(i);
                break;
            }
        }
 
    }
    public static void swap(int[] array,int x,int y){
        int xx = array[x];
        int yy = array[y];
        array[x] = yy;
        array[y] = xx;
    }
 
}

 

以上是关于位运算的主要内容,如果未能解决你的问题,请参考以下文章

编程思想:巧用位运算重构代码

基础位运算基本原理和应用

位运算相关

优雅代码05-从hashMap源码介绍位运算符

c语言位运算问题?

为啥 JSHint 反对位运算符?我应该如何表达这个代码?