代码随想录算法训练营Day6
242.有效的字母异位词
思路
统计每个字符串各个字母的使用频度即可,如果是字母异位词,各个字母的出现频道应该完全相同。
代码实现
bool isAnagram(char* s, char* t) {
// 计算字符串长度
long lengthS = strlen(s);
long lengthT = strlen(t);
//分别记录两个串的字符频度
long listS[26] = {0};
long listT[26] = {0};
if(lengthS != lengthT){
return false;
}
for (int i = 0; i < lengthS; i++) {
//每个字符频度累加到对应的表项中
listS[s[i] - 'a']++;
listT[t[i] - 'a']++;
}
for (int j = 0; j < 26; j++) {
//如果不是所有字母频度都一样,那么一定不是
if(listS[j] != listT[j]){
return false;
}
}
return true;
}
349.两个数组的交集
思路
使用哈希表分别统计元素个数,如果同一个数据的统计值都不是0,则说明是都包含的元素。
代码实现
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
int map1[1001] = {0}; //哈希表1
int map2[1001] = {0}; //哈希表2
int count = 0; //交集容量
//统计数组1中各个元素的频度
for (int i = 0; i < nums1Size; i++) {
map1[nums1[i]]++;
}
//统计数组2中各个元素的频度
for (int i = 0; i < nums2Size; i++) {
map2[nums2[i]]++;
}
//统计交集大小
for (int i = 0; i < 1001; i++) {
//如果某个值在两个数组中的频度都不是0,说明两个数组都包含
if(map1[i] != 0 && map2[i] != 0){
count++;
}
}
//返回交集
int* result = (int*)malloc(sizeof(int) * count);
int idx = 0;
for (int i = 0; i < 1001; i++) {
if(map1[i] != 0 && map2[i] != 0){
result[idx++] = i;
}
}
*returnSize = count;
return result;
}
202.快乐数
思路
分为两个部分:
- 求解各个位数的平方和
- 根据平方和判定是否为快乐数
求平方和
假设待处理的数据为num
- 求最低位low = num % 10,平方为 low * low;
- 求次高位,相当于把去除最低位的数当做新数,回到1进行相同处理,求新数可以用num = num / 10;
- num为0(即上一次已经处理到原数最高位)时停止
判定是否为快乐数
根据快乐数定义,判定是否为快乐数的过程中可能会出现多次计算的情况,假设num的每轮平方和计算结果为num1、num2、num3...根据题意只有两种情况:
- 如果其中有一个值numi为1,那么后续的numi+1、numi+2...必定都是1
- 如果有两个不同轮次的值numj和numk的值相同,则说明陷入了无限循环。
- 如果本次处理得到平方和为1,满足条件判定成功
- 如果不是1,并且之前没遇到过这个值,则标记遇到过这个值,把这个值当做待处理值,回到上次判定
- 如果不是1,并且之前遇到过这个值,则说明陷入了循环,一定不是快乐数
代码实现
// 取数值各个位上的单数之和
int getSum(int n) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
bool isHappy(int n) {
// 2^31 - 1一共10位,因此最大数不超过9*9*10 = 810
int map[811] = {0};
while(1) {
int sum = getSum(n);
if (sum == 1) {
return true;
}
// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
if (map[sum] != 0) {
return false;
} else {
map[sum]++;
}
n = sum;
}
}
1. 两数之和
思路
直接使用哈希表每个数据是否在数组中,遍历数组,如果计算所需的数在数组中,则立刻返回。
代码实现
// 定义哈希表节点结构
typedef struct HashNode {
int key;
int value;
struct HashNode* next;
} HashNode;
// 定义哈希表结构
typedef struct HashTable {
int size;
HashNode** list;
} HashTable;
// 创建新的哈希节点
HashNode* createNode(int key, int value) {
HashNode* newNode = (HashNode*) malloc(sizeof(HashNode));
newNode->key = key;
newNode->value = value;
newNode->next = NULL;
return newNode;
}
// 初始化哈希表
HashTable* createTable(int size) {
HashTable* table = (HashTable*) malloc(sizeof(HashTable));
table->size = size;
table->list = (HashNode**) malloc(sizeof(HashNode*) * size);
for (int i = 0; i < size; i++) {
table->list[i] = NULL;
}
return table;
}
// 简单的哈希函数
int hashCode(HashTable* table, int key) {
if (key < 0) {
return -(key % table->size);
}
return key % table->size;
}
// 插入键值对到哈希表
void insert(HashTable* table, int key, int value) {
int pos = hashCode(table, key);
HashNode* list = table->list[pos];
HashNode* newNode = createNode(key, value);
newNode->next = list;
table->list[pos] = newNode;
}
// 查找哈希表中的值
int lookup(HashTable* table, int key, int* value) {
int pos = hashCode(table, key);
HashNode* list = table->list[pos];
HashNode* temp = list;
while (temp) {
if (temp->key == key) {
*value = temp->value;
return 1;
}
temp = temp->next;
}
return 0;
}
// 释放哈希表
void freeTable(HashTable* table) {
for (int i = 0; i < table->size; i++) {
HashNode* list = table->list[i];
while (list) {
HashNode* temp = list;
list = list->next;
free(temp);
}
}
free(table->list);
free(table);
}
// 两数之和函数
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
int* result = (int*)malloc(sizeof(int) * 2);
*returnSize = 2;
HashTable* table = createTable(1000); // 创建哈希表
for (int i = 0; i < numsSize; i++) {
int complement = target - nums[i];
int index;
if (lookup(table, complement, &index)) {
result[0] = index;
result[1] = i;
freeTable(table);
return result;
}
insert(table, nums[i], i);
}
freeTable(table);
free(result);
return NULL;
}