[英]Most memory efficient data structure to store 2D array values (Java)
所以我正在嘗試針對以下問題制作最高效的算法 memory:我們有一個無限的地下室。
現在我們從網格上沒有硬幣開始,所以結果總是可以預測的。 我為此使用了二維數組。 我想知道是否有另一種方法。 我在考慮 Hashmaps 或 Hashsets 但我不知道那是如何工作的
僅跟蹤訪問過的有硬幣的位置。
一個 HashSet,其中每個條目都是一個 x,y 對; 最初它是空的。
如果 x,y 不在 map 中,則它沒有硬幣 - 添加一個條目。
如果 x,y 在 map 中,它有一個硬幣 - 刪除條目。
memory 利用率應該高於覆蓋您“可能”訪問的任何地方的數組,並且您不必猜測數組有多大才足夠大。
如果你想在你的項目中引入一個Map
,那是可以的。
作為一個鍵,您可以生成一個由x
和y
坐標組合而成的String
,如果您不需要表示除了硬幣是否存在以外的其他情況, Boolean
將是一個方便的選項作為值。
HashMap
可以完全替代代碼中的basement
數組。 除了map之外,您還需要引入兩個int
字段來表示x
和y
方向的大小。
您可以按照與array相同的方式預填充map 。 您可以生成隨機起始值,而不是使用相同的默認值初始化所有坐標。
在游戲循環中,您可以像這樣切換映射到特定圖塊的值:
map.put(key, !map.get(key));
或者通過使用 Java 8 方法compute()
這種方式:
hasCoinByTileKey.compute(key, (k, v) -> !v);
要查明圖塊是否包含硬幣,請使用get()
:
if (map.get(key)) {
// do something
}
在性能方面,它會表現得相當好,但比基於數組的解決方案稍慢。 因為在引擎蓋下, HashMap
由數組支持。 簡而言之,每個數組元素構成一個桶,對應於特定范圍的哈希值。 映射條目將形成一個鏈表,如果幾個鍵映射到同一個桶(在一定閾值之后,列表將被轉換為樹)。 這同樣適用於HashSet
,因為HashSet
class 是在HashMap
之上構建的。
如果你用HashMap
替換一個數組,你的Basement
class 可能看起來像這樣:
public class Basement {
public static void main(String[] args) {
new Basement(20, 20).update();
}
private static final int STEPS = 20;
private Map<String, Boolean> hasCoinByTileKey = new HashMap<>();
private List<Tile> path = new ArrayList<>();
private int rows;
private int cols;
private record Tile(int x, int y) {}
public Basement(int rows, int cols) {
this.rows = rows;
this.cols = cols;
Random random = new Random();
for (int row = 0; row < cols; row++) {
for (int col = 0; col < cols; col++) {
hasCoinByTileKey.put(getKey(row, col), random.nextBoolean());
}
}
}
public static String getKey(int row, int col) {
return row + "," + col;
}
public void update() {
path.clear(); // cleaning the previous keys
int x = rows / 2;
int y = cols / 2;
int orientation = 0;
/*
0 - up
1 - right
2 - left
3 - down
*/
for (int steps = 0; steps < STEPS; steps++) {
path.add(new Tile(x, y)); // updating the path will current coordinates
String key = getKey(x, y);
if (!hasCoinByTileKey.get(key)) {
hasCoinByTileKey.compute(key, (k, v) -> !v); // toggling the boolean value of the tile
if (orientation == 0) {
y += 1;
orientation = 1;
} else if (orientation == 1) {
x += 1;
orientation = 3;
} else if (orientation == 2) {
x -= 1;
orientation = 0;
} else {
y -= 1;
orientation = 2;
}
} else {
hasCoinByTileKey.compute(key, (k, v) -> !v); // toggling the boolean value of the tile
if (orientation == 0) {
y -= 1;
orientation = 2;
} else if (orientation == 1) {
x -= 1;
orientation = 0;
} else if (orientation == 2) {
x += 1;
orientation = 3;
} else {
y += 1;
orientation = 1;
}
}
}
System.out.println(path.size());
System.out.println(path);
this.print();
}
public void print() {
boolean[][] grid = new boolean[rows][cols];
for (Tile tile: path) {
grid[tile.x][tile.y] = true;
}
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
System.out.print(grid[row][col] ? 'a' : ' ');
}
System.out.println();
}
}
}
為了打印路徑,在更新方法的執行過程中使用一個單獨的列表來跟蹤路徑。 持有坐標的 Object 是一條record
。
main()
- 演示
public static void main(String[] args) {
new Basement(20, 20).update();
}
Output - 20 步(模式與您的示例不同,因為大約一半的瓷磚將預先填充硬幣)
aaaa
aaaa
aaa
aaaaa
aaaa
aa
public final class Basement {
private final Map<Integer, Set<Integer>> board = new HashMap<>();
private final Tile curTile = new Tile();
private final Axis row = new Axis();
private final Axis col = new Axis();
public void nextStep() {
if (hasCoin())
pickUpCoinAndRotate();
else
placeCoinAndRotate();
col.update(curTile.col);
row.update(curTile.row);
}
private boolean hasCoin() {
return hasCoin(curTile.col, curTile.row);
}
private boolean hasCoin(int col, int row) {
return board.getOrDefault(row, Set.of()).contains(col);
}
private void placeCoinAndRotate() {
board.computeIfAbsent(curTile.row, val -> new HashSet<>()).add(curTile.col);
curTile.rotateClockwise();
}
private void pickUpCoinAndRotate() {
board.computeIfAbsent(curTile.row, val -> new HashSet<>()).remove(curTile.col);
curTile.rotateCounterclockwise();
}
private void print() {
for (int row = this.row.min; row <= this.row.max; row++) {
for (int col = this.col.min; col <= this.col.max; col++)
System.out.print(hasCoin(col, row) ? 'a' : '.');
System.out.println();
}
}
private enum Orientation {
UP {
@Override
public Orientation rotateClockwise(Tile curTile) {
curTile.col++;
return RIGHT;
}
@Override
public Orientation rotateCounterclockwise(Tile curTile) {
curTile.col--;
return LEFT;
}
},
RIGHT {
@Override
public Orientation rotateClockwise(Tile curTile) {
curTile.row++;
return DOWN;
}
@Override
public Orientation rotateCounterclockwise(Tile curTile) {
curTile.row--;
return UP;
}
},
DOWN {
@Override
public Orientation rotateClockwise(Tile curTile) {
curTile.col--;
return LEFT;
}
@Override
public Orientation rotateCounterclockwise(Tile curTile) {
curTile.col++;
return RIGHT;
}
},
LEFT {
@Override
public Orientation rotateClockwise(Tile curTile) {
curTile.row--;
return UP;
}
@Override
public Orientation rotateCounterclockwise(Tile curTile) {
curTile.row++;
return DOWN;
}
};
public abstract Orientation rotateClockwise(Tile curTile);
public abstract Orientation rotateCounterclockwise(Tile curTile);
}
private static final class Tile {
private int row;
private int col;
private Orientation orientation = Orientation.UP;
public void rotateClockwise() {
orientation = orientation.rotateClockwise(this);
}
public void rotateCounterclockwise() {
orientation = orientation.rotateCounterclockwise(this);
}
}
private static final class Axis {
private int min;
private int max;
public void update(int cur) {
min = Math.min(min, cur);
max = Math.max(max, cur);
}
}
public static void main(String... args) {
Basement basement = new Basement();
for (int steps = 0; steps < 200; steps++) {
basement.nextStep();
basement.print();
System.out.println();
}
}
}
演示:
..aaaa...
.a....a..
aaa....a.
aaaaaaaa.
.aa.a..a.
.a...a.aa
..aaa.aaa
aaa....a.
...aaaa..
使用稀疏矩陣
class Node {
int row;
int col;
int value;
Node next;
Node(int r, int c, int val)
{ row = r; col = c; this.value = val; }
}
public class Sparse{
public static void main(String[] args)
{
/*Assume a 4x4 sparse matrix */
int sparseMatrix[][] = {
{0, 0, 1, 2},
{3, 0, 0, 0},
{0, 4, 5, 0},
{0, 6, 0, 0}
};
Node start = null; /*Start with the empty list*/
Node tail = null;
int k = 0;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
if (sparseMatrix[i][j] != 0) /*Pass only non-zero values*/
{
Node temp = new Node(i, j, sparseMatrix[i][j]);
temp.next = null;
if(start == null){
start = temp;
tail=temp;
}
else{
tail.next = temp;
tail = tail.next;
}
}
}
Node itr = start;
while(start != null){
System.out.println(start.row + " " + start.col + " " + start.value);
start = start.next;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.