👉day 19位运算

201. 数字范围按位与

难度中等398

给你两个整数 leftright ,表示区间 [left, right] ,返回此区间内所有数字 按位与 的结果(包含 leftright 端点)。

  • 0 与谁与都为 0 ,因此只要有一个0,那么无论有多少个 1都是 0

本题其实就是需要求这两个数字的二进制表示的公共前缀,

以5 , 7 为例

21-02-27-01.png

可以看到,5 和 7 二进制形式存在公共前缀 01 ,因此从 5 → 7 ,其前两位 01 是一直不变的,只有后两位一直在变化,从 01 → 11。

我们可以确定按位与的结果,前两位一定是 01。

根据公共前缀确定结果前两位为 01,接下来就要确定剩余部分按位与结果。

若存在剩余部分,剩余部分的表现形式一定是 0XXX → 1XXX。举个极端的例子 01111111 → 10000000(相差仅为 1 )。

即使在最极端的情况下,剩余部分中每一位也一定存在 0 ,因此我们可以认定,剩余部分按位与结果一定为 0。

👉day 20其他

384. 打乱数组

labuladong 题解

难度中等296

给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是 等可能 的。

实现 Solution class:

  • Solution(int[] nums) 使用整数数组 nums 初始化对象
  • int[] reset() 重设数组到它的初始状态并返回
  • int[] shuffle() 返回数组随机打乱后的结果

【宫水三叶】洗牌算法模板题 - 打乱数组 - 力扣(LeetCode)

洗牌算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
int[] nums;
int n;
Random random = new Random();
public Solution(int[] _nums) {
nums = _nums;
n = nums.length;
}
public int[] reset() {
return nums;
}
public int[] shuffle() {
int[] ans = nums.clone();
for (int i = 0; i < n; i++) {
swap(ans, i, i + random.nextInt(n - i));
}
return ans;
}
void swap(int[] arr, int i, int j) {
int c = arr[i];
arr[i] = arr[j];
arr[j] = c;
}
}

🎈202. 快乐数

难度简单1063

编写一个算法来判断一个数 n 是不是快乐数。

  • 这题目上来就一脸懵逼, 暴力计算肯定就又TLE了, 既然是个简单题, 那应该是有什么小窍门

快乐的知识点增加了 - 快乐数 - 力扣(LeetCode)

链表找环
每个数字都会根据 各位平方和 指向另一个数字,所以从任意数字开始进行 各位平方和 的迭代操作,就相当于在链表上游走。如果 无限循环 但始终变不到 1,那说明肯定是链表游走到了环。

为什么呢? (此处应该有图)

为什么无限循环就一定是走到了环了呢?而不是链表上的数字越变越大?这里我来给一个证明。

image-20220906215055055

通过上面的证明, 本题也就化为了链表找环问题 ,

  • 快慢指针

slow每次走一步, fast每次走两步,

  • 这里的走步 , 其实就求平方和 ,

slow==fast的时候, 相当于进入环了,

  • fastslow整整一个环

返回结果就是slow是否为1

  • 其实本题最后如果slow==fast==1 , 1 本身就是一个环

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public boolean isHappy(int n) {
int slow=n,fast=squareSum(n);
while(slow!=fast){
slow=squareSum(slow);
fast=squareSum(squareSum(fast));
}
return slow==1;
}
int squareSum(int n){ //求平方和
int sum=0;
while(n!=0){
sum+=(n%10)*(n%10);
n/=10;
}
return sum;
}
}

149. 直线上最多的点数

难度困难436

给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。