Letcode 夏驰和徐策的每日一题

news/2024/6/15 23:36:35 标签: 算法, 数据结构, 动态规划, Letcode

 

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n^2) 的算法吗?

我的答案:

暴力破解法:

​
#include <stdio.h>
#include <stdlib.h>

int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int i, j;
    int* result = (int*)malloc(2 * sizeof(int));
    *returnSize = 2;
    for(i = 0; i < numsSize - 1; i++){
        for(j = i + 1; j < numsSize; j++){
            if(nums[i] + nums[j] == target){
                result[0] = i;
                result[1] = j;
                return result;
            }
        }
    }
    return NULL;
}

int main(){
    int nums[] = {2, 7, 11, 15};
    int target = 9;
    int numsSize = sizeof(nums) / sizeof(nums[0]);
    int returnSize = 0;
    int* result = twoSum(nums, numsSize, target, &returnSize);
    if(result != NULL){
        printf("[%d, %d]\n", result[0], result[1]);
        free(result);
    }
    return 0;
}


​

 

哈希表解法:

C语言解法

#include <stdio.h>
#include <stdlib.h>

struct hash_node {
    int key;
    int val;
    struct hash_node* next;
};

struct hash_table {
    struct hash_node** nodes;
    int size;
};

struct hash_table* create_hash_table(int size) {
    struct hash_table* table = (struct hash_table*)malloc(sizeof(struct hash_table));
    table->nodes = (struct hash_node**)calloc(size, sizeof(struct hash_node*));
    table->size = size;
    return table;
}

void destroy_hash_table(struct hash_table* table) {
    for (int i = 0; i < table->size; i++) {
        struct hash_node* node = table->nodes[i];
        while (node != NULL) {
            struct hash_node* next = node->next;
            free(node);
            node = next;
        }
    }
    free(table->nodes);
    free(table);
}

int hash(int key, int size) {
    return (key % size + size) % size;
}

void hash_table_put(struct hash_table* table, int key, int val) {
    int idx = hash(key, table->size);
    struct hash_node* node = table->nodes[idx];
    while (node != NULL) {
        if (node->key == key) {
            node->val = val;
            return;
        }
        node = node->next;
    }
    struct hash_node* new_node = (struct hash_node*)malloc(sizeof(struct hash_node));
    new_node->key = key;
    new_node->val = val;
    new_node->next = table->nodes[idx];
    table->nodes[idx] = new_node;
}

int hash_table_get(struct hash_table* table, int key) {
    int idx = hash(key, table->size);
    struct hash_node* node = table->nodes[idx];
    while (node != NULL) {
        if (node->key == key) {
            return node->val;
        }
        node = node->next;
    }
    return -1;
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
    struct hash_table* table = create_hash_table(numsSize);
    for (int i = 0; i < numsSize; i++) {
        int complement = target - nums[i];
        int j = hash_table_get(table, complement);
        if (j != -1) {
            int* result = (int*)malloc(2 * sizeof(int));
            result[0] = j;
            result[1] = i;
            destroy_hash_table(table);
            *returnSize = 2;
            return result;
        }
        hash_table_put(table, nums[i], i);
    }
    destroy_hash_table(table);
    *returnSize = 0;
    return NULL;
}

int main() {
    int nums[] = {2, 7, 11, 15};
    int target = 9;
    int returnSize;
    int* result = twoSum(nums, 4, target, &returnSize);
    if (result != NULL) {
        printf("[%d, %d]\n", result[0], result[1]);
        free(result);
    }
    return 0;
}

C++解法:

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

vector<int> twoSum(vector<int>& nums, int target) {
    unordered_map<int, int> hashTable;
    for (int i = 0; i < nums.size(); i++) {
        int complement = target - nums[i];
        if (hashTable.count(complement)) {
            return {hashTable[complement], i};
        }
        hashTable[nums[i]] = i;
    }
    return {};
}

int main() {
    vector<int> nums = {2, 7, 11, 15};
    int target = 9;
    vector<int> result = twoSum(nums, target);
    for (int i = 0; i < result.size(); i++) {
        cout << result[i] << " ";
    }
    cout << endl;
    return 0;
}

C和C++实现时的区别:

 该代码与之前使用C语言实现的代码类似,也是通过遍历数组和使用哈希表来查找两个数之和等于目标值的下标。不同的是,该代码使用了C++的vector和unordered_map来实现,更加方便和易读。

什么是哈希表?

哈希表(Hash Table)是一种基于哈希函数(Hash Function)实现的数据结构,用于支持快速的插入、删除、查找操作。它的核心思想是通过将元素的关键字映射为一个索引(即哈希值),将元素存储在数组中对应索引的位置上,从而实现快速查找的目的。

哈希表包括两个基本操作:插入和查找。对于插入操作,我们首先计算出待插入元素的哈希值,然后将元素存储在哈希值对应的位置上;对于查找操作,我们先计算出目标元素的哈希值,然后在哈希表中查找是否存在该元素。

哈希表的优点是可以实现快速的插入、删除、查找操作,时间复杂度为O(1)(在哈希函数的选择、哈希冲突的处理等方面有影响)。缺点是在处理哈希冲突时需要额外的时间和空间成本,并且哈希函数的选择对哈希表的性能影响很大。

解析:

哈希表能够降低这个题目的时间复杂度的原因在于,哈希表的查找操作的时间复杂度为O(1),因此可以通过将每个元素的值作为哈希表的键,将每个元素的下标作为哈希表的值,来加速查找过程。

具体地,对于给定的目标值target和数组nums,我们可以遍历一遍数组nums,在遍历的过程中,对于每个元素nums[i],我们计算出其与目标值的差值complement=target-nums[i],然后在哈希表中查找是否存在该差值。如果存在,说明我们已经找到了两个数之和为目标值target,可以直接返回它们的下标;否则,将当前元素nums[i]插入到哈希表中,继续遍历数组。

由于哈希表的查找操作的时间复杂度为O(1),因此总时间复杂度为O(n)。相比于暴力枚举的O(n^2)时间复杂度,哈希表能够显著地降低时间复杂度,提高程序的效率。

反思总结:

从这个题目我们可以学到以下几个方面的知识和技能:

  1. 数据结构算法:这个题目涉及到数组的遍历和哈希表的使用,因此需要熟练掌握数组和哈希表的基本操作和相关算法

  2. 编程语言的基本语法和使用:这个题目需要使用C语言实现,因此需要熟悉C语言的基本语法和常用的函数库。

  3. 问题解决思路的培养:这个题目需要我们思考如何通过一定的数据结构算法来解决问题,因此需要培养问题解决思路和方法的能力。

  4. 实践能力的提升:这个题目需要我们将理论知识转化为实践能力,因此需要多做练习,提高编程实践能力。

总之,这个题目可以帮助我们加深对数据结构算法、编程语言和问题解决思路的理解和掌握,提高实践能力和解决实际问题的能力。

 


http://www.niftyadmin.cn/n/238820.html

相关文章

Nginx中location规则 与 URL重写(rewrite)详解

1.Nginx中location与rewrite 1.1 location与rewrite常用的正则表达式 符号作用^匹配输入字符串的起始位置$ 匹配输入字符串的结束位置*匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll” 匹配前面的字符一次或多次。如“ol”能匹配“ol”及“oll”、“olll”…

网络协议-HTTP协议详情讲解

目录 HTTP协议内容和方法 HTTP请求常见请求头 HTTP常见返回头 HTTP协议基本方法 常见HTTP状态码 面试解惑&#xff1a;301 vs 308 面试解惑&#xff1a;302 / 303 / 307 常见HTTP头 User-Agent Content-Type Origin Accept Referer Connection HTTP协议内容和方法…

【回眸】又是一年毕业季,怎么利用ChatGPT 4.0 优化毕业论文?

目录 【回眸】又是一年毕业季&#xff0c;怎么利用ChatGPT 4.0 优化毕业论文&#xff1f; 前言 ChatGPT4.0降重提示词&#xff08;3.5表现略逊色一些&#xff0c;不过也可以用这个来作为提示词&#xff09; 举个例子 降重前的原文 构思提示词 确定提问词 选用合适的翻译…

【无六级无科研无竞赛】二战上岸上海交大819心路历程

笔者来自通信考研小马哥23上交819全程班学员 我是一个二战考生&#xff0c;本科就读于大连理工大学&#xff0c;本科平均分76&#xff0c;本科无科研无竞赛&#xff0c;四级447低分飘过&#xff0c;考研初试总分379&#xff0c;英语55&#xff0c;政治54&#xff0c;数学138&a…

c#与java的区别

经常有人问这种问题&#xff0c;用了些时间java之后&#xff0c;发现这俩玩意除了一小部分壳子长的还有能稍微凑合上&#xff0c;基本上没什么相似之处&#xff0c;可以说也就是马甲层面上的相似吧&#xff0c;还是比较短的马甲。。。 一般C#多用于业务系统的开发&#xff0c;…

Java知识点学习(第15天)

事务的基本特性和隔离级别 事务基本特性ACID分别是&#xff1a; 原子性&#xff1a;一个事务的操作那么全部成功&#xff0c;要么全部失败。 一致性&#xff1a;数据库从一个一致性状态转换为另一个一致性状态。比如A转给B100元&#xff0c;假如A只有89元&#xff0c;支付之前…

leetcode6376. 一最多的行

给你一个大小为 m x n 的二进制矩阵 mat &#xff0c;请你找出包含最多 1 的行的下标&#xff08;从 0 开始&#xff09;以及这一行中 1 的数目。 如果有多行包含最多的 1 &#xff0c;只需要选择 行下标最小 的那一行。 返回一个由行下标和该行中 1 的数量组成的数组。 示例…

【项目实战课】基于Pytorch的YOLOv3工业缺陷检测实战

欢迎大家来到我们的项目实战课&#xff0c;本期内容是《基于Pytorch的YOLOv3工业缺陷检测实战》。所谓项目课&#xff0c;就是以简单的原理回顾详细的项目实战的模式&#xff0c;针对具体的某一个主题&#xff0c;进行代码级的实战讲解。 本次主题 目标检测是最基础的计算机视觉…