动态编程:Bits数组Java

动态编程:Bits数组Java,java,algorithm,memory,matrix,dynamic-programming,Java,Algorithm,Memory,Matrix,Dynamic Programming,我需要解决一个动态规划问题,我需要在内存中创建一个N*N大小矩阵。如果我确实创建了一个大小为N=100000的byte[][]矩阵然后抛出java.lang.OutOfMemoryError:java堆空间错误 在此矩阵中,我将在特定的ith和jth索引处存储0或1。因此,我的使用仅限于一位,我需要一种方法,使每个矩阵单元只使用1位大小,而不是在一个只需要1位的单元中保留8位的内存溢出 我怎样才能做到这一点 请注意,我关心的不是增加JVM的堆,我只是在寻找一种方法,以最佳方式实现动态问题的解决方

我需要解决一个
动态规划
问题,我需要在内存中创建一个
N*N
大小矩阵。如果我确实创建了一个大小为
N=100000的
byte[][]
矩阵
然后抛出
java.lang.OutOfMemoryError:java堆空间
错误

在此矩阵中,我将在特定的
ith
jth
索引处存储0或1。因此,我的使用仅限于一位,我需要一种方法,使每个矩阵单元只使用1位大小,而不是在一个只需要1位的单元中保留8位的内存溢出

我怎样才能做到这一点


请注意,我关心的不是增加JVM的堆,我只是在寻找一种方法,以最佳方式实现动态问题的解决方案。

更新:我只是检查了一下,不幸的是,忘记了
位集

BitSet
的genious API是基于
int
索引构建的。整数范围超出了
N*N
的范围。因此,您需要自己实现一些东西。建议:

public class BetterBitSet {

  private final long[] values;

  public BetterBitSet(int dimension) {
    values = new long[(int) ((long) dimension) * dimension / 8 / 64 + 1];
  }

  public void set(int i, int j, boolean value) {
    long index = index(i, j);
    int arrayIndex = arrayIndex(index);
    if (value) {
        values[arrayIndex] = set(values[arrayIndex], offset(index));
    } else {
        values[arrayIndex] = unset(values[arrayIndex], offset(index));
    }
  }

  public boolean isSet(int i, int j) {
    long index = index(i, j);
    return isSet(values[arrayIndex(index)], offset(index));
  }

  private boolean isSet(long value, int bitIndex) {
    return (value & (1L << bitIndex)) != 0;
  }

  private long set(long value, int bitIndex) {
    return value | (1L << bitIndex);
  }

  private long unset(long value, int bitIndex) {
    return value & ~(1L << bitIndex);
  }

  private long index(int i, int j) {
    return j * 8L + i;
  }

  private int arrayIndex(long index) {
    return (int) index / 64;
  }

  private int offset(long index) {
    return (int) index % 64;
  }
}
公共类BetterBitSet{
私有最终长[]值;
公共BetterBitSet(整数维){
值=新长[(int)((长)维度)*维度/8/64+1];
}
公共空集(int i,int j,布尔值){
长指数=指数(i,j);
int arrayIndex=arrayIndex(索引);
如果(值){
值[arrayIndex]=集合(值[arrayIndex],偏移量(索引));
}否则{
值[arrayIndex]=未设置(值[arrayIndex],偏移量(索引));
}
}
公共布尔isSet(int i,int j){
长指数=指数(i,j);
返回isSet(值[arrayIndex(索引)],偏移量(索引));
}
私有布尔isSet(长值,int-bitIndex){

return(value&(1LUpdate:我刚检查过,但实际上忘记了
位集

BitSet
的genious API是基于
int
索引构建的。整数范围超出了
N*N
的范围。因此,您需要自己实现一些功能。建议:

public class BetterBitSet {

  private final long[] values;

  public BetterBitSet(int dimension) {
    values = new long[(int) ((long) dimension) * dimension / 8 / 64 + 1];
  }

  public void set(int i, int j, boolean value) {
    long index = index(i, j);
    int arrayIndex = arrayIndex(index);
    if (value) {
        values[arrayIndex] = set(values[arrayIndex], offset(index));
    } else {
        values[arrayIndex] = unset(values[arrayIndex], offset(index));
    }
  }

  public boolean isSet(int i, int j) {
    long index = index(i, j);
    return isSet(values[arrayIndex(index)], offset(index));
  }

  private boolean isSet(long value, int bitIndex) {
    return (value & (1L << bitIndex)) != 0;
  }

  private long set(long value, int bitIndex) {
    return value | (1L << bitIndex);
  }

  private long unset(long value, int bitIndex) {
    return value & ~(1L << bitIndex);
  }

  private long index(int i, int j) {
    return j * 8L + i;
  }

  private int arrayIndex(long index) {
    return (int) index / 64;
  }

  private int offset(long index) {
    return (int) index % 64;
  }
}
公共类BetterBitSet{
私有最终长[]值;
公共BetterBitSet(整数维){
值=新长[(int)((长)维度)*维度/8/64+1];
}
公共空集(int i,int j,布尔值){
长指数=指数(i,j);
int arrayIndex=arrayIndex(索引);
如果(值){
值[arrayIndex]=集合(值[arrayIndex],偏移量(索引));
}否则{
值[arrayIndex]=未设置(值[arrayIndex],偏移量(索引));
}
}
公共布尔isSet(int i,int j){
长指数=指数(i,j);
返回isSet(值[arrayIndex(索引)],偏移量(索引));
}
私有布尔isSet(长值,int-bitIndex){

return(value&(1LUpdate:我刚检查过,但实际上忘记了
位集

BitSet
的genious API是基于
int
索引构建的。整数范围超出了
N*N
的范围。因此,您需要自己实现一些功能。建议:

public class BetterBitSet {

  private final long[] values;

  public BetterBitSet(int dimension) {
    values = new long[(int) ((long) dimension) * dimension / 8 / 64 + 1];
  }

  public void set(int i, int j, boolean value) {
    long index = index(i, j);
    int arrayIndex = arrayIndex(index);
    if (value) {
        values[arrayIndex] = set(values[arrayIndex], offset(index));
    } else {
        values[arrayIndex] = unset(values[arrayIndex], offset(index));
    }
  }

  public boolean isSet(int i, int j) {
    long index = index(i, j);
    return isSet(values[arrayIndex(index)], offset(index));
  }

  private boolean isSet(long value, int bitIndex) {
    return (value & (1L << bitIndex)) != 0;
  }

  private long set(long value, int bitIndex) {
    return value | (1L << bitIndex);
  }

  private long unset(long value, int bitIndex) {
    return value & ~(1L << bitIndex);
  }

  private long index(int i, int j) {
    return j * 8L + i;
  }

  private int arrayIndex(long index) {
    return (int) index / 64;
  }

  private int offset(long index) {
    return (int) index % 64;
  }
}
公共类BetterBitSet{
私有最终长[]值;
公共BetterBitSet(整数维){
值=新长[(int)((长)维度)*维度/8/64+1];
}
公共空集(int i,int j,布尔值){
长指数=指数(i,j);
int arrayIndex=arrayIndex(索引);
如果(值){
值[arrayIndex]=集合(值[arrayIndex],偏移量(索引));
}否则{
值[arrayIndex]=未设置(值[arrayIndex],偏移量(索引));
}
}
公共布尔isSet(int i,int j){
长指数=指数(i,j);
返回isSet(值[arrayIndex(索引)],偏移量(索引));
}
私有布尔isSet(长值,int-bitIndex){

return(value&(1LUpdate:我刚检查过,但实际上忘记了
位集

BitSet
的genious API是基于
int
索引构建的。整数范围超出了
N*N
的范围。因此,您需要自己实现一些功能。建议:

public class BetterBitSet {

  private final long[] values;

  public BetterBitSet(int dimension) {
    values = new long[(int) ((long) dimension) * dimension / 8 / 64 + 1];
  }

  public void set(int i, int j, boolean value) {
    long index = index(i, j);
    int arrayIndex = arrayIndex(index);
    if (value) {
        values[arrayIndex] = set(values[arrayIndex], offset(index));
    } else {
        values[arrayIndex] = unset(values[arrayIndex], offset(index));
    }
  }

  public boolean isSet(int i, int j) {
    long index = index(i, j);
    return isSet(values[arrayIndex(index)], offset(index));
  }

  private boolean isSet(long value, int bitIndex) {
    return (value & (1L << bitIndex)) != 0;
  }

  private long set(long value, int bitIndex) {
    return value | (1L << bitIndex);
  }

  private long unset(long value, int bitIndex) {
    return value & ~(1L << bitIndex);
  }

  private long index(int i, int j) {
    return j * 8L + i;
  }

  private int arrayIndex(long index) {
    return (int) index / 64;
  }

  private int offset(long index) {
    return (int) index % 64;
  }
}
公共类BetterBitSet{
私有最终长[]值;
公共BetterBitSet(整数维){
值=新长[(int)((长)维度)*维度/8/64+1];
}
公共空集(int i,int j,布尔值){
长指数=指数(i,j);
int arrayIndex=arrayIndex(索引);
如果(值){
值[arrayIndex]=集合(值[arrayIndex],偏移量(索引));
}否则{
值[arrayIndex]=未设置(值[arrayIndex],偏移量(索引));
}
}
公共布尔isSet(int i,int j){
长指数=指数(i,j);
返回isSet(值[arrayIndex(索引)],偏移量(索引));
}
私有布尔isSet(长值,int-bitIndex){

return(value&(1LJava提供了一个名为a的基于位的托管数据结构。我说这是托管的,因为Java没有用于存储位的本机类型,
BitSet
将单个位存储为
long
的组件,并保持
long[]
备份数据集。这是一种非常高效的存储方法,但每64位中保留6位用于“寻址”,仅在原始存储层,这就相当于10%的开销

这意味着您可以通过保持并仔细处理自己的
长[]
,在存储上击败
位集
,代价是代码的复杂性和风险。除非您的空间非常有限,否则可能不值得为
位集
节省约10%的原始开销

上面描述的两种解决方案都是一维位数组,这可能毫无意义。通过将一维数组视为行的串联,您可以轻松地将二维数组转换为一维数组(至少在这种情况下,您似乎假设行宽度相等)。寻址中的特定单元格