solve lab 9

This commit is contained in:
2025-04-09 12:19:01 -04:00
parent e41e5e4a0c
commit bb359c9fe7
2 changed files with 234 additions and 24 deletions

View File

@@ -1,23 +1,143 @@
#include <iostream> #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() { 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}; 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) { for (int n : testCases) {
if (isGood(n)) { if (isGood_unordered_set(n))
std::cout << n << " is a good number." << std::endl; std::cout << n << " is a good number." << std::endl;
} else { else
std::cout << n << " is not a good number." << std::endl; 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; return 0;
} }

View File

@@ -1,23 +1,113 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <list>
// A minimal separate-chaining HashSet for integers.
class MyHashSet {
private:
std::vector< std::list<int> > table;
int num_elements;
static const int DEFAULT_SIZE = 16;
static const double LOAD_FACTOR_THRESHOLD;
int hashFunction(int key) const {
int h = key < 0 ? -key : key; // handle negative
return h % (int)table.size();
}
void rehash() {
int newSize = (int)table.size() * 2;
std::vector< std::list<int> > newTable(newSize);
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() {
double load_factor = (double)num_elements / (double)table.size();
if (load_factor > LOAD_FACTOR_THRESHOLD) {
rehash();
}
}
public:
MyHashSet(int initialSize = DEFAULT_SIZE)
: table(initialSize), num_elements(0) {}
bool find(int key) const {
int h = hashFunction(key);
for (int val : table[h]) {
if (val == key) {
return true;
}
}
return false;
}
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;
int longestConsecutive(std::vector<int>& nums) { int longestConsecutive(std::vector<int>& nums) {
if (nums.empty()) return 0;
// Insert all numbers into the custom hash set
MyHashSet set;
for (int n : nums) {
set.insert(n);
}
int longestStreak = 0;
// For each number, only count a sequence if it's a "start"
// i.e., if (n-1) is NOT in the set
for (int n : nums) {
if (!set.find(n - 1)) {
// n is the start of a consecutive sequence
int currentNum = n;
int currentStreak = 1;
while (set.find(currentNum + 1)) {
currentNum++;
currentStreak++;
}
if (currentStreak > longestStreak) {
longestStreak = currentStreak;
}
}
}
return longestStreak;
} }
int main() { int main() {
// You can change these test vectors to experiment:
//std::vector<int> nums = {100, 4, 200, 1, 3, 2}; //std::vector<int> nums = {100, 4, 200, 1, 3, 2};
std::vector<int> nums = {100, 4, 200, 1, 3, 2, 2, 2, 2, 3};
//std::vector<int> nums = {100, 4, 200, 1, 3, 2, 5, 6};
//std::vector<int> nums = {0,3,7,2,5,8,4,6,0,1}; //std::vector<int> nums = {0,3,7,2,5,8,4,6,0,1};
//std::vector<int> nums = {100, 4, 200, 201, 202, 203, 205, 204, 1, 3, 2}; std::vector<int> nums = {100, 4, 200, 1, 3, 2, 2, 2, 2, 3};
//std::vector<int> nums = {-3,0,1,2,3,-2,-1,-5};
int size = nums.size(); int size = nums.size();
std::cout << "for vector {"; std::cout << "for vector {";
for(int i=0;i<size-1;i++){ for(int i = 0; i < size; i++){
std::cout<< nums[i] << ","; if(i < size - 1) std::cout << nums[i] << ",";
else std::cout << nums[i];
} }
std::cout<< nums[size-1] << "}" <<std::endl; std::cout << "}\n";
int length = longestConsecutive(nums); int length = longestConsecutive(nums);
std::cout << "The length of the longest consecutive sequence is: " << length << std::endl; std::cout << "The length of the longest consecutive sequence is: "
<< length << std::endl;
return 0; return 0;
} }