编程总结
每每刷完一道题后,其思想和精妙之处没有地方记录,本篇博客用以记录刷题过程中的遇到的算法和技巧
349. 两个数组的交集
struct unordered_set {
int key;
UT_hash_handle hh;
};
struct unordered_set *find(struct unordered_set **hashtable, int ikey)
{
struct unordered_set *tmp;
HASH_FIND_INT(*hashtable, &ikey, tmp);
return tmp;
}
void insert(struct unordered_set **hashtable, int ikey)
{
struct unordered_set *tmp = find(hashtable, ikey);
if (tmp != NULL) return;
tmp = (struct unordered_set *)malloc(sizeof(struct unordered_set));
tmp->key = ikey;
HASH_ADD_INT(*hashtable, key, tmp);
}
int *getIntersection(struct unordered_set **set1, struct unordered_set **set2, int *returnSize)
{
if (HASH_COUNT(*set1) > HASH_COUNT(*set2)) {
return getIntersection(set2, set1, returnSize);
}
// 储存结果的地方申请内存
int *intersection = (int *)malloc(sizeof(int) * (HASH_COUNT(*set1) + HASH_COUNT(*set2)));
struct unordered_set *s, *tmp;
// 遍历元素少的那个hash表, 在元素多的表中查找是否存在相同的key
HASH_ITER(hh, *set1, s, tmp) {
if (find(set2, s->key)) {
intersection[(*returnSize)++] = s->key;
}
}
return intersection;
}
int *intersection(int *nums1, int nums1Size, int *nums2, int nums2Size, int *returnSize)
{
*returnSize = 0;
struct unordered_set *set1 = NULL, *set2 = NULL;
// 插入元素、构造两个数组的hash集合
for (int i = 0; i < nums1Size; i++) {
insert(&set1, nums1[i]);
}
for (int i = 0; i < nums2Size; i++) {
insert(&set2, nums2[i]);
}
return getIntersection(&set1, &set2, returnSize);
}
705. 设计哈希集合 – Done 2024.06.30
借助 #include “uthash.h”
typedef struct {
int id;
char name[13];
UT_hash_handle hh;
} MyHashSet;
MyHashSet *g_obj = NULL;
MyHashSet *myHashSetCreate()
{
g_obj = NULL;
return g_obj;
}
// 向哈希集合中插入值 key
void myHashSetAdd(MyHashSet *obj, int key)
{
MyHashSet *tmp;
HASH_FIND_INT(g_obj, &key, tmp);
if (tmp == NULL) {
tmp = (MyHashSet *)malloc(sizeof(MyHashSet));
tmp->id = key;
HASH_ADD_INT(g_obj, id, tmp);
}
}
// 将给定值 key 从哈希集合中删除,如果哈希集合中没有这个值,什么也不做
void myHashSetRemove(MyHashSet *obj, int key)
{
MyHashSet *tmp;
HASH_FIND_INT(g_obj, &key, tmp);
if (tmp == NULL) {
return;
}
HASH_DEL(g_obj, tmp);
return;
}
// 返回哈希集合中是否存在这个值 key
bool myHashSetContains(MyHashSet *obj, int key)
{
MyHashSet *tmp = NULL;
HASH_FIND_INT(g_obj, &key, tmp);
if (tmp == NULL) {
return false;
}
return true;
}
void myHashSetFree(MyHashSet *obj)
{
MyHashSet *cur_user;
MyHashSet *tmp;
HASH_ITER(hh, g_obj, cur_user, tmp) {
HASH_DEL(g_obj, cur_user);
free(cur_user);
}
}
void print_users()
{
MyHashSet *s;
for (s = g_obj; s != NULL; s = (MyHashSet *)s->hh.next) {
printf("user id %d\n", s->id);
}
}
法2:万物皆数组
typedef struct {
int hash[1000001];
} MyHashSet;
MyHashSet* myHashSetCreate() {
MyHashSet* obj=(MyHashSet*)calloc(sizeof(MyHashSet),1);
return obj;
}
void myHashSetAdd(MyHashSet* obj, int key) {
obj->hash[key]=1;
}
void myHashSetRemove(MyHashSet* obj, int key) {
obj->hash[key]=0;
}
bool myHashSetContains(MyHashSet* obj, int key) {
return obj->hash[key];
}
void myHashSetFree(MyHashSet* obj) {
free(obj);
}
706. 设计哈希映射
struct List {
int key;
int val;
struct List* next;
};
void listPush(struct List* head, int key, int val) {
struct List* tmp = malloc(sizeof(struct List));
tmp->key = key;
tmp->val = val;
tmp->next = head->next;
head->next = tmp;
}
void listDelete(struct List* head, int key) {
for (struct List* it = head; it->next; it = it->next) {
if (it->next->key == key) {
struct List* tmp = it->next;
it->next = tmp->next;
free(tmp);
break;
}
}
}
struct List* listFind(struct List* head, int key) {
for (struct List* it = head; it->next; it = it->next) {
if (it->next->key == key) {
return it->next;
}
}
return NULL;
}
void listFree(struct List* head) {
while (head->next) {
struct List* tmp = head->next;
head->next = tmp->next;
free(tmp);
}
}
const int base = 769;
int hash(int key) {
return key % base;
}
typedef struct {
struct List* data;
} MyHashMap;
MyHashMap* myHashMapCreate() {
MyHashMap* ret = malloc(sizeof(MyHashMap));
ret->data = malloc(sizeof(struct List) * base);
for (int i = 0; i < base; i++) {
ret->data[i].key = 0;
ret->data[i].val = 0;
ret->data[i].next = NULL;
}
return ret;
}
void myHashMapPut(MyHashMap* obj, int key, int value) {
int h = hash(key);
struct List* rec = listFind(&(obj->data[h]), key);
if (rec == NULL) {
listPush(&(obj->data[h]), key, value);
} else {
rec->val = value;
}
}
int myHashMapGet(MyHashMap* obj, int key) {
int h = hash(key);
struct List* rec = listFind(&(obj->data[h]), key);
if (rec == NULL) {
return -1;
} else {
return rec->val;
}
}
void myHashMapRemove(MyHashMap* obj, int key) {
int h = hash(key);
listDelete(&(obj->data[h]), key);
}
void myHashMapFree(MyHashMap* obj) {
for (int i = 0; i < base; i++) {
listFree(&(obj->data[i]));
}
free(obj->data);
}
1487. 保证文件名唯一
#include <stdint.h>
#include "uthash.h" // 可以使用这个头文件,GitHub开源的,LeetCode有内嵌
#pragma warning(disable : 4996)
typedef struct {
char *key;
int val;
UT_hash_handle hh;
} HashItem;
HashItem *hashFindItem(HashItem **obj, char *key)
{
HashItem *pEntry = NULL;
HASH_FIND_STR(*obj, key, pEntry);
return pEntry;
}
bool hashAddItem(HashItem **obj, char *key, int val)
{
if (hashFindItem(obj, key)) {
return false;
}
HashItem *pEntry = (HashItem *)malloc(sizeof(HashItem));
pEntry->key = (char *)malloc(sizeof(char) *(strlen(key) + 1));
strcpy(pEntry->key, key);
pEntry->val = val;
HASH_ADD_STR(*obj, key, pEntry);
return true;
}
bool hashSetItem(HashItem **obj, char *key, int val)
{
HashItem *pEntry = hashFindItem(obj, key);
if (!pEntry) {
hashAddItem(obj, key, val);
}
else {
pEntry->val = val;
}
return true;
}
int hashGetItem(HashItem **obj, char *key, int defaultVal)
{
HashItem *pEntry = hashFindItem(obj, key);
if (!pEntry) {
return defaultVal;
}
return pEntry->val;
}
void hashFree(HashItem **obj)
{
HashItem *curr = NULL, *tmp = NULL;
HASH_ITER(hh, *obj, curr, tmp) {
HASH_DEL(*obj, curr);
free(curr->key);
free(curr);
}
}
char **getFolderNames(char **names, int namesSize, int *returnSize)
{
HashItem *index = NULL;
char **res = (char **)malloc((sizeof(char *) * namesSize));
int pos = 0;
char *str = NULL;
for (int i = 0; i < namesSize; i++) {
if (!hashFindItem(&index, names[i])) {
res[pos] = (char *)malloc(sizeof(char) * (strlen(names[i]) + 1));
strcpy(res[pos], names[i]);
pos++;
hashAddItem(&index, names[i], 1);
}
else {
// 文件名被占用
int k = hashGetItem(&index, names[i], 0);
str = (char *)malloc(strlen(names[i]) + 16);
sprintf(str, "%s(%d)", names[i], k);
while (hashFindItem(&index, str)) {
k++;
sprintf(str, "%s(%d)", names[i], k);
}
res[pos] = (char *)malloc(sizeof(char) *(strlen(str) + 1));
strcpy(res[pos], str);
pos++;
hashSetItem(&index, names[i], k + 1);
hashAddItem(&index, str, 1);
}
}
*returnSize = pos;
hashFree(&index);
return res;
}
int main()
{
char names[4][10] = { {"pes"}, {"pes(1)"}, {"pes"}, {"pes(2019)"} };
int namesSize = 4;
int returnSize = 4;
char **res = (char **)malloc(sizeof(char **) * 4);
for (int i = 0; i < 4; i++) {
res[i] = names[i];
}
char **result = getFolderNames(res, namesSize, &returnSize);
return 0;
};
299. 猜数字游戏
有多少位属于数字猜对了但是位置不对(称为 “Cows”,奶牛)。也就是说,这次猜测中有多少位非公牛数字可以通过重新排列转换成公牛数字 – 这句话很重要,引出后面使用 B += MIN(dicS[j], dicG[j]); dicG需要看dicS是否有这个坑口可以塞进去,否则多余的dicG是冗余的。
输入:secret = “2211”, guess = “1122”
输出:"0A4B, 不是“0A2B”
char *getHint(char *secret, char *guess) {
int A = 0;
int B = 0;
int dicS[10] = { 0 };
int dicG[10] = { 0 };
int i = 0;
while (secret[i]) {
if (secret[i] == guess[i]) {
// 同位置且相等(完全匹配),公牛数+1
A++;
}
else {
// 同位置不相等,分别配统计 secret 和 guess 中不能完全匹配的数字的个数
dicS[(int)(secret[i] - '0')]++;
dicG[(int)(guess[i] - '0')]++;
}
i++;
}
int j = 0;
for (j = 0; j < 10; j++) {
// 由于多余的数字无法匹配,对于 0-9 的每位数字,应取其在secret 和 guess 中的出现次数的最小值
B += MIN(dicS[j], dicG[j]);
}
char *res = (char *)malloc(sizeof(char) * 9);
sprintf(res, "%dA%dB", A, B);
return res;
}