算法 - 神奇的异或

什么是异或?

同0异1。在java内就是X^Y

  • 任何数异或0为任何数 0 ^ n = n
  • 任何数异或1,n为奇数,n^ 1 = n-1;n为偶数 n^1=n+1
  • 相同的数异或为0: n ^ n = 0
  • a^ b=c a ^b ^d = c ^d 满足结合律

使用经验

1.数组中的单一元素

给你一个仅由整数数组,其中每个元素都会出现两次,唯有一个数只会出现一次。
请你找出并返回只出现一次的那个数。

1 <= nums.length <= 10^5
来自力扣

解法其实很简单,相同的数为0,不同的数为1

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int ans = nums[0];
        for(int i=1; i<nums.length-1;i++){
            ans = ans^x;
        }
        return ans;
    }
}

2.数组中的单一元素(进阶)

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

来源

 public int singleNumber(int[] nums) {
        int a = 0, b = 0;
        for (int num : nums) {
            b = ~a & (b ^ num);
            a = ~b & (a ^ num);
        }
        return b;
    }

3.有序数组中的单一元素

给你一个仅由整数有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。
请你找出并返回只出现一次的那个数。

由于数组是有序的,因此数组中相同的元素一定相邻。对于下标 x 左边的下标 y,如果nums[y]=nums[y+1],则 y一定是偶数;对于下标x 右边的下标 zz,如果nums[z]=nums[z+1],则 z 一定是奇数。由于下标 x 是相同元素的开始下标的奇偶性的分界,因此可以使用二分查找的方法寻找下标 x。

利用按位异或的性质,可以得到mid 和相邻的数之间的如下关系,其中⊕ 是按位异或运算符:

当 mid 是偶数时,mid+ 1 =mid⊕1;

当mid 是奇数时,mid - 1 =mid⊕1。

如果上述比较相邻元素的结果是相等,则 mid<x,调整左边界,否则 mid≥x,调整右边界。调整边界之后继续二分查找,直到确定下标 xx 的值。
因此在二分查找的过程中,不需要判断mid 的奇偶性,mid 和mid⊕1 即为每次需要比较元素的两个下标。
在这里插入图片描述

 public int singleNonDuplicate(int[] nums) {
        if (nums.length == 1) return nums[0];
        int low = 0, high = nums.length - 1;
        while (low < high) {
            int mid = (low + high) / 2;
            if (nums[mid] == nums[mid ^ 1]) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return nums[low];
    }

4. 解码异或后的数组

未知 整数数组 arr 由 n 个非负整数组成。
经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3] 。
给你编码后的数组 encoded 和原数组 arr 的第一个元素 first(arr[0])。
请解码返回原数组 arr 。可以证明答案存在并且是唯一的。
示例 1:
输入:encoded = [1,2,3], first = 1
输出:[1,0,2,1]
解释:若 arr = [1,0,2,1] ,那么 first = 1 且 encoded = [1 XOR 0, 0 XOR 2, 2 XOR 1] = [1,2,3]
示例 2:
输入:encoded = [6,2,7,3], first = 4
输出:[4,2,0,7,4]
链接:https://leetcode-cn.com/problems/decode-xored-array

思路便是从自身异或自身为0出发与结合律。已知首个为first并且下一个与首个有异或关系,令fisrt异或自身,找等价关系。

    /**
     * encoded[i-1]= arr[i] ^ arr[i-1]
     * encoded[i-1]^encoded[i-1] = arr[i]^arr[i-1]^encoded[i-1]
     * encoded[i-1]^encoded[i-1] = 0
     * arr[i]^arr[i-1]^encoded[i-1] =0  由 a异或b = 0 =》a=b 推出 arr[i] = arr[i-1]^encoded[i-1]
     * arr[i]=arr[i-1]^encoded[i-1]
     *
     * @param encoded
     * @param first
     * @return
     */
    public int[] decode(int[] encoded, int first) {
        int[] arr = new int[encoded.length + 1];
        arr[0] = first;
        for (int i = 1; i < arr.length; i++) {
            arr[i] = arr[i - 1] ^ encoded[i - 1];
        }
        return arr;
    }
BP神经网络算法可以用于解决分类和回归问题。下面是BP算法实现异或运算的步骤和代码: 1.问题: 我们需要训练一个BP神经网络来实现异或运算,即输入两个二进制数,输出它们的异或结果。 2.分析: 我们可以使用一个包含两个输入节点、两个隐藏节点和一个输出节点的三层神经网络来解决这个问题。我们需要使用反向传播算法来训练神经网络,以便它可以正确地计算异或运算。 3.代码: ```python import numpy as np # 定义sigmoid函数 def sigmoid(x): return 1 / (1 + np.exp(-x)) # 定义sigmoid函数的导数 def sigmoid_derivative(x): return x * (1 - x) # 定义BP神经网络类 class NeuralNetwork: def __init__(self, x, y): self.input = x self.weights1 = np.random.rand(self.input.shape[1], 2) self.weights2 = np.random.rand(2, 1) self.y = y self.output = np.zeros(self.y.shape) def feedforward(self): self.layer1 = sigmoid(np.dot(self.input, self.weights1)) self.output = sigmoid(np.dot(self.layer1, self.weights2)) def backprop(self): d_weights2 = np.dot(self.layer1.T, (2 * (self.y - self.output) * sigmoid_derivative(self.output))) d_weights1 = np.dot(self.input.T, (np.dot(2 * (self.y - self.output) * sigmoid_derivative(self.output), self.weights2.T) * sigmoid_derivative(self.layer1))) self.weights1 += d_weights1 self.weights2 += d_weights2 def train(self, epochs): for i in range(epochs): self.feedforward() self.backprop() def predict(self, x): self.input = x self.feedforward() return self.output # 训练数据 X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([[0], [1], [1], [0]]) # 创建神经网络对象并训练 nn = NeuralNetwork(X, y) nn.train(10000) # 预测新数据 x_test = np.array([[0, 1]]) print(nn.predict(x_test)) # 输出:[[0.99676596]] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值