-
递归的进一步学习-动态规划之最少硬币问题
阶乘和斐波那契数列相信各位都很熟悉,典型的教材式递归例子,因为简单退化为循环也没啥难度。不过依赖于递归的问题并不都是那么简单的,比如最少硬币问题,需要称为动态规划(DP)的方式来实现。 所谓动态规划个人理解就是缓存一下递归的结果。比如斐波那契数列,简单的实现方式是: public int fib(int n) { if(n == 0 || n == 1) return 1; return fib(n – 2) + fib(n – 1); } 假如计算fib(5),事实上计算了一次fib(4),两次fib(3),三次fib(2),四次fib(1),两次fib(0),换句话说,重复计算了(1 – 1) + (2 – 1) + (3 – 1) + (4 – 1) + (2 – 1)有7次之多。理想情况下每个fib(n)只要计算一次。改进方法很简单,增加cache,其实就是简单的映射数组: public int fib(int n) { if(fib_cache[n] > 0) return fib_cache[n]; //…
-
Dijkstra非负加权有向图最短路径算法
成果在这里,前天完成的,花了大约半天的时间。参考资料主要是维基百科和一篇博客。 在分析自己代码前,先写一点自己对于Dijkstra算法的理解。 u s v
-
二叉查找树学习笔记
二叉查找树如其名是一种主要用于查找的每个非叶子节点最多有两个子节点(左右子节点)的树,其特点是: a b c 任何a, b, c三个节点(父节点和两个子节点,左右子节点可能只有一个或者都没有)满足a < b < c。对于相等的值使用节点计数+1或者节点中的链表等不同的方式来处理。 a < b < c这个条件乍一看和二分搜索binary_search很像,实际查找元素时也是类似的,时间复杂度在O(logn)。 一般的二叉查找树(不考虑链表退化和平衡的处理)包含查找,创建树/增加节点,删除节点,前/中/后序遍历等操作,下面分别介绍。
-
迟到的大学数据结构作业——堆排序
时隔好几年,才发现算法的趣味性,比如堆排序。堆排序同时也是大学时自己未完成的数据结构作业之一,就像《高等数学》一样之后都是抄抄了事…… 个人理解,堆排序是一个有名的排序算法,比较适合优先级队列。虽然时间复杂度是O(nlogn),论排序算法中比较快的还是快速排序。堆排序的特点是使用完全或近似完全二叉树来模拟一种父节点肯定比子节点大(最大堆)或者小(最小堆)的结果,并通过多次“删除”根节点并恢复结构来达到“模拟”排序的目的。实践中需要关注的是三点:
-
【算法学习】趁热打铁,插入,选择和归并排序
插入排序 插入排序最直观的解释是不断拿扑克牌时排序的动作。一开始你只有一张8,第二张是5,你把5放在8的左边。第三张是9,你放在8的右边。第四张是2,你放在最左边。拿这四张牌的过程可以认为是排序4个数字的过程。步骤可以归纳为: 拿起一张牌 -> 取下一个数 比较现有牌,具体来说是从右往左找到第一个不小于当前牌的位置 -> 将所有大于当前数的数字向右移动一位 放入牌 -> 放置数字 形象上来讲,放置数字的过程是多个数字右移的过程,所以不需要swap。Java代码如下: public void sort(int[] xs) { int len = xs.length; if (len <= 1) return; for (int i = 1; i < len; i++) { int x = xs[i]; int j = i; while (j > 0 && xs[j – 1] > x) {…
-
【算法学习】快速排序(原地分区)
最近重新学习算法,先从几个排序算法开始。快速排序是比较有名的一个排序算法,基本原理我明白,但是之前只会筛选构造新序列分区的方式,现在要学的是原地分区的方式。 成果代码如下,使用Java编写(C/C++的数组和指针操作忘得差不多了)。 private void swap(int[] array, int i, int j) { if (i == j) return; System.out.println(String.format(“%d <-> %d”, i, j)); int a = array[i]; array[i] = array[j]; array[j] = a; } private int partition(int[] ns, int begin, int end) { int pivotIndex = (begin + end) / 2; int pivot = ns[pivotIndex]; swap(ns, pivotIndex,…
-
海量积分排序的二分实现
简单描述下问题:有一个网站,现在有很多用户,每个用户有一个积分,要求在用户登录时显示用户的积分排名,用户的积分会有变动。注意考虑数据量比较大的场景。 原理是以树的方式来分解排名的计算。参考在这里。 实际代码分为三部分: 查询某个积分的排名 更新积分 构造积分树 查询积分排名 原理是计算所有右子树或者同级节点的和,再加1。每个节点包含当前积分或者积分段内的用户总数。右子树或者同级节点代表大于指定积分的积分节点。排名的实际含义就是计算所有大于自己积分的人的总数。最后加1是因为大于最大积分的人的总数为0,但是排名不能为0,所以实际显示是必须加1的。 这块实际依赖树的结构,可能是数组或者是链表,但通用逻辑如下(递归): in: current node, score if current node is score node if current node is left leaf return count of right sibling else # current node is right node, no right sibling return 0 else # current node is score range node if score in left subtree…
-
zero sum subsequence problem solution 1
题目是这样的,给定一个整数序列,比如[1, 2, -1, 8, -9],要求找出一个子序列,其所有数字的和为0,比如子序列[2, -1, 8, -9],并输出子序列在主序列中的位置,比如[2, -1, 8, 9]在主序列[1, 2, -1, 8, -9]中的位置为[1, 4]。 以下是我想到的一个方法,暂时不清楚怎么计算这个的时间复杂度。原理是这样的,对于序列[1, 2, -1, 8, -9],设置一个和序列。初始为[0, 0, 0, 0, 0],长度和输入序列一致。 顺序读取输入序列,第一次遇到1,尝试在和序列的[0, 0]区别内增加1,结果为[1, 0, 0, 0, 0]。为什么这么做呢,这样,输入序列区间[0, 0]的和就计算出来了。 第二次遇到2, 尝试在和序列[0, 1]区间内增加2,结果为[3, 2, 0, 0, 0],这样,输入序列区间[0, 1], [1, 1]的和就计算出来了。没有发现0和序列。 接下来依此类推,发现[1, 4]区间的和为0,输出为(1, 4)。代码如下(python): #!/usr/bin/env python import sys def find_zero_sum_seq(seq): sums = [0] *…
-
git svn使用小记2 非标准的分支流
假如你遇到一条非标准的分支流,即不是/branches/xxx这种形式的,该怎么让git识别?以下是我从stackoverflow上学到的一个简单方法,如有更好的方法,欢迎指出。 git config –add svn-remote.newbranch.url https://svn/path_to_newbranch/ git config –add svn-remote.newbranch.fetch :refs/remotes/newbranch git svn fetch newbranch [-r<rev>] git checkout -b local-newbranch -t newbranch git svn rebase newbranch 执行了上述命令后,.git/config中其实会增加如下内容 [svn-remote “newbranch”] url = http://path/to/your/repository fetch = :refs/remotes/newbranch [branch “local/newbranch”] remote = . merge = refs/remotes/newbranch 然后你就可以使用非标准的branch了。
-
代码吐槽1
我发现离厕所远一点有一点好:在去厕所的路上经常会有idea出来,这篇文章就是其中之一。 言归正传,我对看到的别人的代码吐槽的想法由来已久。大部分时候,碍于情面不能直说。有时候委婉地说了,愿意听的当场改,大部分时候都我行我素。以至于我觉得写这些代码的时候是不是都是从北大青鸟出来的? 第一个:尤达表达式,null = someVariable(Java代码中) 我很敬佩从C/C++转到Java的人,但是我很看不起转过来了不学习相应语法的人。 第二个:collection.size() == 0 估计老师没教过collection.isEmpty() 第三个:StringUtils.equals(“foo”, someVariable) 公司规范的受害者,而且顽固不化。什么时候需要用工具类来比较,什么时候不需要分不清。 第四个:someMap.get(SomeConstains.ABC)出现多处 只有一处问题不大,多处不知道static import。