算法导论第三版2.3答案
2.3-1
划分:
{3}, {41}, {52}, {26}, {38}, {57}, {9}, {49}
合并:
{3, 41}, {26, 52}, {38, 57}, {9, 49}
{3, 26, 41, 52}, {9, 38, 49, 57}
{3, 9, 26, 38, 41, 49, 52,57}
2.3-2
void merge(int a[], int l, int mid, int r)
{
int n1 = mid - l + 1, n2 = r - mid;
for(int i = 1; i <= n1; ++i) L[i] = a[l + i - 1];
for(int i = 1; i <= n2; ++i) R[i] = a[mid + i];
int i = 1, j = 1, k = l;
while(i <= n1 && j <= n2)
{
if(L[i] <= R[j]) a[k ++] = L[i++];
else a[k ++] = R[j++];
}
while(i <= n1) a[k ++] = L[i ++];
while(j <= n2) a[k ++] = R[j ++];
}
2.3-3
设 n = 2 k . 若 n = 2 , k = 1 , T ( n ) = 2 = 2 l g 2 , 成立 . 若 n = 2 k , k > 1 , T ( n ) = n l g n = k ∗ 2 k 若 n = 2 k + 1 , k > 1 T ( n ) = ( k + 1 ) ∗ 2 k + 1 = 2 T ( n / 2 ) + n = 2 T ( 2 k ) + 2 k + 1 = 2 k ∗ 2 k + 2 k + 1 = k ∗ 2 k + 1 + 2 k + 1 = ( k + 1 ) ∗ 2 k + 1 = n l g n . 设n = 2^k.\\ 若n = 2,k=1,T(n)=2=2lg2,成立.\\ 若n=2^k,k>1,T(n)=nlgn=k*2^k\\ 若n=2^{k+1},k>1\\ T(n)=(k+1)*2^{k+1} \\ = 2T(n/2)+n\\ =2T(2^k)+2^{k+1}\\ =2k*2^k+2^{k+1}\\ =k*2^{k+1}+2^{k+1}\\ =(k+1)*2^{k+1} =nlgn. 设n=2k.若n=2,k=1,T(n)=2=2lg2,成立.若n=2k,k>1,T(n)=nlgn=k∗2k若n=2k+1,k>1T(n)=(k+1)∗2k+1=2T(n/2)+n=2T(2k)+2k+1=2k∗2k+2k+1=k∗2k+1+2k+1=(k+1)∗2k+1=nlgn.
2.3-4
T ( n ) = { 1 n = 1 T ( n − 1 ) + O ( n ) n > 1 T(n) = \begin{cases} 1 & n = 1 \\ T(n-1) + O(n) & n > 1 \end{cases} T(n)={1T(n−1)+O(n)n=1n>1
2.3-5
/*
* @Author: gorsonpy
* @Date: 2022-12-17 15:46:15
* @Last Modified by: gorsonpy
* @Last Modified time: 2022-12-17 15:46:15
*/
#define NIL -1
int binary_search(int a[], int n, int x)
{
int l = 1, r = n;
while(l < r)
{
int mid = l + r >> 1;
cout << l << " " << r << " " << mid << endl;
if(a[mid] < x) l = mid + 1;
else r = mid;
}
if(a[l] != x) return NIL;
return l;
}
每次都把搜索范围减去一半,故为 O ( l g n ) O(lgn) O(lgn)
2.3-6
这题有点不太明白,感觉书上讲的有点问题,二分优化的插入排序虽然确定插入位置只要 O ( l g n ) O(lgn) O(lgn),但是移动还是需要 O ( n ) O(n) O(n)啊。。
void insert_sort(int a[], int n)
{
for(int i = 2; i <= n; ++i)
{
int x = a[i];
a[i] = INF, a[0] = -2e9;
int l = 0, r = i;
while(l < r)
{
int mid = l + r >> 1;
if(a[mid] < x) l = mid + 1;
else r = mid;
}
int j = i - 1;
while(j && j >= l) a[j + 1] = a[j], --j;
a[l] = x;
}
}
2.3-7
这个就是枚举第一个加数是哪个,然后根据大小关系选择在左右的其中一个部分进行二分查找 x − a i x - a_i x−ai。二分的代码不好写,瞎写了一个也不知道对不对,反正思路是这么个思路~
/*
* @Author: gorsonpy
* @Date: 2022-12-17 16:19:10
* @Last Modified by: gorsonpy
* @Last Modified time: 2022-12-17 16:33:57
*/
/*
* @Author: gorsonpy
* @Date: 2022-12-17 16:19:10
* @Last Modified by: gorsonpy
* @Last Modified time: 2022-12-17 16:37:00
*/
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int main()
{
int n, x;
cin >> n;
for(int i = 0; i < n; ++i) cin >> a[i];
cin >> x;
bool success = false;
for(int i = 0; i < n; ++i)
{
int key = x - a[i], l, r;
if(a[i] < key)
{
l = i + 1, r = n;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(a[mid] > key) r = mid - 1;
else l = mid;
}
if(a[l] == key) success = true;
}
else if(a[i] > key)
{
l = 0, r = i - 1;
while(l < r)
{
int mid = l + r >> 1;
if(a[mid] < key) l = mid + 1;
else r = mid;
}
if(a[r] == key) success = true;
}
else
{
l = i + 1, r = n;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(a[mid] > key) r = mid - 1;
else l = mid;
}
if(a[l] == key) success = true;
l = 0, r = i - 1;
while(l < r)
{
int mid = l + r >> 1;
if(a[mid] < key) l = mid + 1;
else r = mid;
}
if(a[r] == key) success = true;
}
}
cout << (success ? "YES" : "NO") << endl;
return 0;
}
汇总传送门
链接: 算法导论习题答案汇总