0%

概述

MySQL 从 5.7 版本起支持了 JSON(JavaScript Object Notation,JavaScript 对象表示法)数据类型,在这之前,在 MySQL 中存储 JSON 数据的方式是存储 JSON 格式的字符串。与此相比,新增的 JSON 数据类型具有以下优点:

  • 自动验证存储在 JSON 列中的 JSON 文本格式,错误的 JSON 格式会报错。
  • 优化的存储格式。JSON 文本以二进制格式进行存储,可以快速读取其中的某个元素。我们的程序在读取某个 JSON 值时,不需要从文本形式解析该值,可以通过键或数组索引查找或修改值,而无需读取文本中它们之前或之后的所有值。

本文的内容基于 MySQL 8.0.21 版。

阅读全文 »

昨天更新了办公本的 Git 客户端,从 2.25 更新到了 2.28 版本,今天从代码库拉取代码时报错了。

报错信息

1
unable to negotiate with *.*.*.*: no matching key exchange methodfound. Their offer: diffie-hellman-group1-sha1, diffie-hellman-group14-sha1

因为 Git 和远程仓库的连接是基于 ssh 的,而 Openssh 项目在 8.2 版本中弃用了 SHA1:https://www.openssh.com/txt/release-8.2,新版的 Git 客户端也默认禁用了基于 SHA1 加密组件。

以下摘自 openssh 8.2 版本的发行说明:

1
2
3
this release removes the "ssh-rsa" (RSA/SHA1) algorithm from those accepted for certificate signatures (i.e. the client and server CASignatureAlgorithms option) and will use the rsa-sha2-512 signature algorithm by default when the ssh-keygen (1) CA signs new certificates.

this release removes diffie-hellman-group14-sha1 from the default key exchange proposal for both the client and server.

新版的 ssh 从默认的密钥交换协议中移除了 diffie-hellman-group14-sha1,报错信息中可以得知服务器端的 Git 仓库使用的是 diffie-hellman-group14-sha1 协议,所以更新 Git 客户端后,会出现服务器和客户端默认的密钥交换协议不一致的情况,因此连接远程仓库时会报错。

解决方案

在用户目录下的 .ssh 文件中,新建 config 文件,添加以下内容

1
KexAlgorithms +diffie-hellman-group14-sha1

再次尝试更新代码,问题已解决。

参考链接

https://developercommunity.visualstudio.com/content/problem/925718/git-access-by-ssh-fails-with-unsupported-key-excha.html

我的联想 Z500 笔记本的原装网卡是高通的,比较老了,不支持 5G 频段的无线网,于是在淘宝花 50 块买了一个 Intel 7260AC 网卡准备换上。

联想在 2017 年之前的笔记本,都有网卡白名单,写入到 BIOS 了,换新的网卡需要在 BIOS 中更改白名单,否则识别不了新网卡,进不去系统。

在刷 BIOS 之前需要提取原来的 BIOS 固件,修改之后,再刷入 BIOS。

首先开机按 F2 进入 BIOS 设置,BIOS Back Flash 选项设置为 Enable,允许备份 BIOS。

阅读全文 »

最近频繁遇到 IntelliJ IDEA 启动失败的问题,还有启动 TomCat 时 1099 端口占用问题,有时还有 ShadowSocksR 的 1080 端口占用问题。有时重启电脑能够解决问题,但并非总是有效。有时候 IDEA 用的好好的,但是电脑休眠后重新唤醒就打不开 IDEA 了。 TomCat 的 1099 端口占用问题也总是出现,使用 powershell 用以下命令查看端口占用情况,却找不到占用端口的进程。

1
netstat -aon | findstr 1099

查看了 IDEA 的启动日志,应该也是端口占用导致启动失败。Google 搜索到 JetBrains 官方支持社区的一个 帖子,了解到 IDEA 在启动时,会绑定 69426991 之间第一个可用的端口,如果无法绑定此范围内的任何端口,则会引发如下图所示异常:

阅读全文 »

快速排序(Quick Sort)

快速排序是由东尼・霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 $O (n\log n)$ 次比较。在最坏状况下则需要 $O (n^2)$ 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 $O (n\log n)$ 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

快速排序的最坏运行情况是 $O (n^2)$,比如说顺序数列的快排。但它的平摊期望时间是 $O (n\log n)$,且 $O (n\log n)$ 记号中隐含的常数因子很小,比复杂度稳定等于 $O (n\log n)$ 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。

快速排序(Quick Sort)的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

阅读全文 »

交换元素使序列有序求最少交换次数的题有两类:

  1. 第一种是 只能交换相邻元素使序列有序 ,求最小交换次数,假如是是序列升序,只需要求逆序对数。比如 {5, 1, 3, 2, 4, 7, 6, 8},逆序的有:(5, 1)(5, 3)(5, 2)(5, 4)(3, 2)(7, 6),一共 6 对,最小交换次数是 6 次。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static void getMinSwapCount1(int[] arr) {
        int count = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr [i] > arr [j]) {
                    count++;
                }
            }
        }
        System.out.println (count);
    }
    阅读全文 »

源代码分析

实际上 HashSet 内部维护了一个 HashMap,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable {
static final long serialVersionUID = -5024744406713321676L

private transient HashMap<E, Object> map; 

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object (); 

/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();


...
}
阅读全文 »

软件简介

win10 应用商店有一款很棒的 ssh 客户端软件:Token2Shell/MD,是一款 UWP 软件。我曾在几年前它限免的时候安装过,其实当时还不知道是干什么用的。现在它是我的主力 ssh 软件,简洁美观,轻量快速,功能强大。

现在这款软件名字改成了 Token2Shell,而且并不是在 Token2Shell/MD 基础上的更新,而是一个新软件,意味着我并不能从 Token2Shell/MD 更新到这个新版本,想要获得这个软件还需要重新购买。

阅读全文 »

本文参考自 如何写出正确的二分查找?—— 利用循环不变式理解二分查找及其变体的正确性以及构造方式 一文,改进了原文的描述,修改了部分代码。

序言

本文以经典的二分查找为例,介绍如何使用 循环不变式 来理解算法,并利用循环不变式在原始算法的基础上根据需要产生算法的变体。谨以本文献给在理解算法思路时没有头绪而又不甘心于死记硬背的人。

二分查找究竟有多重要?《编程之美》第 2.16 节的最长递增子序列算法,如果想实现 $O (n^2)$ 到 $O (n \log n)$ 的时间复杂度下降,必须借助于二分算法的变形。其实很多算法都是这样,如果出现了在有序序列中元素的查找,使用二分查找总能比线性查找算法拥有更好的性能。

然而,虽然很多人觉得二分查找简单,但随手写一写却不能得到正确的结果:死循环、边界条件等等问题伴随着出现。《编程珠玑》第四章提到:提供充足的时间,仅有约 10% 的专业程序员能够完成一个正确的二分查找。当然,正确的二分查找和变体在算法书籍以及网络上随处可得,但是如果不加以理解,如何掌握?理解时,又往往因想不清楚,一知半解,效果有限。我在看相关的变体算法时就觉得一片茫然,不得要领:或许这个算法可以这么写,稍微变下要求就不能这么写了;举正例说明算法在某些情况下可以正常工作、举反例说明算法有错固然可行,但仅有例子是不够的,怎样一劳永逸地证明自己几经修改的算法之正确?如果每一个变体都进行孤立地理解,那么太花费时间,而且效果也不好。如何解决这个问题?在思考方法和查阅书籍之后发现,还是要靠循环不变式来完成算法正确性的理论支撑。

或许你曾了解过循环不变式,但如果不使用的话,是看不到它的强大之处的:不仅仅能帮助你证明算法正确性,同时也帮助你理解算法,甚至能帮助你在基本算法的基础上,构造出符合要求的相应算法变体。这些都将在后文的各个算法说明中看到。

阅读全文 »