之前写了篇文章 用JavaScript刷LeetCode的正确姿势,简单总结一些用 JavaScript 刷力扣的基本调试技巧。最近又刷了点题,总结了些数据结构和算法,希望能对各为 JSer 刷题提供帮助。

此篇文章主要想给大家一些开箱即用的 JavaScipt 版本的代码模板,涉及到较复杂的知识点,原理部分可能会省略,有需要的话后面有时间可以给部分知识点单独写一篇详细的讲解。

走过路过发现 bug 请指出,拯救一个辣鸡(但很帅)的少年就靠您啦!!!

BigInt

众所周知,JavaScript 只能精确表达 Number.MIN_SAFE_INTEGER(-2^53+1) ~ Number.MAX_SAFE_INTEGER(2^53-1) 的值。

而在一些题目中,常常会有较大的数字计算,这时就会产生误差。举个栗子:在控制台输入下面的两个表达式会得到相同的结果:

>> 123456789*123456789      // 15241578750190520
>> 123456789*123456789+1 // 15241578750190520

而如果使用 BigInt 则可以精确求值:

>> BigInt(123456789)*BigInt(123456789)              // 15241578750190521n
>> BigInt(123456789)*BigInt(123456789)+BigInt(1) // 15241578750190522n

可以通过在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数 BigInt()。上面的表达式也可以写成:

>> 123456789n*123456789n       // 15241578750190521n
>> 123456789n*123456789n+1n // 15241578750190522n

BigInt 只能与 BigInt 做运算,如果和 Number 进行计算需要先通过 BigInt() 做类型转换。

BigInt 支持运算符,+*-**% 。除 >>>(无符号右移)之外的位操作也可以支持。因为 BigInt 都是有符号的, >>>(无符号右移)不能用于 BigIntBigInt 不支持单目 (+) 运算符。

BigInt 也支持 / 运算符,但是会被向上取整。

const rounded = 5n / 2n; // 2n, not 2.5n

取模运算

在数据较大时,一般没有办法直接去进行计算,通常都会给一个大质数(例如,1000000007),求对质数取模后的结果。

取模运算的常用性质:

(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p) % p
(a * b) % p = (a % p * b % p) % p
a ^ b % p = ((a % p) ^ b) % p

可以看出,加/减/乘/乘方,都可直接在运算的时候取模,至于除法则会复杂一些,稍后再讲。

举一个例子,LeetCode 1175. 质数排列

请你帮忙给从 1n 的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。

让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。

由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7 之后的结果即可。

题目很简单,先求出质数的个数 x,则答案为 x!(n-x)!(不理解的可以去看题解区找题解,这里就不详细解释了)

由于阶乘的值很大,所以在求阶乘的时候需要在运算时取模,同时这里用到了上面所说的BigInt

/**
* @param {number} n
* @return {number}
*/
var numPrimeArrangements = function(n) {
const mod = 1000000007n;
// 先把100以内的质数打表(不想再写判断质数的代码了
const prime = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97];
// 预处理阶乘
const fac = new Array(n + 1);
fac[0] = 1n; // 要用bigint
for (let i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * BigInt(i) % mod;
}
// 先求n以内的质数的个数
const x = prime.filter(i => i <= n).length;
// x!(n-x)!
return fac[x] * fac[n - x] % mod;
};

快速幂

快速幂,顾名思义,快速求幂运算。原理也很简单,比如我们求 x^10 我们可以求 (x^5)^2 可以减少一半的运算。

假设我们求 (x^n)

  • 如果 n 是偶数,变为求 (x^(n/2))^2
  • 如果 n 是奇数,则求 (x^⌊n/2⌋)^2 * x⌊⌋ 是向下取整)

因为快速幂涉及到的题目一般数据都很大,需要取模,所以加了取模运算。其中,代码中 n>>=1 相当于 n=n/2if(n&1)是在判断n是否为奇数。

代码如下:

// x ^ n % mod
function pow(x, n, mod) {
let ans = 1;
while (n > 0) {
if (n & 1) ans = ans * x % mod;
x = x * x % mod;
n >>= 1;
}
return ans;
}

乘法逆元(数论倒数)

上面说了除法的取模会复杂一些,其实就是涉及了乘法逆元

当我们求 (a/b)%p 你以为会是简单的 ((a%p)/(b%p))%p?当然不是!(反例自己想去Orz

假设有 (a*x)%p=1 则称 ax关于p互为逆元(ax 关于 p 的逆元,xa 关于 p 的逆元)。比如:2*3%5=123 关于 5 互为逆元。

我们把 a 的逆元用 inv(a) 表示。那么:

(a/b) % p
= ( (a/b) * (b*inv(b)) ) % p // 因为(b*inv(b))为1
= (a * inv(b)) % p
= (a%p * inv(b)%p) % p

现在通过逆元神奇的把除法运算变没了~~~

问题在于怎么求乘法逆元。有两种方式,费马小定理扩展欧几里德算法

不求甚解的我只记了一种解法,即费马小定理:a^(p-1) ≡ 1 (mod p)

由费马小定理我们可以推论:a^(p-2) ≡ inv(a) (mod p)

数学家的事我们程序员就不要想那么多啦,记结论就好了。即:

a关于p的逆元为a^(p-2)

好了,现在可以通过快速幂求出 a 的逆元了。

function inv(a, p) {
return pow(a, p - 2, p); // pow是上面定义的快速幂函数
}

(P.S.其实我数论很烂= =,平时都是直接记结论,所以此处讲解可能存在不准确的情况。仅供参考。

二分答案

解题的时候往往会考虑枚举答案然后检验枚举的值是否正确。若满足单调性,则满足使用二分法的条件。把这里的枚举换成二分,就变成了“二分答案”。二分答案的时间复杂度是O(logN * (单次验证当前值是否满足条件的复杂度))

很多同学在边界问题上经常出bug,也会不小心写个死循环什么的,我总结了一个简单清晰不会出错的二分模板:

// isValid 判断某个值是否合法 根据题目要求实现
// 假设 如果x合法则大于x一定合法 如果x不合法则小于x一定不合法
// 求最小合法值
function binaryCalc() {
let l = 0, r = 10000; // 答案可能出现的最小值l和最大值r 根据题目设置具体值
let ans; // 最终答案
while (l <= r) {
let mid = (l + r) >> 1; // 位运算取中间值 相当于 floor((l+r)/2)
if (isValid(mid)) {
// 如果 mid 合法 则 [mid, r] 都是合法的
// 我们先把ans设置为当前获取的合法值的最小值 mid
ans = mid;
// 然后再去继续去求[l,mid-1]里面是否有合法值
r = mid - 1;
} else {
// 如果mid不合法 则[l,mid]都是不合法的
// 我们去[mid+1,r]中找答案
l = mid + 1;
}
}
return ans;
}

举一个简单的例子,LeetCode 69. x 的平方根 是一个二分模板题。题目要求是,给一个数字 x 求平方小于等于 x的最大整数。此处求的是最大值,和模板中对lr的处理刚好相反。

/**
* @param {number} x
* @return {number}
*/
var mySqrt = function(x) {
let l = 0, r = x; // 根据题目要求 答案可能的值最小为0 最大为x
let ans = 0; // 最终答案 function isValid(v) { // 判断一个数是否合法
return v * v <= x;
} while (l <= r) {
let mid = (l + r) >> 1; // 取中间值
if (isValid(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
};

并查集

个人觉得并查集是非常精妙且简洁优雅的数据结构,推荐学习。

并查集应用场景为,存在一些元素,分别包含在不同集合中,需要快速合并两个集合,同时可快速求出两个元素是否处于同一集合。

简单的理解并查集的实现,就是把每一个集合都当做一棵树,每个节点都有一个父节点,每棵树都有一个根节点(根节点的父节点为其本身)。

判断是否同一集合:我们可以顺着节点的父节点找到该节点所在集合的根节点。当我们确定两个集合拥有同一个根节点,则证明两个节点处于同一个集合。

合并操作:分别取得两个节点所在集合的根节点,把其中一个根节点的父节点设置为另一个根节点即可。

可能说的比较抽象,想详细了解的同学可以自己深入学习,这里直接给出代码模板。

class UnionFind {
constructor(n) {
this.n = n; // 节点个数
// 记录每个节点的父节点 初始时每个节点自己为一个集合 即每个节点的父节点都是其本身
this.father = new Array(n).fill().map((v, index) => index);
}
// 寻找一个节点的根节点
find(x) {
// 如果父节点为其本身 则证明是根节点
if (x == this.father[x]) {
return x;
}
// 递归查询
// 此处进行了路径压缩 即将x的父节点直接设置为根节点 下一次查询的时候 将减少递归次数
return this.father[x] = this.find(this.father[x]);
}
// 合并x和y所在的两个集合
merge(x, y) {
const xRoot = this.find(x); // 找到x的根节点
const yRoot = this.find(y); // 找到y的根节点
this.father[xRoot] = yRoot; // 将xRoot的父节点设置为yRoot 即可将两个集合合并
}
// 计算集合个数
count() {
// 其实就是查询根节点的个数
let cnt = 0;
for (let i = 0; i < this.n; i++) {
if (this.father[i] === i) { // 判断是否为根节点
cnt++;
}
}
return cnt;
}
}

找一个并查集的题目,方便大家理解并查集的妙处。并查集的题目可以出得非常灵活,可能不会轻易看出是并查集。 LeetCode 947. 移除最多的同行或同列石头

n 块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。

如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。

给你一个长度为 n 的数组 stones ,其中 stones[i] = [xi, yi] 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。

此处参考了官方的题解

把二维坐标平面上的石头想象成图的顶点,如果两个石头横坐标相同、或者纵坐标相同,在它们之间形成一条边。

根据可以移除石头的规则:如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。可以发现:一定可以把一个连通图里的所有顶点根据这个规则删到只剩下一个顶点。

我们遍历所有的石头,发现如果有两个石头的横坐标或者纵坐标相等,则证明这两块石头应该在同一个集合(即上面说的连通图)里。那么最后每个集合只留一块石头,剩下的则全部可以被移除。

AC代码:

// 定义 UnionFind 相关代码
/**
* @param {number[][]} stones
* @return {number}
*/
var removeStones = function(stones) {
let n = stones.length;
let uf = new UnionFind(n);
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// 有两个石头的横坐标或者纵坐标相等 则合并
if (stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) {
uf.merge(i, j);
}
}
}
// 石头总数减去集合的个数就是答案
return n - uf.count();
};

KMP

KMP 被一些算法初学者认为是高难度数据结构,一般遇到直接放弃那种。所以我想了下几句话应该也解释不清,那就跳过原理直接上模板吧。

先简单说一下背景,KMP 解决的是子串查找的问题。给两个字符串ST,求T是否是S的子串。解决方法是先预处理T,求出Tnext数组,其中next[i]代表T的子串T[0...i-1](即T.substring(0, i)最长相等的前缀后缀 的长度。

嘛,最长相等的前缀后缀,就是说,比如字符串"abcuuabc"最长相等的前缀后缀就是abc,那么其长度就应该是3

然后借助next数组,可以在线性时间复杂度内求出T是否为S的子串,首次出现下标,以及出现次数。

模板代码:

// 求字符串 s 的 next 数组
function getNext(s) {
let len = s.length;
let next = new Array(len + 1);
let j = 0, k = -1;
next[0] = -1;
while (j < len) {
if (k == -1 || s[j] === s[k]) next[++j] = ++k;
else k = next[k];
}
return next;
}
// 求字符串 t 在字符串 s 中第一次出现的下标 不存在则返回 -1
function findIndex(s, t) {
let i = 0, j = 0;
let next = getNext(t);
let slen = s.length, tlen = t.length;
while (i < slen && j < tlen) {
if (j === -1 || s[i] === t[j]) ++i, ++j;
else j = next[j];
}
return j === tlen ? i - tlen : -1;
}
// 求字符串 t 在字符串 s 出现的次数
function findCount(s, t) {
let ans = 0;
let i = 0, j = 0;
let next = getNext(t);
let slen = s.length, tlen = t.length;
while (i < slen && j < tlen) {
if (j === -1 || s[i] === t[j]) ++i, ++j;
else j = next[j];
if (j === tlen) {
++ans;
j = next[j];
}
}
return ans;
}

如果多次计算子串相同的话,next数组可以预处理,不需要每次在求index时再计算。

举个例子吧,LeetCode 1392. 最长快乐前缀

「快乐前缀」是在原字符串中既是 非空 前缀也是后缀(不包括原字符串自身)的字符串。

给你一个字符串 s,请你返回它的 最长快乐前缀

如果不存在满足题意的前缀,则返回一个空字符串。

我们会发现这不就是 next 数组么,所以我记得这次周赛会 KMP 的同学直接 copy 就得分了.....

AC代码;

// getNext 定义参考上面模板
/**
* @param {string} s
* @return {string}
*/
var longestPrefix = function(s) {
let len = s.length;
let next = getNext(s);
let ansLen = next[len] == len ? len - 1 : next[len]; // 不包含原字符串 需要特殊判断下
return s.substring(0, ansLen);
};

再来一个 LeetCode 28. 实现 strStr() 求一个字符串在另一个字符串中首次出现的位置,就是indexOf的实现,其实也就是模板中的 findIndex 函数。

AC代码:

// findIndex 定义参考模板
/**
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function(haystack, needle) {
return findIndex(haystack, needle);
};

优先队列(堆)

优先队列,我们给每个元素定义优先级,每次取队列中的值都取的是优先级最大的数。

其他的语言中都自带优先队列的实现,JSer就只能QAQ……所以我自己写了一个优先队列,就是通过堆来实现。(原理就不讲啦,学过堆排序的应该懂~(趴

class PriorityQueue {
/**
* 构造函数 可以传入比较函数自定义优先级 默认是最小值排在最前
* @param {function} compareFunc 比较函数 compareFunc(a, b) 为 true 表示 a 的优先级 > b
*/
constructor(compareFunc) {
this.queue = [];
this.func = compareFunc || ((a, b) => a < b);
}
/**
* 向优先队列添加一个元素
*/
push(ele) {
this.queue.push(ele);
this.pushup(this.size() - 1)
}
/**
* 弹出最小值并返回
*/
pop() {
let { queue } = this;
if (queue.length <= 1) return queue.pop(); let min = queue[0];
queue[0] = queue.pop();
this.pushdown(0);
return min;
}
/**
* 返回最小值
*/
top() {
return this.size() ? this.queue[0] : null;
}
/**
* 返回队列中元素的个数
*/
size() {
return this.queue.length;
}
/**
* 初始化堆
*/
setQueue(queue) {
this.queue = queue;
for (let i = (this.size() >> 1); i >= 0; i--) {
this.pushdown(i);
}
}
/**
* 调整以保证 queue[index] 是子树中最小的
* */
pushdown(index) {
let { queue, func } = this;
let fa = index;
let cd = index * 2 + 1;
let size = queue.length;
while (cd < size) {
if (cd + 1 < size && func(queue[cd + 1], queue[cd])) cd++;
if (func(queue[fa], queue[cd])) break;
// 交换 queue[fa] 和 queue[cd]
[queue[fa], queue[cd]] = [queue[cd], queue[fa]];
// 继续处理子树
fa = cd;
cd = fa * 2 + 1;
}
}
/**
* 调整 index 到合法位置
*/
pushup(index) {
let { queue, func } = this;
while (index) {
const fa = (index - 1) >> 1;
if (func(queue[fa], queue[index])) {
break;
}
[queue[fa], queue[index]] = [queue[index], queue[fa]];
index = fa;
}
}
}

举个例子,LeetCode 23. 合并K个升序链表 一道困难题目哦~

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

做法很简单,把链表都放到优先队列里,每次取值最小的链表就行。具体实现看代码。

/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
var mergeKLists = function(lists) {
let queue = new PriorityQueue((a, b) => a.val < b.val); lists.forEach(list => {
list && queue.push(list);
}); const dummy = new ListNode(0);
let cur = dummy; while (queue.size()) {
let node = queue.pop();
if (node.next) queue.push(node.next);
cur.next = new ListNode(node.val);
cur = cur.next;
} return dummy.next;
};

Trie(字典树/前缀树)

字典树应该算是一个比较简单而且直观的数据结构~字典树模板题可以看 LeetCode 208. 实现 Trie (前缀树)

/**
* Initialize your data structure here.
*/
var Trie = function() {
this.nodes = [];
}; /**
* Inserts a word into the trie.
* @param {string} word
* @return {void}
*/
Trie.prototype.insert = function(word) {
let nodes = this.nodes;
for (let w of word) {
if (!nodes[w]) {
nodes[w] = {};
}
nodes = nodes[w];
}
nodes.end = true;
}; /**
* Returns if the word is in the trie.
* @param {string} word
* @return {boolean}
*/
Trie.prototype.search = function(word) {
let nodes = this.nodes;
for (let w of word) {
if (!nodes[w]) {
return false;
}
nodes = nodes[w];
}
return !!nodes.end;
}; /**
* Returns if there is any word in the trie that starts with the given prefix.
* @param {string} prefix
* @return {boolean}
*/
Trie.prototype.startsWith = function(prefix) {
let nodes = this.nodes;
for (let w of prefix) {
if (!nodes[w]) {
return false;
}
nodes = nodes[w];
}
return true;
};

字典树的变种应用,LeetCode 421. 数组中两个数的最大异或值 参考:题解

我们也可以将数组中的元素看成长度为 31 的字符串,字符串中只包含 01。如果我们将字符串放入字典树中,那么在字典树中查询一个字符串的过程,恰好就是从高位开始确定每一个二进制位的过程。对于一个数求异或和的最大值,就是从最高位开始,每一位都找异或和最大的那个分支。

var Trie = function() {
this.nodes = [];
};
Trie.prototype.insert = function(digit) {
let nodes = this.nodes;
for (let d of digit) {
if (!nodes[d]) {
nodes[d] = [];
}
nodes = nodes[d];
}
};
Trie.prototype.maxXor = function(digit) {
let xor = 0;
let nodes = this.nodes;
for (let i = 0; i < digit.length; i++) {
let d = digit[i];
if (nodes[d ^ 1]) {
xor += 1 << (digit.length - i - 1);
nodes = nodes[d ^ 1];
} else {
nodes = nodes[d];
}
}
return xor;
}; /**
* @param {number[]} nums
* @return {number}
*/
var findMaximumXOR = function(nums) {
let trie = new Trie();
let maxXor = 0;
for (let x of nums) {
let binaryX = x.toString(2);
// 因为 0 <= nums[i] <= 2^31 - 1 所以最多为31位
// 补前缀0统一变成31位
binaryX = ('0'.repeat(31) + binaryX).substr(-31);
// 插入Trie
trie.insert(binaryX);
maxXor = Math.max(maxXor, trie.maxXor(binaryX));
}
return maxXor;
};

总结

暂时就想到这么多比较常见的数据结构。如果有其他的可以在评论区补充,如果我会的话会后续加上的。

JSer冲鸭!!!

参考资料

用 JavaScript 刷 LeetCode 的正确姿势【进阶】的更多相关文章

  1. 用JavaScript刷LeetCode的正确姿势

    虽然很多人都觉得前端算法弱,但其实 JavaScript 也可以刷题啊!最近两个月断断续续刷完了 leetcode 前 200 的 middle + hard ,总结了一些刷题常用的模板代码.走过路过 ...

  2. GitHub 热点速览 Vol.18:刷 LeetCode 的正确姿势

    作者:HelloGitHub-小鱼干 摘要:找对路子,事半功倍,正如本周 GitHub Trending #刷 LeetCode# 主题想表达的那般,正确的学习姿势方能让人走得更远,走进大厂

  3. 刷LeetCode的正确姿势——第1、125题

    最近刷LeetCode比较频繁,就购买了官方的参考电子书 (CleanCodeHandbook),里面有题目的解析和范例源代码,可以省去非常多寻找免费经验分享内容和整理这些资料的时间.惊喜的是,里面的 ...

  4. 刷LeetCode的简易姿势

    近期抽空刷了刷LeetCode,算是补补课. 由于不是很习惯直接在网页上Coding&Debug,所以还是在本地环境下进行编码调试,觉得基本OK后再在网页上提交. 主要采用Python3进行提 ...

  5. 吃透Javascript数组操作的正确姿势—再读《Js高程》

    Javascript中关于数组对象的操作方法比较多也比较杂,正好再次捡起<Javascript高级程序设计>来读,把它们一一总结梳理了一下: 方法类别 方法名称 方法描述 参数 返回值 备 ...

  6. 刷leetcode是什么样的体验?【转】

    转自:https://www.zhihu.com/question/32322023 刷leetcode是什么样的体验? https://leetcode.com/ 1 条评论   默认排序 按时间排 ...

  7. jquery选中radio或checkbox的正确姿势

    jquery选中radio或checkbox的正确姿势 Intro 前几天突然遇到一个问题,没有任何征兆的..,jquery 选中radio button单选框时,一直没有办法选中,后来查了许多资料, ...

  8. 【JavaScript】Leetcode每日一题-最大整除子集

    [JavaScript]Leetcode每日一题-最大整除子集 [题目描述] 给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对(an ...

  9. 【JavaScript】Leetcode每日一题-移除元素

    [JavaScript]Leetcode每日一题-移除元素 [题目描述] 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用 ...

随机推荐

  1. Java中,一个存在十几年的bug...

    今天,分享一个JDK中令人惊讶的BUG,这个BUG的神奇之处在于,复现它的用例太简单了,人肉眼就能回答的问题,JDK中却存在了十几年.经过测试,我们发现从JDK8到14都存在这个问题. 大家可以在自己 ...

  2. Java后端精选技术:SpringBoot配置读取

    在早前的博客中曾经写过 Spring 程序通过 Bean 映射实现配置信息的读取. 在SpringBoot 框架中读取配置的方式变得非常多样,这导致读者在搜寻资料时反而容易迷糊. 到底,SpringB ...

  3. 「模拟8.17」star way to heaven(并查集,最小生成树)

    80分打法 首先二分最后答案,答案即为r,可看作以每个k为圆心r为半径的圆 我们进行并查集维护,维护相交的圆的边界 最后判断是否存在圆将上下边界覆盖,如有证明不行 1 #include<iost ...

  4. 20204107 孙嘉临《Python程序设计》实验三报告

    课程:<Python程序设计>班级: 2041姓名: 孙嘉临学号: 20204107实验教师:王志强实验日期:2020年5月24日必修/选修: 公选课## 1.实验内容创建服务端和客户端, ...

  5. <题解>世界树

    世界树<题解> 首先我们拿到这个题之后,能想到的一定是虚树,如果想不到的话,还是重新学一遍去吧 所以我们应该怎么做呢 虚树的板子不需要我再讲一遍了吧 所以对于这个题来说,怎么根据虚树上的节 ...

  6. 36、网卡绑定bond

    注意:虚拟机需要网卡模式为同一模式,否则无法进行通信: 36.1.mode0(平衡负载模式): 平时两块网卡均工作,且自动备援,但需要在与服务器本地网卡相连的交换机设备上进行端口聚合来支持绑定技术. ...

  7. 9、make和make install的区别

    简单来说,make 是编译,make install 是安装. 9.1.configure: 这一步一般用来生成 Makefile,为下一步的编译做准备,你可以通过在 configure 后加上参数来 ...

  8. 11、函数(def)

    11.1.函数: 函数即变量 函数的作用域只跟函数声明时定义的作用域有关,跟函数的调用位置无任何关系 1.函数格式: def test(x): ''' 2*x+1 :param x:整形数字 :ret ...

  9. CentOS-磁盘扩容挂载目录

    挂载 查看存储情况 $ df -kh 查看磁盘情况 $ fdisk -l fdisk创建分区(注:可操作存储上限为2TB)$ fdisk /dev/sdb根据提示,依次输入"n", ...

  10. Java:java -jar命令讲解

    1. 当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 #正常启动jar包 java -jar XXX.jar#当前ssh窗口被锁定,可按CTRL + C打断程序运行, ...