📜  使用位操作进行空间优化

📅  最后修改于: 2021-04-28 17:46:09             🧑  作者: Mango

在很多情况下,我们使用整数值作为数组中的索引来查看是否存在,我们可以使用位操作来优化此类问题中的空间。
让我们以下面的问题为例。
给定两个数字a和b,请使用小于O(| b – a |)的空间标记a和b之间2和5的倍数,并输出每个倍数。

注意:我们必须标记倍数,即在内存中保存(键,值)对,以使每个键的值分别为1或0,分别表示2或5的倍数。

例子 :

Input : 2 10
Output : 2 4 5 6 8 10

Input: 60 95
Output: 60 62 64 65 66 68 70 72 74 75 76 78 
        80 82 84 85 86 88 90 92 94 95

方法1(简单):
将索引从a散列到b并将每个索引标记为1或0。
空间复杂度:O(max(a,b))

方法2(优于简单):
通过将a转换为第0个索引并将b转换为第(ba)个索引来节省内存。
空间复杂度:O(| ba |)。

只需哈希| b – a |数组的位置为0和1。

C++
// C++ program to mark numbers as multiple of 2 or 5
#include 
using namespace std;
 
// Driver code
int main()
{
    int a = 2, b = 10;
    int size = abs(b - a) + 1;
    int* array = new int[size];
 
    // Iterate through a to b, If it is a multiple
    // of 2 or 5 Mark index in array as 1
    for (int i = a; i <= b; i++)
        if (i % 2 == 0 || i % 5 == 0)
            array[i - a] = 1;
 
    cout << "MULTIPLES of 2 and 5:\n";
    for (int i = a; i <= b; i++)
        if (array[i - a] == 1)
            cout << i << " ";
 
    return 0;
}


Java
// Java program to mark numbers as
// multiple of 2 or 5
import java.lang.*;
 
class GFG {
     
    // Driver code
    public static void main(String[] args)
    {
        int a = 2, b = 10;
        int size = Math.abs(b - a) + 1;
        int array[] = new int[size];
     
        // Iterate through a to b, If
        // it is a multiple of 2 or 5
        // Mark index in array as 1
        for (int i = a; i <= b; i++)
            if (i % 2 == 0 || i % 5 == 0)
                array[i - a] = 1;
     
        System.out.println("MULTIPLES of 2"
                              + " and 5:");
        for (int i = a; i <= b; i++)
            if (array[i - a] == 1)
                System.out.printf(i + " ");
    }
}
 
// This code is contributed by
// Smitha Dinesh Semwal


Python3
# Python 3 program to mark numbers
# as multiple of 2 or 5
import math
 
# Driver code
a = 2
b = 10
size = abs(b - a) + 1
array = [0] * size
 
# Iterate through a to b,
# If it is a multiple of 2
# or 5 Mark index in array as 1
for i in range(a, b + 1):
    if (i % 2 == 0 or i % 5 == 0):
            array[i - a] = 1
 
print("MULTIPLES of 2 and 5:")
for i in range(a, b + 1):
    if (array[i - a] == 1):
            print(i, end=" ")
 
# This code is contributed by
# Smitha Dinesh Semwal


C#
// C# program to mark numbers as
// multiple of 2 or 5
using System;
 
class GFG {
     
    // Driver code
    static public void Main ()
    {
        int a = 2, b = 10;
        int size = Math.Abs(b - a) + 1;
        int[] array = new int[size];
     
        // Iterate through a to b, If
        // it is a multiple of 2 or 5
        // Mark index in array as 1
        for (int i = a; i <= b; i++)
            if (i % 2 == 0 || i % 5 == 0)
                array[i - a] = 1;
     
        Console.WriteLine("MULTIPLES of 2" +
                          " and 5:");
        for (int i = a; i <= b; i++)
            if (array[i - a] == 1)
                Console.Write(i + " ");
    }
}
 
// This code is contributed by Ajit.


PHP


Javascript


C++
// CPP code to for marking multiples
#include 
using namespace std;
 
// index >> 5 corresponds to dividing index by 32
// index & 31 corresponds to modulo operation of
// index by 32
 
// Function to check value of bit position whether
// it is zero or one
bool checkbit(int array[], int index)
{
    return array[index >> 5] & (1 << (index & 31));
}
 
// Sets value of bit for corresponding index
void setbit(int array[], int index)
{
    array[index >> 5] |= (1 << (index & 31));
}
 
/* Driver program to test above functions*/
int main()
{
    int a = 2, b = 10;
    int size = abs(b - a);
 
    // Size that will be used is actual_size/32
    // ceil is used to initialize the array with
    // positive number
    size = ceil(size / 32);
     
    // Array is dynamically initialized as
    // we are calculating size at run time
    int* array = new int[size];
 
    // Iterate through every index from a to b and
    // call setbit() if it is a multiple of 2 or 5
    for (int i = a; i <= b; i++)
        if (i % 2 == 0 || i % 5 == 0)
            setbit(array, i - a);
 
    cout << "MULTIPLES of 2 and 5:\n";
    for (int i = a; i <= b; i++)
        if (checkbit(array, i - a))
            cout << i << " ";
 
    return 0;
}


Java
// Java code to for marking multiples
import java.io.*;
import java.util.*;
 
class GFG
{
    // index >> 5 corresponds to dividing index by 32
    // index & 31 corresponds to modulo operation of
    // index by 32
 
    // Function to check value of bit position whether
    // it is zero or one
    static boolean checkbit(int array[], int index)
    {
            int val = array[index >> 5] & (1 << (index & 31));
            if (val == 0)
                return false;
            return true;
    }
 
    // Sets value of bit for corresponding index
    static void setbit(int array[], int index)
    {
            array[index >> 5] |= (1 << (index & 31));
    }
 
    // Driver code
    public static void main(String args[])
    {
            int a = 2, b = 10;
            int size = Math.abs(b-a);
 
            // Size that will be used is actual_size/32
            // ceil is used to initialize the array with
            // positive number
            size = (int)Math.ceil((double)size / 32);
 
            // Array is dynamically initialized as
            // we are calculating size at run time
            int[] array = new int[size];
 
            // Iterate through every index from a to b and
            // call setbit() if it is a multiple of 2 or 5
            for (int i = a; i <= b; i++)
                if (i % 2 == 0 || i % 5 == 0)
                    setbit(array, i - a);
 
            System.out.println("MULTIPLES of 2 and 5:");
            for (int i = a; i <= b; i++)
                if (checkbit(array, i - a))
                    System.out.print(i + " ");
    }
}
 
// This code is contributed by rachana soma


C#
// C# code to for marking multiples
using System;
 
class GFG
{
    // index >> 5 corresponds to dividing index by 32
    // index & 31 corresponds to modulo operation of
    // index by 32
 
    // Function to check value of bit position 
    // whether it is zero or one
    static bool checkbit(int []array, int index)
    {
        int val = array[index >> 5] &
                 (1 << (index & 31));
        if (val == 0)
            return false;
        return true;
    }
 
    // Sets value of bit for corresponding index
    static void setbit(int []array, int index)
    {
            array[index >> 5] |= (1 << (index & 31));
    }
 
    // Driver code
    public static void Main(String []args)
    {
        int a = 2, b = 10;
        int size = Math.Abs(b-a);
 
        // Size that will be used is actual_size/32
        // ceil is used to initialize the array with
        // positive number
        size = (int)Math.Ceiling((double)size / 32);
 
        // Array is dynamically initialized as
        // we are calculating size at run time
        int[] array = new int[size];
 
        // Iterate through every index from a to b and
        // call setbit() if it is a multiple of 2 or 5
        for (int i = a; i <= b; i++)
            if (i % 2 == 0 || i % 5 == 0)
                setbit(array, i - a);
 
        Console.WriteLine("MULTIPLES of 2 and 5:");
        for (int i = a; i <= b; i++)
            if (checkbit(array, i - a))
                Console.Write(i + " ");
    }
}
 
// This code is contributed by 29AjayKumar


输出 :
MULTIPLES of 2 and 5:
2 4 5 6 8 10

方法3(使用位操作)
这是一个优化的空间,它使用位操作技术,该技术可以应用于在数组中映射二进制值的问题。
在64位编译器中,int变量的大小为4个字节。 1个字节由内存中的8位位置表示。因此,内存中的一个整数由32位位置(4字节)表示,这32位位置可以被使用,而不是仅使用一个索引来哈希二进制值。

C++

// CPP code to for marking multiples
#include 
using namespace std;
 
// index >> 5 corresponds to dividing index by 32
// index & 31 corresponds to modulo operation of
// index by 32
 
// Function to check value of bit position whether
// it is zero or one
bool checkbit(int array[], int index)
{
    return array[index >> 5] & (1 << (index & 31));
}
 
// Sets value of bit for corresponding index
void setbit(int array[], int index)
{
    array[index >> 5] |= (1 << (index & 31));
}
 
/* Driver program to test above functions*/
int main()
{
    int a = 2, b = 10;
    int size = abs(b - a);
 
    // Size that will be used is actual_size/32
    // ceil is used to initialize the array with
    // positive number
    size = ceil(size / 32);
     
    // Array is dynamically initialized as
    // we are calculating size at run time
    int* array = new int[size];
 
    // Iterate through every index from a to b and
    // call setbit() if it is a multiple of 2 or 5
    for (int i = a; i <= b; i++)
        if (i % 2 == 0 || i % 5 == 0)
            setbit(array, i - a);
 
    cout << "MULTIPLES of 2 and 5:\n";
    for (int i = a; i <= b; i++)
        if (checkbit(array, i - a))
            cout << i << " ";
 
    return 0;
}

Java

// Java code to for marking multiples
import java.io.*;
import java.util.*;
 
class GFG
{
    // index >> 5 corresponds to dividing index by 32
    // index & 31 corresponds to modulo operation of
    // index by 32
 
    // Function to check value of bit position whether
    // it is zero or one
    static boolean checkbit(int array[], int index)
    {
            int val = array[index >> 5] & (1 << (index & 31));
            if (val == 0)
                return false;
            return true;
    }
 
    // Sets value of bit for corresponding index
    static void setbit(int array[], int index)
    {
            array[index >> 5] |= (1 << (index & 31));
    }
 
    // Driver code
    public static void main(String args[])
    {
            int a = 2, b = 10;
            int size = Math.abs(b-a);
 
            // Size that will be used is actual_size/32
            // ceil is used to initialize the array with
            // positive number
            size = (int)Math.ceil((double)size / 32);
 
            // Array is dynamically initialized as
            // we are calculating size at run time
            int[] array = new int[size];
 
            // Iterate through every index from a to b and
            // call setbit() if it is a multiple of 2 or 5
            for (int i = a; i <= b; i++)
                if (i % 2 == 0 || i % 5 == 0)
                    setbit(array, i - a);
 
            System.out.println("MULTIPLES of 2 and 5:");
            for (int i = a; i <= b; i++)
                if (checkbit(array, i - a))
                    System.out.print(i + " ");
    }
}
 
// This code is contributed by rachana soma

C#

// C# code to for marking multiples
using System;
 
class GFG
{
    // index >> 5 corresponds to dividing index by 32
    // index & 31 corresponds to modulo operation of
    // index by 32
 
    // Function to check value of bit position 
    // whether it is zero or one
    static bool checkbit(int []array, int index)
    {
        int val = array[index >> 5] &
                 (1 << (index & 31));
        if (val == 0)
            return false;
        return true;
    }
 
    // Sets value of bit for corresponding index
    static void setbit(int []array, int index)
    {
            array[index >> 5] |= (1 << (index & 31));
    }
 
    // Driver code
    public static void Main(String []args)
    {
        int a = 2, b = 10;
        int size = Math.Abs(b-a);
 
        // Size that will be used is actual_size/32
        // ceil is used to initialize the array with
        // positive number
        size = (int)Math.Ceiling((double)size / 32);
 
        // Array is dynamically initialized as
        // we are calculating size at run time
        int[] array = new int[size];
 
        // Iterate through every index from a to b and
        // call setbit() if it is a multiple of 2 or 5
        for (int i = a; i <= b; i++)
            if (i % 2 == 0 || i % 5 == 0)
                setbit(array, i - a);
 
        Console.WriteLine("MULTIPLES of 2 and 5:");
        for (int i = a; i <= b; i++)
            if (checkbit(array, i - a))
                Console.Write(i + " ");
    }
}
 
// This code is contributed by 29AjayKumar
输出:
MULTIPLES of 2 and 5:
2 4 5 6 8 10