摘要: 题目假设有这样一个拥有三个操作的队列1. Enqueue(v)2. Dequeue()3. MaxEle()请设计一种数据结构和算法, 让 MAXELE 操作的时间复杂度尽可能的低思路1. 刚看到题, 以为这就是 stack 求 min 的逆过程, 着实是理解有误2. 比较优雅的解法是利用两个堆栈来模拟队列, 模拟的方法以前是做过习题的, 不必多说3. 重点是 stack 的实现. stack 有 4 个私有变量Type stackItem[MAXN]; // store real numbersint stackTop; // point to top of stackint link2Ne 阅读全文
posted @ 2014-02-24 21:06 SangS 阅读(1335) 评论(0) 推荐(0) 编辑
摘要: 题目给定字符串 s1 和 s2, 要求判定 s2能否能够被通过 s1 做循环移位得到的字符包含. s1 = AABCD, s2 = CDAA 返回 true. 给定 s1 = ABCD 和 s2 = ACBD 返回 false解法1. 最直接的方法是对 s1 进行移位然后比较. 若 s1 较长, 那么效率较低2. 题目转化成比较 s2 是否在 s1s1 中,这样可以利用 kmp 等算法提高对比效率 阅读全文
posted @ 2014-02-24 19:52 SangS 阅读(168) 评论(0) 推荐(0) 编辑
摘要: Leetcode 上有连续的两道题, 一个是 insert interval, 一个是 merge interval, 其中 insert interval 是 merge interval. 其中 insert interval 还是 merge interval 的扩展, 即便看起来相反解法1. 先对目标区间进行处理, 先排序后 merge, 时间复杂度为 o(nlogn)2. 使用二分查找, 找到一个区间, 然后看该区间是否包含源区间3. 因为目标区间是非连续的, 所以(2) 只要找出一个区间就好 阅读全文
posted @ 2014-02-24 19:25 SangS 阅读(540) 评论(0) 推荐(0) 编辑
摘要: 解法1. 假设在目标数组 array[] 的前 i 个元素中, 最长递增子序列的长度为 LIS[i]那么状态转移方程为LIS[i] = max(1, LIS[k]+1) array[i+1] > array[k], for any k 2, 就可以直接把 4 加到前面的子序列中形成一个新的递增子序列受此启发, 我们希望找到前 i 个元素中的一个递增子序列, 使得这个递增子序列的最大元素比 array[i+1] 要小, 且长度尽可能的长. 这样将 array[i+1] 加在该递增子序列后, 便可找到以 array[i+1] 为最大元素的最长递增子序列长度为 1 的递增子序列最大元素的最小值 阅读全文
posted @ 2014-02-24 18:43 SangS 阅读(252) 评论(0) 推荐(0) 编辑
摘要: 这道题在算法课上当做例题讲过, 当时的印象也比较深另有一道近似算法的题也在算法课上讲过, 并且印象更深, 复习的时候完全没管, 以为志在必得, 结果真考了那道近似算法, 我却没能打出来为避免阴沟翻船, 寻找最近点对还要再回顾一下算法核心是分治算法1. 分别根据点的 x,y 值进行排序2. 在 x 轴上划一道垂线, 将点均分成两半3. 假设最近点对都在左/右部分, 递归计算左/右半部分的最短距离并返回较小值 dis4. 假设最近点对分别在左右两个部分, 横跨中心的竖线. 中心线为中心, 2*dis 为宽度画一个矩形, 横跨中心线的最近点对 candidate 都在这个矩形内. 将这些点按照 y 阅读全文
posted @ 2014-02-24 18:00 SangS 阅读(1268) 评论(0) 推荐(0) 编辑
摘要: 解法1. 设置 min, max 两个变量, 然后遍历一遍数组, 比较次数为 2*N2. 依然设置 min, max 两个变量并遍历数组, 但将遍历的 step 设置为 2, 比较次数为 1.5 * N3. 改变数组的做法. 先排个序使得 min 总是在偶数位置, max 总在奇数位置, 比较次数依然是 1.5*N4. 分值算法, 实际上就是归并算法的变形实现较为复杂, 但事件复杂度依然为 1.5N 阅读全文
posted @ 2014-02-24 17:30 SangS 阅读(622) 评论(0) 推荐(0) 编辑
摘要: 题目任意给定一个正整数 N, 求一个最小的正整数 M (M > 1), 使得 N*M 的十进制表达式中只有 0 和 1.解法1. 枚举0,1能够组成的数字, 可以组成一颗二叉树然后由 BFS 算法最终能够得到目标解. 但时间复杂度太高2. 优化. 考虑对每一个节点加上一个属性, 对 N 求余的值. 假设两个节点X, Y的余相同, 那么由该节点扩展的下一层的 4 个子节点, 分别为 10*X, 10*X+1, 10*Y, 10*Y+1. 由取模的定理知道 10*X MOD N == 10*Y MOD N, 10*X +1 MOD N == 10*Y +1 MOD N假设 X < Y, 阅读全文
posted @ 2014-02-24 16:30 SangS 阅读(169) 评论(0) 推荐(0) 编辑
摘要: 解法1. f(x,y) = f(y, y%x) (y>0) 辗转相除法2. 取模运算较为耗时, 将取模变成相减. 但对极端数据效果很差, 比如 gcd(1000,1)3. 分析公约数的特点. 3.1 若 x,y 均为偶数, 那么 f(x,y) = 2*f(x/2, y/2) 3.2 若 x 为偶数, y 为奇数, 那么 f(x,y) = 2*f(x/2, y) 3.3 若都为奇数, f(x,y) = f(x, x-y) 那么下一步肯定有一个偶数 3.4 这样一来, 时间复杂度下降到 o(log(max(x,y))) 阅读全文
posted @ 2014-02-24 15:41 SangS 阅读(211) 评论(0) 推荐(0) 编辑
摘要: 有限小数和无限循环小数转化成分数比如 0.9 -> 9/100.333(3) -> 1/3解法1. 主要涉及到一个数学公式的计算.2. 对于有限小数, 分子分母求最大公约数即可3. 对于无限循环小数, 第一步是将非循环部分剔除. 仅讨论循环部分.4. 0.b(b.size() = c ==> b.b(b.size()) = c*pow(10, b.size()) ==> 0.b(b.size()) = c*k-c ==> c = (pow(10,b.size()-1)/b 阅读全文
posted @ 2014-02-24 15:32 SangS 阅读(237) 评论(0) 推荐(0) 编辑
摘要: 总结1. 使用加法解决指数问题时, 可用背包问题的变形2. 题目用到的公式和求解 1~N 中 1 出现的次数的公式类似题目1. 给定一个整数 N, 那么 N 的阶乘 N! 末尾有多少个 0 呢2. 求解 N! 的二进制表示中最低位 1 的位置思路1. 第一道题相当于求解 N! 分别是 2^a 和 5 ^b, 第二道题是 2^a2. 公式: Z = [N/5] + [N/5^2] +... [N/5] 表示不大于 N 的数中 5 的倍数贡献一个 5, [N/5^2]表示不大于 N 的数中, 5^2 再贡献一个52. 但第一题有一个可以优化的地方, 因为 b >= 1; ret +=... 阅读全文
posted @ 2014-02-24 14:43 SangS 阅读(202) 评论(0) 推荐(0) 编辑
摘要: singleton 模式又称单例模式, 它能够保证只有一个实例. 在多线程环境中, 需要小心设计, 防止两个线程同时创建两个实例.解法1. 能在多线程中工作但效率不高public sealed class Singleton2 { private Singleton2() { } private static readonly object synObj = new object(); private static Singleton2 instance = NULL; public static Singleton2 instance { get{ lock(synObj) { ... 阅读全文
posted @ 2014-02-24 13:35 SangS 阅读(359) 评论(0) 推荐(0) 编辑
摘要: 要求为类 CMyString 定义赋值运算符函数.类的定义如下class CMyString {public: CMyString(char* pData = NULL; ) CMyString(const CMyString &str); ~CMyString(void);private: char* m_pData;}; 在定义一个赋值运算符时, 需要考虑如下几点1. 需要把返回值得类型声明定义为该类型的引用, 并且在函数结束前返回实例自身的引用 (*this). 只有返回引用才可以连续赋值2. 需要把传入参数的类型声明为常量引用. 形参必须是引用, 否则会编译报错3. 需要判断引 阅读全文
posted @ 2014-02-24 13:13 SangS 阅读(449) 评论(0) 推荐(0) 编辑
摘要: 总结1. Leetcode 上有一道题, 是不用乘除做乘法, 那道题算是背包问题的变形2. 不用加减乘除, 还可以用移位操作3. 将数字转成二进制格式, 然后运用二进制亦或, 移位运算解决 3.1 仅考虑各位相加, 不考虑进位, num1 ^ num2 3.2 仅考虑进位, (num1 & num2) using namespace std;int Add(int num1, int num2) { int sum, carry; do { sum = num1 ^ num2; carry = (num1 & num2) << 1; num1 = sum; num2 阅读全文
posted @ 2014-02-24 10:42 SangS 阅读(291) 评论(0) 推荐(0) 编辑
摘要: 题目要求不能使用乘除法, for, while, if else, switch, case 等关键字思路1. 循环已经命令禁止, 禁用 if, 意味着递归也不能使用. 但即便如此, 我们仍然要围绕循环或递归作文章2. 利用构造函数求解#include using namespace std;class Temp {public: Temp() { ++ N; Sum += N; cout using namespace std;class A;A *arr[2];class A {public: virtual unsigned int Sum(unsigned int n) { ... 阅读全文
posted @ 2014-02-24 10:25 SangS 阅读(226) 评论(0) 推荐(0) 编辑
摘要: 题目从扑克牌中任意抽取出 5 张牌, 判断是不是顺子, 并且大小王可以看成任意的数字思路1. 把大小王当做 0 插入到数组中, 然后对数组排序2. 统计相邻两个数之间的空隙数, 若空隙数大于 0 的个数, 那么不能成为顺子 阅读全文
posted @ 2014-02-24 09:01 SangS 阅读(167) 评论(0) 推荐(0) 编辑
摘要: 题目把 n 个骰子扔到地上, 所有骰子朝上一面的点数之和为 s. 输入 n, 打印出 s 所有可能的值出现的概率.思路1. 基于递归的求解方法. 深度为 n 的 dfs, 相当于求全排列, 时间效率太低2. 基于循环的实现, 有动态规划的思想在里面. dp[n][i] 表示 n 个骰子时, 出现和为 i 的个数. 那么状态转移方程变成 dp[n+1][i] = dp[n+1][i-1]+...dp[n+1][i-6]总结1. 有必要把之前做过的 poj 题目再重新搞一遍, 动规题目的 dp 数组设置方法需要重新回顾 阅读全文
posted @ 2014-02-24 08:55 SangS 阅读(173) 评论(0) 推荐(0) 编辑
摘要: 总结1. 题目为归并排序的变形, 不过我完全没想到2. 在归并排序进行字符组 merge 时, 统计逆序数. merge 后, 两个子数组是有序的了, 下次再 merge 的时候就能以 o(n) 的时间内找到某一个逆序对第二个元素的个数 阅读全文
posted @ 2014-02-24 08:42 SangS 阅读(212) 评论(0) 推荐(0) 编辑
摘要: 思路1. 经典解法是用环形链表模拟圆圈, 然后每次减少一个节点. 时间复杂度为 o(mn), 空间复杂度为 o(n)2. 转化成数学问题, 递推公式决定下一个元素. 时间复杂度为 o(n), 空间复杂度为 o(1) 阅读全文
posted @ 2014-02-24 00:31 SangS 阅读(147) 评论(0) 推荐(0) 编辑
摘要: 题目100 可以由9~16, 或者 18 ~ 22 组成思路1. 与 LeetcodeContainer With Most Water 有些类似, 依然是平移题目. 但这道更加复杂2. 初始设置 small 为 1, big 为 2 ,然后平移直到等于目标值. 到 small >= big 时结束 阅读全文
posted @ 2014-02-24 00:28 SangS 阅读(169) 评论(0) 推荐(0) 编辑
摘要: 题目1. 翻转单词student. a am I 转换成I am a student.2. 字符串左旋abba 1 转成bbaa总结1. 先对每个单词旋转, 再整齐旋转2. 先翻转一半, 再全部旋转3. 这类似看过多次了, 考研数据结构部分算法题 阅读全文
posted @ 2014-02-24 00:19 SangS 阅读(211) 评论(0) 推荐(0) 编辑