写作起因
最近因为找工作因为算法碰了不少壁。深感自己对算法的缺陷,于是买了《数据结构与算法分析-Java语言描述 第三版》复习一下自己的薄弱的算法基础。
结果做完题的时候,居然找不到一个像样的答案。这就很苦恼了。
Pearson官网必须要有教师资格证才能拿到答案。国内的出版社貌似也一样。既然没有,那就由我来为中文程序猿社区做点贡献吧。
不敢说全对,大体是没问题的。欢迎大家斧正。
3.1
给定一个表L和另一个表P,它们包含以升序排列的整数。操作printLots(L,P)将打印L中那些由P所指定的位置上的元素。例如,如果P=1,3,4,6,那么,L中位于第1、第3、第4和第6个位置上的元素被打印出来。写出过程printLots(L,P)。只可使用public型的Collections API容器操作。该过程的运行时间是多少?
根据题意,L存数据,P存L的下标,然后打印下标对应的元素。要求必须用Collections API来操作。 我特地去看了一下Collections的API,完全无法实现这个操作。看了第二版的题解(题在第二版是一样的),结果用的是List来当容器。好嘛,原来用的是Collection的API。(捂脸)
关于运行时间,应该说的是时间复杂度。
若L长为m,P长为n,那么时间复杂度为:O(m+n)
代码如下
import java.util.*;
public class ThreeOne {
public static void main(String[] args) {
Character[] chars = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
Integer[] idxs = {
1, 4, 7, 10, 17, 25};
ArrayList<Character> L = new ArrayList<Character>(Arrays.asList(chars));
ArrayList<Integer> P = new ArrayList<Integer>(Arrays.asList(idxs));
long startTime = System.nanoTime();
System.out.println("startTime = " + startTime + "nanosec");
printLots(L, P);
long endTime = System.nanoTime();
System.out.println("endTime = " + endTime + "nanosec");
System.out.println("Duration: " + (endTime - startTime) + " nanosec or " + (endTime - startTime) / 1e6 + " milisec");
}
public static <T> void printLots(Collection<T> L, Collection<Integer> P) {
Iterator iterP = P.iterator();
Iterator iterL = L.iterator();
int idxL = 0;
T itemL = null;
while (iterP.hasNext() && iterL.hasNext()) {
int idx = (int) iterP.next();
while (iterL.hasNext() && idxL < idx) {
itemL = (T) iterL.next();
idxL++;
}
System.out.print(itemL + " ");
}
System.out.println();
}
}
3.2
通过只调整链(而不是数据)来交换两个相邻的元素,使用
a.单链表。
b.双链表。
很明显,这题要使用链表来实现。
代码如下
//For convenience, use double linked node as singly linked node.
class Node {
int value;
Node pre;
Node next;
}
public class ThreeTwo {
/**
* @param before the node before the two nodes to be swapped.
*/
public static void swapNodes(Node before) {
if (before == null || (before != null && before.next == null) || (before != null && before.next != null && before.next.next == null)) {
throw new IllegalArgumentException("There are no nodes to swap.");
}
Node first = before.next;
Node second = first.next;
before.next = second;
first.next = second.next;
second.next = first;
}
/**
* @param first the first node to be swapped.
*/
public static void swapNodesD(Node first) {
if (first == null || (first != null && first.next == null)) {
throw new IllegalArgumentException("There are no nodes to swap.");
}
Node second = first.next;
first.pre.next = second;
first.next = second.next;
second.pre = first.pre;
first.pre = second;
second.next = first;
}
/**
* Main
*
* @param args
*/
public static void main(String[] args) {
Node dummyHead = new Node();
Node cur = dummyHead;
for (int i = 0; i < 10; i++) {
cur.next = new Node();
cur.next.pre = cur;
cur.next.value = i;
cur = cur.next;
}
//swap 3 with 4
Node n = dummyHead.next.next.next;
swapNodes(n);
//swap 6 with 7
n = n.next.next.next.next;
swapNodesD(n);
Node p = dummyHead.next;
while (p != null) {
System.out.print(p.value + " ");
p = p.next;
}
}
}
3.3
实现MyLinkedList的contains例程。
题目没啥好解释的。这里我给出了两种方法。
//使用了MyLinkedList实现的Iterable接口。
public Node<AnyType> contains(AnyType value){
Iterable<AnyType> iter = this.iterator();
while(iter.hasNext()){
T next = iter.next();
if(next.data == value){
return next;
}
}
return null;
}
//使用了链表的基础遍历方法。
public Node<AnyType> contains(AnyType value){
Node<AnyType> p = beginMarker.next()
while(p != endMarker){
if(p.data == value)
return p;
p = p.next;
}
return null;
}
倒是在第二版中给出的答案挺有意思的。 在一定程度上,代码更简洁了,不过理解难度有一点点的上升。emm…突然感觉自己的答案不香了。一种bad code smell的感觉。(捂脸)
public boolean contains(AnyType x) {
Node<AnyType> p = beginMarker.next;
while (p != endMarker & !(p.data.equa1s(x))) {
//将判断置于while循环条件里。
p = p.next;
}
return (p != endMarker); //这里返回的是 是否到达末尾。更简化了,而不是上述答案中的两个return。
}
3.4、3.5
3.4 给定两个已排序的表 L 1 L_1 L1和 L 2 L_2 L2,只使用基本的表操作编写计算 L 1 ∩ L 2 L_1 \cap L_2 L1∩L2的过程。
3.5 给定两个已排序的表 L 1 L_1 L1和 L 2 L_2 L2,只使用基本的表操作编写计算 L 1 ∪ L 2 L_1 \cup L_2 L1∪L2的过程。
public class ThreeFour {
public static void main(String[] args) {
Integer[] ints1 = new Integer[]{
3, 5, 7, 9};
Integer[] ints2 = new Integer[]{
1, 4, 5, 7, 10};
List<Integer> i1 = Arrays.asList(ints1);
List<Integer> i2 = Arrays.asList(ints2);
//自己答案的调用
List<Integer> intersection = intersection(i1, i2);
System.out.println("intersection = " + intersection);
List<Integer> union = union(i1, i2);
System.out.println("union = " + union);
//官方答案的调用
intersection.clear();
union.clear();
intersection(i1, i2, intersection);
System.out.println("intersection = " + intersection);
union(i1, i2, union);
System.out.println("union = " + union);
}
}
public static <T> List<T> intersection(List<T> l1, List<T> l2) {
ArrayList<T> list = new ArrayList<T>();
for (T t : l1) {
if (l2.contains(t)) list.add(t);
}
return list;
}
public static <T> List<T> union(List<T> l1, List<T