LeetCode 667 键值映射 C语言

LeetCode 667 键值映射 C语言

实现一个 MapSum 类里的两个方法,insert 和 sum。

对于方法 insert,你将得到一对(字符串,整数)的键值对。字符串表示键,整数表示值。如果键已经存在,那么原来的键值对将被替代成新的键值对。

对于方法 sum,你将得到一个表示前缀的字符串,你需要返回所有以该前缀开头的键的值的总和。

示例 1:

输入: insert(“apple”, 3), 输出: Null
输入: sum(“ap”), 输出: 3
输入: insert(“app”, 2), 输出: Null
输入: sum(“ap”), 输出: 5

什么是键值?String str=“test”; str是一个引用,以地址的形式存储在栈中,相当于键值对中的键,而"test"是存储在内存堆中的一个值,想当于键值对中的值。概念很广,有点线性映射的样子。
思路1:前缀树https://blog.csdn.net/qq_40405527/article/details/108044311

#define Num   26
typedef struct mapsum{
    int isEnd;
    int val;
    struct mapsum* next[Num];    
} MapSum;

/** Initialize your data structure here. */
MapSum* mapSumCreate() {
    MapSum* root = (MapSum*)malloc(sizeof(MapSum));
    memset(root, 0, sizeof(MapSum));
    return root;
}

void mapSumInsert(MapSum* obj, char * key, int val) {
    MapSum* root = obj;
    int len = strlen(key);
    int index = 0;
    for(int i=0;i<len;i++) {
        index = key[i] - 'a';
        if(root->next[index]==NULL) {
            root->next[index] = mapSumCreate();            
        }
        root = root->next[index];
    }
    root->isEnd = true;
    root->val = val; 
}

int sum_all_prefix(MapSum* obj){
    if(obj==NULL) 
        return 0;
    int res = obj->val;
    for(int i=0;i<Num;i++) {
        res += sum_all_prefix(obj->next[i]);
    }
    return res;
}

int mapSumSum(MapSum* obj, char * prefix) {
    MapSum* root = obj;
    int len = strlen(prefix);
    int index = 0;
    for(int i=0;i<len;i++) {  
        index = prefix[i] - 'a';
        if(root->next[index]!=NULL) {
            root = root->next[index];
        } else 
            return 0; //没有该前缀
    }
	return sum_all_prefix(root);//去找所有该前缀结尾的值
}

void mapSumFree(MapSum *obj){
    MapSum *root = obj;
    for(int i=0;i<Num;i++){
        if(root->next[i] != NULL)
            mapSumFree(root->next[i]);
    }
    free(root);
}

思路2:常规解题

1: 首先是创建MapSum_Create()一个指向结构体Struct ListNode 的头结点 root
2: 接着是插入void MapSum_Insert(MapSum * obj,char *str, int val)
  2.1 判断是否有相同键值struct List_node *find_node_in_list(MapSum *obj,char *str):以obj->node为起点判断是否为空,
   如果不为空,判断该节点的node->str与传参str是否一致,如果相同,则返回该节点;否则指向下一个节点(strcmp的参数不能为NULL,所以当传参节点的str为空时,指向下一节点跳出本次循环)
   如果为空,则直接返回,代表没有找到相同键
  2.2 寻找最后一个非空节点struct List_node *get_last_node(MapSum *obj),用于寻找节点插入的位置,以obj->node为起点为判断:
  如果不为空,则循环查找,如果为空则代表是头结点
    find_node_in_list如果没有找到相同键,则分配空间存放新的键;如果找到了,则修改该节点的值;get_last_node如果是空,新节点插入在头结点后;非空,则插入在最后一个节点后;
3: 统计前缀相同的键值和int MapSum_Sum(MapSum *obj,char *prefix);以obj->node为起点判断
   利用strncmp以前缀字符串的长度判断是否一致;如果一致则统计总和sum值
4: 释放void MapSum_free(MapSum *obj)以及void list_free(List_node *temp_node)
  递归调用list_free从尾节点开始释放,结束后释放头文件root

#include <string.h>
#include <stdlib.h>

struct list_node {
    struct list_node* next;
    char* str;
    int val;
};

typedef struct {
    struct list_node* node;
} MapSum;

/** Initialize your data structure here. */
MapSum* mapSumCreate() {
    MapSum * root = (MapSum *)malloc(sizeof(MapSum));
    memset(root,0,sizeof(MapSum));
    return root;
}

struct list_node* find_node_in_list(char* str, MapSum* obj)
{
    struct list_node* find_node = obj->node;
    while (find_node != NULL) {
        if (find_node->str == NULL) {
            find_node = find_node->next;
            continue;
        }
        if (strcmp(find_node->str, str) == 0) {
            return find_node;
        } else {
            find_node = find_node->next;
        }
    }
    return find_node;
}
struct list_node* get_last_node(MapSum* obj)
{
    struct list_node* temp_node = obj->node;

    while (temp_node != NULL) {
        if (temp_node->next == NULL) {
            return temp_node;
        }
        temp_node = temp_node->next;
    }
    return temp_node;
}

void mapSumInsert(MapSum* obj, char * str, int val) {
    struct list_node* node = NULL;
    size_t len = 0;
    struct list_node* last_node = NULL;
    if (obj == NULL || str == NULL) {
        return;
    }
    node = find_node_in_list(str, obj);
    if (node == NULL) {
        node = (struct list_node*)malloc(sizeof(struct list_node));
        #if 1
        if (node == NULL) {
            return;
        }
        memset(node, 0, sizeof(struct list_node));
        last_node = get_last_node(obj);
        if (last_node == NULL) {
            obj->node = node;
        } else {
            last_node->next = node;
        }
        #endif
    }
    if (node->str == NULL) {
        len = strlen(str) + 1;
        node->str = (char*)malloc(len);
        strcpy(node->str, str);
    }
    node->val = val;

}

int mapSumSum(MapSum* obj, char * prefix) {
    size_t len = 0;
    int sum = 0;
    struct list_node* temp_node = obj->node;

    if (obj == NULL || prefix == NULL) {
        return sum;
    }

    len = strlen(prefix);
    while (temp_node != NULL) {
        if (strncmp(temp_node->str, prefix, len) == 0) {
            sum += temp_node->val;
        }
        temp_node = temp_node->next;
    }
    return sum;
}

void list_free(struct list_node* temp_node)
{
    if (temp_node == NULL) {
        return;
    }
    list_free(temp_node->next);
    free(temp_node->str);
    temp_node->str = NULL;
    free(temp_node);
    temp_node = NULL;
}
void mapSumFree(MapSum* obj) {
    if (obj == NULL) {
        return;
    }
    list_free(obj->node);
    free(obj);
}
/*
Map_key.c
以下是在ubuntu 14.04下能实现功能的代码
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct List_node{
    struct List_node *next;
    char *str;
    int val;
};
typedef struct{
    struct List_node *node;
}MapSum;
//MapSum g_list_head = {0};
MapSum * MapSum_Create(){
    MapSum * root =(MapSum*)malloc(sizeof(MapSum)); 
    //return &g_list_head;
    return root;
}
struct List_node * find_node_in_list(char * str,MapSum *obj){
    struct List_node * find_node = obj->node;
    while(find_node != NULL){
        if(find_node->str == NULL){      
            find_node = find_node->next;    
          continue;
        }       

        if(strcmp(find_node->str,str)==0){//找到相同键则返回该节点
           return find_node; 
        }
        else{
           find_node = find_node->next; //没有找到则继续,直到尾节点
        }
    }
    return find_node;
}
struct List_node* get_last_node(MapSum * obj){
    struct List_node * temp_node = obj->node;
    while(temp_node != NULL){ //找到最后一个非空的节点
        if(temp_node->next == NULL){
           return temp_node;       
        }  
        temp_node = temp_node->next; 
    }
    return temp_node;
}
void MapSum_Insert(MapSum *obj, char *str,int val){
    struct List_node * node = NULL;
    int len;
    struct List_node * last_node = NULL;
    if(obj == NULL || str == NULL){
        return;
    }
    node = find_node_in_list(str,obj);
    if(node == NULL){//没有找到相同的键,则分配空间存放下一节点
        node = (struct List_node *)malloc(sizeof(struct List_node));
        if(node == NULL){
            return;
        }
        memset(node,0,sizeof(struct List_node));
        last_node = get_last_node(obj);//找到最后一个非空的节点 插入node
        if(last_node == NULL){
            obj->node = node;//如果为空,为根节点
        }
        else{
           last_node->next = node;     
        } 
    }
    if(node->str == NULL){//如果没有找到相同键,分配新空间的str为空
        len = strlen(str)+1;
        node->str = (char *)malloc(len);
        strcpy(node->str,str);
        node->val = val;
        printf("没有找到相同键,插入新键%s\n",str);
    }
    else{
        node->val = val;//如果存在相同键覆盖,不存在则赋值
        printf("找到相同键%s,修改值为%d\n",str,val);
    }
}
int MapSum_Sum(MapSum * obj,char * prefix){
    int len=0;
    int sum=0;
    struct List_node * temp_node = obj->node;

    if(obj==NULL || prefix==NULL){
        return sum;
    }    
    len = strlen(prefix);
    while(temp_node != NULL){
       if(strncmp(temp_node->str,prefix,len)==0){//比较前缀与键值的前len个字符
           sum += temp_node->val; 
       }
       temp_node = temp_node->next; 
    }
    return sum;
}
#if 0
void List_free(struct List_node ** temp_node){
    if(temp_node == NULL){
        return;
    }//递归释放空间
    List_free(&(*temp_node)->next);//释放node->str的空间
    printf("准备释放释放键%s\n",(*temp_node)->str);
    free((*temp_node)->str);
    (*temp_node)->str=NULL;
    free(*temp_node);
    *temp_node =NULL;
}
#endif
void list_free(struct List_node * temp_node){
    if(temp_node == NULL)
        return;
    list_free(temp_node->next);
    printf("准备释放键%s\n",temp_node->str);
    free(temp_node->str);
    printf("准备释放节点\n");
    free(temp_node);
    temp_node=NULL;
}
void MapSum_free(MapSum * obj){
    if(obj == NULL){
        return; 
    }
   // List_free(&obj->node);
    list_free(obj->node);
    printf("准备释放根结点\n");
    free(obj);
    printf("释放结束\n");
}
void main(){
    MapSum * root =MapSum_Create();
    MapSum_Insert(root,"apple",3);
    printf("\"ap\"前缀的值总和为%d\n",MapSum_Sum(root,"ap"));
    MapSum_Insert(root,"app",2);
    printf("\"ap\"前缀的值总和为%d\n",MapSum_Sum(root,"ap"));
    MapSum_Insert(root,"app",3);
    MapSum_Insert(root,"pp",3);
    printf("\"ap\"前缀的值总和为%d\n",MapSum_Sum(root,"ap"));
    MapSum_free(root);
}

ubnut下实验结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值