leetcodeuthash专题

Posted BHY_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcodeuthash专题相关的知识,希望对你有一定的参考价值。

本文持续更新leetcode上适用于C语言uthash题目解法:

题目:1. 两数之和

链接:https://leetcode-cn.com/problems/two-sum/

解析:num数组值作为key,数组下标作为val。

答案:


typedef struct 
	int num;
 uthash_key_s;
 
typedef struct 
	int index; // 数组下标
 uthash_val_s;
 
typedef struct 
	uthash_key_s key;
	uthash_val_s val;
	UT_hash_handle hh;
 uthash_map_s;
 
uthash_map_s* uthash_create(void)

	uthash_map_s *s = (uthash_map_s *)malloc(sizeof(uthash_map_s));
	s = NULL;
	return s;

 
void uthash_add(uthash_map_s **hash, uthash_key_s key, uthash_val_s val)

	uthash_map_s *s;
 
	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s == NULL) 
		s = (uthash_map_s *)malloc(sizeof(*s));
		s->key = key;
		HASH_ADD(hh, *hash, key, sizeof(uthash_key_s), s);
	
	s->val = val;

 
uthash_map_s* uthash_find(uthash_map_s **hash, uthash_key_s key)

	uthash_map_s *s;
 
	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	return s;

 
void uthash_delete(uthash_map_s **hash, uthash_key_s key)

	uthash_map_s *s;
 
	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s != NULL) 
		HASH_DEL(*hash, s);
		free(s);
	

 
void uthash_delete_all(uthash_map_s **hash)

	uthash_map_s *s, *tmp;
 
	HASH_ITER(hh, *hash, s, tmp) 
		HASH_DEL(*hash, s);
		free(s);
	

 
void uthash_print(uthash_map_s **hash)

	uthash_map_s *s;
 
	for (s = *hash; s != NULL; s = (uthash_map_s *)(s->hh.next)) 
		printf("key %d: val %d\\n", s->key.num, s->val.index); // 自行根据数据结构修改
	

 
unsigned int uthash_get_count(uthash_map_s **hash)

	return HASH_COUNT(*hash);

 
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
    // 边界条件
    if (numsSize <= 0 || returnSize == NULL || nums == NULL) 
        return NULL;
    

    // 初始化
    int *res = (int*)malloc(sizeof(int) * 2);
    *returnSize = 2;

    // hash
    uthash_map_s *hash = uthash_create();
    uthash_key_s key;
    uthash_val_s val;
    for (int i = 0; i < numsSize; i++) 
        key.num = target - nums[i];
        uthash_map_s *tmp = uthash_find(&hash, key);
        if (tmp != NULL) 
            res[0] = i;
            res[1] = tmp->val.index;
            return res;
        

        key.num = nums[i];
        val.index = i;
        uthash_add(&hash, key, val);
    
    return NULL;


结果:

执行结果:通过
执行用时 :8 ms, 在所有 C 提交中击败了95.94%的用户
内存消耗 :7.5 MB, 在所有 C 提交中击败了99.24%的用户

题目:3. 无重复字符的最长子串

链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

解析:直接搞个数组下标代表key就可以,反正就26个字母。但是还是坚持用uthash练习其用法

答案:

typedef struct 
	char ch;
 uthash_key_s;
 
typedef struct 
	int index; // 数组下标
 uthash_val_s;
 
typedef struct 
	uthash_key_s key;
	uthash_val_s val;
	UT_hash_handle hh;
 uthash_map_s;
 
uthash_map_s* uthash_create(void)

	uthash_map_s *s = (uthash_map_s *)malloc(sizeof(uthash_map_s));
	s = NULL;
	return s;

 
void uthash_add(uthash_map_s **hash, uthash_key_s key, uthash_val_s val)

	uthash_map_s *s;
 
	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s == NULL) 
		s = (uthash_map_s *)malloc(sizeof(*s));
		s->key = key;
		HASH_ADD(hh, *hash, key, sizeof(uthash_key_s), s);
	
	s->val = val;

 
uthash_map_s* uthash_find(uthash_map_s **hash, uthash_key_s key)

	uthash_map_s *s;
 
	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	return s;

 
void uthash_delete(uthash_map_s **hash, uthash_key_s key)

	uthash_map_s *s;
 
	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s != NULL) 
		HASH_DEL(*hash, s);
		free(s);
	

 
void uthash_delete_all(uthash_map_s **hash)

	uthash_map_s *s, *tmp;
 
	HASH_ITER(hh, *hash, s, tmp) 
		HASH_DEL(*hash, s);
		free(s);
	

 
void uthash_print(uthash_map_s **hash)

	uthash_map_s *s;
 
	for (s = *hash; s != NULL; s = (uthash_map_s *)(s->hh.next)) 
		printf("key %c: val %d\\n", s->key.ch, s->val.index); // 自行根据数据结构修改
	

 
unsigned int uthash_get_count(uthash_map_s **hash)

	return HASH_COUNT(*hash);


#define max(a,b) ((a)>(b)?(a):(b))
int lengthOfLongestSubstring(char * s)
    int len = strlen(s);
    if (len <= 1) 
        return len;
    

    int left = -1;
    int maxlen = 0;
    uthash_key_s key;
    uthash_val_s val;
    uthash_map_s *hash = uthash_create();
    for (int i = 0; i < len; i++) 
        key.ch = s[i];
        val.index = i;
        // 查看是否已记录该字符
        uthash_map_s *tmp;
        tmp = uthash_find(&hash, key);
        if (tmp != NULL) 
            left = max(left, tmp->val.index); // left不能回头
        
        maxlen = max(maxlen, i - left);
        uthash_add(&hash, key, val); // 如果字符存在,只更新val
    
    return maxlen;


结果:

执行结果:通过
执行用时 :16 ms, 在所有 C 提交中击败了42.76%的用户
内存消耗 :8.5 MB, 在所有 C 提交中击败了5.62%的用户

 

题目:36. 有效的数独

判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

题目链接https://leetcode-cn.com/problems/valid-sudoku/

上图是一个部分填充的有效的数独。

数独部分空格内已填入了数字,空白格用 '.' 表示。

示例 1:

输入:
[
  ["5","3",".",".","7",".",".",".","."],
  ["6",".",".","1","9","5",".",".","."],
  [".","9","8",".",".",".",".","6","."],
  ["8",".",".",".","6",".",".",".","3"],
  ["4",".",".","8",".","3",".",".","1"],
  ["7",".",".",".","2",".",".",".","6"],
  [".","6",".",".",".",".","2","8","."],
  [".",".",".","4","1","9",".",".","5"],
  [".",".",".",".","8",".",".","7","9"]
]
输出: true

说明:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字 1-9 和字符 '.' 。
给定数独永远是 9x9 形式的。

分析:这道题采用C语言的uthash求解,当然有别的更简单的解法,我这里求解只是为了练习uthash,与上一道题【136. 只出现一次的数字】不同的是,这里用的是数组指针,并且所有封装函数的参数均增加了hash指针,用于对不同的hash表操作,重新封装后的uthash如下:

struct my_struct 
    int id; /* key */
    char name[20];
    UT_hash_handle hh; /* makes this structure hashable */
;

struct my_struct *g_hash_row[9] = NULL;
struct my_struct *g_hash_col[9] = NULL;
struct my_struct *g_hash_box[9] = NULL;

void hash_add_ikey(struct my_struct **hash, int ikey_id, char *name)

    struct my_struct *s;

    HASH_FIND_INT(*hash, &ikey_id, s); /* id already in the hash? */
    if (s == NULL) 
        s = (struct my_struct *)malloc(sizeof *s);
        s->id = ikey_id;
        HASH_ADD_INT(*hash, id, s); /* id: name of key field */
    
    // strcpy_s(s->name, 10 * sizeof(char), name); // 自行判断是否使用安全函数,这里不要sizeof(s->name)
    strcpy(s->name, name);


struct my_struct *hash_find_ikey(struct my_struct **hash, int ikey_id)

    struct my_struct *s;

    HASH_FIND_INT(*hash, &ikey_id, s); /* s: output pointer */
    return s;


void hash_delete_ikey(struct my_struct **hash, struct my_struct *ikey)

    struct my_struct *s = NULL;

    HASH_FIND_INT(*hash, &ikey, s);
    if (s == NULL) 
        HASH_DEL(*hash, ikey); /* ikey: pointer to delete */
        free(ikey);
    


void hash_delete_all(struct my_struct **hash)

    struct my_struct *current_ikey, *tmp;

    HASH_ITER(hh, *hash, current_ikey, tmp)
    
        HASH_DEL(*hash, current_ikey); /* delete it (g_hash advances to next) */
        free(current_ikey);             /* free it */
    


void hash_print(struct my_struct **hash)

    struct my_struct *s;

    for (s = *hash; s != NULL; s = (struct my_struct *)(s->hh.next)) 
        printf("ikey id %d: name %s\\n", s->id, s->name);
    


int name_sort(struct my_struct *a, struct my_struct *b)

    return strcmp(a->name, b->name);


int id_sort(struct my_struct *a, struct my_struct *b)

    return (a->id - b->id);


void hash_sort_by_name(struct my_struct **hash)

    HASH_SORT(*hash, name_sort);


void hash_sort_by_id(struct my_struct **hash)

    HASH_SORT(*hash, id_sort);


unsigned int hash_get_count(struct my_struct **hash)

    return HASH_COUNT(*hash);

主函数代码如下,注意每一个return分支都需要clear hash,以免全部变量值对下一个用例产生影响。

void hash_clear()

    for (int i = 0; i < 9; i++) 
        hash_delete_all(&g_hash_row[i]);
        hash_delete_all(&g_hash_col[i]);
        hash_delete_all(&g_hash_box[i]);
    


bool isValidSudoku(char** board, int boardSize, int* boardColSize)
    if (boardSize <= 0 || boardColSize == NULL || *boardColSize <= 0 || board == NULL) 
        return false;
    

    for (int i = 0; i < 9; i++) 
        for (int j = 0; j < 9; j++) 
            if (board[i][j] == '.') 
                continue;
            
            if (hash_find_ikey(&g_hash_row[i], board[i][j]) == NULL) 
                hash_add_ikey(&g_hash_row[i], board[i][j], "g_hash_row");
             else 
                hash_clear();
                return false;
            
            if (hash_find_ikey(&g_hash_col[j], board[i][j]) == NULL) 
                hash_add_ikey(&g_hash_col[j], board[i][j], "g_hash_col");
             else 
                hash_clear();
                return false;
            
            if (hash_find_ikey(&g_hash_box[i/3*3 + j/3], board[i][j]) == NULL) 
                hash_add_ikey(&g_hash_box[i/3*3 + j/3], board[i][j], "g_hash_box");
             else 
                hash_clear();
                return false;
            
        
    

    hash_clear();
    return true;

以上是关于leetcodeuthash专题的主要内容,如果未能解决你的问题,请参考以下文章

2021-09-23:编写一个程序,通过填充空格来解决数独问题。数独的解法需遵循如下规则:数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的(

力扣专题——14. 最长公共前缀——最长公共前缀C语言解法

剑指 の 精选详解「二叉树中序遍历的下一个结点」两种解法

dp专题

专题数位DP

leetcode链表专题