[读书笔记]编程之美(三)

3.1字符串移位包含的问题

  • 问题:给定两个字符串s1和s2,要求判定s2是否能够被s1做循环移位(rotate)得到的字符串包含。例如,给定s1=AABCD和s2=CDAA,返回true;给定s1=ABCD和s2=ACBD,返回false。
  • 思路:str = s1 + s1,判断s2是否在str中。这种要申请新的空间,或者用指针做一个循环两次,这样就不用申请新的空间了。

3.2电话号码对应英语单词

  • 问题:(1)尽可能快地从这些字母组合中找到一个有意义的单词来表述一个电话号码呢?如:可以用单词“computer”来描述号码26678837。
    (2)对于一个电话号码,是否可以用一个单词来代表呢?怎样才是最快的方法呢?
  • 思路:问题一:直接循环法,遍历出所有的单词
while(true)
{for(int i = 0; i < TelLength; i++)printf("%c", c[number[i]][answer[i]]);printf("\n");int k = n - 1;while(k >= 0){if(answer[k] < total[numbeer[k]] - 1){answer[k]++;break;}else{answer[k] = 0;k--;}}if(k < 0)break;
}

问题二:
解法一:全部计算出来,然后去匹配字典。适用于查询次数较少的情况。
解法二:如果次数较多,直接把字典里面的所有单词都按照这种转换规则转换为数字,并存在文件中,使之成为另一本数字字典。

3.3计算字符串的相似度

  • 问题:对于不同的字符串。对于不同的字符串,我们希望能够有办法判断其相似程度,操作方法使得不同的字符串变得相同,
    1.修改一个字符。2.增加一个字符。3.删除一个字符。计算他们之间的距离。
  • 思路:1、一步操作之后,再将A[2,…,lenA]和B[1,…,lenB]变成相同字符串;
    2、一步操作之后,再将A[1,…,lenA]和B[2,…,lenB]变成相同字符串;
    3、一步操作之后,再将A[2,…,lenA]和B[2,…,lenB]变成相同字符串;
  • 核心代码:
int CalculateStringDistance(string strA, int pABegin, int pAEnd, string strB, int pBBegin, int pBEnd)
{if(pABegin > pAEnd){if(pBBegin > pAEnd)return 0;elsereturn pBEnd - pBBegin + 1;}if(pBBegin > pBEnd){if(pABegin > pAEnd)return 0;elsereturn pABegin - pABegin + 1;}if(strA[pABegin] == strB[pBBegin]){return CalculateStringDistance(strA,pABegin+1,pAEnd,strB,pBBegin+1,pBEnd);}else{int t1 = CalculateStringDistance(strA,pABegin,pAEnd,strB,pBBegin+1,pBEnd);int t2 = CalculateStringDistance(strA,pABegin+1,pAEnd,strB,pBBegin,pBEnd);int t3 = CalculateStringDistance(strA,pABegin+1,pAEnd,strB,pBBegin+1,pBEnd);return minValue(t1,t2,t3) + 1;}
}

需要注意的是在递归的过程中,有些数据被重复计算了。需要一些保存一些中间变量。

3.4从无头单链表中删除节点

  • 思路:狸喵换太子

3.5最短摘要的生成

  • 问题:假定给定的已经是经过网页分词之后的结果,词语序列数组为W。其中W[0],W[1],…,W[N]为一些已经分好的词语。
    假定用户输入的搜索关键词为数组Q。其中Q[0],Q[1],…,Q[m]为所有输入的搜索关键词。
    这要,生成的最短摘要实际上就是一串相互联系的分词序列。比如从W[i]到W[j],其中,0< i < j <= N。包含了所有的关键字。
  • 分析:两个指针依次相互扫描,依次扫描下去,在w中找到所有包含q的序列,并且维护并找出其中最小的值。
  • 核心代码:
while(true)
{//假设包含所有的关键词,并且后面的指针没有越界,往后移动指针while(!isAllExisted() && pEnd < nLen)pEnd++;//假设找到一段包含所有关键词信息的字符串while(isAllExisted()){if(pEnd - pBegin < nTargetLen){nTargetLen = pEnd - pBegin;nAbstractBegin = pBegin;nAbstractEnd = pEnd - 1;}pBegin++;}if(pEnd >= N)Break;
}

3.6编程判断两个链表是否相交

  • 问题:给两个单向链表的头指针,判断两个链表是否相交,两个链表不带环,要是带环又如何?

  • 1.判断链表1是否有环,并记录其长度L1,尾节点b1(无环),环入口点a1(有环)

  • 2.判断链表2是否有环,并记录其长度L2,尾节点b2(无环),环入口点a2(有环)
  • 3.若一个有环,另一个没环,则判断不相交,结束
  • 4.若两个都没环,则两个尾节点一点是一样的,所以比较两个尾节点是否相同。若不相同则判断不相交,结束;若相同,则到6。
  • 5.若两个都有环,有如下图三种情况:a1与a2不相等,且不在一个环中,则不相交,结束;a1等于a2,跳到6;a1与a2不相等,但在一个环中,对于链表1来说a1是它的相交首节点,对于链表2来说a2是它的相交首节点。
  • 6.对于两个链表重头开始遍历,长链表节点先出发前进(Max(L1,L2)-Min(L1,L2))步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。

3.7队列中去最大值操作问题

  • 问题:假设有这样一个拥有3个操作的队列:
    1.EnQueue(v):将v加入队列中
    2.DeQueue:使队列中的队首元素删除并返回此元素
    3.MaxElement:返回队列中的最大元素(O(1))
  • 思路:
    队列是遵守“先入先出”原则的一种复杂的数据结构。底层的数据结构可以使用数组或者栈来实现。
    解法一:数组或队列,Max时间复杂度O(N)。
    解法二:最大堆来维护队列中的元素,max(O(1)),入队出队O(lgN)
    解法三:这里我们自定义了一个栈,并在其中维护了一个最大值序列,来保证Max操作的时间复杂度为O(1)。然后用这两个栈,形成一个队列。

3.8求二叉树节点的最大距离

  • 问题:如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义“距离”为两个节点之间边的个数。写一个程序求一颗二叉树中相距最远的两个节点之间的距离。
  • 思路:相据最远的两个节点一定是叶子节点。
  • 核心代码:
struct NODE{NODE* pLeft;NODE* pRight;int nMaxLeft;int nMaxRight;char chValue;
};
int nMaxLen = 0;void FindMaxLen(NODE* pRoot)
{//遍历到叶子节点,返回if(pRoot == nullptr)return;//如果右子树为空,那么该节点的右边最长距离为0if(pRoot->pRight == nullptr)pRoot->nMaxRight = 0;if(pRoot->pLeft == nullptr)pRoot->nMaxLeft = 0;//如果左子树不为空,递归寻找左子树最长距离if(pRoot->pLeft != nullptr)FindMaxLen(pRoot->pLeft);if(pRoot->pRight != nullptr)FindMaxLen(pRoot->pRight);//计算左子树最长节点距离if(pRoot -> pLeft != nullptr){int nTempMax = 0;if(pRoot -> pLeft -> nMaxLeft > pRoot -> pLeft -> nMaxRight)nTempMax = pRoot -> pLeft -> nMaxLeft;elsenTempMax = pRoot -> pRight -> nMaxRight;pRoot -> nMaxLeft = nTempMax + 1;}//计算右子树最长节点距离if(pRoot -> pRight != nullptr){int nTempMax = 0;if(pRoot -> pRight -> nMaxLeft > pRoot -> pRight -> nMaxRight)nTempMax = pRoot -> pRight -> nMaxLeft;elsenTempMax = pRoot -> pRight -> nMaxRight;pRoot -> nMaxRight = nTempMax + 1;}//更新最长距离if(pRoot -> nMaxLeft + pRoot -> nMaxRight > nMaxLen)nMaxLen = pRoot -> nMaxLeft + pRoot -> nMaxRight;
}

3.9重建二叉树

  • 问题:已经有了前序遍历和中序遍历的结果,希望通过一个算法重建这棵树。
  • 核心代码:
#include <bits/stdc++.h>
using namespace std;#define TREELEN 6//树节点
struct NODE{NODE* pLeft;NODE* pRight;char chValue;
}; void ReBuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot)
{//检查边界条件if(pPreOrder == NULL || pInOrder == NULL){return;}//获得前序遍历的第一个节点NODE* pTemp = new NODE;pTemp -> chValue = *pPreOrder;pTemp -> pLeft = NULL;pTemp -> pRight = NULL;//如果节点为空,把当前节点复制到根节点if(*pRoot == NULL)*pRoot = pTemp;//如果当前树长度为1,那么已经是最后一个节点if(nTreeLen == 1)return;//寻找子树长度char* pOrgInorder = pInOrder;char* pLeftEnd = pInOrder;int nTempLen = 0;//找到左子树的结尾while(*pPreOrder != *pLeftEnd){if(pPreOrder == NULL || pLeftEnd == NULL)return;nTempLen++;//记录临时长度,以免溢出if(nTempLen > nTreeLen)break;pLeftEnd++; }//寻找左子树长度int nLeftLen = 0;nLeftLen = (int)(pLeftEnd - pOrgInorder);//寻找右子树长度int nRightLen = 0;nRightLen = nTreeLen - nLeftLen - 1;//重建左子树if(nLeftLen > 0) ReBuild(pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot) -> pLeft));if(nRightLen > 0)ReBuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen + 1, nRightLen, &((*pRoot) -> pRight));
}void InOrder(NODE* root)
{if(root == NULL)return;InOrder(root->pLeft);cout<<root->chValue<<endl;InOrder(root->pRight);
}int main()
{char pre[TREELEN] = {'a','b','d','c','e','f'};char in[TREELEN] = {'d','b','a','e','c','f'};NODE* pRoot = NULL;ReBuild(pre,in,TREELEN, &pRoot);InOrder(pRoot);
}

3.10分层遍历二叉树

  • 问题:给定一颗二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右。
  • 思路:用一个vector存储每一层的节点,从头出一个从尾部加两个。

3.11程序改错

  • 问题:二分查找源码
  • 核心代码:
int bisearch(char** arr, int b, int e, char* v)
{int minIndex = b, maxIndex = e, midIndex;while(minIndex < maxIndex - 1){midIndex =minIndex + (maxIndex - minIndex) / 2;if(strcmp(arr[midIndex], v) <= 0)minIndex = midIndex;elsemaxIndex = midIndex;}if(!strcmp(arr[maxIndex] , v))return maxIndex;else if(!strcmp(arr[minIndex] , v))return minIndex;elsereturn -1;
}

4.1金刚坐飞机

  • 问题:金刚插队随意找了一个座位坐了下来(1)其他乘客也随意的坐下,并坚决不让座给其他乘客。
    (2)如果自己的位置已经被别人占了,就随机选择另一个位置坐下。
  • 思路:(1)F(i) = 1/N
    (2)全概率公式

4.2瓷砖覆盖地板

  • 问题:能否用1 * 2的瓷砖去覆盖N * M的地板呢?
  • 思路:斐波那契数列加强版?

4.3买票找零

  • 问题:每张球票为50元,现在有2n人排队,n个人手持50,n个人100,有多少种正确的排队方式?
  • 思路:卡特兰数h(n)=C(2n,n)/(n+1) (n=0,1,2,…)
  • 核心代码:
int validPermutation(int n)
{  long long lDemonitator = 1;  for(int i = 1 ; i <= n; i++)  {  lDemonitator *= i;  }  long long lMolecule = 1;  for(int i = 2*n ; i > n ; i--)  {  lMolecule *= i;  }  return (int) (lMolecule/((n+1) * lDemonitator));//合法序列的总个数 = 1/(n+1) Cn 2n
}  
  • 相似问题:
  • 1.括号化问题。
    矩阵链乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n)种)
  • 2.出栈次序问题。
    一个栈(无穷大)的进栈序列为1,2,3,..n,有多少个不同的出栈序列?
    类似:有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)
  • 3.将多边行划分为三角形问题。
    将一个凸多边形区域分成三角形区域的方法数?
    类似:一位大城市的律师在她住所以北n个街区和以东n个街区处工作。每天她走2n个街区去上班。如果她
    从不穿越(但可以碰到)从家到办公室的对角线,那么有多少条可能的道路?
    类似:在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?
  • 4.给顶节点组成二叉树的问题。
    给定N个节点,能构成多少种形状不同的二叉树?

4.4点是否在三角形内

  • 问题:二维坐标系,一直三角形定点的坐标,对于坐标系任意一点,判断该点是否在三角形内。
  • 思路:(1)直观的转化为比较三角形的面积。可以利用海伦公式,已知三角形边长为a,b,c,p=(a+b+c)/2。三角形面积为(p-a) * (p-b) * (p-c) * p
    (2)由于三角形是凸的,所以如果有一个点D在三角形ABC内,那么沿着三角形的边界逆时针走,点D一定保持在边界的左边,也就是说点D在边AB、BC、CA左边。
  • 核心代码:
struct point
{double x,y;
};
double Product(point A, point B, point C)
{return (B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y);
}
//A,B,C在逆时针方向 如果D在ABC之外,返回false,否则返回true
bool isInTriangle(point A, point B, point C, point D)
{if(Product(A, B, D) >= 0 && Product(B,C,D) >= 0 && Product(C,A,D) >= 0)return true;return false;
}

4.5磁带文件存放优化

  • 问题:假设其中一盘磁带上有n份文件,他们的长度分别为L[0],L[1],…,L[n-1],且访问的概率为P[0],P[1],…,P[n-1]。请问怎样安排它们在磁带上的存储顺序最好?
  • 思路:判断出P[i]/L[i]的值从大到小排列即为最佳存储顺序。

4.6桶中取黑白球

  • 问题:有一个桶,里面有白球、黑球各100个,人们必须按照以下规则把求取出来:
    1、每次从桶中里面拿两个球;
    2、如果是两个同色的球,就再放一个一个黑球; 1 ^ 1 = 0 0 ^ 0 = 0
    3、如果是两个异色的球,就再放一个白球;1 ^ 0 = 1
    问:最后桶里面只剩下一个黑球的概率是多少?
  • 思路:由异或运算满足结合律可知,取球的过程相当于把里面所有的球 进行抑或操作。

4.7蚂蚁爬杆

  • 问题:有一根木杆27厘米,在3、7、23厘米这几个位置各有一只蚂蚁。木杆很细,不能同时通过两只蚂蚁。开始时,蚂蚁的头朝左、右是任意的,他们只会朝前走或掉头,不会后退,。当两只蚂蚁碰头的时候,他们会同时掉头朝相反的方向走。
  • 思路:题目有陷阱,两只蚂蚁碰头,不会发生任何事。这样,程序只需遍历所有蚂蚁,把每个蚂蚁走出木杆的最长时间,最短时间分别求出来。

4.8三角形测试用例

4.9数独

  • 问题:一共有多少种不同的数独解答呢?其中有多少种是独立的解答呢?如果我们要用一个简单的字符串来表示各种数独。如何在保证一一对应的基础上,让字符串的长度最短?
  • 思路:这种题,明确问题是什么,不要着急一开始就做题。“独立“是什么意思,也不一定要求出最精确的答案,重要的是分析的过程。

4.10数字哑谜和回文

  • 问题:(1)神奇的9位数。能不能找出符合如下条件的9位数:
    这个数字包括了1~9这9个数字;这9位数的前n位都能被n整除,若这个数表示为abcdefghi,则ab可以被2整除,abc可以被3整除…abcdefghi可以被9整除。
    (2)有这样一个乘法算式:人过大佛寺 * 我 = 寺佛大过人
  • 思路:举例,有规律的举例。对于问题1,我们把”整除“的条件列出来。对于问题二、我、不会超过5

4.11扫雷游戏的概率

null A null
null 1 null
null B null
null 2 null
null C null

- 问题一:当这个游戏有40个地雷没有被发现的时候,A、B、C三个方块有地雷的概率(P(A),P(B),P(C))各是多少?
- 问题二:这个游戏局面一共有16*16 = 256个方块,P(A),P(B),P(C)的相互大小关系和当前局面中地雷的总数有联系么?比如,当地雷总数从10个逐渐变化到240个,P(A),P(B),P(C)的三条曲线是如何变化的?他们会不会相交。
- 思路:为什么这一次的概率会和总雷数相关呢?问题就在于中间的方块中的雷数不确定。按照这个思路,题目中的问题就迎刃而解了。

此题适合用MATLAB解答是因为要求作出概率曲线. 如果地雷总数一定, 其实手算也很容易. 根据数字1和2的提示, 图示3×5方格中至少2个地雷, 至多3个地雷. 记为扫雷游戏中格子总数, 为地雷总数. 分两种情况考虑.图中共2个地雷时可能的情况总数: .
A处为地雷的情况总数: .
B处为地雷的情况总数: .
C处为地雷的情况总数: .
图中共3个地雷时可能的情况总数: .
A处为地雷的情况总数: .
B处为地雷的情况总数: .
C处为地雷的情况总数: .
要求的概率可以简单地相除得到:

[读书笔记]编程之美(三)相关推荐

  1. 《编程珠玑,字字珠玑》45678读书笔记——编程技巧

    写在最前面的 就像上一篇文章说的,"编程永远是后话"!在有了可靠的问题分析过程和数据结构的选择,能正确运行的"二分搜索"代码出现之前,把其主要的思路先在草稿上实 ...

  2. 读书笔记:汇编语言 第三版 王爽 清华出版社 章六 章七 章八 章九 章十

    第六章 包含多个段的程序6.0 概述合法地通过操作系统取得的空间都是安全的操作系统不会让多个程序之间发生空间冲突程序向操作系统获得空间的方法程序加载时分配在程序中定义各种段程序运行时分配通过指令向操作 ...

  3. 读书笔记:汇编语言 第三版 王爽 清华出版社 前言 章一 章二 章三 章四 章五

    汇编语言 第三版 王爽 清华出版社文档记录创建 2020年8月9日15:21:11初稿完成 2020年9月5日15:38:22前言汇编语言,CPU提供的机器指令的助记符的集合不同处理器,机器指令可能不 ...

  4. 《阿里巴巴开发手册》读书笔记-编程规约

    Java编程规约 命名风格 常量定义 代码格式 OPP规约 日期时间 集合处理 并发处理 控制语句 注释规约 前后分离 其它注意 命名风格 类名使用UpperCamelCase风格,但下列情形除外: ...

  5. 读书笔记——数学之美

    读完数学之美,收获很多,在这里我对我的收获进行简要的总结,这些总结中不包括对具体算法和模型的详解,详解请参考其他资料,这里只进行简要的总结. 1 文字和语言 vs 数字和信息 文字.数字.语言和数学是 ...

  6. 编程之美-三盏灯的问题

    在编程之美中,有这么一个问题,房间中有三盏灯,房间外有三个开关,分别控制这三盏灯, 只能进入房间一次,怎么判断三盏灯分别由哪个开关控制; – 首先的想法是,进入房间一次,代表一个bit,而一个bit最 ...

  7. 读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第二部分)...

    下面再来看书,去理解书上说的Handler classes就简单多了,我们大概过一下. 假设我们要写一个Person类,如下: 1 class Person 2 { 3 private: 4 stri ...

  8. 读书笔记--《初等数论(第三版)》(闵嗣鹤 严士健 编)第三章 同余(Part I)

    索引 同余基础 一.同余定义 Th3.1.1:∀a,b∈Z,a,b\forall a,b\in \mathbb{Z},\text{ }a,b∀a,b∈Z, a,b对模mmm同余⇔\Leftrighta ...

  9. 读书笔记之呼吸 [美] 特德·姜

    呼吸 [美] 特德·姜 商人和炼金术士之门 没有什么能抹掉过去.但你可以忏悔,可以赎罪.你可以得到宽恕.只有这些,但这已经足够了. 呼吸 得以存在便是一个奇迹,能够思考就是一件乐事. 前路迢迢 你无法 ...

最新文章

  1. IT从业者(程序员等)之强身健体-武术
  2. php动态写入vue,Vue自定义动态组件使用详解
  3. 如何判断一个常量是废弃常量,一个类是无用类
  4. jvm开源_开源JVM Sampling Profiler
  5. leetcode 376. 摆动序列 思考分析
  6. spring boot 分布式锁组件 spring-boot-klock-starter
  7. 26.如何实现关机时清空页面文件:
  8. 使用计算机系统管理商品存货,ERP管理系统中编码的意义
  9. Android 怎么退出整个应用程序?[转]
  10. P1001 蓝桥杯算法提高-用字符串处理大数乘法
  11. C#代码与javaScript函数的相互调用(转)
  12. python自控_怎么自学python,大概要多久?
  13. 本科生、研究生查询框架
  14. 17SWFObject使用
  15. java 多线程 银行排队_3.采用多线程模拟银行排队叫号
  16. Qt 运行时不显示图标
  17. 苹果描述文件服务器证书无效,22.iOS企业版证书、描述文件过期问题解决
  18. search函数和search_n()函数
  19. catti二级笔译综合能力真题_二级笔译CATTI近十年真题及参考答案
  20. 爬虫:Scrapy分类爬取苏宁易购书城

热门文章

  1. 多任务——Cross-stitch
  2. 适用于typecho的百度自动收录链接提交插件及代码操作,解放双手,再也不用手动提交收录了!
  3. jquery 特效 地址
  4. 中国粘胶纤维市场消费量调研及投资商机研究报告2022-2028年
  5. Java WebSocket实现网络聊天室(群聊+私聊)
  6. 《Automatic Estimation and Removal of Noise from a Single Image》阅读笔记
  7. Windows重装win8,Mac安装win7双系统
  8. LOL种刀妹如何对线盖伦?
  9. Windows中安装MinIO文件系统
  10. Win7下编译mosquitto源码