[leetcode 3171][备忘录][Go]关于LogTrick解法的个人理解

[leetcode 3171][备忘录][Go]关于LogTrick解法的个人理解
inkOrCloud题目连接
参考链接
解题思路
主要目的就是算出所有子数组的按位运算值并算出与k的绝对差,暴力解法时间复杂度为
为了更好理解,设一对指针l/r和一个数组dp[],dp[l]表示nums[r]|nums[r-1]|nums[r-2]...nums[l]的值,即子数组r至l的按位与运算值(当r后移时dp[0]至dp[r]中的值会被覆盖)
LogTrick的思路就是利用当a|b=b时a|b|c|d|e == b|c|d|e的特点省去大量的重复计算(最终时间复杂度能达到(nums[r]|dp[l]) == dp[l]就可以直接跳过dp[l-1]到dp[0]的计算,因为此时dp[l],dp[l-1],dp[l-2]…dp[0]与上一个r边界的值完全相同
1 | var dp = make([]int, len(nums)) |
为什么时间复杂度为
假设0 <= nums[i] < 16,即nums[i]为一个4位二进制数,那么对于nums = []int{8, 4, 2, 1, 1, 2, 4, 8}的二进制形式如下:
当r在0,1,2,3时因为每一位都只有一个一所以都需要计算到底,分别计算了1,2,3,4次但从r为4,5,6,7时会在l为0,1,2,3时就出现1
2
3
4
5
6
7
81000
0100
0010
0001
0001
0010
0100
1000(nums[r]|dp[l])==dp[l]的情况所以计算次数都为5次
也就按位或运算呈递增单调性导致平均每位的累积变化都不会超过n次这也使得计算次数不会超过







![[leetcode 3347][Go][答案二分]万能的二分法](https://s3.inkorcloud.top/image/2025/10/b92574e48ab8dfff1b32cc049a61df5f.png)
![[leetcode 3321][Go][有序集合]计算子数组的 x-sum II](https://s3.inkorcloud.top/image/2025/11/c9f55b2ecb04d16a57547b9f4de294ef.png)
![[leetcode 3234][Go]统计1显著的字符串的数量](https://s3.inkorcloud.top/image/2025/11/a72a47911de291f51cbb5902e4811c1f.png)