代码随想录算法训练营Day6

81 阅读4分钟

代码随想录算法训练营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;
}

image-20240103225809416

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

image-20240104001433683

202.快乐数

思路

分为两个部分:

  1. 求解各个位数的平方和
  2. 根据平方和判定是否为快乐数

求平方和

假设待处理的数据为num

  1. 求最低位low = num % 10,平方为 low * low;
  2. 求次高位,相当于把去除最低位的数当做新数,回到1进行相同处理,求新数可以用num = num / 10;
  3. num为0(即上一次已经处理到原数最高位)时停止

判定是否为快乐数

根据快乐数定义,判定是否为快乐数的过程中可能会出现多次计算的情况,假设num的每轮平方和计算结果为num1、num2、num3...根据题意只有两种情况:

  • 如果其中有一个值numi为1,那么后续的numi+1、numi+2...必定都是1
  • 如果有两个不同轮次的值numj和numk的值相同,则说明陷入了无限循环。
  1. 如果本次处理得到平方和为1,满足条件判定成功
  2. 如果不是1,并且之前没遇到过这个值,则标记遇到过这个值,把这个值当做待处理值,回到上次判定
  3. 如果不是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;
    }
}

image-20240104010048329

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

image-20240104013945271