ARTS Week 24
Algorithm
本周的 LeetCode 题目为 69. Sqrt(x)
给你一个非负整数 x
,计算并返回 x
的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
输入:x = 4
输出:2
可以使用二分法来进行处理,因为使用乘法进行判断可能会出现溢出,因此更好地处理策略是使用除法来进行计算。又最后的结果只需要保留整数部分,因此当 mid+1 > x / (mid+1)
且 mid < x / mid
时,那么此刻最后结果就是mid
。
class Solution {
public int mySqrt(int x) {
if (x == 0 || x == 1) {
return x;
}
int left = 1;
int right = x;
int ans = -1;
int mid;
while (left < right) {
mid = left + (right - left) / 2;
if (mid+1 <= x / (mid+1)) {
left = mid;
} else if (mid > x / mid) {
right = mid;
} else {
ans = mid;
break;
}
}
return ans;
}
}
Review
本周 Review 的英文文章为:改善隐私保护配置SSH的3种方法
作者介绍了如何优化SSH体验并保护服务器免受未经授权的访问,下面是作者给出具体建议。
- 更改默认端口
默认的SSH端口是22,尽管你改变端口后,各种端口扫描器仍能发现它,但可以减少被扫描的次数。例如,作者的一个云服务器SSH端口为 TCP 22,平均每天被扫描攻击为24,但将端口改为 TCP 45678 后,每天的攻击数降为了2个。
要更改SSH的默认端口,打开 /etc/ssh/sshd_config
并将端口值更改为大于1024的某个数字,如果有注释需要取消注释,具体示例如下:
#Port 22122
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
更改端口并保存文件后,重新启动SSH服务器。
$ sudo systemctl restart sshd
- 没有更多的密码
作者建议使用非对称密钥进行身份验证,需要先生成一个SSH密钥对,公钥需要传输到服务器,另一个是私有的,与任何人共享。使用 ssh-keygen
创建一个新密钥,并使用 -t
选项指定一个好的、最新的加密库,例如 ed25519
:
$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (~/.ssh/id_ed25519):
按照提示输入密钥所在的位置和自定义名称,并可以指定密码,当然你也可以一路按照默认配置进行。
接下来使用 ssh-copy-id
命令将密钥复制到服务器上,例如下面的命令将公钥复制到一个名为 example.com
的服务器上。
$ ssh-copy-id jgarrido@example.com
一旦你从计算机可以在没有密码的情况下登录,编辑 sshd_config
中的允许密码登录的选项 PasswordAuthentication
设置为 no
最后使用 sudo systemctl restart sshd
重新启动ssh服务即可
- 决定谁可以登录
大多数Linux发行版不允许root用户通过SSH登录,打开SSH的配置文件sshd_config
,添加如下一行:
AllowUsers jgarrido jane tux
这将仅允许jgarrido、jane、tux这三个用户远程登录进行操作。
除此之外,sshd_config
文件中还有大量的有用的功能和选项,你也可以使用 Fail2ban
等应用来进一步保护你的SSH服务。
Tip
C语言中 strcmp
、strncmp
、memcmp
这三个比较函数的区别,它们三个都可以用来比较字符串是否相同,当返回值等于0代表相同,返回值不为0代表不相同。首先根据他们的声明来对比:
函数名 | 函数声明 | 是否需要传入要比较的长度 | 如何结束比较 |
---|---|---|---|
strcmp | int strcmp(const char *s1, const char *s2); | 不需要 | 以 \0 作为 s1 和 s2 的结尾 |
strncmp | int strncmp(const char *s1, const char *s2, size_t n); | 需要 | 以传入的参数 n 作为比较长度,同时以 \0 作为 s1 和 s2 的结尾 |
memcmp | int memcmp(const void *s1, const void *s2, size_t n); | 需要 | 以传入参数 n 作为比较长度 |
需要注意的是,strncmp()
会有两个条件用来判断结束,其一便是传入的长度,其二便是字符串结尾 \0
,字符串 \0
后面的内容并不会被比较。
#include <stdio.h>
#include <string.h>
int main()
{
const char s1[] = "abcd\0\0\0\0";
const char s2[] = "abcd\0xyz";
const char s3[] = "abcdabcd";
printf("----- strcmp() -----\n");
printf("strcmp(s1, s2) = %d\n", strcmp(s1, s2)); // 0
printf("strcmp(s1, s2) = %d\n", strcmp(s1, s2)); // 0
printf("strcmp(s1, s2) = %d\n", strcmp(s2, s3)); // -97
printf("----- strncmp() -----\n");
printf("strncmp(s1, s2, 4) = %d\n", strncmp(s1, s2, 5)); // 0
printf("strncmp(s1, s3, 4) = %d\n", strncmp(s1, s3, 5)); // -97
printf("strncmp(s2, s3, 4) = %d\n", strncmp(s2, s3, 5)); // -97
printf("strncmp(s1, s2, 8) = %d\n", strncmp(s1, s2, 8)); // 0
printf("strncmp(s1, s3, 8) = %d\n", strncmp(s1, s3, 8)); // -97
printf("strncmp(s2, s3, 8) = %d\n", strncmp(s2, s3, 8)); // -97
printf("----- memcmp() -----\n");
printf("memcmp(s1, s2, 4) = %d\n", memcmp(s1, s2, 5)); // 0
printf("memcmp(s1, s3, 4) = %d\n", memcmp(s1, s3, 5)); // -97
printf("memcmp(s2, s3, 4) = %d\n", memcmp(s2, s3, 5)); // -97
printf("memcmp(s1, s2, 8) = %d\n", memcmp(s1, s2, 8)); // -120
printf("memcmp(s1, s3, 8) = %d\n", memcmp(s1, s3, 8)); // -97
printf("memcmp(s2, s3, 8) = %d\n", memcmp(s2, s3, 8)); // -97
return 0;
}
Share
这周分享下自己写的介绍如何使用C语言读写CSV文件的三篇文章。欢迎大家拍砖:)