LeetCode刷题中遇到的小技巧(长期更新)

emmmmm,博主在刷题过程中,总会碰到一些题目会利用我们某些不熟悉的性质因而能够以最优的算法解出题目,因此特开此篇博客来记录刷题中的小技巧。

1.异或

1.任何数和 0 做异或运算,结果仍然是原来的数,即a⊕0=a。
2. 任何数和其自身做异或运算,结果是 0,即 a⊕a=0。

例题

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1] 输出: 1 示例 2:

输入: [4,1,2,1,2] 输出: 4

来源:力扣(LeetCode)
题目链接

题解

/*这道题本来博主是想将数组的数字放在其本身数值对应的地方,
然后对数字进行一些标记比如取正负这样来进行标记,后来发现操作起来着实
过于麻烦因此发现题解的方法其实只是利用了很简单的性质,却达到了如此巧妙
的效果,因此将它记录下来。*/
class Solution {
    public int singleNumber(int[] nums) {
        for(int i=1;i<nums.length;i++){
            nums[0]=nums[0]^nums[i];
        }
        return nums[0];
    }
}

LeetCode刷题中遇到的小技巧(长期更新)_第1张图片

2.Boyer-Moore 投票算法

这个算法来自于leetcode一道题目中的题解,首先我们来看看这个算法。
LeetCode刷题中遇到的小技巧(长期更新)_第2张图片
题目链接
刚开始阅读这道题目,博主的第一反应时利用hash映射,将数组中每个数放进hashmap中,然后相同的数字就让对应的value加一,最后找到value大于n/2的数就是我们要的众数。
然后剩下的解法大概有下面几种:

  1. 排序,然后第n/2个元素就是众数(因为众数个数大于n/2)
  2. 分治,分解的子问题为,将数组区间进行二分,既然是众数,那么他必定至少是其中一个区间的众数,如果两个区间众数不同则统计总区间两个数的个数进行获取,同时对于二分区间不断进行划分,直到划分长度为1,然后直接返回这个数。
  3. Boyer-Moore 投票算法

下面我们主要来看看Boyer-Moore 投票算法的重要思想
如果我们把众数记为 +1,把其他数记为 -1,将它们全部加起来,显然和大于 0,从结果本身我们可以看出众数比其他数多。
算法步骤
我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;
我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:

如果 x 与 candidate 相等,那么计数器 count 的值增加 1;

如果 x 与 candidate 不等,那么计数器 count 的值减少 1。

在遍历完成后,candidate 即为整个数组的众数

这个算法分析的思路主要是这样的:我们依次遍历数组每一个数,因为众数的个数大于一半,所以不管何时我们的candidate是不是众数,经历一半多众数的count-1必然会变为0,此时candidate就变成了众数,而没有一个数的次数能够让众数的count变为0,所以最后的candidate就是众数
代码如下

class Solution {
    public int majorityElement(int[] nums) {
        int candidate =0 ;
        int count = 0;
        for(int i = 0;i<nums.length;i++){
            if(count == 0){
                candidate = nums[i];
                count++;
            }else{
                count+=candidate==nums[i]?1:-1;
            }
        }
        return candidate;
    }
}

<持续更新中~~~>

你可能感兴趣的:(LeetCode刷题中遇到的小技巧(长期更新))