编程之美3-结构之法-字符串及链表的探索

1、字符串移位包含问题:给定两个字符串s1s2,要求判定s2是否被s1做循环移位得到

解法一:对s1进行移位,再进行判定

解法二:s1s1字符串包含了s1循环移位的所有可能性,只要检测s2是否为s1s1的子串即可,牺牲空间换时间。

解法三:不需要额外空间?解决这个问题。可以用指针的方法做到

  1. int ptr_contain(char *src, char *des){  
  2.     char *p = NULL;  
  3.     char *q = NULL;  
  4.     char *r = NULL;  
  5.     p = q = src;  
  6.     r = des;  
  7.     char *tmp = NULL;  
  8.       
  9.     while(*p != '\0' )  
  10.     {  
  11.         while (*p != *r)  
  12.             p++;  
  13.         tmp = p;  
  14.         tmp++;  
  15.         while(*(++r) != '\0')  
  16.         {  
  17.             if(*(++p) == '\0')  
  18.                 p = q;  
  19.             if(*r != *p)  
  20.             {   
  21.                 r = des;  
  22.                 p = tmp;  
  23.                 break;  
  24.             }  
  25.         }  
  26.         if(*r == '\0')  
  27.             return 1;  
  28.   
  29.     }  
  30.       
  31.     return 0;  
  32. }  


2、电话号码对应英文单词,例如2对应abc3对应def,输入一串数字,找到对应的单词。

解法一:构造排列树,将所有可能结果输出,然后跟单词集合比对

解法二:递归方法,找到所有可能的结果

解法三:将字典从单词转换为数字串,查询时只需要使用数字串跟数字词典进行比对,对于多次查询适应。


3、计算字符串的相似度,给定任意两个字符串,计算他们相似度。字符串距离

解法:将问题转化为小问题,如果两个字符串相同,则需要计算a[2,....n]b2,...,n】的距离即可。若不同,则进行变换,删除ab中的第一个字符串,或者修改ab中的第一个字符串,或者增加字符。由于修改字符串或者增加字符串的行为可以理解为删除ab1个,或者两个都删除,因此只需计算一边删除一个,或者两个都删除。由此可以得到一个递程序。

为了减少计算,可以将计算结果保存在数组中


4、从无头链表中删除节点(不是第一个也不是最后一个)

解法:可以将下一个节点覆盖本节点,然后删去下一个节点


5、最短摘要生成

给定一个已经分好词的词语数组W[0]W[1]...,给定一个查询关键词数组Q[0],Q[1]...

解法一:从w中遍历,找到一个包含q的最短序列,记录长度,然后从w的第二个元素重新计算,复杂度ON^2*M

解法二:基于一的优化,不用每次向后移动一位,而是移到第一个q中元素出现的后面,然后移动尾指针,直到有一个在数列q中的元素出现


6、判断两个链表是否相交

--变形判断一个链表是否有环: 两个指针用不同的步长进行遍历,若有相交,则存在环

--找到这个环的起始点:两个指针交点一定在环上,从该交点断开环,就成了两个链表相交问题。


7、队列中取最大值操作问题


8、求二叉树中节点的最大距离

解法:两个距离最大的节点一定是叶子节点,可以采用动态划归的方法,先计算每个子树中距离最大的两个节点,并记录下他们的距离d1,以及其中深度最深的节点到子树根的距离h1,这个子树的父亲节点的最大距离为max{d1,d2,h1+h2+2},因为之需要遍历所有节点1次,因此复杂度为O[V]– 1V是点的集合.

定义的节点信息中保存了左右子树的最长距离,使用全局变量记录最长节点距离。


优化:以上解法有三个缺点:1、加入侵入式数据,即每个节点多加入的信息量:左右节点最长距离. 2、使用全局变量,使得多个线程无法同时计算。3、代码复杂,条件判断多

改进,设计独立的结构,保存每个子树的最长深度,和最大节点距离,然后在计算长度的函数中返回这个结构体。

#include <iostream>
using   namespace   std;
struct   NODE
{
     NODE *pLeft;
     NODE *pRight;
};
struct   RESULT
{
     int  nMaxDistance;
     int  nMaxDepth;
};
RESULT GetMaximumDistance(NODE* root)
{
     if  (!root)
     {
         RESULT empty = { 0, -1 };   // trick: nMaxDepth is -1 and then caller will plus 1 to balance it as zero.
         return  empty;
     }
     RESULT lhs = GetMaximumDistance(root->pLeft);
     RESULT rhs = GetMaximumDistance(root->pRight);
     RESULT result;
     result.nMaxDepth = max(lhs.nMaxDepth + 1, rhs.nMaxDepth + 1);
     result.nMaxDistance = max(max(lhs.nMaxDistance, rhs.nMaxDistance), lhs.nMaxDepth + rhs.nMaxDepth + 2);
     return  result;
}

9、重建二叉树


10、分层遍历二叉树

使用游标记录每一层的开始和结尾,这样就不需要额外开辟空间,记录每一个点所在层次。也可以选择在队列中插入元素作为分隔


11、程序改错

注意:程序mid= (max+min)/2,有可能因为max+min导致溢出,可以写成min= min + (max-min)/2

二分查找,循环结束的条件应该为min<max-1否则可能进入死循环,例如23



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值