写的比较随意,班里同学可以参考一下。找到 hack 数据麻烦告诉我一下,找时间更正。
第三周:
1. 定义一个函数,在一组整型数据中查找数据x,返回查找成功还是失败?分析该函数执行过程中,做了多少次的数据比较?
#include <stdio.h> // 遍历一下就好了吧
using namespace std;
const int MAXN = 1e5 + 10;
int n[MAXN];
int find(int* n, int len, int x) {
for (int i = 1; i <= len; i++)
if (n[i] == x)
return i;
return 0;
}
int main () {
int N, x;
scanf("%d", &N);
for (int i = 1; i <= N; i++)
scanf("%d", n + i);
scanf("%d", &x);
printf("%d\n", find(n, N, x));
}
2. 一组整型数据记为a0,a1,...,an-1,请定义一个函数将所有小于a0的数据移动到a0前面.(时间和空间性能最优)
我的理解就是只需要把比 a0 小的数移到它前面就好,不用关心两边的顺序问题
还有就是等于 a0 的数,照题意是只要不夹在小于 a0 的数中间就行吗?也就是说不用挨在一起?
因此如 4,5,1,2,4 这样的数据,转换后是 2,1,4,5,4 。按我的理解不是 hack 数据Orz
具体做法就是双指针,一个在头部,一个在尾部
- 头指针:从头向尾遍历,遇到大于 a0 的数停止
- 尾指针:从尾向头遍历,遇到小于 a0 的数停止
当符合 l < r 条件时,每次交换两个指针的值
不符合条件时,说明交换完成。把一开始 a0 (a0 已经不在一开始的头位置,此时一定在后半部分) 和临界值交换便可
因为要追求时间和空间性能的最优,所以这样写
#include <stdio.h> //不用开辟新的空间,直接用原数组便可。扫一遍就好,线性
using namespace std;
const int MAXN = 1e5 + 10;
int n[MAXN];
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void sort(int n[], int len) {
int x = n[0], l = 0, r = len - 1, temp = len - 1;
while (l < r) {
while (n[l] < x && l < len && l < r) l ++;
while (n[r] >= x && r > 0 && l < r) r --;
if (l == len) return;
if (l != r) {
swap(n + l, n + r);
if (l == 0) temp = r;
l ++;
r --;
}
}
if (l > r)
if (l != 0 && r != len - 1)
swap(n + temp, n + l);
if (l == r && l != 0 && r != len - 1) {
if (n[l] > x) swap(n + temp, n + l);
else if (n[l] < x) swap(n + temp, n + l + 1);
else if (n[l] == x) {
while (n[l] <= x) l ++;
swap(n + temp, n + l);
}
}
}
int main () {
int N;
scanf("%d", &N);
for (int i = 0; i < N; i++)
scanf("%d", n + i);
sort(n, N);
for (int i = 0; i < N; i++)
printf("%d ", n[i]);
printf("\n");
return 0;
}
3. 设整数序列(a0, a1,a2,…,an-1)存储于一维数组A中,编写求解最小值的 递归 程序。
比较偷懒,直接写了线段树,节点维护区间最小值。建树和查询用递归实现的版本。
#include <stdio.h>
#define min(a,b) (((a) < (b)) ? (a) : (b))
using namespace std;
const int MAXN=1e5 + 10;
int origin[MAXN], tree[MAXN<<2], lazy[MAXN<<2];
void pushup(int p) {
tree[p]=min(tree[p << 1], tree[p << 1 | 1]);
}
void build(int p, int l, int r) {
if (l == r) {
tree[p] = origin[l];
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
pushup(p);
}
int query(int p, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return tree[p]; //被包含在询问区域内的区间(有效的部分)
int mid = (l + r) >> 1;
int temp = 0x3f3f3f;
if (qr > mid) temp = min(temp,query(p << 1 | 1, mid + 1, r, ql, qr));
if (ql <= mid) temp = min(temp,query(p << 1, l, mid, ql, qr));
return temp;
}
int main () {
int N;
scanf("%d", &N);
for (int i = 1; i <= N; i++)
scanf("%d", origin + i);
build(1, 1, N);
printf("%d\n", query(1, 1, N, 1, N));
}
4. 已知两组数据(a0, a1,a2,…,an-1)与(b0, b1,b2,…,bn-1)都是从小到大的排列,请编写一个函数将这两组数据合并成一个从小到大的序列.
#include <stdio.h>
using namespace std;
const int MAXN = 1e5 + 10;
int a[MAXN], b[MAXN], c[MAXN];
void solve(int a[], int b[], int c[], int len) {
int ptr1 = 0, ptr2 = 0, cnt = 0;
while (ptr1 < len && ptr2 < len) {
if (a[ptr1] < b[ptr2]) {
c[cnt] = a[ptr1];
cnt ++;
ptr1 ++;
}
else{
c[cnt] = b[ptr2];
cnt ++;
ptr2 ++;
}
}
if (ptr1 == len)
while (ptr2 < len) {
c[cnt] = b[ptr2];
cnt ++;
ptr2 ++;
}
else if (ptr2 == len)
while (ptr1 < len) {
c[cnt] = a[ptr1];
cnt ++;
ptr1 ++;
}
}
int main () {
int N;
scanf("%d", &N);
for (int i = 0; i < N; i++)
scanf("%d", a + i);
for (int i = 0; i < N; i++)
scanf("%d", b + i);
solve(a, b, c, N);
N *= 2;
for (int i = 0; i < N; i++)
printf("%d ", c[i]);
printf("\n");
}
更新中。。。