3周攻克数据结构(入门)——1.两数之和

这篇博客介绍了LeetCode的1.两数之和问题,探讨了两种解决方案:暴力求解(两层for循环嵌套)和优化后的哈希表方法。哈希表方法降低了时间复杂度,从O(N^2)优化到O(N),并保持了空间复杂度为O(N)。文章通过具体示例分析了这两种方法的优劣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode:1.两数之和(Two Sum)
包含输入的完整代码可去LeetCode:1.两数之和(Two Sum)Java完整代码

题目内容描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

方法一:直接两层for循环嵌套,暴力求解

两层for循环

for(int i=0;i<nums.length;i++){
	for(int j=0;j<nums.length;j++){
		if(nums[j]==target-nums[i]){
               result[0]=i;
               result[1]=j;
        }
    }
 }

当找到nums[i]+nums[j]=target的时候,将i,j保存入result数组中。

同时因为题目中说,同一元素不能在答案中重复出现,即不应该出现如下情况:

输入:nums=[-1,-2,-3,-4,-5] target=-8
预期输出:[2,4]
实际输出:[3,3]

所以我们在第二个for循环时,让j从i+1开始遍历,这样做的另一个好处就是减少了重复计算。
并且,因为题目中明确说明,只会存在一个有效答案,所以当我们得到需要的i,j的时候,可以直接跳出循环。

修改代码如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
		int n=nums.length;
        int[] result=new int[2];
        for(int i=0;i<n-1;i++){
            for(int j=i+1;j<n;j++){
                if(nums[j]==target-nums[i]){
                    result[0]=i;
                    result[1]=j;
                    break;
                }
            }
        }
        return result;
    }
}

在这里插入图片描述
然而对于这种方法
时间复杂度为:O(N^2)
其中 N 是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
空间复杂度为:O(1)

我们可以清楚意识到,它还有可以需要改进的地方。

以上算法的问题在于,寻找target-nums[i]的时间复杂度过高,那么有没有办法对它进行优化呢?
当然有,答案就是利用hash表。

方法二:哈希表

遍历数组nums,i为当前的数组下标,每一个值都判断hashtable中是否存在target-nums[i]的key值。

如果存在,就得到了两个值,如果不存在就将当前的(nums[i],i)存入hashtable中,继续遍历,直到找到为止。

接下来,我们就以如下的例子进行分析:

输入:nums=[2,7,11,15] target=13
预期输出:[0,2]或者[2,0](题目中有说明,可以按任意顺序输出)

第一步,初始化hashtable
在这里插入图片描述
遍历nums,此时数组下标为0
在这里插入图片描述
遍历nums,此时数组下标为1
在这里插入图片描述

遍历nums,此时数组下标为2
在这里插入图片描述

代码如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
		int n=nums.length;
        int[] result=new int[2];
        Map<Integer,Integer> hashtable=new HashMap<Integer,Integer>();
        for(int i=0;i<n;i++){
            if(hashtable.containsKey(target-nums[i])){
                result[0]=hashtable.get(target-nums[i]);
                result[1]=i;
            }
            hashtable.put(nums[i],i);
        }
        return result;
    }
}

在这里插入图片描述
时间复杂度分析:O(N)
其中N 是数组中的元素数量。对于每一个元素 nums[i],我们可以O(1) 地寻找 target - x。
空间复杂度分析:O(N)
其中 N 是数组中的元素数量。主要为哈希表的开销。

<think>嗯,用户之前问过作为小白应该从哪里开始学编程,我推荐了Python,但现在用户说想先学C语言。我需要调整之前的建议,但保持同样的结构。用户可能对底层感兴趣,或者有特定目标,比如嵌入式系统、操作系统开发。不过作为小白,C语言可能比较难,需要更详细的指导。 首先,我得确认用户了解C语言的挑战,比如指针和内存管理,但也要鼓励他们,说明学习C的好处,比如打好基础。然后,按照之前的步骤结构,分阶段引导,从环境搭建到基础语法,再到项目练习,最后进阶内容。可能需要更多的比喻和简单例子,避免用户被吓到。 要注意用户是小白,所以例子要更简单,解释更详细。比如,变量部分用储物柜的比喻,指针用房间号的例子。项目方面,选择计算器、温度转换、成绩统计这些贴近生活的例子。同时,避坑指南部分要针对C常见错误,比如分号忘记、头文件缺失等。 还要比较C和Python的不同,说明为什么从C开始可能有挑战,但如果有兴趣和坚持是可以的。最后,鼓励用户,强调动手实践的重要性,并提供资源链接,比如编译器安装、在线学习平台。确保整个回答结构清晰,步骤明确,语言浅显易懂。</think>好的!想从C语言入门是个很棒的选择——它就像编程世界的「骨架」,能帮你深入理解计算机底层原理。不过要注意,C语言的学习曲线比Python陡峭(像直接骑两轮自行车),需要更多耐心。以下是**针对小白的C语言学习路线**,用生活化案例拆解: --- ### **C语言特点先知道**(心理准备) 1. **贴近硬件**:直接操作内存(像自己管理仓库库存) 2. **高效但复杂**:需要手动管理细节(像开手动挡汽车) 3. **影响深远**:C++/Java/Python等语言都借鉴了它的设计 --- ### **第一阶段:搭建「工作台」(第1天)** **工具准备**(就像木匠需要锯子和锤子): 1. **编译器安装**: - Windows:下载[MinGW](https://sourceforge.net/projects/mingw/) - Mac/Linux:系统自带`gcc`(终端输入`gcc --version`测试) 2. **编辑器推荐**: - [VS Code](https://code.visualstudio.com/)(安装C/C++扩展) - [Code::Blocks](http://www.codeblocks.org/)(新手友好) **验证安装**:写第一个程序(就像学做菜先煮鸡蛋) ```c #include <stdio.h> // 包含标准输入输出库 int main() { // 程序入口(像房子的主门) printf("Hello, 世界!\n"); // \n代表换行 return 0; // 告诉系统程序正常结束 } ``` ➔ 保存为`hello.c`,终端执行: ```bash gcc hello.c -o hello # 编译 ./hello # 运行(Windows用hello.exe) ``` --- ### **第二阶段:掌握「基础语法」(第2-7天)** **核心四件套**(像学做菜的刀工和火候): 1. **变量与数据类型**(储物柜分类管理) ```c int age = 20; // 整数柜(-2147483648 ~ 2147483647) float price = 9.8; // 小数柜(精确到6位) char grade = &#39;A&#39;; // 字符柜(单引号) char name[] = "小明"; // 字符串(双引号+方括号) ``` 2. **输入输出**(与用户对话) ```c int score; printf("请输入分数:"); // 显示提示 scanf("%d", &score); // %d对应整数,&符号不能少! printf("你输入的是:%d\n", score); ``` 3. **条件语句**(if-else决策树) ```c int temperature; printf("当前温度:"); scanf("%d", &temperature); if (temperature > 30) { printf("建议开空调\n"); } else if (temperature < 10) { printf("记得穿羽绒服\n"); } else { printf("天气舒适\n"); } ``` 4. **循环结构**(重复劳动自动化) ```c // for循环:精确控制次数(像微波炉定时) for(int i=1; i<=5; i++) { printf("第%d次浇水\n", i); } // while循环:条件满足就执行(像烧水等沸腾) int water = 0; while(water < 100) { printf("当前水温:%d℃\n", water); water += 10; } ``` --- ### **第三阶段:攻克「难点关卡」(第2-3)** **三大重点难点**(像学自行车时的刹车和平衡): 1. **数组**(批量数据管理) ```c // 存储一温度 float temperatures[7] = {22.5, 23.0, 24.3, 21.7, 20.9, 25.1, 19.8}; printf("三温度:%.1f℃\n", temperatures[2]); // 输出24.3 ``` 2. **函数**(代码模块化) ```c // 声明函数(像菜谱目录) float convertFtoC(float fahrenheit); int main() { float f = 77.0; printf("%.1f华氏度 = %.1f摄氏度\n", f, convertFtoC(f)); return 0; } // 定义函数(具体做菜步骤) float convertFtoC(float fahrenheit) { return (fahrenheit - 32) * 5 / 9; } ``` 3. **指针**(C语言精髓,像掌握仓库的钥匙) ```c int num = 10; // 定义一个变量 int *p = &num; // p存储num的地址(像记下储物柜编号) printf("num的值:%d\n", num); // 输出10 printf("通过指针访问:%d\n", *p); // *p表示取该地址的值 *p = 20; // 通过指针修改值 printf("修改后:%d\n", num); // 输出20 ``` --- ### **第四阶段:实战小项目(第4)** **推荐项目清单**(从简单到复杂): 1. **智能计算器**(支持加减乘除) ```c #include <stdio.h> int main() { char op; double num1, num2; printf("输入运算符(+ - * /): "); scanf("%c", &op); printf("输入两个数字: "); scanf("%lf %lf", &num1, &num2); switch(op) { case &#39;+&#39;: printf("%.1lf + %.1lf = %.1lf", num1, num2, num1+num2); break; case &#39;-&#39;: printf("%.1lf - %.1lf = %.1lf", num1, num2, num1-num2); break; case &#39;*&#39;: printf("%.1lf * %.1lf = %.1lf", num1, num2, num1*num2); break; case &#39;/&#39;: if(num2 != 0) printf("%.1lf / %.1lf = %.1lf", num1, num2, num1/num2); else printf("除数不能为0"); break; default: printf("无效运算符"); } return 0; } ``` 2. **温度单位转换器**(摄氏←→华氏) 3. **学生成绩管理系统**(存储多科成绩,计算平均分) --- ### **C语言常见问题急救包** | 问题 | 解决方法 | 类比解释 | |-----------------------|--------------------------|----------------------| | 编译报错`undefined reference` | 检查是否漏写main函数 | 像房子没装门 | | 程序闪退 | 在return前加`getchar();` | 让程序等待用户按回车 | | `scanf`不读取输入 | 检查变量前是否漏写`&`符号 | 像填快递单不写地址 | | 死循环 | 确认循环条件有终止机会 | 像烧水不关火 | --- ### **学习资源推荐** 1. **书籍**: - 《C Primer Plus》(详细全面) - 《啊哈C语言》(漫画风格入门) 2. **网站**: - [菜鸟教程C语言](https://www.runoob.com/cprogramming/c-tutorial.html) - [Learn-C.org](https://www.learn-c.org/)(在线练习) 3. **视频**: - B站【C语言入门到精通】[浙江大学翁恺课程](https://www.bilibili.com/video/BV1dr4y1j7Mz) --- ### **关键学习建议** 1. **从模仿开始**:先抄写代码,再逐步修改 2. **理解内存模型**:画图辅助理解指针和数组 3. **坚持调试**:使用`printf`打印中间值(像给程序做X光检查) 现在就可以尝试这个指针练习: ```c #include <stdio.h> int main() { int a = 5; int *p = &a; printf("a的地址:%p\n", p); printf("通过指针改值前:%d\n", a); *p = 10; printf("改值后:%d\n", a); return 0; } ``` 你会看到通过指针可以直接修改变量的值——这就是C语言的魔法!✨
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值