[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 3321][Go][有序集合]计算子数组的 x-sum II](https://s3.inkorcloud.top/image/2025/11/c9f55b2ecb04d16a57547b9f4de294ef.png)
![[leetcode 2589][Go][贪心]完成所有任务的最少时间](https://s3.inkorcloud.top/image/2025/11/b966fd1a91aa1ea098b86e6d778523c2.png)
![[leetcode 3234][Go]统计1显著的字符串的数量](https://s3.inkorcloud.top/image/2025/11/a72a47911de291f51cbb5902e4811c1f.png)
![[leetcode 1611][Go][位运算][记忆化搜索]使整数变为 0 的最少操作次数](https://s3.inkorcloud.top/image/2025/11/9715b5f3d8a7574ded3648767538558e.png)
![[leetcode 2528][Go][二分答案][差分数组][前缀和]最大化城市的最小电量](https://s3.inkorcloud.top/image/2025/11/fa0013722d9361b4383839722394dcf2.png)