青训营X豆包MarsCode 技术训练营 刷题 找单独的数 | 豆包MarsCode AI 刷题

25 阅读3分钟

解题思路总结

问题理解

在这个问题中,我们需要在一个整数数组中找到唯一一个出现次数为奇数的数字。数组中的其他数字都恰好出现两次,只有这个独特的数字出现一次。这个问题可以被视为一个经典的“寻找唯一元素”问题,通常在算法和数据结构课程中作为练习题出现。

数据结构选择

由于题目要求时间复杂度为 O(n),并且尽量减少额外空间的使用,我们需要选择一个既高效又节省空间的数据结构或算法。考虑到数组中的数字都是整数,并且我们只需要找到一个独特的数字,位运算中的异或(XOR)操作是一个非常合适的选择。

算法步骤

  1. 初始化结果变量:我们可以从数组的第一个元素开始,将其作为初始结果。
  2. 遍历数组:从数组的第二个元素开始,依次对每个元素进行异或操作。
  3. 异或操作:异或操作有一个重要的性质,即 a ^ a = 0a ^ 0 = a。这意味着,如果一个数字出现两次,它们会相互抵消,最终结果为0。而唯一出现一次的数字会保留下来。
  4. 返回结果:遍历结束后,结果变量中存储的就是唯一出现一次的数字。

异或操作的优势

  • 时间复杂度:异或操作的时间复杂度为 O(1),因此整个算法的时间复杂度为 O(n),符合题目要求。
  • 空间复杂度:异或操作只需要一个额外的变量来存储结果,因此空间复杂度为 O(1),非常节省空间。

具体实现

在具体实现时,我们可以从数组的第一个元素开始,将其赋值给一个变量 res,然后遍历数组,依次对 res 和当前元素进行异或操作。最终,res 中存储的就是唯一出现一次的数字。

测试样例

main 方法中,我们添加了几个测试样例来验证算法的正确性。通过这些测试样例,我们可以确保算法在不同情况下都能正确找到唯一出现一次的数字。

总结

通过使用异或操作,我们可以在 O(n) 的时间复杂度和 O(1) 的空间复杂度内解决这个问题。异或操作的性质使得我们可以高效地找到唯一出现一次的数字,而不需要额外的数据结构。这种解法不仅高效,而且非常简洁,体现了算法设计中的优化思想。

进一步优化

虽然当前的解法已经非常高效,但在实际应用中,我们还可以考虑以下几点:

  1. 边界条件检查:在实际应用中,可以添加对数组长度的检查,确保数组长度为奇数,符合题目要求。
  2. 异常处理:如果输入的数组不符合题目要求(例如长度为偶数),可以添加异常处理机制,避免程序崩溃。

通过这些优化,我们可以进一步提高算法的健壮性和实用性。

public class Main {
    public static int solution(int[] cards) {
        // Edit your code here
        int res = cards[0];
        for(int i=1; i<cards.length; i++){
            res=(res^cards[i]);
        }
        return res;
    }

    public static void main(String[] args) {
        // Add your test cases here
        
        System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) == 4);
        System.out.println(solution(new int[]{0, 1, 0, 1, 2}) == 2);
    }
}