第三章 表、栈、队列 ——【习题解答】数据结构与算法分析-Java语言描述 第三版

写作起因

最近因为找工作因为算法碰了不少壁。深感自己对算法的缺陷,于是买了《数据结构与算法分析-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 L1L2的过程。
3.5 给定两个已排序的表 L 1 L_1 L1 L 2 L_2 L2,只使用基本的表操作编写计算 L 1 ∪ L 2 L_1 \cup L_2 L1L2的过程。


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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值