Implement an iterator to flatten a 2d vector.
For example,
Given 2d vector =
[ [1,2], [3], [4,5,6] ]
By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6]
.
Hint:
- How many variables do you need to keep track?
- Two variables is all you need. Try with
x
andy
. - Beware of empty rows. It could be the first few rows.
- To write correct code, think about the invariant to maintain. What is it?
- The invariant is
x
andy
must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it? - Not sure? Think about how you would implement
hasNext()
. Which is more complex? - Common logic in two different places should be refactored into a common method.
Follow up:
As an added challenge, try to code it using only iterators in C++ or iterators in Java.
這道題讓我們壓平一個二維向量數組,並且實現一個 iterator 的功能,包括 next 和 hasNext 函數,那么最簡單的方法就是將二維數組按順序先存入到一個一維數組里,然后此時只要維護一個變量i來記錄當前遍歷到的位置,hasNext 函數看當前坐標是否小於元素總數,next 函數即為取出當前位置元素,坐標后移一位,參見代碼如下:
解法一:
class Vector2D { public: Vector2D(vector<vector<int>>& vec2d) { for (auto a : vec2d) { v.insert(v.end(), a.begin(), a.end()); } } int next() { return v[i++]; } bool hasNext() { return i < v.size(); } private: vector<int> v; int i = 0; };
下面我們來看另一種解法,不直接轉換為一維數組,而是維護兩個變量x和y,將x和y初始化為0,對於 hasNext 函數,檢查當前x是否小於總行數,y是否和當前行的列數相同,如果相同,說明要轉到下一行,則x自增1,y初始化為0,若此時x還是小於總行數,說明下一個值可以被取出來,那么在 next 函數就可以直接取出行為x,列為y的數字,並將y自增1,參見代碼如下:
解法二:
class Vector2D { public: Vector2D(vector<vector<int>>& vec2d): data(vec2d), x(0), y(0) {} int next() { hasNext(); return data[x][y++]; } bool hasNext() { while (x < data.size() && y == data[x].size()) { ++x; y = 0; } return x < data.size(); } private: vector<vector<int>> data; int x, y; };
題目中的 Follow up 讓我們用 interator 來做,C++中 iterator 不像 Java 中的那么強大,自己本身並沒有包含 next 和 hasNext 函數,所以得自己來實現,將x定義為行的 iterator,再用個 end 指向二維數組的末尾,定義一個整型變量y來指向列位置,實現思路和上一種解法完全相同,只是寫法略有不同,參見代碼如下:
解法三:
class Vector2D { public: Vector2D(vector<vector<int>>& vec2d): x(vec2d.begin()), end(vec2d.end()) {} int next() { hasNext(); return (*x)[y++]; } bool hasNext() { while (x != end && y == (*x).size()) { ++x; y = 0; } return x != end; } private: vector<vector<int>>::iterator x, end; int y = 0; };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/251
類似題目:
參考資料:
https://leetcode.com/problems/flatten-2d-vector/