Coursera Algorithms Programming Assignment 2: Deque and Randomized Queue (100分)
作业原文:http://coursera.cs.princeton.edu/algs4/assignments/queues.html
这次作业与第一周作业相比,稍微简单一些。有三个编程练习:双端队列(Deque)设计、随机队列(Randomized Queue)设计,还有一个排列组合类Permutation。
一、双端队列Deque
设计要求:A double-ended queue or deque (pronounced "deck") is a generalization of a stack and a queue that supports adding and removing items from either the front or the back of the data structure.
异常处理要求:Throw a java.lang.IllegalArgumentException if the client attempts to add a null item; throw a java.util.NoSuchElementException if the client attempts to remove an item from an empty deque; throw a java.lang.UnsupportedOperationException if the client calls the remove() method in the iterator; throw a java.util.NoSuchElementException if the client calls the next() method in the iterator and there are no more items to return.
性能要求:Your deque implementation must support each deque operation (including construction) in constant worst-case time. A deque containing n items must use at most 48n + 192 bytes of memory and use space proportional to the number of items currently in the deque. Additionally, your iterator implementation must support each operation (including construction) in constant worst-case time.
分析:
要求可以同时从头尾移除元素,那么该队列内部采用链表更合适,代码如下
- import java.util.Iterator;
- import java.util.NoSuchElementException;
- public class Deque<Item> implements Iterable<Item> {
- private Node first; // 8 bytes
- private Node last; // 8 bytes
- private int size; // 4 bytes
- private class Node { // 16字节对象开销+8字节内部类额外开销+8+8+8=48 bytes, n个节点就是48n bytes
- private Node preNode; // 前一个节点的引用
- private Item item;
- private Node nextNode; // 后一个节点的引用
- }
- private class ListIterator implements Iterator<Item> {
- // 16字节对象开销+8字节内部类额外开销+8=32 bytes
- private Node curr = first;
- @Override
- public boolean hasNext() {
- // TODO Auto-generated method stub
- return curr != null;
- }
- @Override
- public Item next() {
- // TODO Auto-generated method stub
- if (curr == null)
- throw new NoSuchElementException("there are no more items!");
- Item item = curr.item;
- curr = curr.nextNode;
- return item;
- }
- //remove不用设计,父类Iterator的remove方法就抛出UnsupportedOperationException("remove");
- }
- public Deque() {
- // construct an empty deque
- size = 0;
- first = null;
- last = null;
- }
- public boolean isEmpty() {
- // is the deque empty?
- return (size == 0);
- }
- public int size() {
- // return the number of items on the deque
- return size;
- }
- public void addFirst(Item item) {
- // add the item to the front
- valivate(item);
- Node newNode = new Node();
- newNode.item = item;
- if (size == 0) { // 空队列的情况
- newNode.preNode = null;
- newNode.nextNode = null;
- first = newNode;
- last = newNode;
- } else {
- newNode.preNode = null;
- newNode.nextNode = first;
- first.preNode = newNode;
- first = newNode;
- }
- size++;
- }
- public void addLast(Item item) {
- // add the item to the end
- valivate(item);
- Node newNode = new Node();
- newNode.item = item;
- if (size == 0) { // 空队列的情况
- newNode.preNode = null;
- newNode.nextNode = null;
- first = newNode;
- last = newNode;
- } else {
- last.nextNode = newNode;
- newNode.preNode = last;
- newNode.nextNode = null;
- last = newNode;
- }
- size++;
- }
- public Item removeFirst() {
- // remove and return the item from the front
- if (size == 0)
- throw new NoSuchElementException("the deque is empty!");
- Item returnItem = null;
- if (size == 1) {
- returnItem = first.item;
- first = null;
- last = null;
- } else {
- Node oldfirst = first;
- returnItem = oldfirst.item;
- first = oldfirst.nextNode;
- first.preNode = null;
- oldfirst.nextNode = null;
- oldfirst.item = null;
- }
- size--;
- return returnItem;
- }
- public Item removeLast() {
- // remove and return the item from the end
- if (size == 0)
- throw new NoSuchElementException("the deque is empty!");
- Item returnItem = null;
- if (size == 1) {
- returnItem = first.item;
- first = null;
- last = null;
- } else {
- Node oldlast = last;
- returnItem = oldlast.item;
- last = oldlast.preNode;
- last.nextNode = null;
- oldlast.preNode = null;
- oldlast.item = null;
- }
- size--;
- return returnItem;
- }
- public Iterator<Item> iterator() {
- // return an iterator over items in order from front to end
- return new ListIterator();
- }
- private void valivate(Item item) {
- if (item == null)
- throw new IllegalArgumentException("the item is null!");
- }
- public static void main(String[] args) {
- // unit testing (optional)
- Deque<String> queue = new Deque<String>();
- System.out.println(queue.size);
- queue.addFirst("a");
- queue.addFirst("b");
- queue.addLast("c");
- queue.addFirst("d");
- queue.addLast("e");
- System.out.println(queue.size);
- Iterator<String> iter = queue.iterator();
- while (iter.hasNext()) {
- System.out.println(iter.next());
- }
- }
- }
二、随机队列Randomized Queue
设计要求:A randomized queue is similar to a stack or queue, except that the item removed is chosen uniformly at random from items in the data structure.
异常处理:The order of two or more iterators to the same randomized queue must be mutually independent; each iterator must maintain its own random order. Throw a java.lang.IllegalArgumentException if the client attempts to add a null item; throw a java.util.NoSuchElementException if the client attempts to sample or dequeue an item from an empty randomized queue; throw a java.lang.UnsupportedOperationException if the client calls the remove() method in the iterator; throw a java.util.NoSuchElementException if the client calls the next() method in the iterator and there are no more items to return.
性能要求: Your randomized queue implementation must support each randomized queue operation (besides creating an iterator) in constant amortized time. That is, any sequence of m randomized queue operations (starting from an empty queue) should take at most cm steps in the worst case, for some constant c. A randomized queue containing n items must use at most 48n + 192 bytes of memory. Additionally, your iterator implementation must support operations next() and hasNext() in constant worst-case time; and construction in linear time; you may (and will need to) use a linear amount of extra memory per iterator.
分析:
该队列每次移除的元素是随机的,性能要求提到迭代器的next方法必须是常数时间,很容易发现链表不容易满足该需求,需要用数组,代码如下:
- import java.util.Iterator;
- import java.util.NoSuchElementException;
- import edu.princeton.cs.algs4.StdRandom;
- public class RandomizedQueue<Item> implements Iterable<Item> {
- private Item[] rqArrays;
- private int size;
- private class RandomIterator implements Iterator<Item> {
- private int rank; // rank 记录便利的次数
- private Item[] iterArrays; //两个迭代器必须相互独立,并且拥有自己的随机顺序
- public RandomIterator(){
- rank = size;
- iterArrays = (Item[]) new Object[rank];
- for(int i = 0; i<size; i++){
- iterArrays[i] = rqArrays[i];
- }
- }
- @Override
- public boolean hasNext() {
- // TODO Auto-generated method stub
- return (rank > 0);
- }
- @Override
- public Item next() {
- // TODO Auto-generated method stub
- if (rank == 0)
- throw new NoSuchElementException("there are no more items!");
- int r = StdRandom.uniform(0, rank); // 随机选取一个位置的元素返回
- rank--;
- Item item = iterArrays[r];
- iterArrays[r] = iterArrays[rank];
- iterArrays[rank] = item; // 将已经遍历过的元素放置队列末尾,这样下次迭代就不会被选到
- return item;
- }
- }
- public RandomizedQueue() {
- // construct an empty randomized queue
- rqArrays = (Item[]) new Object[1];
- size = 0;
- }
- private void valivate(Item item) {
- if (item == null)
- throw new IllegalArgumentException("the item is null!");
- }
- public boolean isEmpty() {
- // is the queue empty?
- return (size == 0);
- }
- public int size() {
- // return the number of items on the queue
- return size;
- }
- private void resize(int cap) {
- Item[] temp = (Item[]) new Object[cap];
- for (int i = 0; i < size; i++)
- temp[i] = rqArrays[i];
- rqArrays = temp;
- }
- public void enqueue(Item item) {
- // add the item
- valivate(item);
- rqArrays[size++] = item;
- if (size == rqArrays.length)
- resize(2 * rqArrays.length);
- }
- public Item dequeue() {
- // remove and return a random item
- // 随机选取一个位置,将这个位置的元素与队列末尾的元素交换位置
- // dequeue末尾元素时就达到随机remove元素的目的
- if (size == 0)
- throw new NoSuchElementException("the RandomizeQueue is empty!");
- int r = StdRandom.uniform(0, size);
- size--;
- Item delItem = rqArrays[r];
- rqArrays[r] = rqArrays[size];
- rqArrays[size] = null;
- if (size > 0 && size == rqArrays.length / 4)
- resize(rqArrays.length / 2);
- return delItem;
- }
- public Item sample() {
- // return (but do not remove) a random item
- if (size == 0)
- throw new NoSuchElementException("the RandomizeQueue is empty!");
- return rqArrays[StdRandom.uniform(0, size)];
- }
- public Iterator<Item> iterator() {
- // return an independent iterator over items in random order
- return new RandomIterator();
- }
- public static void main(String[] args) {
- // unit testing (optional)
- RandomizedQueue<String> rq = new RandomizedQueue<String>();
- rq.enqueue("a");
- rq.enqueue("b");
- rq.enqueue("c");
- rq.enqueue("d");
- rq.enqueue("e");
- rq.enqueue("f");
- rq.enqueue("g");
- rq.dequeue();
- Iterator<String> iter1 = rq.iterator();
- Iterator<String> iter2 = rq.iterator();
- while (iter1.hasNext()) {
- System.out.print(iter1.next() + ",");
- }
- System.out.println();
- while (iter2.hasNext()) {
- System.out.print(iter2.next() + ",");
- }
- System.out.println();
- }
- }
三、 排列组合类Permutation
设计要求:Write a client program Permutation.java that takes a command-line integer k; reads in a sequence of strings from standard input using StdIn.readString(); and prints exactly k of them, uniformly at random. Print each item from the sequence at most once.
性能要求:The running time of Permutation must be linear in the size of the input. You may use only a constant amount of memory plus either one Deque or RandomizedQueue object of maximum size at most n. (For an extra challenge, use only one Deque or RandomizedQueue object of maximum size at most k.)
输出示例:
分析:
显然Permutation要做的事情就是读取一个k,并且从加载的输入文件内容中选取k个String进行展示,故采用RandomizedQueue比较合适。将文件中所有String都放入RandomizedQueue的话其size就是n,如果只放入k个String的话,RandomizedQueue的size就会是k,目前我只实现了size==n的方法,作业提交得分100。size==k的方法需要再斟酌下,若有进展,及时更新。
- import edu.princeton.cs.algs4.StdIn;
- public class Permutation {
- public static void main(String[] args) {
- RandomizedQueue<String> rq = new RandomizedQueue<String>();
- int k = Integer.parseInt(args[0]);
- while (!StdIn.isEmpty()) {
- rq.enqueue(StdIn.readString());
- // System.out.println(StdIn.readString());
- }
- while (k > 0) {
- System.out.println(rq.dequeue());
- k--;
- }
- }
- }
Coursera Algorithms Programming Assignment 2: Deque and Randomized Queue (100分)的更多相关文章
- Coursera Algorithms Programming Assignment 3: Pattern Recognition (100分)
题目原文详见http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 程序的主要目的是寻找n个points中的line seg ...
- Coursera Algorithms Programming Assignment 5: Kd-Trees (98分)
题目地址:http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 分析: Brute-force implementation. ...
- Coursera Algorithms Programming Assignment 4: 8 Puzzle (100分)
题目原文:http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 题目要求:设计一个程序解决8 puzzle问题以及该问题的推广 ...
- Coursera Algorithms Programming Assignment 1: Percolation(100分)
题目来源http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 作业分为两部分:建立模型和仿真实验. 最关键的部分就是建 ...
- Algorithms : Programming Assignment 3: Pattern Recognition
Programming Assignment 3: Pattern Recognition 1.题目重述 原题目:Programming Assignment 3: Pattern Recogniti ...
- Programming Assignment 2: Deques and Randomized Queues
编程作业二 作业链接:Deques and Randomized Queues & Checklist 我的代码:Deque.java & RandomizedQueue.java & ...
- Coursera Algorithms week2 栈和队列 练习测验: Queue with two stacks
题目原文: Implement a queue with two stacks so that each queue operations takes a constant amortized num ...
- Programming Assignment 2: Randomized Queues and Deques
实现一个泛型的双端队列和随机化队列,用数组和链表的方式实现基本数据结构,主要介绍了泛型和迭代器. Dequeue. 实现一个双端队列,它是栈和队列的升级版,支持首尾两端的插入和删除.Deque的API ...
- Algorithms: Design and Analysis, Part 1 - Programming Assignment #1
自我总结: 1.编程的思维不够,虽然分析有哪些需要的函数,但是不能比较好的汇总整合 2.写代码能力,容易挫败感,经常有bug,很烦心,耐心不够好 题目: In this programming ass ...
随机推荐
- 转:selenium自动化脚本错误总结
https://blog.csdn.net/zxy987872674/article/details/53141118
- 吐得了,vue的多选组合框回显必须是字符串集合
下面这个typeIdList,如果给他赋值,就能回显到页面,但是必须是字符串的集合,如果是数值类型的id,不好意思,请转成字符串
- ionic错误
1. 问题:Error: read ECONNRESET 启动使用ionic serve启动服务器之后只要一刷新界面就会导致服务器关闭,报的错误如下: events.js:136 throw er; ...
- linux强制踢出已登录的用户及本地用户
方法一: pkill -kill -t pts/0 方法二: fuser -k /dev/pts/0 你也可以给他发送关闭信息然后关闭 echo "你被管理员踢出了" > / ...
- demo_static_resrouce
环境 win10 + webstorm 2019.1.3 + node 12.x + yarn 实现的的功能 基本的js打包(支持规范:ES6 module | requirejs | commonj ...
- 多目标跟踪笔记二:Efficient Algorithms for Finding the K Best Paths Through a Trellis
Abstract 本文提出了一种新的方法来寻找不相交k最优路径.最坏情况下计算复杂度为N3log(N).该方法比WVD算法(https://www.cnblogs.com/walker-lin/p/1 ...
- Sort HDU5884(二分+多叉哈夫曼树)
HDU5884 Sort 题意:有n个序列要进行归并,每次归并的代价是两个序列的长度的和,要求最终的代价不能超过规定的T,求在此前提下一次能同时进行归并的序列的个数k. 思路:还是太单纯,看完题目一直 ...
- 15.most_fields策略进行cross-fields search
主要知识点: cross-fields 的使用场景 cross-fields 使用方法 cross-fields 的缺点 一.cross-fields 的使用场景 cross-fiel ...
- 单层gmetad高可用
虽然gmetad可以多层,但是层层gmetad都需要开启gweb,还是很麻烦.如果只是担心一个gmetad不安全,可以做成gmetad高可用,但是我还不知道有没有想hadoop ha那样自动failo ...
- OpenStack命令行工具与API
Openstack命令行工具 我们推荐Openstack命令行工具和Openstack的Dashboard两者结合使用.一些用户由于使用过其他云技术背景的,可能会使用EC2兼容的API,相对于我们需要 ...