目录
201.数组al[O,mid-l]和al[mid,num-l],都分别有序。将其 merge成有序数组al[O,num-1],要求空间复杂度0(1).
203.将单向链表reverse,如ABCD变成DCBA,只能搜索链表一 次.
204. A,B,C,D四个进程,A向Buf里面写数据,B,C,D向Buf里面读 数据,当A写完,且B,C,D都读一次后,A才能再写.用PV操作实 现.
209. if [$2 -a $2 = "test"]中-a 是什么意思?
211. 模式串的长度是m,主串的长度是n(m),使用kmp算法>
213. C++ 智能指针 shared_ptr、weak ptr 的实现.
215. 智能指针是线程安全的吗?哪些地方需要考虑线程安全?
220. Linux日志文件统计某几个字符串,如何一条命令就能统 计岀来?
201.数组al[O,mid-l]和al[mid,num-l],都分别有序。将其 merge成有序数组al[O,num-1],要求空间复杂度0(1).
首先把给定的数组分成两部分,前一部分包括A m]中的元素,而后者则包括(m口]中的 元素。然后找到第一个数组中的中间值,也就是ql=(l侦)/2, ql位置的元素就是我们 要找的元素,大家可以举个例子自己算一下,当找到ql的时候,Q1前面的元素有Q1个, 这对接下来的编程很有影响,所以这点一定要弄清楚。这样第一个数组我们就分为了两 部分。接下来我们用Q1去划分(人工】这段元素,也是分成两部分。建议在取元素范围的 时候,(叫工】这段的前一部分个数为(q2-l-m)个,后一部分为(r - q2 +1)个,这样 约定后思路会清晰。接下来划分好了之后就是交换,有一种叫做block swapping的算 法,这个算法能在。(1)的空间复杂度下交换两个长度不相同的相邻存储区的数组。
#include<stdio. h>
Siiic lude^assert.
void swap (int *a, int low, int high; {
while(low < high) {
int temp = *(a + low);
*(a + low) = *(a + high);
*(a + high) = temp;
low++;
high—;
void block_exchange (int int low, int mid, int high) {
swap (a, low, mid);
swap (a, mid + 1$ high);
swap (a, low, high);
int b inar y_s e ar ch (int value, int *a, int low, int high) { /*
如果数组中存在要查找的元素,那么返回high的位置的前后都有可能等于value 的值:
a: 1, 2, 4,4, 7,9 value=4 mid=2返回的high位置的元素后有值等于value
b: 1, 2, 4,4, 7,9,10 value=4 mid=3.返回的high位置的元素前有值等于value
c: 1,2, 7,9 value=4 high=3,返回的high值之前的元素都小于value,包括high 在内的以后得元素都大于value
*/
assert(a != NULL);
while(low < high) {
int mid = low + (high - low: / 2;
if(value 仁 a[mid])
high = mid;
else
low = mid + 1;
}
return high;
void merge__iri_place (int *a, int low, int mid, int high) {
int length! = mid 一 low +1;
int length2 = high - mid;
if(J(lengthl >= 0 && length2 >= 0))
return ;
if (lengthl >= length2) {
if (leng th2 <= 0)
return;
int ql = (low + mid) / 2;
int qZ = binary^sear ch (a [ql., a, mid 十 1 , high); int q3 = ql + (q2 - 1 - mid;;
ql, mid, q2 - 1); low, ql - 1, q3 - 1); q3 + 1, q2 - 1, high);
} else {
if (leng thl <= 0)
return;
int ql = (mid + 1 int q2 = binary_search(a[ql_, a, low, mid);
int q3 = q2 + (ql - 1 - mid;; block_exchange (a, q2, mid, ql);
merge_in_place (a, low, q2 - 1, q3 -1);
merge_in_place (a, q3 + 1, ql, high);
}
I
void main() {
int a[] = {爲 3, 5, 7,9, 2, 4,6,8,10};
int len = sizeof(a) /sizeof(int;;
int mid = len / 2 - 1;
merge_in_place (a, 0, mid, len - 1);
for(int i = 0; i < len; i++)
printf a[i]);
printfCXn^);
}
202. 一个url指向的页面里面有另一个url,最终有一个url指 向之前岀现过的url或空,这两种情形都定义为nulL这样构 成一个单链表。给两条这样单链表,判断里面是否存在同样 的url。url以亿级计,资源不足以hasho本題可以抽象为有环和无环情况下的链表交叉问题:
情况一:两条单链表均无环
最简单的一种情况,由于两条链表如果交叉,他们的尾节点必然相等(Y字归并), 所以只需要判断他们的尾节点是否相等即可。
情况二:两条单链表均有环
这种情况只需要拆开一条环路(注意需要保存被设置成null的节点),然后判断 另一个单链表是否仍然存在环路,如果有在,说明无交叉,反之,则有交叉的情况。 情况三:两条单链表,一条有环路,一条无环路
这种情况显然他们是不可能有交叉的
附:如何判断一条单链表是否存在环路,以及找出环路的入口
快慢指针:在表头设置两个指针fast与slow, fast指针与slow指针同时向前移动, 但是f as t每次移动2个节点,slow每次移动1个节点,若fast指向null或者fast==slow 时停止,这时如果fast指向mil,则说明没有环路,若faSt==slow则说明有环路。 找环路入口:当fast==slow时,将fast重新指向表头。slow原地不动。然后fast和 slow在同时以每次一个节点的速度向前移动,当他们再次重合时,就是环路入口。证 明如下:
1.证明fast和slow肯定会重合 在slow和fast第一次相谒的时候,假定Slow走了 n步骤,环路的入口是在p步的时 候经过的,那么有slow走的路径:p+c = n; c为pl和p2相交点,距离环路入口 的距离;fast走的路径:p+c+k*L =如;L为环路的周长,k是整数。显然,如 果从p+c点开始,pl再走n步骤的话,还可以回到p+c这个点同时p2从头开始走的话, 经过n步,也会达到p+c这点。
2. fast和slow在p+c点会重合,显然他们从环的入口点就开始重合
203.将单向链表reverse,如ABCD变成DCBA,只能搜索链表一 次.
#include <iostream>
using namespace std;
struct node
[
char data;
struct node *next;
};
typedef struct node NODE;
void test_exercise()
[
NODE *head = new NODE; /健立附加头结点 head~>next = NULL;
/彳创建链表*/
NODE *curr ent, *pr evi ous;
previous = head;
char irput;
cout « ^Irput your list table NODE data, end with
cin » irput;
while(irput J=)
{
current - new NODE;
current-〉data - irpu■:; current">next = NULL.
previous">next - curlent;
previous = pr evi ous"/ne x t;
cout « ^Irput your list table NODE data, end with cin » irput;
/欄出链表*/ current - head">next; while(current != NULL)
[
cout << current-〉data << current - current~>next;
}
cout << endl;
湖转链表*/ current - head">next;
NODE *p = current~>next;
NODE *q = p->next;
while(q != NULL)
[
p->next = current; current - p;
P = q;
q = q->next;
}
p->next = current;
current - p; head->next->next = NULL; head">next = current;
/欄出链表*/
current = head~>next; while(current != NULL) {
cout << current-〉data << current - current~>next;
204. A,B,C,D四个进程,A向Buf里面写数据,B,C,D向Buf里面读 数据,当A写完,且B,C,D都读一次后,A才能再写.用PV操作实 现.
响B,C, D四个进程,A向buf里面写数据,B, C, D向buf里面读数据, 当A写完,
semaphore semaphore semaphore semaphore semaphore semaphore
while(true){ P(empty);
P(b);
Pic 丿;
P(d); p(mutex); write ();
v(mutex): v(full)
while(true){ p(full); p(mutex); write ();
v(mutex); v(