ARTS-02
Algorithm
leetcode 1: Two Sum
public int[] twoSum(int[] nums, int target) {
if (nums == null || nums.length < 2) return new int[] {-1, -1};
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
int key = target - nums[i];
if (map.containsKey(key)) return new int[] {map.get(key), i};
else map.put(nums[i], i);
}
return new int[] {-1, -1};
}
leetcode 15: 3Sum
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> list = new ArrayList<>();
for(int i = 0; i < nums.length - 2; i++) {
if(i == 0 || nums[i] != nums[i-1]) {
int lo = i + 1;
int hi = nums.length - 1;
int value = 0 - nums[i];
while(lo < hi) {
if(nums[lo] + nums[hi] == value) {
list.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
while(lo < hi && nums[lo] == nums[lo+1]) lo++;
while(lo < hi && nums[hi] == nums[hi-1]) hi--;
lo++;
hi--;
} else if(nums[lo] + nums[hi] < value) {
// while(lo < hi && nums[lo] == nums[lo+1]) lo++;
lo++;
} else {
// while(lo < hi && nums[hi] == nums[hi-1]) hi--;
hi--;
}
}
}
}
return list;
}
注释掉的两个循环语句是没有必要加的,不仅不会提高程序的性能,反而会让程序多执行一些判断语句。
leetcode 16: 3Sum Closest
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int result = nums[0] + nums[1] + nums[nums.length - 1];
for(int i = 0; i < nums.length - 2; i++) {
int lo = i + 1;
int hi = nums.length - 1;
while(lo < hi) {
int value = nums[i] + nums[lo] + nums[hi];
if(value == target) return target;
else if(value < target) lo++;
else hi--;
if(Math.abs(value - target) < Math.abs(result - target)) result = value;
}
}
return result;
}
leetcode 18: 4Sum
这道题和 3Sum 很相似,因此可以用同样思路解答这道题。为了方便去重,我们先进行排序。
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> list = new ArrayList<>();
for(int i = 0; i < nums.length - 3; i++) {
if(i > 0 && nums[i] == nums[i-1]) continue;
for(int j = i+1; j < nums.length - 2; j++) {
// if(nums[j] == nums[j-1]) continue;
if((j - 1) != i && nums[j] == nums[j-1]) continue;
int lo = j + 1;
int hi = nums.length - 1;
while(lo < hi) {
int value = nums[i] + nums[j] + nums[lo] + nums[hi];
if(value == target) {
list.add(Arrays.asList(nums[i], nums[j], nums[lo], nums[hi]));
while(lo < hi && nums[lo] == nums[lo+1]) lo++;
while(lo < hi && nums[hi] == nums[hi-1]) hi--;
lo++;
hi--;
} else if(value < target) {
lo++;
} else {
hi--;
}
}
}
}
return list;
}
注意不能用注释部分 if(nums[j] == nums[j-1]) continue; 对 j 进行过滤。因为第一个元素可以和第二个元素相同。
当我们刷完 3Sum 和 4Sum 后,我们隐约会有一种感觉,对于任意整数 k(k >= 2),我们都可以解答 kSum。确实如此,对于 kSum, 我们可以将问题分解成两个子问题:
- 求解 2Sum
- 将 kSum 降低成 (k-1)Sum
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
return kSum(nums, target, 4);
}
public List<List<Integer>> kSum(int[] nums, int target, int k) {
Arrays.sort(nums);
return kSum(nums, target, k, 0);
}
private List<List<Integer>> kSum(int[] nums, int target, int k, int fromIndex) {
List<List<Integer>> list = new ArrayList<>();
if(fromIndex + k > nums.length) return list;
if(k == 2) {
int lo = fromIndex;
int hi = nums.length - 1;
while(lo < hi) {
int value = nums[lo] + nums[hi];
if(value == target) {
List<Integer> t = new LinkedList<>();
t.add(nums[lo]);
t.add(nums[hi]);
list.add(t);
while(lo < hi && nums[lo] == nums[lo+1]) lo++;
while(lo < hi && nums[hi] == nums[hi-1]) hi--;
lo++;
hi--;
} else if(value < target) {
lo++;
} else {
hi--;
}
}
return list;
}
for(int i = fromIndex; i <= nums.length - k; i++) {
List<List<Integer>> temp = kSum(nums, target-nums[i], k-1, i+1);
if(!temp.isEmpty()) {
for(List<Integer> t : temp) {
t.add(0, nums[i]);
}
list.addAll(temp);
}
while(i <= nums.length - k && nums[i] == nums[i+1]) i++;
}
return list;
}
}
Review
这周阅读地是 medium 上的一篇文章,文章的题目是《Great Developers Never Stop Learning》。在文章中,作者探讨了 IT 专业人员保持持续学习的 7 种方式:
- The Art of Reading
- From Avid Reader to Avid Writer
- Listen Up
- Take Online Courses
- Practice Makes Perfect
- Tap Into Your Colleagues Network
- Socialise
Tip
MySQL 经常使用 show processlist 命令排查问题。
show processlist 查看的是线程的信息。只有 root 用户可以看到所有线程,其他用户只能看到自己启动的线程,除非这个用户被赋予 PROCESS 权限。
show processlist 查询的是 MySQL 系统库 information_schema 中的 processlist 表。show processlist 等价于:
select * from information_schema.processlist;
下面简单介绍各个字段的意思:
Id: 线程的标识,也是 information_schema.processlist 表的主键。
User: 启动这个线程的用户。
Host: 记录了客户端的 ip 地址和端口。
db: 当前是在哪个数据库上执行命令。如果没有 use database, 则为 NULL。
Command: 线程正在执行的命令,和 State 对应。
Time: 已经处于当前状态多长时间。
State: 线程的状态,比较复杂。
Info: 一般记录的是当前执行的命令。默认只显示 100 个字符。
Share
熵与热力学第二定律息息相关,简单来讲,熵就是描述事物无序的程度,熵越大,无序度就越高。我们知道热力学第二定律描述的是不可逆过程,而这也是一个熵增的过程。
所以,在孤立的系统中,事物总是朝着更加无序的方向发展,这就是熵增原理。因此,宇宙最终会走上彻底的无序,我们可以称之为“永恒的死亡”。
或许,人类存在的意义就是,在宇宙一步一步走向彻底无序的过程中,努力保持自身的有序。
浙公网安备 33010602011771号