AcWing&Leetcode好题分享(入门级)day3
文章目录
前言
今天是算法小学徒分享自己在Acwing&leetcode平台准备笔试面试刷题过程中觉得质量高的题目的第三天,下面配有作者的讲解,希望能够帮助到大家
一、前置知识
滚动数组
滚动数组是一种能够在动态规划中降低空间复杂度的方法,是动态规划(Dynamic Programming,DP)中的一种编程思想,简单地理解就是让数组滚动起来,每次都使用固定的几个存储空间。来达到压缩,节省存储空间的作用。可起到起到优化突间的作用,主要应用在递推或动态规划中(如01背包问题)。而且DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N(个数,项数)很大的情况下可以达到压缩存储的作用。
二、1.斐波那契数列
输入一个整数 n ,求斐波那契数列的第 n 项。
假定从 0 开始,第 0 项为 0。
数据范围
0≤n≤39
样例
输入整数 n=5
返回 5
题目分析:简单介绍一下这题面试中常考的题目斐波那契数列,首先简单介绍一下斐波那契数列是什么:
a0=0,a1=1,an=an−1+an−2,求an是多少
我们可以看到这题的数据范围非常小,可以直接用复杂度为O(n)的递推来做
具体解法:先定义两个变量a,b,分别表示第n−1项和第n项。且定义c=a+b来表示第 n+1项,然后让a,b滚动地顺次往后移一位(滚动数组解法)
class Solution {
public:
int Fibonacci(int n) {
int a=0,b=1;
while(n--)
{
int c=a+b;
a=b,b=c;
}
return a;
}
};
2.替换空格
请实现一个函数,把字符串中的每个空格替换成"%20"。
数据范围
0≤ 输入字符串的长度 ≤1000。
注意输出字符串的长度可能大于 1000。
样例
输入:“We are happy.”
输出:“We%20are%20happy.”
题目分析:
这题用C++做会很方便,我们可以从前往后枚举原字符串;
如果遇到空格,则在string类型的答案中添加"%20";
如果遇到其他字符,则直接将它添加在答案中;
class Solution {
public:
string replaceSpaces(string &str) {
string res;
for(auto x:str)
if (x==' ')
res+="%20";
else
res+=x;
return res;
}
};
3.求1+2+…+n
求 1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句 (A?B:C)。
数据范围
1≤n≤1000。
样例
输入:10
输出:55
题目分析:
(递归) 时间复杂度O(n)
这题最直接的想法就是用递归,sum(n)=n+sum(n-1),
但是要注意终止条件,由于求的是1+2+…+n的和,
所以需要在n=0的时候跳出递归,但是题目要求不能使用if,while等分支判断,
所以可以考虑利用&&短路特性运算来终止判断。
class Solution {
public:
int getSum(int n)
{
int res=n;
n>0&&(res+=getSum(n-1));
return res;
}
};
4.在O(1)时间删除链表结点
给定单向链表的一个节点指针,定义一个函数在O(1)时间删除该结点。
假设链表一定存在,并且该节点一定不是尾节点。
数据范围
链表长度 [1,500]。
样例
输入:链表 1->4->6->8
删掉节点:第2个节点即6(头节点为第0个节点)
输出:新链表 1->4->8
(链表) O(1)
由于是单链表,所以不能找到前驱节点,所以我们不能按常规方法将该节点删除。
我们可以换一种思路,将下一个节点的值复制到当前节点,然后将下一个节点删除即可。
时间复杂度
只有常数次操作,所以时间复杂度是O(1)。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
auto p=node->next;//auto自动定义数据类型
node->val = p->val;
node->next = p->next;
// 这两步的作用就是将 *(node->next) 赋值给 *node,所以可以合并成一条语句:
// *node = *(node->next);
delete p;
}
};
总结
链表是一种线性的数据结构,由分散的节点组成,而每个节点包含数据元素和指向下一个节点的链接(指针)
链表特性:
1.链表是线性表(Linear List)
2.链表节点在内存中存储的空间不连续
3.可以动态地增加或减少元素
链表对比数组
内存空间存储结构:
数组:存储在一组连续的内存空间中
链表:节点分散在各自不同的内存空间中
调整各自的大小
数组:增加或减少元素个数,大多需要重新分配一整块连续的内存空间,然后复制原有数据
链表:节点不需要连续地存储在一块地方,增加和删除节点,非常方便
内部随机访问
数组:可以通过下标地址随机访问数组
链表:只能通过一个节点一个节点轮询,效率低
链表组成元素
节点 Node
数据
指向下一个节点的链接或指针
头 Head
尾 Tail
链表是一种重要的数据结构,在面试中常用来考察应聘者的基本功,希望大家可以在日常学习中多多练习链表这种线性的数据结构,这种数据结构可以用在很多地方,比如内核的消息队列、缓存管理、跳表,B+ 树等。
在面试过程中你能干脆利落地解决链表问题,可以说明你具有一定的算法思想,同时证明了你的编程功底。