图论建模
现实中有很多的问题可以建模为图论问题,然后使用 DFS 与 BFS 算法轻松的解决,现在我们打算从 LeetCode 选择几道题,来了解如何将现实问题建模为图论问题。
二分图检测题目介绍给定一个无向图graph,当这个图为二分图时返回true。如果我们能将一个图的节点集合分割成两个独立的子集 A 和 B,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,我们就将这个图称为二分图。
graph 将会以邻接表方式给出,graph[i] 表示图中与节点 i 相连的所有节点。每个节点都是一个在 0 到graph.length-1 之间的整数。这图中没有自环和平行边: graph[i] 中不存在 i,并且 graph[i] 中没有重复的值。
注意:
graph 的长度范围为 [1, 100]。
graph[i] 中的元素的范围为 [0, graph.length - 1]。
graph[i] 不会包含 i 或者有重复的值。
图是无向的: 如果 j 在 graph[i] 里边, 那么 i 也会在 graph[j] 里边。
解题思路这道题的解法是对图中的节点染色,我们使用 ...
ES6:函数
默认参数如果在调用函数时没有传入参数时,我们希望使用默认值,ES5 的写法如下
function getValue(url, timeout, callback) { timeout = timeout || 2000; callback = callback || function(data) { console.log(data); } // 其他处理逻辑}
但是上面的代码有问题,如果 timeout 传入的是 0,那么 timeout 还是会使用默认值,因为 0 对应的 boolean 为 false,所以代码会修改如下
function getValue(url, timeout, callback) { timeout = (typeof timeout !== 'undefined') ? timeout : 2000; callback = (typeof callback !== 'undefined') ? callback : function( ...
ES6:字符串和正则表达式
首先推荐两篇文章了解字符编码相关细节
Unicode与JavaScript详解
Javascript中的string类型使用UTF-16编码
Unicode、UTF-8 与 UTF-16在开发的过程中,经常会碰到 Unicode,UTF-8,UTF-16 等等术语,在很多的时候我一直是将它们混为一谈的,不过今天详细的了解了它们之间的不同,作为本章的前言,方便本章内容的理解。
首先 Unicode 表示的是字符集,而 UTF-8,UTF-16 表示的是字符编码。所谓的字符集指的就是字符的集合,Unicode 字符集几乎包含了世界上所有国家的字符,所以 Unicode 又被称为是万国码,如果使用 Unicode 字符集的话,那么可以表示几乎所有国家中的字符(ASCII字符集只包含了英文,而 GBK 字符集包含中日韩等几个国家的字符以及英文字符)。对于每一个字符,Unicode 都为它们对应了一个码点(Code Point),码点从 0 开始计算,例如 \u0000 表示的就是 null,表示空的意思。
UFT-8,UTF-16 则是将 Unicode 字符集中包含的字符编码为数字存储在计算 ...
ES6:let 和 const
var 声明变量使用 var 声明变量的特点:
变量提升
console.log(value); // undefiendvar value = 'hello';
上述代码在变量 value 声明之前就访问了 value,在其他的类 C 语言中,要使用变量必须先声明变量,如果没有声明则会报错,但是对于上述的代码,JavaScript 并没有报错,而是打印出了 undefiend,这时因为 JavaScript 对使用 var 声明的变量做了变量提升,将变量 value 的声明放置在所在作用域的最前面,所以上面的代码相当于如下
var value;console.log(value);value = 'hello';
无块级作用域
对于其他的类 C 语言,变量的作用域一般是在一个块级作用域中的,一旦出了所在的块级作用域,就无法访问到该变量。但是 JavaScript 并没有块级作用域,只有全局作用域和函数作用域
if (true) { var value = "hello";}console ...
图的广度优先遍历
树的层序遍历树的层序遍历是指一层一层的遍历树的节点,它的实现是借助于队列进行实现的:
每一次从队列的头部取出元素进行遍历,然后将该元素的左右孩子添加进队列,以此往复,直至队列为空,遍历结束。
import java.util.LinkedList;import java.util.Queue;public class BinaryTree { private class Node { private Node left; private Node right; private int value; public Node(int value) { this.value = value; } } private Node root; public BinaryTree(int value) { root = new Node(value); } ...
最长回文字符串
题目描述给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"输出: "bab"注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"输出: "bb"
暴力法扫描一遍字符串,判断 $[i, j]$ 范围内的字符串是不是回文字符串,并且在这个过程中记录最长的字符串
class Solution { public String longestPalindrome(String s) { if (s == null || s.length() < 2) { return s; } char[] str = s.toCharArray(); int start = 0; int maxLength = 1; for (int i = 0; i & ...
安全与算法
我们在使用互联网交换数据时,数据需要经过各种各样的网络设备才能到达通信双方,如果数据在传输的过程中经过某些恶意用户的设备,就有可能导致信息被窃取。所以如果想安全的使用互联网,了解必须的安全技术是不可或缺的。
安全问题我们首先了解一下在通信的过程中会遇到什么样的安全问题。
窃听
$A$ 向 $B$ 发送的信息可能会在传输的过程中被 $X$ 偷看,这就是窃听。
假冒
$A$ 以为给 $B$ 发送了消息,但是 $B$ 有可能是 $X$ 冒充的;同样 $B$ 以为收到了 $A$ 的消息,但是 $A$ 也有可能是 $X$ 冒充的,这种问题叫做假冒。
篡改
$B$ 确实收到了 $A$ 发送的信息,但是内容已经被 $X$ 给改变了,这种行为叫做篡改。
事后否认
$B$ 从 $A$ 那里收到了消息,但是 $A$ 在事后宣称消息不是它发的,这会导致互联网上的商业交易或合同无法成立,这种行为叫做事后否认。
在这篇文章中就着重解决这四类问题,对于窃听,我们对消息进行加密技术;对于假冒,我们使用消息认证码或数字签名;对于篡改,我们同样可以使用消息认证码或数字签名;对于事后否认,我们可以使用数字签名。
...
numpy之数学方法
文章是使用 jupyter 写的,为了插入到博客中,使用 iframe 进行嵌入,所以阅读体验可能不是很好
numpy之矩阵
文章是使用 jupyter 写的,为了插入到博客中,使用 iframe 进行嵌入,所以阅读体验可能不是很好
图的深度优先遍历
图的深度优先遍历所谓图的遍历就是按照某种顺序访问图中所有的节点,根据访问的顺序不同,可以分为两类:
深度优先遍历
广度优先遍历
在本节中讲解深度优先遍历。
所谓深度优先遍历(Depth First Search,简称 DFS),是指在遍历时,尽可能深的访问图的节点。为了更好的理解图的深度优先遍历,我们先看看树的深度优先遍历,与图的深度优先遍历一样,树的深度优先遍历也是指尽可能深的访问树的节点,也就是说如果一个节点有孩子节点,那么我们下一步就应该遍历它的孩子节点(深度),如下
从上面的动图可以看出,当我们遍历完当前节点以后,如果该节点有孩子节点,那么接下来我们去遍历孩子节点,我们的遍历策略就是尽可能深的遍历。类比于图,对于图来说,如果一个图的节点有邻接节点,那么在遍历完该节点后,我们下一步就去遍历它的邻接节点
这就是图的深度优先遍历,上图深度优先遍历访问的顺序是 $[0, 1, 3, 2, 4, 5]$,我们将在下面的编程中验证是否正确。
图的遍历与树的遍历有一处不同,那就是重复访问问题。树不会发生重复访问的问题,这是因为树的节点只能通过父节点访问到,只有一种路径到达该节点, ...