1.18 LeetCode总结(基本算法)_设计类

编程总结

在刷题之前需要反复练习的编程技巧,尤其是手写各类数据结构实现,它们好比就是全真教的上乘武功

手写完成后,我们针对性的进行练习,练习题如下:
在这里插入图片描述
1603. 设计停车系统
379. 电话目录管理系统
1396. 设计地铁系统
1427. 设计浏览器历史记录
635. 设计日志存储系统

1. 入门

1603. 设计停车系统

在这里插入图片描述
数据结构

typedef struct {
	int bigCar;
	int mediumCar;
	int smallCar;
} ParkingSystem;

主函数

// 1.建立停车系统
ParkingSystem *parkingSystemCreate(int bigCar, int mediumCar, int smallCar)
{
	ParkingSystem *sys = (ParkingSystem *)malloc(sizeof(ParkingSystem));
	sys->bigCar    = bigCar;
	sys->mediumCar = mediumCar;
	sys->smallCar  = smallCar;
	return sys;
}
// 2.增加汽车停车
bool parkingSystemAddCar(ParkingSystem *obj, int carType)
{
	if (carType == 1) {
		if (obj->bigCar > 0) {
			obj->bigCar--;
		} else {
			return false;
		}
	} else if (carType == 2) {
		if (obj->mediumCar > 0) {
			obj->mediumCar--;
		} else {
			return false;
		}
	} else if (carType == 3) {
		if (obj->smallCar > 0) {
			obj->smallCar--;
		} else {
			return false;
		}
	} else {
		return false;
	}
	return true;
}
// 3.释放汽车停车系统
void parkingSystemFree(ParkingSystem *obj)
{
	free(obj);
}

2. 栈与队列

1427. 设计浏览器历史记录

在这里插入图片描述

typedef struct {
	int top;
	int cur;
	char url[5001][21];
} BrowserHistory;
BrowserHistory *browserHistoryCreate(char *homepage)
{
	BrowserHistory *obj = (BrowserHistory *)malloc(sizeof(BrowserHistory));
	obj->top = -1;
	obj->top++;
	obj->cur = obj->top;
	strcpy(obj->url[obj->cur], homepage);

	return obj;
}
void browserHistoryVisit(BrowserHistory *obj, char *url)
{
	obj->cur++;
	strcpy(obj->url[obj->cur], url);
	obj->top = obj->cur; // 将浏览历史前进的记录删除,更新了Top
}
char *browserHistoryBack(BrowserHistory *obj, int steps)
{
	if (steps > obj->cur) {
		steps = obj->cur;
	}
	obj->cur = obj->cur - steps;
	return obj->url[obj->cur];
}
char *browserHistoryForward(BrowserHistory *obj, int steps)
{
	if ((obj->top - obj->cur) < steps) {
		steps = obj->top - obj->cur;
	}
	obj->cur = obj->cur + steps;
	return obj->url[obj->cur];
}
void browserHistoryFree(BrowserHistory *obj)
{
	free(obj);
}

3. 哈希

705. 设计哈希集合

在这里插入图片描述

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);
}

379. 电话目录管理系统

1. get: 分配给用户一个未被使用的电话号码,获取失败请返回 -1
2. check: 检查指定的电话号码是否被使用
3. release: 释放掉一个电话号码,使其能够重新被分配

在这里插入图片描述
数据结构

#define PHONE_OCCUPY  2  // 未被使用赋值为 2,已占用赋值为1
#define PHONE_FREE    1
// 号码节点的定义
typedef struct Node_t {
	int valid;
	int val;
} Node;
// 电话目录的定义
typedef struct {
	Node *node;
	int capacity;
} PhoneDirectory;

主函数

// 1.电话目录的初始化
PhoneDirectory *phoneDirectoryCreate(int maxNumbers)
{
	PhoneDirectory *obj = (PhoneDirectory *)malloc(sizeof(PhoneDirectory));
	obj->node = (Node *)malloc(sizeof(Node) * maxNumbers);
	for (int i = 0; i < maxNumbers; i++) {
		obj->node[i].valid = PHONE_FREE;
		obj->node[i].val   = i;
		obj->capacity      = maxNumbers;
	}

	return obj;
}
// 2.分配用户一个号码
int phoneDirectoryGet(PhoneDirectory *obj)
{
	for (int i = 0; i < obj->capacity; i++) {
		if (obj->node[i].valid == PHONE_FREE) {
			obj->node[i].valid = PHONE_OCCUPY;
			return obj->node[i].val;
		}
	}

	return -1;
}
// 3.检查指定号码是否被使用
bool phoneDirectoryCheck(PhoneDirectory *obj, int number)
{
	for (int i = 0; i < obj->capacity; i++) {
		if (obj->node[i].valid == PHONE_FREE && obj->node[i].val == number) {
			return true;
		}
	}

	return false;
}
// 4.释放特定的号码
void phoneDirectoryRelease(PhoneDirectory *obj, int number)
{
	for (int i = 0; i < obj->capacity; i++) {
		if (obj->node[i].valid == PHONE_OCCUPY && obj->node[i].val == number) {
			obj->node[i].valid = PHONE_FREE;
			return;
		}
	}
	return;
}
// 5.回收
void phoneDirectoryFree(PhoneDirectory *obj)
{
	memset(obj->node, 0, sizeof(Node) * obj->capacity);
	free(obj->node);
	free(obj);
}

1396. 设计地铁系统

在这里插入图片描述
数据结构

#define MAX_SIZE     10000
#define STANAME_LEN  12
// 乘客结构体
typedef struct {
	int    passenger_id;
	char   start_station[STANAME_LEN];
	char   end_station[STANAME_LEN];
	double start_time;
	double end_time;
} Passenger;

// 地铁系统
typedef struct {
	int       passenger_num;
	Passenger passenger[MAX_SIZE];
} UndergroundSystem;

主函数

// 创建地铁系统
UndergroundSystem *undergroundSystemCreate()
{
	UndergroundSystem *obj = (UndergroundSystem *)malloc(sizeof(UndergroundSystem) * 1);
	memset(obj, 0, sizeof(UndergroundSystem));
	if (!obj) {
		return NULL;
	}
	obj->passenger_num = 0;
	return obj;
}
// 通行卡ID等于id的乘客,在时间t,从stationName站进入
void undergroundSystemCheckIn(UndergroundSystem *obj, int id, char *stationName, int t)
{
	obj->passenger[obj->passenger_num].passenger_id = id;
	strcpy(obj->passenger[obj->passenger_num].start_station, stationName);
	obj->passenger[obj->passenger_num].start_time = t;
	obj->passenger_num++;
	return;
}
// 通行卡ID等于id的乘客,在时间t,从stationName站离开
void undergroundSystemCheckOut(UndergroundSystem *obj, int id, char *stationName, int t)
{
	int pnum = obj->passenger_num;
	// 找到id的乘客
	for (int i = 0; i < obj->passenger_num; i++) {
		if (obj->passenger[i].passenger_id == id) {
			if (obj->passenger[i].end_station[0] != '\0') {
				continue;
			}
			pnum = i;
			break;
		}
	}
	// 如果找到的ID合法,则记录下离开站与时间
	if (pnum != obj->passenger_num) {
		strcpy(obj->passenger[pnum].end_station, stationName);
		obj->passenger[pnum].end_time = t;
	}
	return;
}
// 返回从startStation站到endStation站的平均时间
double undergroundSystemGetAverageTime(UndergroundSystem *obj, char *startStation, char *endStation)
{
	double num = 0.0;
	double sum = 0.0;
	for (int i = 0; i < obj->passenger_num; i++) {
		if (!strcmp(startStation, obj->passenger[i].start_station)
			&& !strcmp(endStation, obj->passenger[i].end_station)) {
			num++;
			sum += obj->passenger[i].end_time - obj->passenger[i].start_time;
		}
	}

	return sum / num;
}
// 释放
void undergroundSystemFree(UndergroundSystem* obj)
{
	free(obj);
	return;
}

635. 设计日志存储系统

在这里插入图片描述
strncmp 总结需要

这题巧用了 strncmp 函数,用来比较带size的字符串,且
int strncmp(const char *str1, const char *str2, size_t n);
// 如果返回值 < 0,则表示 str2 大于 str1
// 如果返回值 > 0,则表示 str2 小于 str1

数据结构

#define MAXSIZE 500
// 日志存储数据结构
typedef struct {
	char *timeStamp[MAXSIZE];
	int  id[MAXSIZE];
	int  count;
} LogSystem;

主函数

// 初始化LogSystem对象
LogSystem *logSystemCreate(void)
{
	LogSystem *gLogsys = (LogSystem *)malloc(sizeof(LogSystem));
	gLogsys->count     = 0;
	memset(gLogsys, 0, sizeof(LogSystem));
	for (int i = 0; i < MAXSIZE; i++) {
		gLogsys->timeStamp[i] = (char *)malloc(sizeof(char) * (MAXSIZE));
		memset(gLogsys->timeStamp[i], 0, sizeof(char) * (MAXSIZE));
	}
	return gLogsys;
}
// 给定日志的id和timestamp,将这个日志存入你的存储系统中
void logSystemPut(LogSystem *obj, int id, char *timestamp)
{
	obj->id[obj->count] = id;
	memcpy(obj->timeStamp[obj->count], timestamp, strlen(timestamp) + 1);
	obj->count++;

	return;
}
// 检索给定时间区间[start, end](包含两端)内的所有日志的id
int *logSystemRetrieve(LogSystem *obj, char *start, char *end, char *granularity, int *retSize)
{
	int i;
	int len = 0;
	char *classification[6] = { "Year", "Month", "Day", "Hour", "Minute", "Second" };
	int   classLength[6]    = { 4, 7, 10, 13, 16, 19 }; // 上述时间的字符串长度

	for (i = 0; i < 6; i++) {
		// granularity表示考虑的时间粒度(例如,精确到 Day、Minute 等)
		if (strcmp(granularity, classification[i]) == 0) {
			len = classLength[i];
			break;
		}
	}
	int *ret = (int *)malloc(sizeof(int) * (obj->count)); 
	memset(ret, 0, sizeof(int)*obj->count);
	// 如果返回值 < 0,则表示 str2 大于 str1
	// 如果返回值 > 0,则表示 str2 小于 str1
	for (i = obj->count; i >= 0; i--) { // 由于题目要求输出的顺序,所以这里从后往前了.
		if (strncmp(start, obj->timeStamp[i], len) <= 0 && strncmp(end, obj->timeStamp[i], len) >= 0) {
			ret[(*retSize)++] = obj->id[i];
		}
	}
	return ret;
}
void logSystemFree(LogSystem *obj)
{
	memset(obj, 0, sizeof(LogSystem));
	obj->count = 0;
}

4. 缓存

146. LRU 缓存机制

在这里插入图片描述

typedef struct {
	int key;
	int val;
	UT_hash_handle hh;
} LRUCache;
LRUCache *g_usr = NULL;
int g_size;
// 1.初始化
LRUCache *lRUCacheCreate(int capacity)
{
	g_size = capacity;
	return g_usr;
}
// 2.如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
int lRUCacheGet(LRUCache *obj, int key)
{
	LRUCache *cur_usr = NULL;
	HASH_FIND_INT(g_usr, &key, cur_usr);
	// 因为链表表头存的是最久为使用的数据,所以get一次就要把它更新到链表末尾
	if (cur_usr != NULL) { // get存在的key,则该key被使用了一次,因此需要先删后入,满足LRU
		HASH_DEL(g_usr, cur_usr);
		HASH_ADD_INT(g_usr, key, cur_usr);
		return cur_usr->val;
	}
	// 如果没有找到,则返回-1
	return -1;
}
// 3.如果关键字 key 已经存在,则变更其数据值 value
void lRUCachePut(LRUCache *obj, int key, int value)
{
	LRUCache *cur_usr = NULL, *next_usr = NULL;
	HASH_FIND_INT(g_usr, &key, cur_usr);
	if (cur_usr != NULL) {
		HASH_DEL(g_usr, cur_usr);
		cur_usr->key = key;
		cur_usr->val = value;
		HASH_ADD_INT(g_usr, key, cur_usr);
	} else { // 新插入
		int cnt = HASH_COUNT(g_usr);
		// 如果已经满size了
		if (cnt == g_size) { // 这段的含义
			HASH_ITER(hh, g_usr, cur_usr, next_usr) {
				HASH_DEL(g_usr, cur_usr);
				free(cur_usr);
				break;
			}
		}
		LRUCache *new_usr = (LRUCache *)malloc(sizeof(LRUCache));
		new_usr->key = key;
		new_usr->val = value;
		HASH_ADD_INT(g_usr, key, new_usr);
	}
	return;
}
void lRUCacheFree(LRUCache *obj)
{
	LRUCache *cur_usr = NULL, *next_usr = NULL;
	HASH_ITER(hh, g_usr, cur_usr, next_usr) {
		HASH_DEL(g_usr, cur_usr);
		free(cur_usr);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值