有两个各存放在数组A和数组B中的n位二进制整数,考虑其相加问题。将所得结果以二进制形式存放在数组C中,C的维数为[n+1]。写出伪代码
解决:
func(A,B,C):
carry_bit = 0
for i = 1 ~ n:
v = A[i] + B[i] + carry_bit
C[i] = v % 2
carry_bit = v / 2
C[n + 1] = carry_bit
题目:2.3-6:
若将插入排序中查找位置的部分改用为二分查找,则最坏情况下算法的复杂度是否仅为 O(nlogn )
解决:
对第 i 个元素,此时查找到合适位置所需要的平均比较次数为 lg(i)。但是找到合适位置后,还需要将合适位置及之后的元素向后挪动,最坏情况下,最合适位置为第一个元素位置,此时仍然需要 i 次挪动。复杂度仍为 O(n^2)
题目:2.3-7
给定长度为 n 的整数集合S,再给一个整数 x,求其中是否有两个元素满足:两个元素的和为 x 。要求算法复杂度为 O(nlogn)
解决:
1. 将整数集合 S 进行排序,所花费时间为 O(nlogn)
2. 然后用两个迭代器 i, j 分别指向排序后的集合S‘ 的第一个元素和最后一个元素:
若 *i + *j > x : j-- // j 挪到更小的位置
若 *i + *j < x : ++i
题目:2-1
对合并排序算法进行改进,将 n 个数组划分为大小为 k 的 n/k 个数组,对每个小数组使用插入排序。再对 n/k 个数组进行合并排序。
算法复杂度分析:
k 个数进行插入排序(O(n^2))最差情况下的复杂度为:n/k*O(k^2) = O(nk)
合并 n/k 个小数组(O(n))在最差情况下的复杂度为: lg(n/k)*O(n),解释:该分治算法一共要分的层数为lg(n/k)次,而每一层,合并算法的时间复杂度为Θ(n),所以总的时间复杂度为Θ(nlg(n/k))
所以:该算法的复杂度为Θ(nlg(n/k))
题目:2-4
逆序对——给出一个算法,在O(nlogn)的复杂度算出 n 个数组成的数组中存在的逆序对数量(适量修改合并排序)
解答:
在合并排序的基础上,每次合并子数组前先统计当前两个子数组之间存在多少个逆序对。统计时注意使用特性:两个子数组分别是排好序的。统计好后将这两个子数组排序合并。避免重复计算逆序对。源代码如下:
<span style="font-family:Microsoft YaHei;"><span style="font-size:18px;">int merge(vector<int> & v, vector<int>::iterator beg, vector<int>::iterator mid, vector<int>::iterator end)
{
vector<int> left(beg, mid);
vector<int> right(mid, end);
vector<int>::iterator l = left.begin();
vector<int>::iterator r = right.begin();
/////////////////////////////////////// 主要计数功能在此实现
int count = 0;
int n = 0;
int n_left(left.size()), n_right(right.size());
int l_i(0), r_i(0);
while (l_i != n_left)
{
n = 0;
while (r_i != n_right && right[r_i] < left[l_i])
{
++n;
++r_i;
}
count += (n_left - l_i) * n;
if (r_i == n_right)
break;
++l_i;
}
////////////////////////////////////// 下面是普通的合并排序中合并的实现源码
while (l != left.end() && r != right.end())
{
if (*l <= *r)
{
*beg = *l;
++l;
}
else
{
*beg = *r;
++r;
}
++beg;
}
if (l != left.end())
{
while (l != left.end())
*beg++ = *l++;
}
else if (r != right.end())
{
while (r != right.end())
{
*beg++ = *r++;
}
}
else;
return count;
}
int merge_sort(vector<int>& v, vector<int>::iterator beg, vector<int>::iterator end)
{
if (beg + 1 >= end)
return 0;
vector<int>::iterator mid = beg + (end - beg) / 2;
int count = 0;
count += merge_sort(v,beg, mid);
count += merge_sort(v,mid, end);
count += merge(v, beg, mid, end);
return count;
}
int main()
{
vector<int> v = { 4, 1, 6, 3, 2, 5, 8 };
cout << merge_sort(v, v.begin(), v.end()) << endl;
}</span></span>