算法导论之2.3-7练习题
来源:互联网 发布:windows tts 语音库 编辑:程序博客网 时间:2024/04/30 11:31
题目:给出一个Θ(nlgn)时间的算法。判断在集合S中,是否存在两个元素的和为x。
算法导论的教师手册解法如下:
1.对集合S排序。
2.创建集合T = {z : z = x − y ,y ∈ S}。
3.对集合T排序。
4.去除S和T中的重复元素。
5.按照从小到大顺序或者从大到小顺序合并两个集合
6.对于合并以后的集合而言,当且仅当集合中的相邻位置出现相等元素,则存在,否则不存在。
这个解法的大致含义:假设集合T中存在一个元素w,那么w = x - y,而集合S中存在y,由于集合中已经没有重复的元素,如果集合S与集合T中的元素合并,相邻位置出现相等元素, 则表明集合S中存在w,因此w + y = x,则存在。
由于所需时间复杂度为O(nlogn),所以我们用归并排序,Java代码如下:
private static void mergeSort(int[] arr, int lo, int hi) { if (lo < hi) { int mi = (lo + hi) / 2; mergeSort(arr, lo, mi); mergeSort(arr, mi + 1, hi); rewriteMerge(arr, lo, mi, hi); } } // 不使用哨兵的方法 private static void rewriteMerge(int[] arr, int lo, int mi, int hi) { int frontLength = mi - lo + 1; int backLength = hi - mi; int[] l = new int[frontLength]; int[] r = new int[backLength]; for (int i = 0; i < frontLength; i++) l[i] = arr[lo + i]; for (int i = 0; i < backLength; i++) r[i] = arr[mi + 1 + i]; int lp = 0; int rp = 0; for (int i = lo; i <= hi; i++) { if (lp == frontLength) break; if (rp == backLength) { arr[i] = l[lp]; lp++; continue; } if (l[lp] < r[rp]) { arr[i] = l[lp]; lp++; } else { arr[i] = r[rp]; rp++; } } }
So step one 的时间复杂度为O(nlogn)。
我把step two and step three 合并在一个方法中了,Java代码如下:
private static int[] createAndSort(int[] a, int aLength, int x) { int[] aCopy = new int[aLength]; for (int i = 0; i < aCopy.length; i++) // 我将第三步合并到这,由于a数组是有序的,通过x减去a中的最大值,放在a副本中的最小位置上 aCopy[i] = x - a[aLength - 1 - i]; return aCopy; }
上面这个方法时间复杂度为O(n)。
step 4 Java代码如下:
private static int[] distinctArray(int[] a) { //定义一个临时的数组 int[] temp = new int[a.length]; //将数组中的重复元素都置为整数的最小值 for (int i = 0; i < a.length - 1; i++) if (a[i] == a[i + 1]) a[i] = Integer.MIN_VALUE; //定义指向temp的指针,去除数组a中的重复值,将其保存到数组temp中 //temp数组中的后面的元素有可能为空 int pot = 0; for (int i = 0; i < a.length; i++) if (a[i] != Integer.MIN_VALUE) temp[pot++] = a[i]; if (pot != a.length) { //如果有重复元素,去除temp数组中的空元素 int[] result = new int[pot]; for (int i = 0; i < result.length; i++) result[i] = temp[i]; return result; } else //如果没有重复元素,则直接返回temp数组 return temp; }
上面这个方法时间复杂度为O(n)。
Step 5 Java代码如下:
private static int[] mergeDoubleArray(int[] a, int[] aCopy) { int alength = a.length; int acopylength = aCopy.length; int[] ret = new int[alength + acopylength]; for (int i = 0; i < alength; i++) ret[i] = a[i]; for (int i = 0; i < acopylength; i++) ret[alength + i] = aCopy[i]; rewriteMerge(ret, 0, a.length - 1, ret.length - 1); return ret; }
上面这个方法时间复杂度为O(n)。
Step 6 Java代码如下:
private static boolean validate(int[] result) { boolean isExist = false; for (int i = 0; i < result.length - 1; i++) { if (result[i] == result[i + 1]) return true; } return isExist; }
上面这个方法时间复杂度为O(n)。
主方法Java代码如下:
public static void main(String[] args) { int[] a = { 7, 4, 3, 34, 56, 34, 1 }; int aLength = a.length; int x = 12; // step one mergeSort(a, 0, aLength - 1); // step two and step three int[] aCopy = createAndSort(a, aLength, x); // step four a = distinctArray(a); aCopy = distinctArray(aCopy); // step five int[] result = mergeDoubleArray(a, aCopy); // step six boolean isExist = validate(result); System.out.println(isExist);}
综上所述:总共所需时间为:O(nlogn) + O(n) + O(n) + O(n) + O(n) = O(nlogn)
方案二如下:
public static void main(String[] args) { int[] b = { 6,6,1}; int bLength = b.length; int y = 12; //用归并排序为数组b排序 mergeSort(b, 0, bLength - 1); for (int i = 0; i < b.length; i++) { Integer res = IterativeBinarySearch(b, y - b[i], 0, b.length - 1); if ( res != -1 && res.intValue() != i ) { System.out.println(true); return; } } System.out.println(false);}
二分查找算法,我就不列在这里了。这个算法很简单,算法时间复杂度为O(nlogn)。
但我个人觉得,如果令x = 12,而集合S中存在一个元素6(2个元素6正确),这种算法将会导致错误的结果。希望大家看看有什么好的建议来解决这个Bug,期待您的评论。
- 算法导论之2.3-7练习题
- 《算法导论》练习题2.3-7
- 算法导论 练习题 2.3-7
- 算法导论 练习题 2.3-2
- 算法导论 练习题 2.3-3
- 算法导论 练习题 2.3-4
- 算法导论 练习题 2.3-6
- 算法导论 练习题 3.2-7
- 算法导论 练习题 4.2-7
- 算法导论 练习题 4.3-7
- 算法导论 练习题 4.4-7
- 算法导论 练习题 6.1-7
- 算法导论 练习题 6.5-7
- 算法导论 练习题 9.3-7
- 算法导论 练习题 10.2-7
- 算法导论 练习题 12.2-7
- 算法导论 练习题 13.1-7
- 算法导论 练习题 13.4-7
- 短信拒绝服务漏洞
- x的平方根
- 关于闭包
- 分分钟学会一门语言之Python篇
- 51NOD1265(四点共面)
- 算法导论之2.3-7练习题
- 以太网OAM技术介绍 http://blog.chinaunix.net/uid-113269-id-267427.html
- Spring AOP的底层实现技术
- 协同过滤工具推荐
- hadoop 读书笔记(1)
- 2.11 行列式
- Java-ServletRequestListener-ServletRequestAttributeListener
- 【FastDev4Android框架开发】Android 列表下拉刷新组件PullToRefreshListView使用(三)
- iOS常见问题---const和volatile