分享笔试面试题

目录

1.区间查找

2.断号问题

3.设计一个包含main函数的栈,支持如下操作,这些操作的算法复杂度是常熟级O(1)


1.区间查找

给定一个排序数组num(有重复元素),与目标值target,如果target在num里面出现,则返回target所在区间的左右下标[左下标,右下标],如果没有则返回0

例如:num[]={5,7,7,8,8,8,8,10},查找8,则返回[3,6];

思路:给的是排序好的数组,为了使时间复杂度较低,我们应该选择折半查找,折半查找一次并不能找到两个值,所以我们分为两个函数,分别用折半查找

int GetLeftIndex(int* num, int n,int k)
{
	int begin=0, end=n-1;
	int mid;
	while (begin <= end)
	{
		mid = (begin + end) / 2;
		if (num[mid] == k)
		{
			if (mid == 0 || num[mid - 1] < k)
				return mid;
			end = mid - 1;//mid之前的数如果等于k值,
		}
		else if (num[mid] > k)
		{
			end = mid - 1;
		}
		else if (num[mid] < k)
		{
			begin = mid + 1;
		}
	}
	return -1;//没找到的情况
}
int GetRightIndex(int* num, int n,int k)
{
	int begin = 0, end = n - 1;
	int mid = 0;
	while (begin <= end)
	{
		mid = (begin + end) / 2;
		if (num[mid] == k)
		{
			if (mid == 0 || num[mid + 1] >k)
				return mid;
			begin = mid + 1;
		}
		else if (num[mid] > k)
		{
			end = mid - 1;
		}
		else if (num[mid] < k)
		{
			begin = mid + 1;
		}
	}
	return -1;
}
void main()
{
	int num[] = { 5,7,7,8,8,8,8,10 };
	int n = sizeof(num) / sizeof(num[0]);
	cout << "[" << GetLeftIndex(num, n, 6) <<","<< GetRightIndex(num, n, 6) << "]" << endl;

}

截图:

2.断号问题

(全局范围) 某涉密单位下发了某种票据,并要在年终全部收回 每张票据有唯一的 ID 号。全年所有票据的 ID 号是连续的,但 ID 的开始数码是随机选定的。因为工作人员疏忽, 在录入 ID 号的时候发生了一处错误,造成了某个 ID 断号,另外一个 ID 重号。你的任务是通过编程,找出断号的 ID 和重号的 ID 。假设断号不可能发生在最大和最小号。 输入格式,要求程序首先输入一个整数 N ( N <100)表示后面数据行数。接着读入 N 行数据。 每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000),请注意行内和行末可能有多余的空格你的程序需要能处理这些空格每个整数代表一个 ID 号。 输出格式要求程序输出1行,含两个整数 m n ,用空格分隔。其中, m 表示断号 ID , n 表示重号 ID 样例输入1

2

5 6 8 11 9 10 12 9

样例输出1

7,9

样例输入2 6

164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196 172 189 127 107 112 192 103 131 133 169 158 128 102 110 148 139 157 140 195 197 185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190 149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188 113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119

样例输出2 105 120

思路:因为数据的多少不一定,所以我们需要去计算数据的最大值和最小值,让他输出的时候是有一个范围的。其次,定义a数组标记数据出现的次数,在遍历完成之后,0代表缺失的数据,1就代表出现一次的数据,2代表重复出现的数据,最后只需要输出0和2对应的数据就好

代码:

void main()
{
	int a[100001] = { 0 };
	int n, i;//n是行数,i是循环要用的
	int max = 0, min = 100000;
	char c;
	int value;
	scanf_s("%d", &n);
	for (i = 0; i < n; i++)
	{
		while (1)
		{
			scanf_s("%d", &value);
			if (value > max)
				max = value;
			if (value < min)
				min = value;
			a[value]++;//标志
			c = getchar();
			if (c != ' ')//c不是空格的时候,就是回车,可以进入下一行了
				break;
		}
	}
	for (i = min; i <= max; i++)
	{
		if (a[i] == 0)
			cout << "缺失的ID号是:" << i << endl;
		if (a[i] == 2)
			cout << "重复的ID号是:" << i << endl;
	}
}

截图:

3.设计一个包含main函数的栈,支持如下操作,这些操作的算法复杂度是常熟级O(1)

push(x) pop() top() GetMin()---返回栈内最小元素

思路:首先不能有循环,其次是对stack的运用,详情请查看代码

#include<stack>
class MinStack
{
public:
	void Push(int x)//压栈
	{
		data.push(x);
		if (min.empty())//最小值的栈是空的
			min.push(x);
		else//栈不为空
		{
			if (x > min.top())//且大于此时的栈顶元素
			{
				x = min.top();//确保两个栈的元素是一样多的,如果数据栈的元素不入min栈的时候,把原来的栈顶元素又给了x,让原来min栈的最小值再次入栈,在pop的时候就不会出现错位,即pop数据栈里的元素,min栈有可能它的最小值还是原来的数值,但是一经pop出栈,那这个元素就没了,出现误差
			}
				min.push(x);//入栈
		}
	}
	void Pop()
	{
		data.pop();
		min.pop();
	}
	int Top()
	{
		return data.top();
	}
	int GetMin()
	{
		return min.top();
	}
private:
	stack<int> data;//存数据的栈
	stack<int> min;//存最小值的栈

};
void main()
{
	MinStack ms;
	ms.Push(-1);
	ms.Push(-5);
	ms.Push(3);
	ms.Push(4);
	ms.Push(7);
	cout << ms.GetMin() << endl;//-5
	ms.Pop();//出去7
	cout << ms.GetMin() << endl;//最小值还是-5,表明这时候min栈的-5不能出去,所以min栈存储了两份-5

}

 截图:

猜你喜欢

转载自blog.csdn.net/weixin_62456756/article/details/129115337