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 进行过滤。因为第一个元素可以和第二个元素相同。

当我们刷完 3Sum4Sum 后,我们隐约会有一种感觉,对于任意整数 k(k >= 2),我们都可以解答 kSum。确实如此,对于 kSum, 我们可以将问题分解成两个子问题:

  1. 求解 2Sum
  2. 将 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 种方式:

  1. The Art of Reading
  2. From Avid Reader to Avid Writer
  3. Listen Up
  4. Take Online Courses
  5. Practice Makes Perfect
  6. Tap Into Your Colleagues Network
  7. Socialise

Tip

MySQL 经常使用 show processlist 命令排查问题。

1567347324431

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

熵与热力学第二定律息息相关,简单来讲,熵就是描述事物无序的程度,熵越大,无序度就越高。我们知道热力学第二定律描述的是不可逆过程,而这也是一个熵增的过程。

所以,在孤立的系统中,事物总是朝着更加无序的方向发展,这就是熵增原理。因此,宇宙最终会走上彻底的无序,我们可以称之为“永恒的死亡”。

或许,人类存在的意义就是,在宇宙一步一步走向彻底无序的过程中,努力保持自身的有序。

posted @ 2019-09-01 23:32  Thomas_hzp  阅读(128)  评论(0)    收藏  举报