01-Kotlin的WhenElse一共有几种写法

Int等基本类型的WhenElse

1
2
3
4
5
6
7
8
9
private fun whenElseInt(intNumber: Int) {
val number: String = when(intNumber) {
0 -> "Zero"
1 -> "One"
2 -> "Two"
else -> "Unknown"
}
println(number)
}

编译后的字节码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private final static whenElseInt(I)V
L0
LINENUMBER 22 L0
ILOAD 0
TABLESWITCH
0: L1
1: L2
2: L3
default: L4
L1
LINENUMBER 23 L1
FRAME SAME
LDC "Zero"
GOTO L5
L2
LINENUMBER 24 L2
FRAME SAME
LDC "One"
GOTO L5
L3
LINENUMBER 25 L3
FRAME SAME
LDC "Two"
GOTO L5
L4
LINENUMBER 26 L4
FRAME SAME
LDC "Unknown"
L5
LINENUMBER 22 L5
FRAME SAME1 java/lang/String
ASTORE 1
L6
LINENUMBER 28 L6
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
L7
LINENUMBER 29 L7
RETURN
L8
LOCALVARIABLE number Ljava/lang/String; L6 L8 1
LOCALVARIABLE intNumber I L0 L8 0
MAXSTACK = 2
MAXLOCALS = 2

可以看到,编译器生成了TABLESWITCH指令,可以根据数值快速查表,找到跳转位置

如果是一下几种情况,则不会生成TABLESWITCH

阅读更多

基础06-ViewGroup

dispatchTouchEvent

flowchart TD
    A[开始] --> B{过滤事件}
    B -->|true| C{是否ACTION_DOWN}
    B -->|false| D[返回false]
    C -->|true| E[清除TouchTargets,重置TouchState]
    C -->|false| F{111}
    E --> G[调用onInterceptTouchEvent]@{ shape: comment, label: "计算新事件的x,y,传递给child\n若child空,调用super.dispatchTouchEvent" }
    G --> J[处理hover事件]
    J --> F[遍历TouchTarget,调用dispatchTransformedTouchEvent传递event]
    F --> H[如果是up/cancel,重置TouchState]
    H --> I[返回是否handle]

过滤事件

  • 如果this存在flag:FILTER_TOUCHES_WHEN_OBSCURED,event存在flag:FLAG_WINDOW_IS_OBSCURED,就丢掉
  • window被上面的window遮住了,不管这个时间了
1
2
3
4
public void setFilterTouchesWhenObscured(boolean enabled) {
setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
FILTER_TOUCHES_WHEN_OBSCURED);
}

调用view的这个函数,就会设置这个flag

阅读更多

00-Java数组遍历性能对比

三种遍历方式性能对比

  1. 循环与数组的length比较

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class JavaMain {
    static Object[] objs = new Object[10000000];
    static int zero() {
    int sum = 0;
    for(int i = 0; i < objs.length; i++) {
    sum ^= objs[i].hashCode();
    }
    return sum;
    }
    }
  2. 将数组length存在方法栈中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class JavaMain {
    static Object[] objs = new Object[10000000];
    static int one() {
    int sum = 0;
    int len = objs.length;
    for(int i = 0; i < len; i++) {
    sum ^= objs[i].hashCode();
    }
    return sum;
    }
    }
  3. for-each循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class JavaMain {
    static Object[] objs = new Object[10000000];
    static int two() {
    int sum = 0;
    for (Object obj : objs) {
    sum ^= obj.hashCode();
    }
    return sum;
    }
    }

测试速度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class JavaMain {
static Object[] objs = new Object[10000000];
static long run(IntSupplier f) {
long start = System.currentTimeMillis();
int result = 0;
for(int i = 0; i < 100; i++) {
result = f.getAsInt();
}
long end = System.currentTimeMillis();
System.out.println("result = " + result + ", time = " + (end - start) / 1000.0);
return end - start;
}
public static void main(String[] args) {
for (int i = 0; i < objs.length; i++) {
objs[i] = new Object();
objs[i].hashCode(); // 首次计算hashcode更慢,先缓存
}
for (int i = 0; i < 10; i++) {
long zeroTime = run(JavaMain::zero);
long oneTime = run(JavaMain::one);
long twoTime = run(JavaMain::two);
System.out.printf("2比1快: %.2f%%\n", ((double)oneTime - twoTime) / oneTime * 100);
System.out.printf("2比0快: %.2f%%\n", ((double)zeroTime - twoTime) / zeroTime * 100);
System.out.printf("1比0快: %.2f%%\n", ((double)zeroTime - oneTime) / oneTime * 100);
}
}
}

测试结果

1
2
3
4
5
6
result = 360970567, time = 1.393
result = 360970567, time = 1.174
result = 360970567, time = 0.886
2比1快: 24.53%
2比0快: 36.40%
1比0快: 18.65%
阅读更多

LeetCode-38

2181. 合并零之间的节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
ListNode* mergeNodes(ListNode* head) {
int sum = 0;
ListNode dummy;
ListNode *move_dummy = &dummy;
ListNode *move = head;
while(move->next) {
sum = 0;
while(move->next && move->next->val != 0) {
sum += move->next->val;
move = move->next;
}
move->val = sum;
move_dummy->next = move;
move_dummy = move_dummy->next;
move = move->next;
move_dummy->next = nullptr;
}
return dummy.next;
}
};

977. 有序数组的平方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int len = nums.size();
vector<int> merged_array(len);
int i = 0, j = len - 1;
for(int k = len - 1; k >= 0; k--) {
if(abs(nums[i]) > abs(nums[j])) {
merged_array[k] = nums[i] * nums[i];
i++;
} else {
merged_array[k] = nums[j] * nums[j];
j--;
}
}
return merged_array;
}
};
  • 按照绝对值归并
  • 双指针,从左右两端开始移动,

3174. 清除数字

阅读更多

牛客刷题-2

1.小美的平衡矩阵

1.
小美的平衡矩阵
小美拿到了一个nnn*n的矩阵,其中每个元素是 0 或者 1。
小美认为一个矩形区域是完美的,当且仅当该区域内 0 的数量恰好等于 1 的数量。
现在,小美希望你回答有多少个iii*i的完美矩形区域。你需要回答1in1\leq i \leq n的所有答案。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入描述:
第一行输入一个正整数n,代表矩阵大小。
接下来的n行,每行输入一个长度为n的 01 串,用来表示矩阵。
1\leq n \leq 200
输出描述:
输出n行,第i行输出i*i的完美矩形区域的数量。
示例1
输入例子:
4
1010
0101
1100
0011
输出例子:
0
7
0
1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <vector>
using namespace std;

int main() {
int n;
cin >> n;
vector<vector<int>> preSum(n, vector<int>(n+1));
for(int i = 0; i < n; i++) {
string s;
cin >> s;
for(int j = 0; j < n; j++) {
preSum[i][j+1] = preSum[i][j] + (s[j] - '0');
}
}
for(int window = 1; window <= n; window++) {
if(window & 1) {
cout << "0\n";
continue;
}
int perfect = 0;
for(int j = 0; j <= n - window; j++) {
int sum = 0;
for(int i = 0; i < window; i++) {
sum += preSum[i][window + j] - preSum[i][j];
}
if(sum * 2 == window * window) {
perfect++;
}
for(int i = window; i < n; i++) {
sum -= preSum[i - window][window + j] - preSum[i - window][j];
sum += preSum[i][window + j] - preSum[i][j];
if(sum * 2 == window * window) {
perfect++;
}
}
}
cout << perfect << "\n";
}
}

2.小美的数组询问

2.
小美的数组询问
小美拿到了一个由正整数组成的数组,但其中有一些元素是未知的(用 0 来表示)。
现在小美想知道,如果那些未知的元素在区间[l,r][l,r]范围内随机取值的话,数组所有元素之和的最小值和最大值分别是多少?
共有qq次询问。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入描述:
第一行输入两个正整数n,q,代表数组大小和询问次数。
第二行输入n个整数a_i,其中如果输入的a_i为 0,那么说明a_i是未知的。
接下来的q行,每行输入两个正整数 l,r,代表一次询问。
1\leq n,q \leq 10^5
0 \leq a_i \leq 10^9
1\leq l \leq r \leq 10^9
输出描述:
输出q行,每行输出两个正整数,代表所有元素之和的最小值和最大值。
示例1
输入例子:
3 2
1 0 3
1 2
4 4
输出例子:
5 6
8 8
例子说明:
只有第二个元素是未知的。
第一次询问,数组最小的和是 1+1+3=5,最大的和是 1+2+3=6。
第二次询问,显然数组的元素和必然为 8。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;

int main() {
int n, q;
cin >> n >> q;
long long sum = 0;
long long zeroCnt = 0;
for(int i = 0; i < n; i++) {
int ai;
cin >> ai;
zeroCnt += (ai == 0 ? 1 : 0);
sum += ai;
}
for(int i = 0; i < q; i++) {
int l, r;
cin >> l >> r;
cout << sum + zeroCnt*l << " " << sum + zeroCnt*r << "\n";
}
}
阅读更多

OI KIWI 02-二分

二分查找

左闭右闭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int binarySearch(vector<int>& vec, int target) {
int len = vec.size();
int l = 0, r = len - 1; //
while(l <= r) {
int mid = (r - l) / 2 + l;
if(vec[mid] == target) {
return mid;
} else if(vec[mid] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return -1;
}

左闭右开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
int search(vector<int>& nums, int target) {
int len = nums.size();
int l = 0, r = len;
while(l < r) {
int mid = (r - l) / 2 + l;
if(nums[mid] == target) {
return mid;
} else if(nums[mid] > target) {
r = mid;
} else {
l = mid + 1;
}
}
return -1;
}
};

总结

阅读更多

LeetCode-37

698. 划分为k个相等的子集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Solution {
class Solve {
vector<int>& nums;
int k;
int n;
vector<int> bucket;
int target;
int sum;
bool canPartition;
bool dfs(int index) {
if(index >= n) { // 所有数都放进来了,且没有超过target
// 说明一定全等于target
// 如果有桶<target, 则一定有桶>target,所以所有桶一定>=target
// 如果有桶>target, 则一定有桶<target,所以所有桶一定<=target
// 所以所有桶一定==target
return true;
}
for(int i = 0; i < k; i++) {
if(i>0 && bucket[i] == bucket[i-1]) continue;
if(bucket[i] + nums[index] <= target) {
bucket[i] += nums[index];
if(dfs(index+1)) {
return true;
}
bucket[i] -= nums[index];
}
}
return false;
}
public:
Solve(vector<int>& nums, int k):nums(nums), k(k), bucket(k) {
n = nums.size();
sum = accumulate(nums.begin(), nums.end(), 0);
target = sum / k;
sort(nums.begin(), nums.end(), greater<int>());
if(sum % k != 0) {
canPartition = false;
return;
}
canPartition = dfs(0);
}
bool solve() {
return canPartition;
}
};
public:
bool canPartitionKSubsets(vector<int>& nums, int k) {
return Solve(nums, k).solve();
}
};

硬搜

690. 员工的重要性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int getImportance(vector<Employee*> employees, int id) {
int len = employees.size();
unordered_map<int, Employee*> id2Node;
for(Employee *employee : employees) {
id2Node[employee->id] = employee;
}
function<int(int)> dfs = [&](int currentId) {
Employee *node = id2Node[currentId];
int ans = node->importance;
for(int child : node->subordinates) {
ans += dfs(child);
}
return ans;
};
return dfs(id);
}
};

699. 掉落的方块

阅读更多

OI KIWI 01-倍增

OI KIWI 倍增

思想

图片来源

查找小于limit的最大数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int maxValueInVecSmallerThenLimit(vector<int>& vec, int limit) {
int n = vec.size();
int l = 0;
int p = 1;
while(p) {
if(l + p < n && vec[l + p] < limit) {
l += p;
p <<= 1;
} else {
p >>= 1;
}
}
return vec[l];
}
阅读更多

LeetCode-36

551. 学生出勤记录 I

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
bool checkRecord(string s) {
int count = 0;
int max_seq_late = 0;
int seq_late = 0;
for(char c : s) {
if(c == 'A') count++;
if(c == 'L') {
seq_late++;
} else {
max_seq_late = max(max_seq_late, seq_late);
seq_late = 0;
}
}
max_seq_late = max(max_seq_late, seq_late);
return count < 2 && max_seq_late < 3;

}
};
  • 连续相同的值的个数
  • 统计元素出现的次数

3137. K 周期字符串需要的最少操作次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
int minimumOperationsToMakeKPeriodic(string word, int k) {
unordered_map<string, int> subStrCount;
int len = word.length();
for(int i = 0; i < len; i += k) {
subStrCount[word.substr(i, k)]++;
}
int minOpCnt = len / k;
for(auto& ite : subStrCount) {
minOpCnt = min(minOpCnt, len / k - ite.second);
}
return minOpCnt;
}
};
  • 翻译一下规则,就是把长度为nk的字符串切割成n个长度为k的子串,一次操作可以把一个子串替换成另一个字串,求如何替换,将所有字串都相同。
  • 翻译好需求,就很清楚了,直接统计每个字串出现的次数,取出现次数最大的,替换次数最少,为n - cnt[i]
阅读更多

基础05-Navigation

简介

NavController是中央导航 API。它会跟踪用户访问过的目的地,并允许用户在目的地之间移动。

获取NavController

  • fragment

如果是NavHostFragment

1
val navController = this.navController
阅读更多