[CareerCup] 14.6 CircularArray 环形数组

简介:

14.6 Implement a CircularArray class that supports an array-like data structure which can be efficiently rotated.The class should use a generic type, and should support iteration via the standard for (Obj o : CircularArray) notation.

这道题让我们实现一个环形数组类CircularArray,由于环形数组需要调用rotate(int shiftRight)函数,在这里,我们并不会真的去旋转数组,因为这样十分不高效。我们采用另一种实现方法,用一个变量head来记录环形数组的起始位置,那么调用rotate实际上就是改变head的位置而已。请参见如下代码:

public static class CircularArray<T> implements Iterable<T> {
    private T[] items;
    private int head = 0;
    
    public CircularArray(int size) {
        items = (T[]) new Object[size];
    }
    
    private int convert(int idx) {
        if (idx < 0) {
            idx += items.length;
        }
        return (head + idx) % items.length;
    }
    
    public void rotate(int shiftRight) {
        head = convert(shiftRight);
    }
    
    public T get(int i) {
        if (i < 0 || i >= items.length) {
            throw new java.lang.IndexOutOfBoundsException("...");
        }
        return items[convert(i)];
    }
    
    public void set(int i, T item) {
        items[convert(i)] = item;
    }
    
    public Iterator<T> iterator() {
        return new CircularArrayIterator<T> (this);
    }
    
    private class CircularArrayIterator<TI> implements Iterator<TI> {
        private int _current = -1;
        private TI[] _items;
        
        public CircularArrayIterator(CircularArray<TI> array) {
            _items = array.items;
        }
        
        @Override
        public boolean hasNext() {
            return _current < items.length - 1;
        }
        
        @Override
        public TI next() {
            ++_current;
            TI item = (TI) _items[convert(_current)];
            return item;
        }
        
        @Override
        public void remove() {
            throw new UnsupportedOperationException("...");
        }
    }
}

上述代码中主要有两部分:

1. 实现CircularArray类

实现的过程中容易犯一些错误,比如:

- 我们不能新建一个泛类的数组,我们必须cast数组或者定义类型为List<T>.

- 取余操作符%对于负数运算后会得到负数,这和数学家们定义的取余运算不同,所以我们需要给负数序列加上items.length,时期变为正数再做运算。

- 我们必须一致地保证将原序列转为旋转序列。

2. 实现迭代器Iterator接口

为了使用迭代来遍历数组for (Obj o : CircularArray),我们必须实现迭代器Iterator接口:

- 修改CircularArray<T>的定义,添加implements Iteratble<T>。这需要我们添加一个iterator()方法给CircularArray<T>。

- 建立CircularArrayIterator<T>类implements Iterator<T>,这需要我们实现CircularArrayIterator的一些方法,如hasNext(), next(), 和 remove()。

一旦我们实现了上面两项,for (Obj o : CircularArray)循环就会神奇的运行了。

本文转自博客园Grandyang的博客,原文链接:环形数组[CareerCup] 14.6 CircularArray ,如需转载请自行联系原博主。

相关文章
|
6月前
|
存储 算法 Linux
【C/C++ 线性表】C++ 从零开始实现 双向循环链表(Exploring Doubly Circular Linked List in C++)
【C/C++ 线性表】C++ 从零开始实现 双向循环链表(Exploring Doubly Circular Linked List in C++)
120 0
|
算法
LeetCode每日1题--链表相交
LeetCode每日1题--链表相交
66 0
|
人工智能
Codeforces 220B-Little Elephant and Array-扫描线 & 树状数组
题意: 给出一个长度为n的数组,有m个询问,每次询问给出一个区间,问这个区间内有多少个数x恰好出现x次
124 0
Codeforces 220B-Little Elephant and Array-扫描线 & 树状数组
|
算法 前端开发 程序员
「LeetCode」215-数组中的第K个最大元素⚡️
「LeetCode」215-数组中的第K个最大元素⚡️
118 0
「LeetCode」215-数组中的第K个最大元素⚡️
[路飞]_leetcode-剑指 Offer 21-调整数组顺序使奇数位于偶数前面
leetcode-剑指 Offer 21-调整数组顺序使奇数位于偶数前面
LeetCode 622:设计循环队列 Design Circular Queue
LeetCode 622:设计循环队列 Design Circular Queue 首先来看看队列这种数据结构: 队列:先入先出的数据结构 在 FIFO 数据结构中,将首先处理添加到队列中的第一个元素。
967 0