寫的比較隨意,班裏同學可以參考一下。找到 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");
}
更新中。。。