solve lab 9
This commit is contained in:
@@ -1,23 +1,143 @@
|
||||
#include <iostream>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
bool isGood(int n) {
|
||||
// Compute the sum of the squares of a number's digits.
|
||||
int sumOfSquaresOfDigits(int x) {
|
||||
int sum = 0;
|
||||
while (x > 0) {
|
||||
int digit = x % 10;
|
||||
sum += digit * digit;
|
||||
x /= 10;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
// std::unordered_set
|
||||
bool isGood_unordered_set(int n) {
|
||||
std::unordered_set<int> visited;
|
||||
while (n != 1 && visited.find(n) == visited.end()) {
|
||||
visited.insert(n);
|
||||
n = sumOfSquaresOfDigits(n);
|
||||
}
|
||||
return (n == 1);
|
||||
}
|
||||
|
||||
// std::unordered_map
|
||||
bool isGood_unordered_map(int n) {
|
||||
// We only need to mark that we have "seen" a number.
|
||||
// The bool value is arbitrary; storing true is enough.
|
||||
std::unordered_map<int, bool> visited;
|
||||
while (n != 1 && visited.find(n) == visited.end()) {
|
||||
visited[n] = true; // Mark n as visited
|
||||
n = sumOfSquaresOfDigits(n);
|
||||
}
|
||||
return (n == 1);
|
||||
}
|
||||
|
||||
class MyHashSet {
|
||||
private:
|
||||
// store integers in a vector of lists
|
||||
std::vector< std::list<int> > table;
|
||||
int num_elements;
|
||||
static const int DEFAULT_SIZE = 16;
|
||||
static const double LOAD_FACTOR_THRESHOLD;
|
||||
|
||||
// A simple hash function for int
|
||||
int hashFunction(int key) const {
|
||||
// take abs value
|
||||
int h = key < 0 ? -key : key;
|
||||
return h % (int)table.size();
|
||||
}
|
||||
|
||||
void rehash() {
|
||||
int newSize = (int)table.size() * 2; // doubling
|
||||
std::vector< std::list<int> > newTable(newSize);
|
||||
|
||||
// re-insert all existing elements into newTable
|
||||
for (auto &chain : table) {
|
||||
for (int val : chain) {
|
||||
int h = (val < 0 ? -val : val) % newSize;
|
||||
newTable[h].push_back(val);
|
||||
}
|
||||
}
|
||||
table.swap(newTable);
|
||||
}
|
||||
|
||||
void rehashIfNeeded() {
|
||||
// If load factor = num_elements / table.size() is too big, rehash
|
||||
double load_factor = (double)num_elements / (double)table.size();
|
||||
if (load_factor > LOAD_FACTOR_THRESHOLD) {
|
||||
rehash();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
MyHashSet(int initialSize = DEFAULT_SIZE)
|
||||
: table(initialSize), num_elements(0) {}
|
||||
|
||||
// Return true if key is found
|
||||
bool find(int key) const {
|
||||
int h = hashFunction(key);
|
||||
// Search the list in bin h
|
||||
for (int val : table[h]) {
|
||||
if (val == key) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert key if not already in the hash set
|
||||
void insert(int key) {
|
||||
if (!find(key)) {
|
||||
int h = hashFunction(key);
|
||||
table[h].push_back(key);
|
||||
num_elements++;
|
||||
rehashIfNeeded();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const double MyHashSet::LOAD_FACTOR_THRESHOLD = 1.0;
|
||||
|
||||
// The "isGood" function that uses MyHashSet
|
||||
bool isGood_custom_hash(int n) {
|
||||
MyHashSet visited;
|
||||
while (n != 1 && !visited.find(n)) {
|
||||
visited.insert(n);
|
||||
n = sumOfSquaresOfDigits(n);
|
||||
}
|
||||
return (n == 1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Test cases
|
||||
// 2, 4, 5, 6, 17, 18, 20 are not good numbers.
|
||||
// 1, 7, 10, 13, 19, 23, 28, 68 are good numbers.
|
||||
|
||||
int testCases[] = {2,4,5,6,17,18,20,1,7,10,13,19,23,28,68};
|
||||
|
||||
std::cout << "=== Using std::unordered_set ===" << std::endl;
|
||||
for (int n : testCases) {
|
||||
if (isGood(n)) {
|
||||
if (isGood_unordered_set(n))
|
||||
std::cout << n << " is a good number." << std::endl;
|
||||
} else {
|
||||
else
|
||||
std::cout << n << " is not a good number." << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "\n=== Using std::unordered_map ===" << std::endl;
|
||||
for (int n : testCases) {
|
||||
if (isGood_unordered_map(n))
|
||||
std::cout << n << " is a good number." << std::endl;
|
||||
else
|
||||
std::cout << n << " is not a good number." << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "\n=== Using custom separate-chaining HashSet ===" << std::endl;
|
||||
for (int n : testCases) {
|
||||
if (isGood_custom_hash(n))
|
||||
std::cout << n << " is a good number." << std::endl;
|
||||
else
|
||||
std::cout << n << " is not a good number." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user