Algorithm I assignment Deque and Randomized Queue

这周的作业时要实现一个双向队列和一个随机队列。并且实现要保证一定的效率。

要保证效率的话其实首先想到的是HashMap,不过由于作业只能使用一个iterator的包,所以不能使用HashMap。想了下,思路其实很简单,用用双向链表就可以实现,不过涉及到链表,要注意一些容易犯错的情况。

我在这个assignment中犯了一下错误:

  1. 在Randomized Queue中,为了实现一个random的iterator,为了优化时间复杂度,我把当前状态的变量存到了iterator内部,这导致了如果获取iterator之后又enqueue,iterator并不会更新。
  2. 时间复杂度没有通过,sample()和dequeue()不是常数时间。原因是我采用了双向链表,每次得到一个随机数时,就要遍历一遍,所以这里是O(n),应该实现类似hash的映射。这里对memory的要求只要是O(n)即可,所以可以用一个数组来映射对应的链表。不过这样的话,我其实应该直接用数组的,不然memory可能又要超出了。
  3. 改用数组实现后,依旧在iterator这个地方出了好几次错。要想实例化的iterator随着队列变化而变化,需要监控随机队列的变化,一旦发生变化,则需要重新设置迭代的顺序和元素。这里采用了一个局部变量size作为标志位,一旦和全局变量N不一致,则重新设置迭代顺序和元素,并将标志位设置为新的N。
  4. memory超了3个用例。检查后发现是因为在deque时,废弃的对象没有删掉对应的引用,导致了内存的浪费。这点对java程序员来说却是容易忽略,毕竟有了GC,就很少再关心过内存了,但是这里还是必须要把引用指向null,不然会一直有处于未被使用,但是仍有引用的对象。这些对象会一直占用内存。

下面是代码:

  1 import java.util.Iterator;
  2 
  3 public class Deque<Item> implements Iterable<Item> {
  4 
  5     private Node front, end;
  6 
  7     private class Node {
  8         Item item;
  9         Node left, right;
 10 
 11         Node(Item item, Node left, Node right) {
 12             this.item = item;
 13             this.left = left;
 14             this.right = right;
 15         }
 16     }
 17 
 18     private int N;
 19 
 20     // construct an empty deque
 21     public Deque() {
 22         front = end = null;
 23         N = 0;
 24     }
 25 
 26     // is the deque empty?
 27     public boolean isEmpty() {
 28         return N == 0;
 29     }
 30 
 31     // return the number of items on the deque
 32     public int size() {
 33         return N;
 34     }
 35 
 36     // add the item to the front
 37     public void addFirst(Item item) {
 38         if (item == null)
 39             throw new java.lang.NullPointerException();
 40         if (N == 0) {
 41             front = end = new Node(item, null, null);
 42         } else {
 43             Node temp = new Node(item, front, null);
 44             front.right = temp;
 45             front = temp;
 46         }
 47         N++;
 48     }
 49 
 50     // add the item to the end
 51     public void addLast(Item item) {
 52         if (item == null)
 53             throw new java.lang.NullPointerException();
 54         if (N == 0) {
 55             end = front = new Node(item, null, null);
 56         } else {
 57             Node temp = new Node(item, null, end);
 58             end.left = temp;
 59             end = temp;
 60         }
 61         N++;
 62     }
 63 
 64     // remove and return the item from the front
 65     public Item removeFirst() {
 66         if (N == 0) {
 67             throw new java.util.NoSuchElementException();
 68         }
 69         Item result = front.item;
 70         if (N == 1) {
 71             front = end = null;
 72         } else if (N == 2) {
 73             front = end;
 74             end.left = end.right = null;
 75         } else {
 76             front = front.left;
 77             front.right = null;
 78         }
 79         N--;
 80         return result;
 81     }
 82 
 83     // remove and return the item from the end
 84     public Item removeLast() {
 85         if (N == 0) {
 86             throw new java.util.NoSuchElementException();
 87         }
 88         Item result = end.item;
 89         if (N == 1) {
 90             end = front = null;
 91         } else if (N == 2) {
 92             end = front;
 93             front.left = front.right = null;
 94         } else {
 95             end = end.right;
 96             end.left = null;
 97         }
 98         N--;
 99         return result;
100     }
101 
102     // return an iterator over items in order from front to end
103     public Iterator<Item> iterator() {
104         return new Iterator<Item>() {
105             int index = N;
106             Node current = front;
107 
108             @Override
109             public boolean hasNext() {
110                 return index > 0;
111             }
112 
113             @Override
114             public Item next() {
115                 if (index == 0)
116                     throw new java.util.NoSuchElementException();
117                 Node temp = current;
118                 current = current.left;
119                 index--;
120                 return temp.item;
121             }
122 
123         };
124     }
125 
126     // unit testing
127     public static void main(String[] args) {
128         Deque<Integer> unittest = new Deque<Integer>();
129         unittest.addFirst(1);
130         unittest.addFirst(2);
131 
132         unittest.addLast(7);
133         unittest.addLast(8);
134         Iterator<Integer> it = unittest.iterator();
135         while (it.hasNext()) {
136             System.out.println(it.next());
137         }
138         System.out.println(unittest.removeFirst());
139         System.out.println(unittest.removeFirst());
140         System.out.println(unittest.removeFirst());
141         System.out.println(unittest.removeLast());
142     }
143 }
  1 import java.util.Iterator;
  2 
  3 import edu.princeton.cs.algs4.StdRandom;
  4 
  5 public class RandomizedQueue<Item> implements Iterable<Item> {
  6     private int N;
  7     private Item[] item;
  8 
  9     // construct an empty randomized queue
 10     @SuppressWarnings("unchecked")
 11     public RandomizedQueue() {
 12         item = (Item[]) new Object[2];
 13     }
 14 
 15     // is the queue empty?
 16     public boolean isEmpty() {
 17         return N == 0;
 18     }
 19 
 20     // return the number of items on the queue
 21     public int size() {
 22         return N;
 23     }
 24 
 25     // add the item
 26     public void enqueue(Item item) {
 27         if (item == null)
 28             throw new java.lang.NullPointerException();
 29         if (N > this.item.length / 2) {
 30             resize(2 * this.item.length);
 31         }
 32         this.item[N] = item;
 33         N++;
 34     }
 35 
 36     // remove and return a random item
 37     public Item dequeue() {
 38         if (N == 0) {
 39             throw new java.util.NoSuchElementException();
 40         }
 41         int index = StdRandom.uniform(N);
 42         if (N < this.item.length / 4) {
 43             resize(this.item.length / 2);
 44         }
 45         Item temp = this.item[index];
 46         this.item[index] = this.item[N - 1];
 47         this.item[N - 1] = null;
 48         N--;
 49         return temp;
 50     }
 51 
 52     // return (but do not remove) a random item
 53     public Item sample() {
 54         if (N == 0) {
 55             throw new java.util.NoSuchElementException();
 56         }
 57         int index = StdRandom.uniform(N);
 58         return this.item[index];
 59     }
 60 
 61     // return an independent iterator over items in random order
 62     public Iterator<Item> iterator() {
 63         Iterator<Item> it = new IteratorOfRand();
 64         return it;
 65     }
 66 
 67     private class IteratorOfRand implements Iterator<Item> {
 68         private int used = 0;
 69         private int size = N;
 70         private int[] shuffle;
 71 
 72         IteratorOfRand() {
 73             shuffle = new int[N];
 74             for (int i = 0; i < N; i++) {
 75                 shuffle[i] = i;
 76             }
 77             StdRandom.shuffle(shuffle);
 78         }
 79 
 80         @Override
 81         public boolean hasNext() {
 82             if (size != N) {
 83                 size = N;
 84                 shuffle = new int[N];
 85                 for (int i = 0; i < N; i++) {
 86                     shuffle[i] = i;
 87                 }
 88                 StdRandom.shuffle(shuffle);
 89             }
 90             if (used == N) {
 91                 used = 0;
 92                 return false;
 93             } else {
 94                 return true;
 95             }
 96         }
 97 
 98         @Override
 99         public Item next() {
100             if (!this.hasNext())
101                 throw new java.util.NoSuchElementException();
102             Item result = item[shuffle[used]];
103             used++;
104             return result;
105         }
106     }
107 
108     @SuppressWarnings("unchecked")
109     private void resize(int n) {
110         Item[] temp = this.item;
111         item = (Item[]) new Object[n];
112         int j = 0;
113         for (int i = 0; i < N; i++) {
114             item[j++] = temp[i];
115         }
116     }
117 
118     // unit testing
119     public static void main(String[] args) {
120         RandomizedQueue<Integer> unittest = new RandomizedQueue<Integer>();
121         unittest.enqueue(1);
122         unittest.enqueue(2);
123         Iterator it =  unittest.iterator();
124         while(it.hasNext()) {
125             System.out.println(it.next());
126         }
127         unittest.enqueue(3);
128         while(it.hasNext()) {
129             System.out.println(it.next());
130         }
131 //        for (int i = 0; i < 7; i++) {
132 //         System.out.println(i+"th sample:" + unittest.sample()
133 //         +" rand:"+unittest.dequeue());
134 //        
135 //         }
136     }
137 }

 

import edu.princeton.cs.algs4.StdIn;

public class Subset {
    public static void main(String[] args) {
        int k = Integer.parseInt(args[0]);
        RandomizedQueue<String> rq = new RandomizedQueue<String>();
        while (!StdIn.isEmpty()) {
            rq.enqueue(StdIn.readString());
        }
        for (int i = 0; i < k; i++) {
            System.out.println(rq.dequeue());
        }
    }
}

经过不断修改,这周还是满分通过,不过这次用的时间比上次要长。

 

posted @ 2015-09-19 18:19  一路绝尘  阅读(237)  评论(0编辑  收藏  举报