笔试算法题(19):判断两条单向链表的公共节点 & 字符集删除函数
出题:给定两个单向链表的头结点,判断其是否有公共节点并确定第一个公共节点的索引;
分析:
- 由于是单向链表,所以每个节点有且仅有一个后续节点,所以只可能是Y型交叉(每条链表中的某个节点同时指向一个公共节点,并共享后面的所有节点)。首先计 算每条链表的长度,m和n(m>n);
- 然后设定两个指针A和B分别指向两条链表头(A指向较长链表),让A先走(m-n)步,然后A和B同时前进, 当(A==B)成立的时候A和B当前指向的节点就是第一个公共节点;
解题:
struct Node {
int v;
Node *next;
}; Node* findFirstCommon(Node *first, Node *second) {
/**
* 首先计算first和second各自的长度
* 当任一链表长度为0时返回NULL
* */
Node *firstT=first, *firstP=NULL;
Node *secondT=second, *secondP=NULL;
int firstL=, secondL=;
while(firstT!=NULL) {
firstL++;
firstP=firstT;
firstT=firstT->next;
}
while(secondT!=NULL) {
secondL++;
secondP=secondT;
secondT=secondT->next;
}
/**
* 判断是否存在公共节点,也就是长度不为0并且最后一个
* 节点相同
* */
if(firstL== || secondL==)
return NULL;
if(firstP!=secondP)
return NULL;
/**
* 同步链条链表的指针,使得firstT和secondT指向的
* 位置距离链表最后一个节点有相同的距离
* */
int difference=;
if(firstL>secondL) {
difference=firstL-secondL;
firstT=first;
secondT=second;
for(int i=;i<difference;i++)
firstT=firstT->next;
} else if(firstL<secondL) {
difference=secondL-firstL;
firstT=first;
secondT=second;
for(int i=;i<difference;i++)
secondT=secondT->next;
}
printf("%d, %d",firstT->v,secondT->v);
/**
* 同步指针之后,同时向前移动,firstT==secondT的时候
* 表示第一个公共节点,由于已经现在已经确定肯定有公共
* 节点,所以可以这样判断
* */
while(firstT!=NULL && secondT!=NULL) {
if(firstT==secondT)
break;
firstT=firstT->next;
secondT=secondT->next;
}
return firstT;
}
出题:实现字符集删除函数,要求在第一个字符串first中删除所有在第二个字符串second中出现的字符;
分析:
- 解法1:可以使用暴力解法,遍历first中每一个字符,并与second中的字符比较,如果有相同则删除,然后比较first中下一个字符,时间复杂度为O(mn);
- 解法2:由于是判断某一个字符是否存在的情况,所以可以使用Hash Table,将first映射到256大小的HT中,然后将second也映射过去,一旦遇到已经存在的字符,则删除;最后遍历first并比较HT中的 结果然后输出。此方法时间复杂度为O(N),但是需要使用额外内存保存最终结果,并不会改变原有的字符串;
- 解法3:由于解法2需要使用额外的空间保存字符串,当字符串较大的时候不可取;所以需要考虑如何快速的在原有字符串上进行字符删除,可以考虑两个指针 left和right,使用right对first字符串进行遍历并通过hashTable(仅仅映射second字符串)判断是否需要删除当前字符,如 果需要进行删除则right指针直接跳过,如果不需要删除则将*left=*right,然后处理下一个字符,所以left指针记录了最终保存的字符串, 这样可以在O(N)的时间内完成,并且不需要任何额外内存;
解题:
void charSetDelete(char *first, char *second) {
/**
* 由于char集一般为256,所以初始化一个bool数组
* 并且缺省所有的值都为false
* */
bool hashTable[];
for(int i=;i<;i++)
hashTable[i]=false;
/**
* 首先映射first字符串,true表示需要输出
* 然后映射second字符串,false表示不需要输出
* */
char *firstT=first, *secondT=second;
while(*firstT != '\0') {
hashTable[*firstT]=true;
firstT++;
}
while(*secondT != '\0') {
hashTable[*secondT]=false;
secondT++;
}
/**
* 通过hashTable对应元素是true还是false进行
* 输出判断
* */
firstT=first;
printf("\n");
while(*firstT != '\0') {
if(hashTable[*firstT])
printf("%c",*firstT);
firstT++;
}
printf("\n");
} void betterVersion(char *first, char *second) {
bool hashTable[];
for(int i=;i<;i++)
hashTable[i]=false;
/**
* hashTable用于记录second中指定需要
* 删除的字符集合
* */
char *secondT=second;
while(*secondT!='\0') {
hashTable[*secondT]=true;
secondT++;
}
/**
* 使用两个指针完成字符串的删除移动操作
* 仅当right索引的字符不需要删除的时候
* 才将其复制给left指向的位置
* */
char *left=first, *right=first;
while(*right!='\0') {
if(!hashTable[*right]) {
*left=*right;
left++;
}
right++;
}
*left='\0';
char *temp=first;
while(*temp!='\0')
printf("%c",*temp++);
} int main() {
char first[]="abcdefgghjjjj";
char second[]="agj";
charSetDelete(first, second);
betterVersion(first, second);
return ;
}
笔试算法题(19):判断两条单向链表的公共节点 & 字符集删除函数的更多相关文章
- 笔试算法题(13):反转链表 & 左旋转字符串
出题:反转链表(递归和非递归解法): 分析:有递归跟非递归实现,注意对原始链表头节点的处理,因为其他节点都指向下一个节点,其需要指向NULL: 解题: struct Node { int v; Nod ...
- 算法题 19 二叉平衡树检查 牛客网 CC150
算法题 19 二叉平衡树检查 牛客网 CC150 实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1. 给定指向树根结点的指针TreeNode* ro ...
- Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解
Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全 Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...
- POJ1269:Intersecting Lines(判断两条直线的关系)
题目:POJ1269 题意:给你两条直线的坐标,判断两条直线是否共线.平行.相交,若相交,求出交点. 思路:直线相交判断.如果相交求交点. 首先先判断是否共线,之后判断是否平行,如果都不是就直接求交点 ...
- C# 判断两条直线距离
本文告诉大家获得两条一般式直线距离 一般式的意思就是 Ax+By+C=0" role="presentation">Ax+By+C=0Ax+By+C=0 如果有两个 ...
- 2018-7-31-C#-判断两条直线距离
title author date CreateTime categories C# 判断两条直线距离 lindexi 2018-07-31 14:38:13 +0800 2018-05-08 10: ...
- 笔试算法题(27):判断单向链表是否有环并找出环入口节点 & 判断两棵二元树是否相等
出题:判断一个单向链表是否有环,如果有环则找到环入口节点: 分析: 第一个问题:使用快慢指针(fast指针一次走两步,slow指针一次走一步,并判断是否到达NULL,如果fast==slow成立,则说 ...
- 笔试算法题(54):快速排序实现之单向扫描、双向扫描(single-direction scanning, bidirectional scanning of Quick Sort)
议题:快速排序实现之一(单向遍历) 分析: 算法原理:主要由两部分组成,一部分是递归部分QuickSort,它将调用partition进行划分,并取得划分元素P,然后分别对P之前的部分和P 之后的部分 ...
- 笔试算法题(25):复制拥有多个指针的链表 & 判断二元树B是否为A的子树
出题:定义一个复杂链表:在单向链表的基础上,每个节点附加一个指向链表中其他任意节点的指针sibling,实现CNode* Clone(Cnode *head)函数复制这个复杂链表: 分析: 解法1:将 ...
随机推荐
- UVa 12716 && UVaLive 6657 GCD XOR (数论)
题意:给定一个 n ,让你求有多少对整数 (a, b) 1 <= b <= a 且 gcd(a, b) = a ^ b. 析:设 c = a ^ b 那么 c 就是 a 的约数,那么根据异 ...
- CodeForces 723B Text Document Analysis (水题模拟)
题意:给定一行字符串,让你统计在括号外最长的单词和在括号内的单词数. 析:直接模拟,注意一下在左右括号的时候有没有单词.碰到下划线或者括号表示单词结束了. 代码如下: #pragma comment( ...
- FOJ2252:Yu-Gi-Oh!
传送门 题意 略 分析 枚举合成ab的数量,在此基础上合成bc和ac,复杂度\(O(n)\) trick 代码 #include<cstdio> #include<algorithm ...
- $Edmonds-Karp$[网络流]
\(原题戳这里\) >最大流最小割定理$(Maximum Flow, Minimum Cut Theorem): $ 网络的最大流等于最小割 具体的证明分三部分 1.任意一个流都小于等于任意一个 ...
- 《windows核心编程系列》二十一谈谈基址重定位和模块绑定
每个DLL和可执行文件都有一个首选基地址.它表示该模块被映射到进程地址空间时最佳的内存地址.在构建可执行文件时,默认情况下链接器会将它的首选基地址设为0x400000.对于DLL来说,链接器会将它的首 ...
- ACM复习专项
资料整理 ACM训练营 邝斌的ACM模板 牛客网哈理工ACM教学视频 视频网盘资料(密码:kntr) 1. 训练阶段 第一阶段:练习经典常用算法 (本周任务) 1. 最短路(Floyd.Dijstra ...
- Word排版技巧
点击打开链接 # 整体布局 ## 页面布局 如果是新建一个Word文件,这里「页面布局」一般不用设置了: 文字方向:从左到右: 页边距:普通(日常使用建议用适中或窄,节约用纸,提交的论文报告什么才用普 ...
- 225 Implement Stack using Queues 队列实现栈
Implement the following operations of a stack using queues. push(x) -- Push element x onto stack.pop ...
- D. Arpa's weak amphitheater and Mehrdad's valuable Hoses 分组背包模板题
http://codeforces.com/problemset/problem/742/D 并查集预处理出所有关系. 一开始的时候,我预处理所有关系后,然后选择全部的时候,另起了一个for,然后再判 ...
- Codeforces Round #235 (Div. 2) D (dp)
以为是组合,后来看着像数位dp,又不知道怎么让它不重复用..然后就没思路 了. 其实状压就可以了 状压是可以确定一个数的使用顺序的 利用01也可以确定所有的数的使用以及不重复 dp[i+1<&l ...