用于计算整数中设置位数的查找表

时间:2015-07-08 19:44:17

标签: hashmap bit lookup-tables

试图解决这个热门的采访问题 - http://www.careercup.com/question?id=3406682

我能够掌握两种方法 -

  1. Brian Kernighan的算法 - Bits counting algorithm (Brian Kernighan) in an integer time complexity

  2. 查找表。

  3. 我假设当人们说使用查找表时,它们表示以整数为键的Hashmap,以及设置位数为值的计数。

    如何构建此查找表?我们是否使用Brian的算法来计算第一次遇到整数时的位数,将其放入哈希表中,下次遇到该整数时,从哈希表中检索值?

    PS:我知道可以执行popcount(Integer.bitCount())的硬件和软件api,但在这个面试问题的上下文中,我们不允许使用这些方法。

3 个答案:

答案 0 :(得分:1)

整数可以直接用于索引数组; 例如所以你只有一个简单的无符号8位整数数组,其中包含0x0001,0x0002,0x0003的设置位数...并按array[number_to_test]进行查找。

您不需要实现哈希函数来将16位整数映射到您可以订购的东西,这样您就可以拥有查找功能!

答案 1 :(得分:1)

回答有关如何计算此表格的问题:

import com.basho.riak.client.api.RiakClient;
import com.basho.riak.client.api.commands.kv.DeleteValue;
import com.basho.riak.client.api.commands.kv.FetchValue;
import com.basho.riak.client.api.commands.kv.StoreValue;
import com.basho.riak.client.api.commands.kv.UpdateValue;
import com.basho.riak.client.core.RiakCluster;
import com.basho.riak.client.core.RiakNode;
import com.basho.riak.client.core.query.Location;
import com.basho.riak.client.core.query.Namespace;
import com.basho.riak.client.core.query.RiakObject;
import com.basho.riak.client.core.util.BinaryValue;

import java.net.UnknownHostException;

public class TasteOfRiak {
    // A basic POJO class to demonstrate typed exchanges with Riak
    public static class Book {
        public String title;
        public String author;
        public String body;
        public String isbn;
        public Integer copiesOwned;
    }

    // This will allow us to update the book object handling the
    // entire fetch/modify/update cycle.
    public static class BookUpdate extends UpdateValue.Update<Book> {
        private final Book update;
        public BookUpdate(Book update){
            this.update = update;
        }

        @Override
        public Book apply(Book t) {
            if(t == null) {
                t = new Book();
            }

            t.author = update.author;
            t.body = update.body;
            t.copiesOwned = update.copiesOwned;
            t.isbn = update.isbn;
            t.title = update.title;

            return t;
        }
    }

    // This will create a client object that we can use to interact with Riak
    private static RiakCluster setUpCluster() throws UnknownHostException {
        // This example will use only one node listening on localhost:10017
        RiakNode node = new RiakNode.Builder()
                .withRemoteAddress("127.0.0.1")
                .withRemotePort(8087)
                .build();

        // This cluster object takes our one node as an argument
        RiakCluster cluster = new RiakCluster.Builder(node)
                .build();

        // The cluster must be started to work, otherwise you will see errors
        cluster.start();

        return cluster;
    }

    public static void main( String[] args ) {
        try {
            // First, we'll create a basic object storing a movie quote
            RiakObject quoteObject = new RiakObject()
                    // We tell Riak that we're storing plaintext, not JSON, HTML, etc.
                    .setContentType("text/plain")
                            // Objects are ultimately stored as binaries
                    .setValue(BinaryValue.create("You're dangerous, Maverick"));
            System.out.println("Basic object created");

            // In the new Java client, instead of buckets you interact with Namespace
            // objects, which consist of a bucket AND a bucket type; if you don't
            // supply a bucket type, "default" is used; the Namespace below will set
            // only a bucket, without supplying a bucket type
            Namespace quotesBucket = new Namespace("quotes");

            // With our Namespace object in hand, we can create a Location object,
            // which allows us to pass in a key as well
            Location quoteObjectLocation = new Location(quotesBucket, "Iceman");
            System.out.println("Location object created for quote object");

            // With our RiakObject in hand, we can create a StoreValue operation
            StoreValue storeOp = new StoreValue.Builder(quoteObject)
                    .withLocation(quoteObjectLocation)
                    .build();
            System.out.println("StoreValue operation created");

            // And now we can use our setUpCluster() function to create a cluster
            // object which we can then use to create a client object and then
            // execute our storage operation
            RiakCluster cluster = setUpCluster();
            RiakClient client = new RiakClient(cluster);
            System.out.println("Client object successfully created");

            StoreValue.Response storeOpResp = client.execute(storeOp);
            System.out.println("Object storage operation successfully completed");

            // Now we can verify that the object has been stored properly by
            // creating and executing a FetchValue operation
            FetchValue fetchOp = new FetchValue.Builder(quoteObjectLocation)
                    .build();
            RiakObject fetchedObject = client.execute(fetchOp).getValue(RiakObject.class);
            assert(fetchedObject.getValue().equals(quoteObject.getValue()));
            System.out.println("Success! The object we created and the object we fetched have the same value");

            // Now update the fetched object
            fetchedObject.setValue(BinaryValue.create("You can be my wingman any time."));
            StoreValue updateOp = new StoreValue.Builder(fetchedObject)
                    .withLocation(quoteObjectLocation)
                    .build();
            StoreValue.Response updateOpResp = client.execute(updateOp);
            updateOpResp = client.execute(updateOp);

            // And we'll delete the object
            DeleteValue deleteOp = new DeleteValue.Builder(quoteObjectLocation)
                    .build();
            client.execute(deleteOp);
            System.out.println("Quote object successfully deleted");

            Book mobyDick = new Book();
            mobyDick.title = "Moby Dick";
            mobyDick.author = "Herman Melville";
            mobyDick.body = "Call me Ishmael. Some years ago...";
            mobyDick.isbn = "1111979723";
            mobyDick.copiesOwned = 3;
            System.out.println("Book object created");

            // Now we'll assign a Location for the book, create a StoreValue
            // operation, and store the book
            Namespace booksBucket = new Namespace("books");
            Location mobyDickLocation = new Location(booksBucket, "moby_dick");
            StoreValue storeBookOp = new StoreValue.Builder(mobyDick)
                    .withLocation(mobyDickLocation)
                    .build();
            client.execute(storeBookOp);
            System.out.println("Moby Dick information now stored in Riak");

            // And we'll verify that we can fetch the info about Moby Dick and
            // that that info will match the object we created initially
            FetchValue fetchMobyDickOp = new FetchValue.Builder(mobyDickLocation)
                    .build();
            Book fetchedBook = client.execute(fetchMobyDickOp).getValue(Book.class);
            System.out.println("Book object successfully fetched");

            assert(mobyDick.getClass() == fetchedBook.getClass());
            assert(mobyDick.title.equals(fetchedBook.title));
            assert(mobyDick.author.equals(fetchedBook.author));
            // And so on...

            // Now to update the book with additional copies
            mobyDick.copiesOwned = 5;
            BookUpdate updatedBook = new BookUpdate(mobyDick);
            UpdateValue updateValue = new UpdateValue.Builder(mobyDickLocation)
                    .withUpdate(updatedBook).build();
            UpdateValue.Response response = client.execute(updateValue);

            System.out.println("Success! All of our tests check out");

            // Now that we're all finished, we should shut our cluster object down
            cluster.shutdown();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

在给定整数的每个字节上查找此表,并对获得的值求和。

答案 2 :(得分:0)

我到处都在寻找答案,但无法获得令人满意的解释。

让我们先了解左移概念。当我们将数字左移时,我们将数字乘以2 ,然后右移将其除以2。

例如,如果要从数字10(01010)生成数字20(二进制10100),则必须将数字10左移一。我们可以看到10和20中的置位位数是相同的,除了20中的位数与第10位数相比向左移动了一个位置。因此,从这里我们可以得出结论:n中的置位位数为与n / 2中的设置位数相同(如果n为偶数)。

如果是奇数,例如21(10101),则除最后一位外,所有位都将与数字20相同;如果最后一位,则将其设置为1,导致21产生奇数的额外一位。

让我们概括一下这个形式

number of set bits in n is number of set bits in n/2 if n is even
number of set bits in n is number of set bit in n/2 + 1 if n is odd (as in case of odd number last bit is set. 

更通用的公式是:

BitsSetTable256[i] = (i & 1) +  BitsSetTable256[i / 2];

其中BitsetTable256是我们要构建的用于计数的表。对于基本情况,我们可以设置BitsetTable256 [0] = 0;表格的其余部分可以使用自下而上的方法使用上述公式进行计算。